Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
767be39673 | ||
|
|
714d966d48 |
@@ -12,13 +12,6 @@
|
||||
(def left-icon
|
||||
{:margin-right gap})
|
||||
|
||||
(defn left-image
|
||||
[size border-radius]
|
||||
{:margin-right gap
|
||||
:width (- size gap)
|
||||
:height (- size gap)
|
||||
:border-radius border-radius})
|
||||
|
||||
(defn right-icon
|
||||
[label-color]
|
||||
{:color label-color
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.foundations.customization-colors :as customization-colors]
|
||||
[quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.fast-image :as fast-image]))
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn view
|
||||
"Props:
|
||||
@@ -17,8 +16,6 @@
|
||||
- state: :default (default) | :active | :disabled
|
||||
- emoji?: boolean
|
||||
- icon?: boolean
|
||||
- image?: boolean
|
||||
- image-source: image source
|
||||
- no-icon-color?: boolean
|
||||
- background: :blur | :photo (optional)
|
||||
- icon-name: keyword
|
||||
@@ -26,7 +23,7 @@
|
||||
|
||||
Child: string - used as label or emoji (for emoji only)"
|
||||
[{:keys [type size state background customization-color on-press icon-name icon? emoji?
|
||||
accessibility-label no-icon-color? image? image-source]
|
||||
accessibility-label no-icon-color?]
|
||||
:or {type :grey
|
||||
size :size-40
|
||||
state :default
|
||||
@@ -77,10 +74,6 @@
|
||||
:no-color no-icon-color?
|
||||
:size icon-size
|
||||
:container-style style/left-icon}])
|
||||
(when image?
|
||||
[fast-image/fast-image
|
||||
{:source (or (:source image-source) image-source)
|
||||
:style (style/left-image icon-size border-radius)}])
|
||||
[text/text
|
||||
{:size text-size
|
||||
:weight :medium
|
||||
|
||||
@@ -25,25 +25,22 @@
|
||||
:blur :grey})
|
||||
|
||||
(defn- page-nav-base
|
||||
[{:keys [margin-top background on-press accessibility-label icon-name behind-overlay? align-center?
|
||||
left-component]
|
||||
[{:keys [margin-top background on-press accessibility-label icon-name behind-overlay? align-center?]
|
||||
:or {background :white}}
|
||||
& children]
|
||||
(into [rn/view {:style (style/container margin-top)}
|
||||
(when (or icon-name left-component)
|
||||
(when icon-name
|
||||
[rn/view (when align-center? {:style style/icon-container})
|
||||
(if icon-name
|
||||
[button/button
|
||||
{:type (button-type background)
|
||||
:icon-only? true
|
||||
:size 32
|
||||
:on-press on-press
|
||||
:background (if behind-overlay?
|
||||
:blur
|
||||
(when (button-properties/backgrounds background) background))
|
||||
:accessibility-label accessibility-label}
|
||||
icon-name]
|
||||
[left-component])])]
|
||||
[button/button
|
||||
{:type (button-type background)
|
||||
:icon-only? true
|
||||
:size 32
|
||||
:on-press on-press
|
||||
:background (if behind-overlay?
|
||||
:blur
|
||||
(when (button-properties/backgrounds background) background))
|
||||
:accessibility-label accessibility-label}
|
||||
icon-name]])]
|
||||
children))
|
||||
|
||||
(defn- right-section-spacing [] [rn/view {:style style/right-actions-spacing}])
|
||||
@@ -117,19 +114,22 @@
|
||||
title]]))
|
||||
|
||||
(defn- dropdown-center
|
||||
[{:keys [background dropdown-props center-content-container-style]}]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
dropdown-type (cond
|
||||
(= background :photo) :grey
|
||||
(and (= theme :dark) (= background :blur)) :grey
|
||||
:else :ghost)]
|
||||
[{:keys [background dropdown-on-press dropdown-selected? dropdown-text
|
||||
center-content-container-style]}]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
dropdown-type (cond
|
||||
(= background :photo) :grey
|
||||
(and (= theme :dark) (= background :blur)) :grey
|
||||
:else :ghost)
|
||||
dropdown-state (if dropdown-selected? :active :default)]
|
||||
[reanimated/view {:style center-content-container-style}
|
||||
[dropdown/view
|
||||
(merge {:type dropdown-type
|
||||
:size :size-32
|
||||
:background (when (dropdown-properties/backgrounds background) background)}
|
||||
dropdown-props)
|
||||
(:dropdown-text dropdown-props)]]))
|
||||
{:type dropdown-type
|
||||
:state dropdown-state
|
||||
:size :size-32
|
||||
:background (when (dropdown-properties/backgrounds background) background)
|
||||
:on-press dropdown-on-press}
|
||||
dropdown-text]]))
|
||||
|
||||
(defn- token-center
|
||||
[{:keys [background token-logo token-name token-abbreviation center-content-container-style]}]
|
||||
@@ -215,7 +215,6 @@
|
||||
- accessibility-label
|
||||
- on-press: callback for left button
|
||||
- icon-name: icon for left button
|
||||
- left-component: custom left component instead of icon
|
||||
- right-side (optional):
|
||||
- vector of maps to render buttons, e.g.:
|
||||
{:icon-name :i/my-icon
|
||||
@@ -296,7 +295,7 @@
|
||||
{:background background
|
||||
:content right-side
|
||||
:max-actions 1
|
||||
:support-account-switcher? true}]]
|
||||
:support-account-switcher? false}]]
|
||||
|
||||
:token
|
||||
[page-nav-base props
|
||||
|
||||
@@ -36,9 +36,8 @@
|
||||
(def gesture-values (atom {}))
|
||||
|
||||
(defn get-sheet-gesture
|
||||
[translate-y bg-opacity window-height on-close disable-gestures?]
|
||||
[translate-y bg-opacity window-height on-close]
|
||||
(-> (gesture/gesture-pan)
|
||||
(gesture/enabled (not disable-gestures?))
|
||||
(gesture/on-start
|
||||
(fn [_]
|
||||
(swap! gesture-values assoc :pan-y (reanimated/get-shared-value translate-y))))
|
||||
@@ -65,9 +64,8 @@
|
||||
[{:keys [hide? insets]}
|
||||
{:keys [content selected-item padding-bottom-override border-radius on-close shell?
|
||||
gradient-cover? customization-color hide-handle? blur-radius
|
||||
hide-on-background-press? dim-background? disable-gestures?]
|
||||
hide-on-background-press?]
|
||||
:or {border-radius 12
|
||||
dim-background? true
|
||||
hide-on-background-press? true}}]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
{window-height :height} (rn/get-window)
|
||||
@@ -92,8 +90,7 @@
|
||||
sheet-gesture (rn/use-memo #(get-sheet-gesture translate-y
|
||||
bg-opacity
|
||||
window-height
|
||||
on-close
|
||||
disable-gestures?)
|
||||
on-close)
|
||||
[window-height on-close])
|
||||
selected-item-smaller-than-sheet? (< item-height
|
||||
(- window-height
|
||||
@@ -130,9 +127,7 @@
|
||||
{:style (reanimated/apply-animations-to-style
|
||||
{:opacity bg-opacity}
|
||||
{:flex 1
|
||||
:background-color (if dim-background?
|
||||
(if shell? colors/neutral-100-opa-60 colors/neutral-100-opa-70)
|
||||
:transparent)})}]]
|
||||
:background-color (if shell? colors/neutral-100-opa-60 colors/neutral-100-opa-70)})}]]
|
||||
;; sheet
|
||||
[gesture/gesture-detector {:gesture sheet-gesture}
|
||||
[reanimated/view
|
||||
|
||||
@@ -12,10 +12,6 @@
|
||||
:upper-limit nil
|
||||
:lower-limit nil})
|
||||
|
||||
(defn init-value
|
||||
[value]
|
||||
(assoc init-state :value value))
|
||||
|
||||
(defn input-value
|
||||
[state]
|
||||
(:value state))
|
||||
|
||||
@@ -37,16 +37,13 @@
|
||||
{:fx [[:dispatch [:wallet/signal-received event-js]]]}
|
||||
|
||||
"wallet.suggested.routes"
|
||||
{:fx [[:dispatch [:wallet.routes/handle-suggested-routes (transforms/js->clj event-js)]]
|
||||
[:dispatch [:wallet/handle-suggested-routes (transforms/js->clj event-js)]]]}
|
||||
{:fx [[:dispatch [:wallet/handle-suggested-routes (transforms/js->clj event-js)]]]}
|
||||
|
||||
"wallet.router.sign-transactions"
|
||||
{:fx [[:dispatch [:wallet.routes/on-transactions-built (transforms/js->clj event-js)]]
|
||||
[:dispatch [:wallet/sign-transactions-signal-received (transforms/js->clj event-js)]]]}
|
||||
{:fx [[:dispatch [:wallet/sign-transactions-signal-received (transforms/js->clj event-js)]]]}
|
||||
|
||||
"wallet.router.transactions-sent"
|
||||
{:fx [[:dispatch [:wallet.routes/on-transactions-sent (transforms/js->clj event-js)]]
|
||||
[:dispatch [:wallet/transactions-sent-signal-received (transforms/js->clj event-js)]]]}
|
||||
{:fx [[:dispatch [:wallet/transactions-sent-signal-received (transforms/js->clj event-js)]]]}
|
||||
|
||||
"envelope.sent"
|
||||
(messages.transport/update-envelopes-status
|
||||
|
||||
@@ -40,8 +40,7 @@
|
||||
#{;; Tabs
|
||||
:communities-stack
|
||||
:chats-stack
|
||||
:wallet-stack
|
||||
:trading-stack})
|
||||
:wallet-stack})
|
||||
|
||||
(defn track-view-id-event
|
||||
[view-id]
|
||||
|
||||
@@ -275,7 +275,8 @@
|
||||
{:events [:chat/unmute-chat-community]}
|
||||
[{:keys [db]} chat-id]
|
||||
(let [{:keys [community-id]} (get-in db [:chats chat-id])]
|
||||
{:db (assoc-in db [:communities community-id :muted] false)}))
|
||||
(when community-id
|
||||
{:db (assoc-in db [:communities community-id :muted] false)})))
|
||||
|
||||
(rf/defn mute-chat-failed
|
||||
{:events [:chat/mute-failed]}
|
||||
|
||||
@@ -11,9 +11,8 @@
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn bottom-tab
|
||||
[icon stack-id shared-values]
|
||||
[icon stack-id shared-values notifications-data]
|
||||
(let [customization-color (rf/sub [:profile/customization-color])
|
||||
notifications-data (rf/sub [:shell/bottom-tabs-notifications-data])
|
||||
on-press (rn/use-callback #(rf/dispatch [:shell/change-tab stack-id]))
|
||||
icon-color (->> stack-id
|
||||
(get shell.constants/tabs-icon-color-keywords)
|
||||
@@ -30,7 +29,8 @@
|
||||
|
||||
(defn view
|
||||
[shared-values]
|
||||
(let [communities-double-tab-gesture (-> (gesture/gesture-tap)
|
||||
(let [notifications-data (rf/sub [:shell/bottom-tabs-notifications-data])
|
||||
communities-double-tab-gesture (-> (gesture/gesture-tap)
|
||||
(gesture/number-of-taps 2)
|
||||
(gesture/on-start
|
||||
(fn [_event]
|
||||
@@ -44,12 +44,10 @@
|
||||
[reanimated/view
|
||||
{:style (style/bottom-tabs-container (:bottom-tabs-height shared-values))}
|
||||
[rn/view {:style (style/bottom-tabs)}
|
||||
[bottom-tab :i/wallet :wallet-stack shared-values]
|
||||
;; TODO: add the right icon
|
||||
[bottom-tab :i/wallet :trading-stack shared-values]
|
||||
[bottom-tab :i/wallet :wallet-stack shared-values notifications-data]
|
||||
[gesture/gesture-detector {:gesture messages-double-tap-gesture}
|
||||
[bottom-tab :i/messages :chats-stack shared-values]]
|
||||
[bottom-tab :i/messages :chats-stack shared-values notifications-data]]
|
||||
[gesture/gesture-detector {:gesture communities-double-tab-gesture}
|
||||
[bottom-tab :i/communities :communities-stack shared-values]]
|
||||
[bottom-tab :i/communities :communities-stack shared-values notifications-data]]
|
||||
(when config/show-not-implemented-features?
|
||||
[bottom-tab :i/browser :browser-stack shared-values])]]]))
|
||||
[bottom-tab :i/browser :browser-stack shared-values notifications-data])]]]))
|
||||
|
||||
@@ -9,26 +9,23 @@
|
||||
(def ^:const bottom-tabs-container-height-ios 82)
|
||||
|
||||
;; Stacks
|
||||
(def ^:const stacks-ids [:communities-stack :chats-stack :wallet-stack :trading-stack :browser-stack])
|
||||
(def ^:const stacks-ids [:communities-stack :chats-stack :wallet-stack :browser-stack])
|
||||
|
||||
;; Keywords
|
||||
(def ^:const stacks-opacity-keywords
|
||||
{:communities-stack :communities-stack-opacity
|
||||
:chats-stack :chats-stack-opacity
|
||||
:wallet-stack :wallet-stack-opacity
|
||||
:trading-stack :trading-stack-opacity
|
||||
:browser-stack :browser-stack-opacity})
|
||||
|
||||
(def ^:const tabs-icon-color-keywords
|
||||
{:communities-stack :communities-tab-icon-color
|
||||
:chats-stack :chats-tab-icon-opacity
|
||||
:wallet-stack :wallet-tab-icon-opacity
|
||||
:trading-stack :trading-tab-icon-opacity
|
||||
:browser-stack :browser-tab-icon-opacity})
|
||||
|
||||
(def ^:const stacks-z-index-keywords
|
||||
{:communities-stack :communities-stack-z-index
|
||||
:chats-stack :chats-stack-z-index
|
||||
:wallet-stack :wallet-stack-z-index
|
||||
:trading-stack :trading-stack-z-index
|
||||
:browser-stack :browser-stack-z-index})
|
||||
|
||||
@@ -8,11 +8,3 @@
|
||||
(assoc :view-id stack-id)
|
||||
(assoc :shell/selected-stack-id stack-id))
|
||||
:fx [[:effects.shell/change-tab stack-id]]}))
|
||||
|
||||
(re-frame/reg-event-fx :shell/hide-tabs
|
||||
(fn [{:keys [db]}]
|
||||
{:db (assoc db :shell/bottom-tabs-visible? false)}))
|
||||
|
||||
(re-frame/reg-event-fx :shell/show-tabs
|
||||
(fn [{:keys [db]}]
|
||||
{:db (assoc db :shell/bottom-tabs-visible? true)}))
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
[status-im.contexts.shell.constants :as shell.constants]
|
||||
[status-im.contexts.shell.home-stack.style :as style]
|
||||
[status-im.contexts.shell.state :as state]
|
||||
[status-im.contexts.wallet.home.view :as wallet]
|
||||
[status-im.contexts.wallet.trading.home.view :as trading]))
|
||||
[status-im.contexts.wallet.home.view :as wallet]))
|
||||
|
||||
(defn load-stack?
|
||||
[stack-id]
|
||||
@@ -18,8 +17,7 @@
|
||||
:communities-stack @state/load-communities-stack?
|
||||
:chats-stack @state/load-chats-stack?
|
||||
:browser-stack @state/load-browser-stack?
|
||||
:wallet-stack @state/load-wallet-stack?
|
||||
:trading-stack @state/load-trading-stack?))
|
||||
:wallet-stack @state/load-wallet-stack?))
|
||||
|
||||
(defn- f-stack-view
|
||||
[stack-id shared-values]
|
||||
@@ -34,7 +32,6 @@
|
||||
:communities-stack [communities/view]
|
||||
:chats-stack [chat/view]
|
||||
:wallet-stack [wallet/view]
|
||||
:trading-stack [trading/view]
|
||||
:browser-stack [browser.stack/browser-stack]
|
||||
[:<>])])
|
||||
|
||||
@@ -50,5 +47,4 @@
|
||||
[lazy-screen :communities-stack shared-values]
|
||||
[lazy-screen :chats-stack shared-values]
|
||||
[lazy-screen :browser-stack shared-values]
|
||||
[lazy-screen :trading-stack shared-values]
|
||||
[lazy-screen :wallet-stack shared-values]]))
|
||||
|
||||
@@ -12,4 +12,3 @@
|
||||
(def load-chats-stack? (reagent/atom false))
|
||||
(def load-wallet-stack? (reagent/atom false))
|
||||
(def load-browser-stack? (reagent/atom false))
|
||||
(def load-trading-stack? (reagent/atom false))
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
:communities-stack (reset! state/load-communities-stack? true)
|
||||
:chats-stack (reset! state/load-chats-stack? true)
|
||||
:wallet-stack (reset! state/load-wallet-stack? true)
|
||||
:trading-stack (reset! state/load-trading-stack? true)
|
||||
:browser-stack (reset! state/load-browser-stack? true)
|
||||
""))
|
||||
|
||||
@@ -34,5 +33,4 @@
|
||||
(reset! state/load-communities-stack? (= selected-stack-id :communities-stack))
|
||||
(reset! state/load-chats-stack? (= selected-stack-id :chats-stack))
|
||||
(reset! state/load-wallet-stack? (= selected-stack-id :wallet-stack))
|
||||
(reset! state/load-trading-stack? (= selected-stack-id :trading-stack))
|
||||
(reset! state/load-browser-stack? (= selected-stack-id :browser-stack))))
|
||||
|
||||
@@ -17,12 +17,11 @@
|
||||
|
||||
(defn shell-stack
|
||||
[]
|
||||
(let [shared-values (shared-values/calculate-and-set-shared-values)
|
||||
show-tabs? (rf/sub [:shell/bottom-tabs-visible?])]
|
||||
(let [shared-values (shared-values/calculate-and-set-shared-values)]
|
||||
(rn/use-mount
|
||||
(fn []
|
||||
(rn/hw-back-add-listener navigate-back-handler)
|
||||
#(rn/hw-back-remove-listener navigate-back-handler)))
|
||||
[rn/view {:style {:background-color colors/neutral-100 :flex 1}}
|
||||
[home-stack/view shared-values]
|
||||
(when show-tabs? [bottom-tabs/view shared-values])]))
|
||||
[bottom-tabs/view shared-values]]))
|
||||
|
||||
@@ -22,15 +22,13 @@
|
||||
|
||||
(defn view
|
||||
[{:keys [type on-press accessibility-label icon-name switcher-type margin-top params
|
||||
show-dapps-button? address]
|
||||
show-dapps-button?]
|
||||
:or {icon-name :i/close
|
||||
accessibility-label :top-bar
|
||||
switcher-type :account-options
|
||||
show-dapps-button? false
|
||||
type :no-title}}]
|
||||
(let [{:keys [color emoji watch-only?]} (if address
|
||||
(rf/sub [:wallet/account-by-address address])
|
||||
(rf/sub [:wallet/current-viewing-account]))
|
||||
(let [{:keys [color emoji watch-only?]} (rf/sub [:wallet/current-viewing-account])
|
||||
networks (rf/sub [:wallet/selected-network-details])
|
||||
sending-collectible? (rf/sub [:wallet/sending-collectible?])]
|
||||
[quo/page-nav
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
(defn view
|
||||
[{:keys [content-container-style search-text on-token-press preselected-token-symbol chain-ids]
|
||||
:or {content-container-style {:padding-horizontal 8}}}]
|
||||
(let [filtered-tokens (rf/sub [:wallet/account-tokens-filtered
|
||||
(let [filtered-tokens (rf/sub [:wallet/current-viewing-account-tokens-filtered
|
||||
{:query search-text
|
||||
:chain-ids chain-ids}])
|
||||
currency-symbol (rf/sub [:profile/currency-symbol])
|
||||
|
||||
@@ -480,23 +480,3 @@
|
||||
(filter (fn [{:keys [tokens]}]
|
||||
(some positive-balance-in-any-chain? tokens))
|
||||
operable-account))))
|
||||
|
||||
(defn balances-by-account
|
||||
[accounts]
|
||||
(letfn [(add-symbol-with-balances
|
||||
[acc token]
|
||||
(assoc acc (:symbol token) (:balances-per-chain token)))
|
||||
(balances-per-symbol
|
||||
[account]
|
||||
(reduce add-symbol-with-balances {} (:tokens account)))
|
||||
(add-address-with-balances [acc [address account]]
|
||||
(assoc acc address (balances-per-symbol account)))]
|
||||
(reduce add-address-with-balances {} accounts)))
|
||||
|
||||
(defn swap-flow?
|
||||
[db route-uuid]
|
||||
(= route-uuid (-> db :wallet :ui :swap :last-request-uuid)))
|
||||
|
||||
(defn send-flow?
|
||||
[db route-uuid]
|
||||
(= route-uuid (-> db :wallet :ui :send :last-request-uuid)))
|
||||
|
||||
@@ -191,20 +191,15 @@
|
||||
(when $
|
||||
(assoc $ :chain-id chain-id))))
|
||||
|
||||
(defn add-details-to-network
|
||||
[network]
|
||||
(-> network
|
||||
:chain-id
|
||||
get-network-details
|
||||
(assoc
|
||||
:chain-id (:chain-id network)
|
||||
:related-chain-id (:related-chain-id network)
|
||||
:layer (:layer network))))
|
||||
|
||||
(defn sorted-networks-with-details
|
||||
[networks]
|
||||
(->> networks
|
||||
(map add-details-to-network)
|
||||
(map
|
||||
(fn [{:keys [chain-id related-chain-id layer]}]
|
||||
(assoc (get-network-details chain-id)
|
||||
:chain-id chain-id
|
||||
:related-chain-id related-chain-id
|
||||
:layer layer)))
|
||||
(sort-by (juxt :layer :short-name))))
|
||||
|
||||
(defn format-address
|
||||
|
||||
@@ -767,39 +767,33 @@
|
||||
(rf/reg-event-fx
|
||||
:wallet/sign-transactions-signal-received
|
||||
(fn [{:keys [db]} [{send-details :sendDetails :as data}]]
|
||||
(let [routes-uuid (:uuid send-details)
|
||||
type (cond
|
||||
(utils/send-flow? db routes-uuid)
|
||||
(let [type (if (or (= (:fromToken send-details)
|
||||
(:toToken send-details))
|
||||
(string/blank? (:toToken send-details)))
|
||||
:send
|
||||
(utils/swap-flow? db routes-uuid)
|
||||
:swap)
|
||||
callback-fx (get-in db [:wallet :ui type :sign-transactions-callback-fx])
|
||||
error-response (:errorResponse send-details)]
|
||||
(when type
|
||||
{:fx [(when (and callback-fx (not error-response))
|
||||
callback-fx)]
|
||||
:db (-> db
|
||||
(assoc-in [:wallet :ui type :sign-transactions-callback-fx] nil)
|
||||
(assoc-in [:wallet :ui type :route-error]
|
||||
error-response)
|
||||
(assoc-in [:wallet :ui type :transaction-for-signing] data))}))))
|
||||
{:fx [(when (and callback-fx (not error-response))
|
||||
callback-fx)]
|
||||
:db (-> db
|
||||
(assoc-in [:wallet :ui type :sign-transactions-callback-fx] nil)
|
||||
(assoc-in [:wallet :ui type :error-response] error-response)
|
||||
(assoc-in [:wallet :ui type :transaction-for-signing] data))})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/transactions-sent-signal-received
|
||||
(fn [{:keys [db]}
|
||||
[{sent-transactions :sentTransactions
|
||||
send-details :sendDetails}]]
|
||||
(let [routes-uuid (:uuid send-details)
|
||||
swap? (utils/swap-flow? db routes-uuid)
|
||||
send? (utils/send-flow? db routes-uuid)]
|
||||
(when (or swap? send?)
|
||||
{:fx [[:dispatch
|
||||
(if-let [error-response (:errorResponse send-details)]
|
||||
[(if swap?
|
||||
:wallet.swap/transaction-failure
|
||||
:wallet/transaction-failure)
|
||||
error-response]
|
||||
[(if swap?
|
||||
:wallet.swap/transaction-success
|
||||
:wallet/transaction-success)
|
||||
sent-transactions])]]}))))
|
||||
(let [swap? (get-in db [:wallet :ui :swap])]
|
||||
{:fx [[:dispatch
|
||||
(if-let [error-response (:errorResponse send-details)]
|
||||
[(if swap?
|
||||
:wallet.swap/transaction-failure
|
||||
:wallet/transaction-failure)
|
||||
error-response]
|
||||
[(if swap?
|
||||
:wallet.swap/transaction-success
|
||||
:wallet/transaction-success)
|
||||
sent-transactions])]]})))
|
||||
|
||||
@@ -1,201 +0,0 @@
|
||||
(ns status-im.contexts.wallet.routes.events
|
||||
(:require
|
||||
[re-frame.core :as rf]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.routes.route :as route]
|
||||
[status-im.contexts.wallet.routes.utils :as utils]
|
||||
[status-im.contexts.wallet.send.utils :as send-utils]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.security.core :as security]
|
||||
[utils.transforms :as transforms]))
|
||||
|
||||
(rf/reg-event-fx :wallet.routes/get-routes
|
||||
(fn [{:keys [db]} [{:keys [params on-error]}]]
|
||||
(let [route-uuid (:uuid params)]
|
||||
{:db (update-in db
|
||||
[:wallet :route]
|
||||
assoc
|
||||
:uuid route-uuid
|
||||
:state :requesting-routes
|
||||
:best-route nil
|
||||
:transactions-for-signing nil)
|
||||
:fx [[:json-rpc/call
|
||||
[{:method "wallet_getSuggestedRoutesAsync"
|
||||
:params [params]
|
||||
:on-error (fn [error]
|
||||
(when on-error
|
||||
(on-error error))
|
||||
(rf/dispatch [:wallet.routes/on-error error])
|
||||
(log/error "failed to get suggested routes (async)"
|
||||
{:event :wallet.routes/get-routes
|
||||
:error (:message error)
|
||||
:params params}))}]]]})))
|
||||
|
||||
(rf/reg-event-fx :wallet.routes/stop-get-routes
|
||||
(fn [_]
|
||||
(log/info "Stopping getting routes and clearing route data")
|
||||
{:fx [[:dispatch [:wallet.routes/clear-route]]
|
||||
[:json-rpc/call
|
||||
[{:method "wallet_stopSuggestedRoutesAsyncCalculation"
|
||||
:params []
|
||||
:on-error (fn [error]
|
||||
(log/error "failed to stop fetching swap proposals"
|
||||
{:error error}))}]]]}))
|
||||
|
||||
(rf/reg-event-fx :wallet.routes/clear-route
|
||||
(fn [{:keys [db]}]
|
||||
{:db (update-in db [:wallet] dissoc :route)}))
|
||||
|
||||
(rf/reg-event-fx :wallet.routes/on-error
|
||||
(fn [{:keys [db]} [error]]
|
||||
(let [valid-error? (utils/valid-error? error)]
|
||||
(println :valid-error valid-error?)
|
||||
(when valid-error?
|
||||
{:db (update-in db
|
||||
[:wallet :route]
|
||||
assoc
|
||||
:error error
|
||||
:state :error)}))))
|
||||
|
||||
(rf/reg-event-fx :wallet.routes/reset-error
|
||||
(fn [{:keys [db]}]
|
||||
{:db (update-in db [:wallet :route] dissoc :error)}))
|
||||
|
||||
(rf/reg-event-fx :wallet.routes/handle-suggested-routes
|
||||
(fn [{:keys [db]} [routes]]
|
||||
(let [best-route (route/get-best-suggested-route routes)
|
||||
error (route/error-response routes)
|
||||
route-uuid (route/routes-uuid routes)]
|
||||
(log/info "Getting routes for" route-uuid)
|
||||
{:db (update-in db
|
||||
[:wallet :route]
|
||||
assoc
|
||||
:uuid route-uuid
|
||||
:state :receiving-routes
|
||||
:best-route best-route)
|
||||
:fx [(if error
|
||||
[:dispatch [:wallet.routes/on-error error]]
|
||||
[:dispatch [:wallet.routes/reset-error]])]})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet.routes/build-transactions
|
||||
(fn [{:keys [db]} [{:keys [request-uuid slippage] :or {slippage constants/default-slippage}}]]
|
||||
{:db (assoc-in db [:wallet :route :state] :building-transactions)
|
||||
:fx [[:json-rpc/call
|
||||
[{:method "wallet_buildTransactionsFromRoute"
|
||||
:params [{:uuid request-uuid
|
||||
:slippagePercentage slippage}]
|
||||
:on-error (fn [error]
|
||||
(log/error "failed to build transactions from route"
|
||||
{:event :wallet/build-transactions-from-route
|
||||
:error error})
|
||||
(rf/dispatch [:toasts/upsert
|
||||
{:id :build-transactions-from-route-error
|
||||
:type :negative
|
||||
:text (:message error)}]))}]]]}))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet.routes/on-transactions-built
|
||||
(fn [{:keys [db]} [transactions-for-signing]]
|
||||
(let [error (-> transactions-for-signing :sendDetails :errorResponse)
|
||||
route-uuid (get-in db [:wallet :route :uuid])
|
||||
built-transaction-uuid (-> transactions-for-signing :sendDetails :uuid)]
|
||||
(when (= route-uuid built-transaction-uuid)
|
||||
{:db (update-in db
|
||||
[:wallet :route]
|
||||
assoc
|
||||
:state :transactions-built
|
||||
:transactions-for-signing transactions-for-signing)
|
||||
:fx [(when error
|
||||
[:dispatch [:wallet.routes/on-error error]])]}))))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet.routes/sign-transactions
|
||||
(fn [{:keys [db]} [sha3-pwd]]
|
||||
(let [{:keys [hashes address signOnKeycard]} (get-in db
|
||||
[:wallet :route :transactions-for-signing
|
||||
:signingDetails])
|
||||
on-success (fn [signatures]
|
||||
(rf/dispatch
|
||||
[:wallet.routes/send-transactions signatures]))
|
||||
on-error (fn [error]
|
||||
(log/error
|
||||
"failed to prepare signatures for transactions"
|
||||
{:event :wallet/prepare-signatures-for-transactions
|
||||
:error error})
|
||||
(rf/dispatch
|
||||
[:toasts/upsert
|
||||
{:id :prepare-signatures-for-transactions-error
|
||||
:type :negative
|
||||
:text (:message error)}]))]
|
||||
(if signOnKeycard
|
||||
{:fx [[:dispatch
|
||||
[:standard-auth/authorize-with-keycard
|
||||
{:on-complete #(rf/dispatch [:keycard/connect-and-sign-hashes
|
||||
{:keycard-pin %
|
||||
:address address
|
||||
:hashes hashes
|
||||
:on-success on-success
|
||||
:on-failure on-error}])}]]]}
|
||||
{:fx [[:effects.wallet/sign-transaction-hashes
|
||||
{:hashes hashes
|
||||
:address address
|
||||
:password (security/safe-unmask-data sha3-pwd)
|
||||
:on-success on-success
|
||||
:on-error on-error}]]}))))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet.routes/send-transactions
|
||||
(fn [{:keys [db]} [signatures]]
|
||||
(let [transactions-for-signing (get-in db [:wallet :route :transactions-for-signing])
|
||||
signatures-map (reduce (fn [acc {:keys [message signature]}]
|
||||
(assoc acc
|
||||
message
|
||||
(send-utils/signature-rsv signature)))
|
||||
{}
|
||||
signatures)]
|
||||
(log/info "Sending transactions with signatures")
|
||||
{:db (assoc-in db [:wallet :route :state] :sending-transactions)
|
||||
:fx [[:json-rpc/call
|
||||
[{:method "wallet_sendRouterTransactionsWithSignatures"
|
||||
:params [{:uuid (get-in transactions-for-signing [:sendDetails :uuid])
|
||||
:signatures signatures-map}]
|
||||
:on-success (fn [] (rf/dispatch [:hide-bottom-sheet]))
|
||||
:on-error (fn [error]
|
||||
(log/error "failed to send router transactions with signatures"
|
||||
{:event :wallet/send-router-transactions-with-signatures
|
||||
:error error})
|
||||
(rf/dispatch [:toasts/upsert
|
||||
{:id :send-router-transactions-with-signatures-error
|
||||
:type :negative
|
||||
:text (:message error)}]))}]]]})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet.routes/on-transactions-sent
|
||||
(fn [{:keys [db]} [{:keys [sentTransactions sendDetails]}]]
|
||||
(let [error (:errorResponse sendDetails)
|
||||
state-transactions (get-in db [:wallet :route :transactions] {})
|
||||
sent-transactions (route/sent-transactions-map sentTransactions)]
|
||||
{:db (update-in db
|
||||
[:wallet :route]
|
||||
assoc
|
||||
:state :transactions-sent
|
||||
:transactions (merge state-transactions sent-transactions))
|
||||
:fx [(when error
|
||||
[:dispatch [:wallet.routes/on-error error]])]})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet.routes/pending-transaction-status-changed
|
||||
(fn [{:keys [db]} [data]]
|
||||
(let [tx-message (-> data :message transforms/json->clj)
|
||||
tx-status (:status tx-message)
|
||||
tx-hash (:hash tx-message)
|
||||
new-status (cond
|
||||
(= tx-status constants/transaction-status-success)
|
||||
:confirmed
|
||||
(= tx-status constants/transaction-status-pending)
|
||||
:pending
|
||||
(= tx-status constants/transaction-status-failed)
|
||||
:failed)]
|
||||
(log/info "Transaction status changed" tx-hash new-status)
|
||||
{:db (update-in db [:wallet :route :transactions tx-hash] assoc :status new-status)})))
|
||||
@@ -1,31 +0,0 @@
|
||||
(ns status-im.contexts.wallet.routes.hooks
|
||||
(:require [react-native.core :as rn]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- use-previous
|
||||
[value]
|
||||
(let [ref-value (rn/use-ref-atom value)]
|
||||
(rn/use-effect (fn [] (reset! ref-value value)) [value])
|
||||
@ref-value))
|
||||
|
||||
(defn use-transactions-built
|
||||
[cb]
|
||||
(let [route-state (rf/sub [:wallet.routes/state])
|
||||
previous-route-state (use-previous route-state)
|
||||
transactions-for-signing (rf/sub [:wallet.routes/transactions-for-signing])]
|
||||
(rn/use-effect (fn []
|
||||
(when (and (= :transactions-built route-state)
|
||||
(not= route-state previous-route-state))
|
||||
(apply cb [transactions-for-signing])))
|
||||
[route-state])))
|
||||
|
||||
(defn use-transactions-sent
|
||||
[cb]
|
||||
(let [route-state (rf/sub [:wallet.routes/state])
|
||||
previous-route-state (use-previous route-state)
|
||||
transactions (rf/sub [:wallet.routes/transactions])]
|
||||
(rn/use-effect (fn []
|
||||
(when (and (= :transactions-sent route-state)
|
||||
(not= route-state previous-route-state))
|
||||
(apply cb [transactions])))
|
||||
[route-state])))
|
||||
@@ -1,25 +0,0 @@
|
||||
(ns status-im.contexts.wallet.routes.route)
|
||||
|
||||
(defn get-best-suggested-route
|
||||
[routes]
|
||||
(-> routes :Best first))
|
||||
|
||||
(defn error-response
|
||||
[routes]
|
||||
(:ErrorResponse routes))
|
||||
|
||||
(defn routes-uuid
|
||||
[routes]
|
||||
(get routes :Uuid))
|
||||
|
||||
(defn sent-transactions-map
|
||||
[sent-transactions]
|
||||
(reduce
|
||||
(fn [acc transaction]
|
||||
(let [tx-hash (:hash transaction)]
|
||||
(assoc acc
|
||||
tx-hash
|
||||
{:status :pending
|
||||
:transaction transaction})))
|
||||
{}
|
||||
sent-transactions))
|
||||
@@ -1,10 +0,0 @@
|
||||
(ns status-im.contexts.wallet.routes.utils)
|
||||
|
||||
(defn valid-error?
|
||||
[{:keys [code details]}]
|
||||
(println :error code details)
|
||||
(cond
|
||||
(and (= code "0")
|
||||
(contains? details "context changed")) false
|
||||
|
||||
:else true))
|
||||
@@ -663,14 +663,11 @@
|
||||
(rf/reg-event-fx
|
||||
:wallet/handle-suggested-routes
|
||||
(fn [{:keys [db]} [data]]
|
||||
(let [{send :send} (-> db :wallet :ui)
|
||||
skip-processing-routes? (:skip-processing-suggested-routes? send)
|
||||
routes-uuid (:Uuid data)
|
||||
swap? (utils/swap-flow? db routes-uuid)
|
||||
send? (utils/send-flow? db routes-uuid)
|
||||
clean-user-tx-settings? (get-in db
|
||||
[:wallet :ui :send :custom-tx-settings
|
||||
:delete-on-routes-update?])]
|
||||
(let [{send :send swap? :swap} (-> db :wallet :ui)
|
||||
skip-processing-routes? (:skip-processing-suggested-routes? send)
|
||||
clean-user-tx-settings? (get-in db
|
||||
[:wallet :ui :send :custom-tx-settings
|
||||
:delete-on-routes-update?])]
|
||||
(when (or swap? (not skip-processing-routes?))
|
||||
(let [{error-code :code
|
||||
:as error} (:ErrorResponse data)
|
||||
@@ -684,14 +681,13 @@
|
||||
(merge
|
||||
(when clean-user-tx-settings?
|
||||
{:db (update-in db [:wallet :ui :send] dissoc :custom-tx-settings)})
|
||||
(when (or swap? send?)
|
||||
{:fx [[:dispatch
|
||||
(cond
|
||||
(and failure? swap?) [:wallet/swap-proposal-error error]
|
||||
(and failure? send?) [:wallet/suggested-routes-error error-message]
|
||||
swap? [:wallet/swap-proposal-success (fix-routes data)]
|
||||
send? [:wallet/suggested-routes-success (fix-routes data)
|
||||
enough-assets?])]]})))))))
|
||||
{:fx [[:dispatch
|
||||
(cond
|
||||
(and failure? swap?) [:wallet/swap-proposal-error error]
|
||||
failure? [:wallet/suggested-routes-error error-message]
|
||||
swap? [:wallet/swap-proposal-success (fix-routes data)]
|
||||
:else [:wallet/suggested-routes-success (fix-routes data)
|
||||
enough-assets?])]]}))))))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/transaction-success
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
(def ^:private rounding-decimals 4)
|
||||
|
||||
(defn list-item
|
||||
[{:keys [account selected-account-address on-press]}]
|
||||
[{:keys [account selected-account-address]}]
|
||||
(let [{:keys [color address]} account]
|
||||
[quo/account-item
|
||||
{:type :default
|
||||
@@ -18,13 +18,11 @@
|
||||
:customization-color color
|
||||
:state (if (= address selected-account-address) :selected :default)
|
||||
:on-press (fn []
|
||||
(if (fn? on-press)
|
||||
(on-press address)
|
||||
(rf/dispatch [:wallet/switch-current-viewing-account address]))
|
||||
(rf/dispatch [:wallet/switch-current-viewing-account address])
|
||||
(rf/dispatch [:hide-bottom-sheet]))}]))
|
||||
|
||||
(defn list-item-with-balance
|
||||
[{:keys [account selected-account-address asset-symbol network on-press]}]
|
||||
[{:keys [account selected-account-address asset-symbol network]}]
|
||||
(let [{:keys [color address tokens]} account
|
||||
token (->> tokens
|
||||
(filter #(= (:symbol %) asset-symbol))
|
||||
@@ -41,33 +39,27 @@
|
||||
:customization-color color
|
||||
:state (if (= address selected-account-address) :selected :default)
|
||||
:on-press (fn []
|
||||
(if (fn? on-press)
|
||||
(on-press address)
|
||||
(rf/dispatch [:wallet/switch-current-viewing-account address]))
|
||||
(rf/dispatch [:wallet/switch-current-viewing-account address])
|
||||
(rf/dispatch [:hide-bottom-sheet]))}]))
|
||||
|
||||
(defn view
|
||||
[{:keys [show-account-balances? asset-symbol network address on-press-account]}]
|
||||
(let [selected-account-address (or address (rf/sub [:wallet/current-viewing-account-address]))
|
||||
[{:keys [show-account-balances? asset-symbol network]}]
|
||||
(let [selected-account-address (rf/sub [:wallet/current-viewing-account-address])
|
||||
accounts (rf/sub [:wallet/operable-accounts])]
|
||||
[:<>
|
||||
[quo/drawer-top {:title (i18n/label :t/select-account)}]
|
||||
[gesture/flat-list
|
||||
{:data accounts
|
||||
:render-fn (fn [account _ _
|
||||
{:keys [selected-account-address on-press-account]}]
|
||||
:render-fn (fn [account _ _ {:keys [selected-account-address]}]
|
||||
(if show-account-balances?
|
||||
[list-item-with-balance
|
||||
{:account account
|
||||
:selected-account-address selected-account-address
|
||||
:asset-symbol asset-symbol
|
||||
:network network
|
||||
:on-press on-press-account}]
|
||||
:network network}]
|
||||
[list-item
|
||||
{:account account
|
||||
:selected-account-address selected-account-address
|
||||
:on-press on-press-account}]))
|
||||
:render-data {:selected-account-address selected-account-address
|
||||
:on-press-account on-press-account}
|
||||
:selected-account-address selected-account-address}]))
|
||||
:render-data {:selected-account-address selected-account-address}
|
||||
:content-container-style style/list-container
|
||||
:shows-vertical-scroll-indicator false}]]))
|
||||
|
||||
@@ -69,11 +69,10 @@
|
||||
title])
|
||||
|
||||
(defn view
|
||||
[{:keys [address search-text on-token-press preselected-token-symbol network hide-token-fn
|
||||
[{:keys [search-text on-token-press preselected-token-symbol network hide-token-fn
|
||||
disable-token-fn]}]
|
||||
(let [my-tokens (rf/sub [:wallet/account-tokens-filtered
|
||||
{:address address
|
||||
:query search-text
|
||||
(let [my-tokens (rf/sub [:wallet/current-viewing-account-tokens-filtered
|
||||
{:query search-text
|
||||
:chain-ids #{(:chain-id network)}
|
||||
:hide-token-fn hide-token-fn}])
|
||||
popular-tokens (rf/sub [:wallet/tokens-filtered
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
(ns status-im.contexts.wallet.sheets.select-asset.style)
|
||||
|
||||
(ns status-im.contexts.wallet.sheets.select-asset.style
|
||||
(:require
|
||||
[react-native.navigation :as navigation]
|
||||
[react-native.platform :as platform]))
|
||||
|
||||
(defn container
|
||||
[window-height]
|
||||
{:flex 1
|
||||
:display :flex
|
||||
:height window-height})
|
||||
{:flex 1
|
||||
:display :flex
|
||||
:height window-height
|
||||
:padding-top (when platform/android? (navigation/status-bar-height))})
|
||||
|
||||
(def search-input-container
|
||||
{:padding-horizontal 20
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
:on-change-text on-change-text}]])
|
||||
|
||||
(defn- assets-view
|
||||
[{:keys [search-text on-change-text on-select network address hide-token-fn disable-token-fn]}]
|
||||
[{:keys [search-text on-change-text on-select network hide-token-fn disable-token-fn]}]
|
||||
[:<>
|
||||
[search-input search-text on-change-text]
|
||||
[asset-list/view
|
||||
@@ -29,14 +29,12 @@
|
||||
(on-select token))
|
||||
(rf/dispatch [:hide-bottom-sheet]))
|
||||
:network network
|
||||
:address address
|
||||
:hide-token-fn hide-token-fn
|
||||
:disable-token-fn disable-token-fn}]])
|
||||
|
||||
(defn- account-view
|
||||
[address]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
{:keys [name emoji color]} (rf/sub [:wallet/account-by-address address])]
|
||||
[{:keys [emoji name color]}]
|
||||
(let [theme (quo.theme/use-theme)]
|
||||
[quo/context-tag
|
||||
{:theme theme
|
||||
:type :account
|
||||
@@ -62,7 +60,7 @@
|
||||
:type :network}])
|
||||
|
||||
(defn- subheader-view
|
||||
[{:keys [provider address network]}]
|
||||
[{:keys [provider account network]}]
|
||||
[rn/view {:style style/subheader-container}
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
@@ -70,14 +68,14 @@
|
||||
(i18n/label :t/select-asset-on)]
|
||||
(if provider
|
||||
[provider-view provider]
|
||||
[account-view address])
|
||||
[account-view account])
|
||||
(when provider
|
||||
[:<>
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium}
|
||||
(i18n/label :t/to)]
|
||||
[account-view address]])
|
||||
[account-view account]])
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium}
|
||||
@@ -85,9 +83,8 @@
|
||||
[network-view network]])
|
||||
|
||||
(defn view
|
||||
[{:keys [address title network provider on-select hide-token-fn disable-token-fn]}]
|
||||
(let [account-address (or address
|
||||
(rf/sub [:wallet/current-viewing-account-address-or-default]))
|
||||
[{:keys [title network provider on-select hide-token-fn disable-token-fn]}]
|
||||
(let [account (rf/sub [:wallet/current-viewing-account-or-default])
|
||||
[search-text set-search-text] (rn/use-state "")
|
||||
window-height (:height (rn/get-window))]
|
||||
[rn/safe-area-view {:style (style/container window-height)}
|
||||
@@ -100,7 +97,7 @@
|
||||
{:title title
|
||||
:title-accessibility-label :title-label}]
|
||||
[subheader-view
|
||||
{:address account-address
|
||||
{:account account
|
||||
:network network
|
||||
:provider provider}]
|
||||
[assets-view
|
||||
@@ -108,6 +105,5 @@
|
||||
:on-change-text #(set-search-text %)
|
||||
:on-select on-select
|
||||
:network network
|
||||
:address account-address
|
||||
:hide-token-fn hide-token-fn
|
||||
:disable-token-fn disable-token-fn}]]))
|
||||
|
||||
@@ -51,9 +51,6 @@
|
||||
"pending-transaction-status-changed"
|
||||
{:fx
|
||||
[[:dispatch
|
||||
[:wallet.routes/pending-transaction-status-changed
|
||||
(transforms/js->clj event-js)]]
|
||||
[:dispatch
|
||||
[:wallet/pending-transaction-status-changed-received
|
||||
(transforms/js->clj event-js)]]]}
|
||||
|
||||
|
||||
@@ -10,26 +10,6 @@
|
||||
[utils.money :as money]
|
||||
[utils.number :as number]))
|
||||
|
||||
(rf/reg-event-fx :wallet.swap/initialize-state
|
||||
(fn [{:keys [db]} [{:keys [asset-to-pay asset-to-receive network launch-screen start-point] :as opts}]]
|
||||
(let [all-initialized? (every? (complement nil?) (vals opts))]
|
||||
(cond-> {:db (-> db
|
||||
(assoc-in [:wallet :ui :swap :asset-to-pay] asset-to-pay)
|
||||
(assoc-in [:wallet :ui :swap :asset-to-receive] asset-to-receive)
|
||||
(assoc-in [:wallet :ui :swap :network] network)
|
||||
(assoc-in [:wallet :ui :swap :launch-screen] launch-screen)
|
||||
(assoc-in [:wallet :ui :swap :start-point] start-point))}
|
||||
|
||||
all-initialized? (assoc :fx
|
||||
[[:dispatch [:wallet.swap/set-default-slippage]]
|
||||
[:dispatch
|
||||
[:centralized-metrics/track :metric/swap-start
|
||||
{:network (:chain-id network)
|
||||
:pay_token (:symbol asset-to-pay)
|
||||
:receive_token (:symbol asset-to-receive)
|
||||
:start_point start-point
|
||||
:launch_screen launch-screen}]]])))))
|
||||
|
||||
(rf/reg-event-fx :wallet.swap/start
|
||||
(fn [{:keys [db]} [{:keys [network asset-to-receive open-new-screen? from-account] :as data}]]
|
||||
(let [{:keys [wallet]} db
|
||||
@@ -54,42 +34,44 @@
|
||||
network' (or network
|
||||
(swap-utils/select-network asset-to-pay))
|
||||
start-point (if open-new-screen? :action-menu :swap-button)]
|
||||
{:fx (into [[:dispatch
|
||||
[:wallet.swap/initialize-state
|
||||
{:asset-to-pay asset-to-pay
|
||||
:asset-to-receive asset-to-receive
|
||||
:network network'
|
||||
:launch-screen view-id
|
||||
:start-point start-point}]]]
|
||||
(cond
|
||||
(and multi-account-balance?
|
||||
root-screen?
|
||||
(not from-account))
|
||||
[[:dispatch [:open-modal :screen/wallet.swap-select-account]]]
|
||||
|
||||
network'
|
||||
[[:dispatch [:wallet/switch-current-viewing-account (:address account)]]
|
||||
[:dispatch
|
||||
(if open-new-screen?
|
||||
[:open-modal :screen/wallet.setup-swap]
|
||||
[:navigate-to-within-stack
|
||||
[:screen/wallet.setup-swap :screen/wallet.swap-select-asset-to-pay]])]]
|
||||
|
||||
(not network')
|
||||
[[:dispatch
|
||||
[:show-bottom-sheet
|
||||
{:content (fn []
|
||||
[network-selection/view
|
||||
{:token-symbol (:symbol asset-to-pay)
|
||||
:on-select-network (fn [network]
|
||||
(rf/dispatch [:hide-bottom-sheet])
|
||||
(rf/dispatch
|
||||
[:wallet.swap/start
|
||||
{:asset-to-pay asset-to-pay
|
||||
:asset-to-receive asset-to-receive
|
||||
:network network
|
||||
:open-new-screen? open-new-screen?
|
||||
:from-account from-account}]))}])}]]]))})))
|
||||
{:db (-> db
|
||||
(assoc-in [:wallet :ui :swap :asset-to-pay] asset-to-pay)
|
||||
(assoc-in [:wallet :ui :swap :asset-to-receive] asset-to-receive)
|
||||
(assoc-in [:wallet :ui :swap :network] network')
|
||||
(assoc-in [:wallet :ui :swap :launch-screen] view-id)
|
||||
(assoc-in [:wallet :ui :swap :start-point] start-point))
|
||||
:fx (if (and multi-account-balance? root-screen? (not from-account))
|
||||
[[:dispatch [:open-modal :screen/wallet.swap-select-account]]]
|
||||
(if network'
|
||||
[[:dispatch [:wallet/switch-current-viewing-account (:address account)]]
|
||||
[:dispatch
|
||||
(if open-new-screen?
|
||||
[:open-modal :screen/wallet.setup-swap]
|
||||
[:navigate-to-within-stack
|
||||
[:screen/wallet.setup-swap :screen/wallet.swap-select-asset-to-pay]])]
|
||||
[:dispatch
|
||||
[:centralized-metrics/track :metric/swap-start
|
||||
{:network (:chain-id network)
|
||||
:pay_token (:symbol asset-to-pay)
|
||||
:receive_token (:symbol asset-to-receive)
|
||||
:start_point start-point
|
||||
:launch_screen view-id}]]
|
||||
[:dispatch [:wallet.swap/set-default-slippage]]]
|
||||
[[:dispatch
|
||||
[:show-bottom-sheet
|
||||
{:content (fn []
|
||||
[network-selection/view
|
||||
{:token-symbol (:symbol asset-to-pay)
|
||||
:on-select-network (fn [network]
|
||||
(rf/dispatch [:hide-bottom-sheet])
|
||||
(rf/dispatch
|
||||
[:wallet.swap/start
|
||||
{:asset-to-pay asset-to-pay
|
||||
:asset-to-receive asset-to-receive
|
||||
:network network
|
||||
:open-new-screen?
|
||||
open-new-screen?
|
||||
:from-account from-account}]))}])}]]]))})))
|
||||
|
||||
(rf/reg-event-fx :wallet.swap/select-asset-to-pay
|
||||
(fn [{:keys [db]} [{:keys [token]}]]
|
||||
|
||||
@@ -39,17 +39,3 @@
|
||||
:key-fn
|
||||
(fn [{:keys [chainId address] :as token}]
|
||||
(str chainId "-" (if (get-in token [:communityData :id]) address (:symbol token)))))))
|
||||
|
||||
(defn normalized-tokens
|
||||
[data chain-ids]
|
||||
(->> data
|
||||
(mapcat :tokens)
|
||||
(reduce (fn [acc token]
|
||||
(let [token-symbol (:symbol token)
|
||||
chain-id (:chainId token)
|
||||
supported-chain-id? (some #{chain-id} chain-ids)
|
||||
token-added? (get-in acc [token-symbol chain-id])]
|
||||
(if (and supported-chain-id? (not token-added?))
|
||||
(assoc-in acc [token-symbol chain-id] token)
|
||||
acc)))
|
||||
{})))
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
(ns status-im.contexts.wallet.tokens.events
|
||||
(:require
|
||||
[re-frame.core :as rf]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.tokens.data :as tokens-data]
|
||||
[status-im.contexts.wallet.tokens.effects]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.address]
|
||||
[utils.ethereum.chain :as chain]))
|
||||
(:require [re-frame.core :as rf]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.tokens.data :as tokens-data]
|
||||
[status-im.contexts.wallet.tokens.effects]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.address]
|
||||
[utils.ethereum.chain :as chain]))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet.tokens/get-token-list
|
||||
@@ -84,8 +83,7 @@
|
||||
{:sources (:sources tokens)
|
||||
:supported-chains-by-symbol supported-chains-by-symbol
|
||||
:by-address (-> tokens :by-address vals)
|
||||
:by-symbol by-symbol-vals
|
||||
:normalized-tokens (tokens-data/normalized-tokens data chain-ids)})
|
||||
:by-symbol by-symbol-vals})
|
||||
(assoc-in [:wallet :ui :loading]
|
||||
{:token-list false
|
||||
:market-values true
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
(ns status-im.contexts.wallet.trading.home.view
|
||||
(:require [status-im.contexts.wallet.trading.swap.view :as swap]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
[swap/view])
|
||||
@@ -1,11 +0,0 @@
|
||||
(ns status-im.contexts.wallet.trading.swap.approval-confirmation.style
|
||||
(:require [quo.foundations.colors :as colors]))
|
||||
|
||||
(def summary-section-container
|
||||
{:padding-horizontal 20
|
||||
:padding-bottom 16})
|
||||
|
||||
(defn section-label
|
||||
[theme]
|
||||
{:margin-bottom 8
|
||||
:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)})
|
||||
@@ -1,208 +0,0 @@
|
||||
(ns status-im.contexts.wallet.trading.swap.approval-confirmation.view
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.resources :as resources]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[status-im.common.standard-authentication.core :as standard-auth]
|
||||
[status-im.contexts.wallet.common.utils.external-links :as external-links]
|
||||
[status-im.contexts.wallet.trading.swap.approval-confirmation.style :as style]
|
||||
[status-im.contexts.wallet.trading.swap.components.info-bar.view :as info-bar]
|
||||
[status-im.contexts.wallet.trading.swap.components.transaction.container :as transaction.container]
|
||||
[status-im.contexts.wallet.trading.swap.components.transaction.provider-footer :as
|
||||
transaction.provider-footer]
|
||||
[status-im.contexts.wallet.trading.swap.components.transaction.title :as transaction.title]
|
||||
[utils.address :as address-utils]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- on-confirm
|
||||
[password]
|
||||
(rf/dispatch [:dismiss-modal :screen/trading.swap-approval-confirmation])
|
||||
(rf/dispatch [:wallet.routes/sign-transactions password]))
|
||||
|
||||
(defn- swap-title
|
||||
[]
|
||||
(let [pay-token-symbol (rf/sub [:trading.swap/pay-token-symbol])
|
||||
pay-amount (rf/sub [:trading.swap/pay-amount])
|
||||
account (rf/sub [:trading.swap/account])
|
||||
provider (rf/sub [:trading.swap/provider])]
|
||||
[transaction.title/container
|
||||
[transaction.title/row {:first? true}
|
||||
[transaction.title/text
|
||||
{:label (i18n/label :t/set-spending-cap-of)
|
||||
:accessibility-label :set-spending-cap-of}]]
|
||||
[transaction.title/row
|
||||
[quo/summary-tag
|
||||
{:token pay-token-symbol
|
||||
:label (str pay-amount " " pay-token-symbol)
|
||||
:type :token}]
|
||||
[transaction.title/text
|
||||
{:label (i18n/label :t/for)
|
||||
:accessibility-label :for}]]
|
||||
[transaction.title/row
|
||||
[quo/summary-tag
|
||||
{:label (:full-name provider)
|
||||
:type :network
|
||||
:image-source (resources/get-network (:name provider))
|
||||
:customization-color (:color provider)}]
|
||||
[transaction.title/text
|
||||
{:label (i18n/label :t/on)
|
||||
:accessibility-label :on}]]
|
||||
[transaction.title/row
|
||||
[quo/summary-tag
|
||||
{:label (:name account)
|
||||
:type :account
|
||||
:emoji (:emoji account)
|
||||
:customization-color (:color account)}]]]))
|
||||
|
||||
(defn- spending-cap-section
|
||||
[]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
pay-token-symbol (rf/sub [:trading.swap/pay-token-symbol])
|
||||
pay-amount (rf/sub [:trading.swap/pay-amount])]
|
||||
[rn/view {:style style/summary-section-container}
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:style (style/section-label theme)
|
||||
:accessibility-label :spending-cap-label}
|
||||
(i18n/label :t/spending-cap)]
|
||||
(when (and pay-token-symbol pay-amount)
|
||||
[quo/approval-info
|
||||
{:type :spending-cap
|
||||
:unlimited-icon? false
|
||||
:label (str pay-amount " " pay-token-symbol)
|
||||
:avatar-props {:token pay-token-symbol}}])]))
|
||||
|
||||
(defn- account-section
|
||||
[]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
pay-token-symbol (rf/sub [:trading.swap/pay-token-symbol])
|
||||
account (rf/sub [:trading.swap/account])
|
||||
pay-amount (rf/sub [:trading.swap/pay-amount])]
|
||||
[rn/view {:style style/summary-section-container}
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:style (style/section-label theme)
|
||||
:accessibility-label :account-label}
|
||||
(i18n/label :t/account)]
|
||||
(when (and pay-token-symbol pay-amount)
|
||||
[quo/approval-info
|
||||
{:type :account
|
||||
:unlimited-icon? false
|
||||
:label (:name account)
|
||||
:description (address-utils/get-short-wallet-address (:address account))
|
||||
:tag-label (str pay-amount " " pay-token-symbol)
|
||||
:avatar-props {:emoji (:emoji account)
|
||||
:customization-color (:color account)}}])]))
|
||||
|
||||
(defn- on-option-press
|
||||
[{:keys [chain-id contract-address]}]
|
||||
(rf/dispatch
|
||||
[:show-bottom-sheet
|
||||
{:content (fn []
|
||||
[quo/action-drawer
|
||||
[[{:icon :i/link
|
||||
:accessibility-label :view-on-etherscan
|
||||
:on-press (fn []
|
||||
(rf/dispatch
|
||||
[:wallet/navigate-to-chain-explorer-from-bottom-sheet
|
||||
(external-links/get-explorer-url-by-chain-id chain-id)
|
||||
contract-address]))
|
||||
:label (i18n/label :t/view-on-eth)
|
||||
:right-icon :i/external}]]])}]))
|
||||
|
||||
(defn- token-section
|
||||
[]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
pay-token (rf/sub [:trading.swap/pay-token])
|
||||
network (rf/sub [:trading.swap/network])
|
||||
pay-token-symbol (:symbol pay-token)
|
||||
network-chain-id (:chain-id network)
|
||||
pay-token-address (:address pay-token)]
|
||||
[rn/view {:style style/summary-section-container}
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:style (style/section-label theme)
|
||||
:accessibility-label :token-label}
|
||||
(i18n/label :t/token)]
|
||||
(when pay-token
|
||||
[quo/approval-info
|
||||
{:type :token-contract
|
||||
:option-icon :i/options
|
||||
:on-option-press #(on-option-press {:chain-id network-chain-id
|
||||
:contract-address pay-token-address})
|
||||
:unlimited-icon? false
|
||||
:label pay-token-symbol
|
||||
:description (address-utils/get-short-wallet-address pay-token-address)
|
||||
:avatar-props {:token pay-token-symbol}}])]))
|
||||
|
||||
(defn- spender-contract-section
|
||||
[]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
network (rf/sub [:trading.swap/network])
|
||||
provider (rf/sub [:trading.swap/provider])
|
||||
spender-contract-address (rf/sub [:trading.swap/approval-contract-address])
|
||||
network-chain-id (:chain-id network)]
|
||||
[rn/view {:style style/summary-section-container}
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:style (style/section-label theme)
|
||||
:accessibility-label :spender-contract-label}
|
||||
(i18n/label :t/spender-contract)]
|
||||
(when provider
|
||||
[quo/approval-info
|
||||
{:type :token-contract
|
||||
:option-icon :i/options
|
||||
:on-option-press #(on-option-press {:chain-id network-chain-id
|
||||
:contract-address spender-contract-address})
|
||||
:unlimited-icon? false
|
||||
:label (:full-name provider)
|
||||
:description (address-utils/get-short-wallet-address spender-contract-address)
|
||||
:avatar-props {:image (resources/get-network (:name provider))}}])]))
|
||||
|
||||
(defn- transaction-info-bar
|
||||
[]
|
||||
(let [approval-fees (rf/sub [:trading.swap/approval-fee-fiat])
|
||||
estimated-time (rf/sub [:trading.swap/approval-estimated-time])]
|
||||
[info-bar/container {:style {:padding-top 7 :padding-horizontal 4}}
|
||||
[info-bar/network]
|
||||
[info-bar/fiat-max-fee {:fee-amount approval-fees}]
|
||||
[info-bar/estimated-time {:estimated-time-mins estimated-time}]]))
|
||||
|
||||
(defn- slide-button
|
||||
[]
|
||||
(let [swap-proposal (rf/sub [:trading.swap/route])
|
||||
customization-color (rf/sub [:trading.swap/customization-color])
|
||||
transaction-for-signing (rf/sub [:wallet.routes/transactions-for-signing])
|
||||
sign-on-keycard? (get-in transaction-for-signing
|
||||
[:signingDetails :signOnKeycard])]
|
||||
[standard-auth/slide-button
|
||||
{:size :size-48
|
||||
:track-text (i18n/label :t/slide-to-sign)
|
||||
:container-style {:z-index 2}
|
||||
:customization-color customization-color
|
||||
:disabled? (not swap-proposal)
|
||||
:on-complete (when sign-on-keycard? #(on-confirm ""))
|
||||
:on-auth-success on-confirm
|
||||
:auth-button-label (i18n/label :t/confirm)}]))
|
||||
|
||||
(defn- footer
|
||||
[]
|
||||
[:<>
|
||||
[transaction-info-bar]
|
||||
[slide-button]
|
||||
[transaction.provider-footer/view]])
|
||||
|
||||
(defn view
|
||||
[]
|
||||
[transaction.container/view {:footer footer}
|
||||
[swap-title]
|
||||
[spending-cap-section]
|
||||
[account-section]
|
||||
[token-section]
|
||||
[spender-contract-section]])
|
||||
@@ -1,72 +0,0 @@
|
||||
(ns status-im.contexts.wallet.trading.swap.components.alert-banner
|
||||
(:require [quo.core :as quo]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.sheets.buy-token.view :as buy-token]
|
||||
[status-im.contexts.wallet.trading.swap.style :as style]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- error-message-from-code
|
||||
[error-code error-details]
|
||||
(cond
|
||||
(= error-code
|
||||
constants/router-error-code-not-enough-liquidity)
|
||||
(i18n/label :t/not-enough-liquidity)
|
||||
(= error-code
|
||||
constants/router-error-code-price-timeout)
|
||||
(i18n/label :t/fetching-the-price-took-longer-than-expected)
|
||||
(= error-code
|
||||
constants/router-error-code-price-impact-too-high)
|
||||
(i18n/label :t/price-impact-too-high)
|
||||
(= error-code
|
||||
constants/router-error-code-paraswap-custom-error)
|
||||
(i18n/label :t/paraswap-error
|
||||
{:paraswap-error error-details})
|
||||
(= error-code
|
||||
constants/router-error-code-generic)
|
||||
(i18n/label :t/generic-error
|
||||
{:generic-error error-details})
|
||||
(= error-code
|
||||
constants/router-error-code-not-enough-native-balance)
|
||||
(i18n/label :t/not-enough-assets-to-pay-gas-fees)
|
||||
:else
|
||||
(i18n/label :t/something-went-wrong-please-try-again-later)))
|
||||
|
||||
(defn- on-buy-crypto-press
|
||||
[]
|
||||
(rf/dispatch [:centralized-metrics/track :metric/swap-buy-eth])
|
||||
(rf/dispatch
|
||||
[:show-bottom-sheet
|
||||
{:content (fn [] [buy-token/view])}]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [route-error (rf/sub [:trading.swap/route-error])
|
||||
pay-input-error? (rf/sub [:trading.swap/pay-amount-error?])
|
||||
processing-route? (rf/sub [:trading.swap/processing-route?])
|
||||
error-response-code (:code route-error)
|
||||
error-response-details (:details route-error)]
|
||||
(when (and (or pay-input-error? route-error)
|
||||
(not processing-route?))
|
||||
[quo/alert-banner
|
||||
(cond-> {:container-style style/alert-banner
|
||||
:text-number-of-lines 0
|
||||
:text (if pay-input-error?
|
||||
(i18n/label :t/insufficient-funds-for-swaps)
|
||||
(error-message-from-code error-response-code
|
||||
error-response-details))}
|
||||
|
||||
pay-input-error?
|
||||
(merge {:action? true
|
||||
:on-button-press (fn []
|
||||
(rf/dispatch [:centralized-metrics/track
|
||||
:metric/swap-buy-assets])
|
||||
(rf/dispatch [:show-bottom-sheet
|
||||
{:content buy-token/view}]))
|
||||
:button-text (i18n/label :t/add-assets)})
|
||||
|
||||
(= error-response-code
|
||||
constants/router-error-code-not-enough-native-balance)
|
||||
(merge {:action? true
|
||||
:on-button-press on-buy-crypto-press
|
||||
:button-text (i18n/label :t/add-eth)}))])))
|
||||
@@ -1,21 +0,0 @@
|
||||
(ns status-im.contexts.wallet.trading.swap.components.exchange-rate.style
|
||||
(:require [quo.foundations.colors :as colors]))
|
||||
|
||||
(defn exchange-rate-loader
|
||||
[theme]
|
||||
{:margin-top 16
|
||||
:width 72
|
||||
:height 14
|
||||
:border-radius 6
|
||||
:background-color (colors/theme-colors colors/neutral-5 colors/neutral-90 theme)})
|
||||
|
||||
(def exchange-rate-container
|
||||
{:margin-top 16
|
||||
:flex-direction :row})
|
||||
|
||||
(def exchange-rate-crypto-label
|
||||
{:color colors/neutral-50})
|
||||
|
||||
(defn exchange-rate-fiat-label
|
||||
[theme]
|
||||
{:color (colors/theme-colors colors/neutral-40 colors/neutral-60 theme)})
|
||||
@@ -1,32 +0,0 @@
|
||||
(ns status-im.contexts.wallet.trading.swap.components.exchange-rate.view
|
||||
(:require [quo.core :as quo]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[status-im.contexts.wallet.trading.swap.components.exchange-rate.style :as style]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
input-valid? (rf/sub [:trading.swap/pay-amount-valid?])
|
||||
pay-token-symbol (rf/sub [:trading.swap/pay-token-symbol])
|
||||
receive-token-symbol (rf/sub [:trading.swap/receive-token-symbol])
|
||||
{:keys [crypto fiat]} (rf/sub [:trading.swap/exchange-rate])]
|
||||
(when input-valid?
|
||||
(if crypto
|
||||
[rn/view {:style style/exchange-rate-container}
|
||||
[quo/text
|
||||
{:weight :medium
|
||||
:size :paragraph-2
|
||||
:style style/exchange-rate-crypto-label}
|
||||
(i18n/label :t/swap-exchange-rate-in-crypto
|
||||
{:receive-token-symbol receive-token-symbol
|
||||
:pay-token-symbol pay-token-symbol
|
||||
:exchange-rate crypto})]
|
||||
[quo/text
|
||||
{:weight :medium
|
||||
:size :paragraph-2
|
||||
:style (style/exchange-rate-fiat-label theme)}
|
||||
(str " (" fiat ")")]]
|
||||
[rn/view {:style (style/exchange-rate-loader theme)}]))))
|
||||
@@ -1,19 +0,0 @@
|
||||
(ns status-im.contexts.wallet.trading.swap.components.flip-tokens
|
||||
(:require [quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[status-im.contexts.wallet.trading.swap.style :as style]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn view
|
||||
[{:keys [pay-input]}]
|
||||
;;TODO
|
||||
(let [approval-required? (rf/sub [:trading.swap/approval-required?])
|
||||
receive-amount (rf/sub [:trading.swap/receive-amount])
|
||||
on-flip-press (rn/use-callback (fn []
|
||||
(when receive-amount
|
||||
(apply (:set-input-value pay-input) [receive-amount]))
|
||||
(rf/dispatch [:trading.swap/flip-tokens]))
|
||||
[receive-amount pay-input])]
|
||||
[quo/swap-order-button
|
||||
{:container-style (style/swap-order-button approval-required?)
|
||||
:on-press on-flip-press}]))
|
||||
@@ -1,59 +0,0 @@
|
||||
(ns status-im.contexts.wallet.trading.swap.components.footer
|
||||
(:require [quo.core :as quo]
|
||||
[status-im.contexts.wallet.trading.swap.components.alert-banner :as alert-banner]
|
||||
[status-im.contexts.wallet.trading.swap.components.info-bar.view :as info-bar]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- on-press-review
|
||||
[]
|
||||
(rf/dispatch [:open-modal :screen/trading.swap-confirmation])
|
||||
(rf/dispatch [:trading.swap/swap-confirmation]))
|
||||
|
||||
(defn- submit-button
|
||||
[{:keys [disabled?]}]
|
||||
(let [customization-color (rf/sub [:trading.swap/customization-color])]
|
||||
[quo/bottom-actions
|
||||
{:container-style {:background-color :transparent}
|
||||
:actions :one-action
|
||||
:button-one-label (i18n/label :t/review-swap)
|
||||
:button-one-props {:disabled? disabled?
|
||||
:customization-color customization-color
|
||||
:on-press on-press-review}}]))
|
||||
|
||||
(defn transaction-info-bar
|
||||
[]
|
||||
(let [max-slippage (rf/sub [:trading.swap/max-slippage])
|
||||
max-fee (rf/sub [:trading.swap/total-fee-fiat])
|
||||
error-response (rf/sub [:wallet/swap-error-response])
|
||||
processing-route? (rf/sub [:trading.swap/processing-route?])]
|
||||
[info-bar/container
|
||||
{:style {:padding-top 12
|
||||
:padding-horizontal 20}}
|
||||
[info-bar/fiat-max-fee
|
||||
{:fee-amount max-fee
|
||||
:subtitle-error? (boolean error-response)}]
|
||||
[info-bar/max-slippage
|
||||
{:slippage max-slippage
|
||||
:disabled? processing-route?}]]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [processing-route? (rf/sub [:trading.swap/processing-route?])
|
||||
route (rf/sub [:trading.swap/route])
|
||||
route-error (rf/sub [:trading.swap/route-error])
|
||||
input-valid? (rf/sub [:trading.swap/pay-amount-valid?])
|
||||
approval-required? (rf/sub [:trading.swap/approval-required?])
|
||||
approval-transaction-status (rf/sub [:trading.swap/approval-status])]
|
||||
[:<>
|
||||
(when (and input-valid? (not processing-route?))
|
||||
[alert-banner/view])
|
||||
(when input-valid?
|
||||
[transaction-info-bar])
|
||||
[submit-button
|
||||
{:disabled? (or (not (seq route))
|
||||
(not input-valid?)
|
||||
route-error
|
||||
(and approval-required?
|
||||
(not= approval-transaction-status :confirmed))
|
||||
processing-route?)}]]))
|
||||
@@ -1,86 +0,0 @@
|
||||
(ns status-im.contexts.wallet.trading.swap.components.header-nav
|
||||
(:require [quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[status-im.contexts.profile.utils :as profile.utils]
|
||||
[status-im.contexts.wallet.sheets.select-account.view :as select-account]
|
||||
[status-im.contexts.wallet.trading.swap.components.network-selector :as network-selector]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn profile-button
|
||||
[]
|
||||
(let [{:keys [public-key] :as profile} (rf/sub [:profile/profile-with-image])
|
||||
online? (rf/sub [:visibility-status-updates/online?
|
||||
public-key])
|
||||
customization-color (rf/sub [:profile/customization-color])]
|
||||
[rn/pressable
|
||||
{:on-press #(rf/dispatch [:open-modal :settings])
|
||||
:accessibility-label :open-profile}
|
||||
[quo/user-avatar
|
||||
{:status-indicator? true
|
||||
:ring? true
|
||||
:static? true
|
||||
:customization-color customization-color
|
||||
:size :small
|
||||
:online? online?
|
||||
:full-name (profile.utils/displayed-name profile)
|
||||
:profile-picture (profile.utils/photo profile)}]]))
|
||||
|
||||
(defn- show-account-selector
|
||||
[address token-symbol network]
|
||||
(rf/dispatch [:show-bottom-sheet
|
||||
{:content (fn []
|
||||
[select-account/view
|
||||
{:show-account-balances true
|
||||
:address address
|
||||
:on-press-account (fn [address]
|
||||
(rf/dispatch [:trading.swap/set-account-address
|
||||
address]))
|
||||
:asset-symbol token-symbol
|
||||
:network network}])}]))
|
||||
|
||||
(defn- show-network-selector
|
||||
[token-symbol address]
|
||||
(rf/dispatch [:show-bottom-sheet
|
||||
{:content (fn []
|
||||
[network-selector/view
|
||||
{:token-symbol token-symbol
|
||||
:address address
|
||||
:on-select-network (fn [{:keys [chain-id]}]
|
||||
(rf/dispatch [:hide-bottom-sheet])
|
||||
(rf/dispatch
|
||||
[:trading.swap/set-chain-id chain-id]))}])}]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [{:keys [color emoji address]} (rf/sub [:trading.swap/account])
|
||||
input-focused? (rf/sub [:trading.swap/focused?])
|
||||
network (rf/sub [:trading.swap/network])
|
||||
pay-token-symbol (rf/sub [:trading.swap/pay-token-symbol])]
|
||||
[quo/page-nav
|
||||
(cond-> {}
|
||||
input-focused? (assoc :icon-name :i/close
|
||||
:on-press (fn []
|
||||
#_(rf/dispatch [:hide-bottom-sheet])
|
||||
(rf/dispatch [:trading.swap/blur-input])))
|
||||
(not input-focused?) (assoc :left-component profile-button)
|
||||
:always (assoc :type :dropdown
|
||||
:left-component profile-button
|
||||
:dropdown-props {:dropdown-text (:full-name network)
|
||||
:on-press #(show-network-selector
|
||||
pay-token-symbol
|
||||
address)
|
||||
:type :outline
|
||||
:image? true
|
||||
:image-source (:source network)}
|
||||
:margin-top (safe-area/get-top)
|
||||
:background :blur
|
||||
:accessibility-label :top-bar
|
||||
:align-center? true
|
||||
:right-side [{:content-type :account-switcher
|
||||
:customization-color color
|
||||
:on-press #(show-account-selector
|
||||
address
|
||||
pay-token-symbol
|
||||
network)
|
||||
:emoji emoji}]))]))
|
||||
@@ -1,12 +0,0 @@
|
||||
(ns status-im.contexts.wallet.trading.swap.components.info-bar.style)
|
||||
|
||||
(def bar-item
|
||||
{:flex 1
|
||||
:height 36
|
||||
:background-color :transparent})
|
||||
|
||||
(def bar-container
|
||||
{:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:height 52
|
||||
:padding-horizontal 1})
|
||||
@@ -1,75 +0,0 @@
|
||||
(ns status-im.contexts.wallet.trading.swap.components.info-bar.view
|
||||
(:require [quo.core :as quo]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[status-im.contexts.wallet.common.utils :as utils]
|
||||
[status-im.contexts.wallet.trading.swap.components.info-bar.style :as style]
|
||||
[status-im.contexts.wallet.trading.swap.components.slippage-settings :as slippage-settings]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn container
|
||||
[& args]
|
||||
(let [[props children] (if (map? (first args))
|
||||
[(first args) (rest args)]
|
||||
[nil args])]
|
||||
(into [rn/view
|
||||
{:style [style/bar-container (:style props)]}]
|
||||
children)))
|
||||
|
||||
(def ^:private default-data-item-props
|
||||
{:container-style style/bar-item
|
||||
:blur? false
|
||||
:card? false
|
||||
:subtitle-type :default
|
||||
:status :default
|
||||
:size :small})
|
||||
|
||||
(defn network
|
||||
[]
|
||||
(let [{:keys [source full-name]} (rf/sub [:trading.swap/network])]
|
||||
[quo/data-item
|
||||
(assoc default-data-item-props
|
||||
:subtitle-type :network
|
||||
:network-image source
|
||||
:title (i18n/label :t/network)
|
||||
:subtitle full-name)]))
|
||||
|
||||
(defn fiat-max-fee
|
||||
[{:keys [fee-amount subtitle-error?]}]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
currency-symbol (rf/sub [:profile/currency-symbol])
|
||||
formatted-fee (utils/fiat-formatted-for-ui currency-symbol
|
||||
fee-amount)]
|
||||
[quo/data-item
|
||||
(assoc default-data-item-props
|
||||
:title (i18n/label :t/max-fees)
|
||||
:status (if fee-amount :default :loading)
|
||||
:subtitle formatted-fee
|
||||
:subtitle-color (when subtitle-error?
|
||||
(colors/theme-colors colors/danger-50
|
||||
colors/danger-60
|
||||
theme)))]))
|
||||
|
||||
(defn estimated-time
|
||||
[{:keys [estimated-time-mins]}]
|
||||
[quo/data-item
|
||||
(assoc default-data-item-props
|
||||
:title (i18n/label :t/est-time)
|
||||
:status (if estimated-time-mins :default :loading)
|
||||
:subtitle (i18n/label :t/time-in-mins {:minutes (str estimated-time-mins)}))])
|
||||
|
||||
(defn max-slippage
|
||||
[{:keys [slippage disabled?]}]
|
||||
[quo/data-item
|
||||
(assoc default-data-item-props
|
||||
:title (i18n/label :t/max-slippage)
|
||||
:subtitle (str slippage "%")
|
||||
:subtitle-type :editable
|
||||
:icon :i/edit
|
||||
:size :small
|
||||
:on-press (fn []
|
||||
(when-not disabled?
|
||||
(rf/dispatch [:show-bottom-sheet
|
||||
{:content slippage-settings/view}]))))])
|
||||
@@ -1,71 +0,0 @@
|
||||
(ns status-im.contexts.wallet.trading.swap.components.keyboard
|
||||
(:require [quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[react-native.platform :as platform]
|
||||
[status-im.common.controlled-input.utils :as controlled-input]
|
||||
[status-im.contexts.wallet.trading.swap.components.footer :as footer]
|
||||
[status-im.contexts.wallet.trading.swap.style :as style]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.string :as utils.string]))
|
||||
|
||||
(defn- should-allow-input-char?
|
||||
[input-state character token-decimals]
|
||||
(let [new-state-amount (-> (controlled-input/input-value input-state)
|
||||
(str character))]
|
||||
(utils.string/valid-amount-for-token-decimals? token-decimals
|
||||
new-state-amount)))
|
||||
|
||||
(defn keyboard-view
|
||||
[{:keys [input input-token-decimals]}]
|
||||
(fn []
|
||||
(let [{:keys [value add-input-char
|
||||
delete-last-input-char
|
||||
clear-input-value]} input
|
||||
on-keyboard-long-press (rn/use-callback
|
||||
(fn []
|
||||
(clear-input-value)
|
||||
;; TODO: investigate
|
||||
;;(rf/dispatch
|
||||
;;[:wallet/clean-suggested-routes])
|
||||
)
|
||||
[clear-input-value])
|
||||
on-keyboard-press (rn/use-callback
|
||||
(fn [c]
|
||||
(when (should-allow-input-char?
|
||||
value
|
||||
c
|
||||
input-token-decimals)
|
||||
(add-input-char c value)))
|
||||
[value input-token-decimals add-input-char])
|
||||
on-keyboard-delete (rn/use-callback
|
||||
(fn []
|
||||
(delete-last-input-char)
|
||||
;; TODO: investigate
|
||||
;; (rf/dispatch
|
||||
;; [:wallet/clean-swap-proposal
|
||||
;; {:clean-amounts? true
|
||||
;; :clean-approval-transaction?
|
||||
;; true}])
|
||||
)
|
||||
[delete-last-input-char])]
|
||||
[rn/view
|
||||
[footer/view]
|
||||
[quo/numbered-keyboard
|
||||
{:container-style style/keyboard-container
|
||||
:left-action :dot
|
||||
:delete-key? true
|
||||
:on-press on-keyboard-press
|
||||
:on-delete on-keyboard-delete
|
||||
:on-long-press-delete on-keyboard-long-press}]])))
|
||||
|
||||
(defn show
|
||||
[{:keys [on-close] :as keyboard-opts} theme]
|
||||
(rf/dispatch
|
||||
[:show-bottom-sheet
|
||||
{:hide-handle? true
|
||||
:theme theme
|
||||
:dim-background? false
|
||||
:shell? platform/ios?
|
||||
:disable-gestures? true
|
||||
:on-close on-close
|
||||
:content (keyboard-view keyboard-opts)}]))
|
||||
@@ -1,59 +0,0 @@
|
||||
(ns status-im.contexts.wallet.trading.swap.components.network-selector
|
||||
(:require [quo.core :as quo]
|
||||
[quo.foundations.resources :as quo.resources]
|
||||
[react-native.core :as rn]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.sheets.network-selection.style :as style]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- network-item
|
||||
[{:keys [network on-select-network mainnet? token-symbol address]}]
|
||||
(let [{:keys [network-name full-name chain-id]} network
|
||||
{:keys [crypto fiat]} (rf/sub [:wallet/token-balance address token-symbol
|
||||
chain-id])]
|
||||
[quo/network-list
|
||||
{:label full-name
|
||||
:network-image (quo.resources/get-network network-name)
|
||||
:token-value crypto
|
||||
:fiat-value fiat
|
||||
:on-press #(on-select-network network)
|
||||
:container-style (style/network-list-container mainnet?)}]))
|
||||
|
||||
(defn view
|
||||
[{:keys [token-symbol on-select-network address]}]
|
||||
(let [supported-networks (rf/sub [:wallet/network-details])
|
||||
networks-by-layer (group-by :layer supported-networks)
|
||||
mainnet-network (-> networks-by-layer (get constants/layer-1-network) first)
|
||||
layer-2-networks (get networks-by-layer constants/layer-2-network)
|
||||
render-fn (rn/use-callback (fn [network]
|
||||
[network-item
|
||||
{:network network
|
||||
:address address
|
||||
:token-symbol token-symbol
|
||||
:on-select-network on-select-network}])
|
||||
[on-select-network address])]
|
||||
[:<>
|
||||
[rn/view {:style style/header-container}
|
||||
[quo/text
|
||||
{:size :heading-2
|
||||
:weight :semi-bold}
|
||||
(i18n/label :t/select-network)]
|
||||
[quo/context-tag
|
||||
{:type :token
|
||||
:size 24
|
||||
:token token-symbol
|
||||
:container-style style/context-tag}]]
|
||||
(when mainnet-network
|
||||
[network-item
|
||||
{:network mainnet-network
|
||||
:address address
|
||||
:token-symbol token-symbol
|
||||
:mainnet? true
|
||||
:on-select-network on-select-network}])
|
||||
[quo/divider-label {:container-style style/divider-label}
|
||||
(i18n/label :t/layer-2)]
|
||||
[rn/flat-list
|
||||
{:data layer-2-networks
|
||||
:render-fn render-fn
|
||||
:scroll-enabled false}]]))
|
||||
@@ -1,67 +0,0 @@
|
||||
(ns status-im.contexts.wallet.trading.swap.components.pay-input
|
||||
(:require [quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[status-im.contexts.wallet.trading.swap.components.token-list :as token-list]
|
||||
[status-im.contexts.wallet.trading.swap.hooks :as hooks]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- on-press-approve
|
||||
[]
|
||||
(rf/dispatch [:open-modal :screen/trading.swap-approval-confirmation])
|
||||
(rf/dispatch [:trading.swap/approve-confirmation]))
|
||||
|
||||
(defn view
|
||||
[{:keys [pay-input on-pay-input-focus input-ref]}]
|
||||
(let [{:keys [value set-input-value]} pay-input
|
||||
set-input-ref (rn/use-callback (fn [ref] (reset! input-ref ref)))
|
||||
pay-input-focused? (rf/sub [:trading.swap/focused?])
|
||||
customization-color (rf/sub [:trading.swap/customization-color])
|
||||
processing-route? (rf/sub [:trading.swap/processing-route?])
|
||||
error? (rf/sub [:trading.swap/error?])
|
||||
pay-token-symbol (rf/sub [:trading.swap/pay-token-symbol])
|
||||
pay-token-balance-formatted (rf/sub [:trading.swap/formatted-pay-token-balance])
|
||||
pay-fiat-amount (rf/sub [:trading.swap/pay-fiat-amount])
|
||||
network (rf/sub [:trading.swap/network])
|
||||
approval-required? (rf/sub [:trading.swap/approval-required?])
|
||||
approval-transaction-id (rf/sub [:trading.swap/approval-transaction-id])
|
||||
approval-status (rf/sub [:trading.swap/approval-status])
|
||||
approval-amount (rf/sub [:trading.swap/approval-amount])
|
||||
{:keys [input-error?]} (hooks/use-input-validation value)
|
||||
show-approval-label? (or approval-required?
|
||||
(boolean approval-transaction-id))
|
||||
on-max-press (rn/use-callback
|
||||
(fn []
|
||||
(set-input-value pay-token-balance-formatted))
|
||||
[pay-token-balance-formatted set-input-value])]
|
||||
[quo/swap-input
|
||||
{:type :pay
|
||||
:get-ref set-input-ref
|
||||
:error? input-error?
|
||||
:token pay-token-symbol
|
||||
:customization-color customization-color
|
||||
:auto-focus? true
|
||||
:show-keyboard? false
|
||||
:status (cond pay-input-focused? :typing
|
||||
:else :default)
|
||||
:on-token-press (token-list/show pay-token-symbol)
|
||||
:on-max-press on-max-press
|
||||
:on-input-focus on-pay-input-focus
|
||||
:value value
|
||||
:fiat-value pay-fiat-amount
|
||||
:show-approval-label? show-approval-label?
|
||||
:network-tag-props {:title (i18n/label :t/max-token
|
||||
{:number pay-token-balance-formatted
|
||||
:token-symbol pay-token-symbol})
|
||||
:networks [{:source (:source network)}]}
|
||||
:approval-label-props (when show-approval-label?
|
||||
{:status (case approval-status
|
||||
:pending :approving
|
||||
:confirmed :approved
|
||||
:finalised :approved
|
||||
:approve)
|
||||
:token-value approval-amount
|
||||
:button-props {:on-press on-press-approve
|
||||
:disabled? (or processing-route? error?)}
|
||||
:customization-color customization-color
|
||||
:token-symbol pay-token-symbol})}]))
|
||||
@@ -1,41 +0,0 @@
|
||||
(ns status-im.contexts.wallet.trading.swap.components.receive-input
|
||||
(:require [quo.core :as quo]
|
||||
[status-im.contexts.wallet.trading.swap.components.token-list :as token-list]
|
||||
[status-im.contexts.wallet.trading.swap.style :as style]
|
||||
[status-im.contexts.wallet.trading.swap.utils :as utils]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn view
|
||||
[{:keys [pay-input]}]
|
||||
(let [customization-color (rf/sub [:trading.swap/customization-color])
|
||||
receive-token-symbol (rf/sub [:trading.swap/receive-token-symbol])
|
||||
processing-route? (rf/sub [:trading.swap/processing-route?])
|
||||
route (rf/sub [:trading.swap/route])
|
||||
receive-amount (rf/sub [:trading.swap/receive-amount])
|
||||
pay-amount (:value pay-input)
|
||||
receive-fiat-amount (rf/sub [:trading.swap/receive-fiat-amount])
|
||||
error? (rf/sub [:trading.swap/error?])
|
||||
loading-input? (or processing-route?
|
||||
error?
|
||||
(and (not route)
|
||||
(not (utils/input-empty? pay-amount))))
|
||||
approval-required? (rf/sub [:trading.swap/approval-required?])]
|
||||
[quo/swap-input
|
||||
{:type :receive
|
||||
:error? false
|
||||
:token receive-token-symbol
|
||||
:customization-color customization-color
|
||||
:show-approval-label? false
|
||||
:enable-swap? true
|
||||
:input-disabled? true
|
||||
:show-keyboard? false
|
||||
:status (cond
|
||||
loading-input? :loading
|
||||
:else :disabled)
|
||||
:on-token-press (token-list/show receive-token-symbol)
|
||||
:value (if (and (utils/input-empty? receive-amount)
|
||||
(utils/input-empty? pay-amount))
|
||||
"0"
|
||||
receive-amount)
|
||||
:fiat-value receive-fiat-amount
|
||||
:container-style (style/receive-token-swap-input-container approval-required?)}]))
|
||||
@@ -1,154 +0,0 @@
|
||||
(ns status-im.contexts.wallet.trading.swap.components.slippage-settings
|
||||
(:require [clojure.string :as string]
|
||||
[quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[react-native.platform :as platform]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.common.utils :as utils]
|
||||
[status-im.contexts.wallet.sheets.slippage-settings.style :as style]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.money :as money]
|
||||
[utils.number :as number]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- validate-slippage
|
||||
[slippage]
|
||||
(let [slippage-value (number/parse-float slippage)]
|
||||
(cond
|
||||
(<= slippage-value 0)
|
||||
{:message (i18n/label :t/slippage-should-be-more-than-0)
|
||||
:type :error}
|
||||
(> slippage-value constants/max-slippage)
|
||||
{:message (i18n/label :t/slippage-cant-be-more-than-30)
|
||||
:type :error}
|
||||
(> (count (second (string/split slippage ".")))
|
||||
constants/max-slippage-decimal-places)
|
||||
{:message (i18n/label :t/max-2-decimals)
|
||||
:type :error}
|
||||
(> slippage-value constants/max-recommended-slippage)
|
||||
{:message (i18n/label :t/slippage-may-be-higher-than-necessary)
|
||||
:type :warning})))
|
||||
|
||||
(defn- on-cancel
|
||||
[]
|
||||
(rf/dispatch [:hide-bottom-sheet]))
|
||||
|
||||
(defn- update-string-on-keypress
|
||||
[k s]
|
||||
(if (= :i/backspace k)
|
||||
(subs s 0 (dec (count s)))
|
||||
(str s k)))
|
||||
|
||||
(defn- calculate-receive-amount
|
||||
[asset-to-receive amount-out max-slippage]
|
||||
(let [receive-token-decimals (:decimals asset-to-receive)
|
||||
amount-out-whole-number (number/hex->whole amount-out receive-token-decimals)
|
||||
amount-out-num (number/to-fixed amount-out-whole-number
|
||||
receive-token-decimals)
|
||||
slippage-num (-> (money/bignumber amount-out-num)
|
||||
(money/mul (money/bignumber max-slippage))
|
||||
(money/div (money/bignumber 100)))
|
||||
amount-out-minus-slippage (money/sub (money/bignumber amount-out-num) slippage-num)
|
||||
display-decimals (min receive-token-decimals
|
||||
constants/min-token-decimals-to-display)
|
||||
receive-amount (if (money/above-zero? amount-out-minus-slippage)
|
||||
(str (utils/sanitized-token-amount-to-display
|
||||
amount-out-minus-slippage
|
||||
display-decimals))
|
||||
0)]
|
||||
receive-amount))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [current-slippage (rf/sub [:trading.swap/max-slippage])
|
||||
account-color (rf/sub [:trading.swap/customization-color])
|
||||
asset-to-receive (rf/sub [:trading.swap/receive-token])
|
||||
amount-out (rf/sub [:trading.swap/receive-amount])
|
||||
[max-slippage set-max-slippage] (rn/use-state (str current-slippage))
|
||||
[error set-error] (rn/use-state nil)
|
||||
[custom? set-custom?] (rn/use-state (not-any? #{current-slippage}
|
||||
constants/slippages))
|
||||
receive-token-symbol (:symbol asset-to-receive)
|
||||
receive-amount (calculate-receive-amount asset-to-receive
|
||||
amount-out
|
||||
max-slippage)
|
||||
handle-slippage-change (rn/use-callback
|
||||
(fn [value]
|
||||
(let [new-slippage (update-string-on-keypress value
|
||||
max-slippage)]
|
||||
(set-max-slippage new-slippage)
|
||||
(set-error (validate-slippage new-slippage))))
|
||||
[max-slippage set-max-slippage set-error])
|
||||
on-select-slippage (rn/use-callback (fn [slippage]
|
||||
(set-max-slippage (str slippage))
|
||||
(set-custom? (nil? slippage))
|
||||
(when slippage (set-error nil)))
|
||||
[set-max-slippage set-custom?])
|
||||
save-disabled? (rn/use-memo (fn []
|
||||
(or (= max-slippage (str current-slippage))
|
||||
(= (:type error) :error)
|
||||
(and custom?
|
||||
(empty? max-slippage))))
|
||||
[max-slippage current-slippage error custom?])
|
||||
on-save (rn/use-callback (fn []
|
||||
(rf/dispatch [:trading.swap/set-max-slippage
|
||||
max-slippage])
|
||||
(rf/dispatch [:hide-bottom-sheet]))
|
||||
[max-slippage])]
|
||||
[:<>
|
||||
[quo/drawer-top
|
||||
{:title (i18n/label :t/slippage-settings)
|
||||
:description (i18n/label :t/slippage-settings-description)}]
|
||||
[rn/view {:style style/slippages}
|
||||
(map (fn [slippage]
|
||||
^{:key slippage}
|
||||
[quo/drawer-action
|
||||
(cond-> {:title (str slippage "%")
|
||||
:on-press #(on-select-slippage slippage)}
|
||||
(and (= (str slippage) max-slippage) (not custom?)) (assoc :state :selected))])
|
||||
constants/slippages)
|
||||
[quo/drawer-action
|
||||
(cond-> {:title (i18n/label :t/custom)
|
||||
:action :input
|
||||
:on-press #(on-select-slippage nil)
|
||||
:input-props {:auto-focus true
|
||||
:customization-color account-color
|
||||
:placeholder (i18n/label :t/type-slippage)
|
||||
:right-icon {:icon-name :i/percentage
|
||||
:on-press identity
|
||||
:style-fn style/percentage-icon}
|
||||
:value max-slippage
|
||||
:show-soft-input-on-focus false
|
||||
:on-focus (fn []
|
||||
(when platform/android?
|
||||
(rf/dispatch [:dismiss-keyboard])))}}
|
||||
custom? (assoc :state :selected))]]
|
||||
(when (and custom? error)
|
||||
[quo/info-message
|
||||
{:status (:type error)
|
||||
:size :default
|
||||
:container-style style/info-message
|
||||
:icon :i/alert}
|
||||
(:message error)])
|
||||
[quo/bottom-actions
|
||||
{:actions :two-actions
|
||||
:button-one-label (i18n/label :t/save-changes)
|
||||
:button-one-props {:disabled? save-disabled?
|
||||
:customization-color account-color
|
||||
:on-press on-save}
|
||||
:button-two-label (i18n/label :t/cancel)
|
||||
:button-two-props {:on-press on-cancel
|
||||
:customization-color account-color
|
||||
:type :grey}
|
||||
:description :top
|
||||
:context-tag-props {:size 24
|
||||
:type :token
|
||||
:token receive-token-symbol
|
||||
:amount receive-amount}
|
||||
:description-top-text (i18n/label :t/receive-at-least)}]
|
||||
(when custom?
|
||||
[quo/numbered-keyboard
|
||||
{:left-action :dot
|
||||
:delete-key? true
|
||||
:on-press handle-slippage-change
|
||||
:on-delete handle-slippage-change}])]))
|
||||
@@ -1,50 +0,0 @@
|
||||
(ns status-im.contexts.wallet.trading.swap.components.token-list
|
||||
(:require [status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.sheets.select-asset.view :as select-asset]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- view-fn
|
||||
[current-token-symbol]
|
||||
(fn []
|
||||
(let [network (rf/sub [:trading.swap/network])
|
||||
pay-token-symbol (rf/sub [:trading.swap/pay-token-symbol])
|
||||
receive-token-symbol (rf/sub [:trading.swap/receive-token-symbol])
|
||||
address (rf/sub [:trading.swap/account-address])
|
||||
pay-token-list? (= current-token-symbol pay-token-symbol)
|
||||
disable-current-token (fn [_ token]
|
||||
(or (= (:symbol token)
|
||||
pay-token-symbol)
|
||||
(= (:symbol token)
|
||||
receive-token-symbol)))]
|
||||
[select-asset/view
|
||||
(cond->
|
||||
{:network network
|
||||
:address address
|
||||
:disable-token-fn disable-current-token}
|
||||
|
||||
pay-token-list?
|
||||
(assoc
|
||||
:title (i18n/label :t/select-asset-to-pay)
|
||||
:on-select
|
||||
(fn [token]
|
||||
(if pay-token-list?
|
||||
(rf/dispatch [:trading.swap/set-pay-token (:symbol token)])
|
||||
(rf/dispatch [:trading.swap/set-receive-token (:symbol token)])))
|
||||
:hide-token-fn (fn [type {:keys [balances-per-chain]}]
|
||||
(let [balance
|
||||
(get-in balances-per-chain [(:chain-id network) :balance] "0")]
|
||||
(and (= type constants/swap-tokens-my)
|
||||
(= balance "0")))))
|
||||
|
||||
(not pay-token-list?)
|
||||
(assoc :title (i18n/label :t/select-asset-to-receive)
|
||||
:on-select (fn [token]
|
||||
(rf/dispatch [:trading.swap/set-receive-token (:symbol token)]))))])))
|
||||
|
||||
(defn show
|
||||
[current-token-symbol]
|
||||
(fn []
|
||||
(rf/dispatch [:show-bottom-sheet
|
||||
{:content (view-fn current-token-symbol)
|
||||
:options {:overlay {:interceptTouchOutside false}}}])))
|
||||
@@ -1,27 +0,0 @@
|
||||
(ns status-im.contexts.wallet.trading.swap.components.transaction.container
|
||||
(:require [quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[status-im.common.events-helper :as events-helper]
|
||||
[status-im.common.floating-button-page.view :as floating-button-page]
|
||||
[status-im.contexts.wallet.trading.swap.components.transaction.style :as style]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn view
|
||||
[{:keys [footer]} & children]
|
||||
(let [customization-color (rf/sub [:trading.swap/customization-color])]
|
||||
[rn/view {:style style/container}
|
||||
[floating-button-page/view
|
||||
{:footer-container-padding 0
|
||||
:content-container-style {:margin-bottom 168}
|
||||
:header [quo/page-nav
|
||||
{:icon-name :i/close
|
||||
:on-press events-helper/navigate-back
|
||||
:margin-top 8
|
||||
:background :blur
|
||||
:accessibility-label :top-bar}]
|
||||
:footer [footer]
|
||||
:gradient-cover? true
|
||||
:customization-color customization-color}
|
||||
(into
|
||||
[rn/scroll-view {:style style/scroll-view-container}]
|
||||
children)]]))
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
(ns status-im.contexts.wallet.trading.swap.components.transaction.provider-footer
|
||||
(:require [quo.core :as quo]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[status-im.contexts.wallet.trading.swap.components.transaction.style :as style]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
provider (rf/sub [:trading.swap/provider])
|
||||
on-press (rn/use-callback #(when provider
|
||||
(rf/dispatch [:open-url (:terms-and-conditions-url provider)]))
|
||||
[provider])]
|
||||
[rn/view {:style style/providers-container}
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:style (style/swaps-powered-by theme)}
|
||||
(i18n/label :t/swaps-powered-by
|
||||
{:provider (if provider (:full-name provider) (i18n/label :t/unknown))})]
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:style (style/terms-and-conditions theme)
|
||||
:on-press on-press}
|
||||
(i18n/label :t/terms-and-conditions)]]))
|
||||
@@ -1,33 +0,0 @@
|
||||
(ns status-im.contexts.wallet.trading.swap.components.transaction.style
|
||||
(:require [quo.foundations.colors :as colors]))
|
||||
|
||||
(def container
|
||||
{:flex 1
|
||||
:margin-top -20})
|
||||
|
||||
(def scroll-view-container
|
||||
{:flex 1
|
||||
:padding-bottom 20})
|
||||
|
||||
(def title-container
|
||||
{:padding-top 12
|
||||
:padding-horizontal 20
|
||||
:padding-bottom 32})
|
||||
|
||||
(def title-text
|
||||
{:margin-horizontal 4})
|
||||
|
||||
(def title-row
|
||||
{:flex-direction :row})
|
||||
|
||||
(def providers-container
|
||||
{:align-items :center
|
||||
:margin-top 12})
|
||||
|
||||
(defn swaps-powered-by
|
||||
[theme]
|
||||
{:color (colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-70 theme)})
|
||||
|
||||
(defn terms-and-conditions
|
||||
[theme]
|
||||
{:color (colors/theme-colors colors/neutral-100 colors/white theme)})
|
||||
@@ -1,28 +0,0 @@
|
||||
(ns status-im.contexts.wallet.trading.swap.components.transaction.title
|
||||
(:require [quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[status-im.contexts.wallet.trading.swap.components.transaction.style :as style]))
|
||||
|
||||
(defn container
|
||||
[& children]
|
||||
(into [rn/view {:style style/title-container}] children))
|
||||
|
||||
(defn text
|
||||
[{:keys [label accessibility-label]}]
|
||||
[quo/text
|
||||
{:size :heading-1
|
||||
:weight :semi-bold
|
||||
:style style/title-text
|
||||
:accessibility-label accessibility-label}
|
||||
label])
|
||||
|
||||
(defn row
|
||||
[& args]
|
||||
(let [[props children] (if (map? (first args))
|
||||
[(first args) (rest args)]
|
||||
[nil args])]
|
||||
(into [rn/view
|
||||
{:style [style/title-row
|
||||
(when-not (:first? props)
|
||||
{:margin-top 4})]}]
|
||||
children)))
|
||||
@@ -1 +0,0 @@
|
||||
(ns status-im.contexts.wallet.trading.swap.components.transaction-information)
|
||||
@@ -1,10 +0,0 @@
|
||||
(ns status-im.contexts.wallet.trading.swap.constants)
|
||||
|
||||
;;(def ^:const default-pay-asset "ETH")
|
||||
(def ^:const default-pay-asset "SNT")
|
||||
(def ^:const default-receive-asset "ETH")
|
||||
(def ^:const default-network-chain-id 1)
|
||||
(def ^:const default-slippage 0.5)
|
||||
(def ^:const default-pay-amount "0")
|
||||
|
||||
(def ^:const get-suggested-routes-debounce-ms 1000)
|
||||
@@ -1,265 +0,0 @@
|
||||
(ns status-im.contexts.wallet.trading.swap.events
|
||||
(:require [re-frame.core :as rf]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.common.utils :as common.utils]
|
||||
[status-im.contexts.wallet.trading.swap.constants :as swap-constants]
|
||||
[status-im.contexts.wallet.trading.swap.routes :as routes]
|
||||
[status-im.contexts.wallet.trading.swap.utils :as utils]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.money :as money]
|
||||
[utils.number :as number]))
|
||||
|
||||
(def swap-db-path [:wallet :ui :trading-swap])
|
||||
|
||||
(defn- get-default-state
|
||||
[db]
|
||||
(let [account-address (-> db utils/default-account :address)]
|
||||
{:pay-token-symbol swap-constants/default-pay-asset
|
||||
:receive-token-symbol swap-constants/default-receive-asset
|
||||
:pay-amount swap-constants/default-pay-amount
|
||||
:max-slippage swap-constants/default-slippage
|
||||
:chain-id swap-constants/default-network-chain-id
|
||||
:account-address account-address}))
|
||||
|
||||
(rf/reg-event-fx :trading.swap/initialize-state
|
||||
(fn [{:keys [db]}
|
||||
[{:keys [pay-amount pay-token-symbol receive-token-symbol chain-id max-slippage
|
||||
account-address]}]]
|
||||
{:db (update-in db
|
||||
swap-db-path
|
||||
assoc
|
||||
:focused? false
|
||||
:account-address account-address
|
||||
:pay-token-symbol pay-token-symbol
|
||||
:pay-amount pay-amount
|
||||
:receive-token-symbol receive-token-symbol
|
||||
:chain-id chain-id
|
||||
:max-slippage max-slippage
|
||||
:initialized? true)}))
|
||||
|
||||
(rf/reg-event-fx :trading.swap/init
|
||||
(fn [{:keys [db]}]
|
||||
(let [default-state (get-default-state db)]
|
||||
{:fx [[:dispatch
|
||||
[:trading.swap/initialize-state default-state]]
|
||||
[:dispatch
|
||||
[:centralized-metrics/track :metric/swap-start
|
||||
{:network (:chain-id default-state)
|
||||
:pay_token (:pay-token-symbol default-state)
|
||||
:receive_token (:receive-token-symbol default-state)
|
||||
:start_point (:view-id db)
|
||||
:launch_screen :trading-tab}]]]})))
|
||||
|
||||
(rf/reg-event-fx :trading.swap/reset-swap
|
||||
(fn [{:keys [db]}]
|
||||
{:db (update-in db swap-db-path dissoc :pay-amount :requested-route-uuid :approvals :focused?)}))
|
||||
|
||||
;; == setters ==
|
||||
|
||||
(rf/reg-event-fx :trading.swap/focus-input
|
||||
(fn [{:keys [db]}]
|
||||
{:db (update-in db swap-db-path assoc :focused? true)}))
|
||||
|
||||
(rf/reg-event-fx :trading.swap/blur-input
|
||||
(fn [{:keys [db]}]
|
||||
{:db (update-in db swap-db-path assoc :focused? false)}))
|
||||
|
||||
(rf/reg-event-fx :trading.swap/set-pay-amount
|
||||
(fn [{:keys [db]} [amount]]
|
||||
{:db (update-in db swap-db-path assoc :pay-amount amount)}))
|
||||
|
||||
(rf/reg-event-fx :trading.swap/set-pay-token
|
||||
(fn [{:keys [db]} [token-symbol]]
|
||||
{:db (update-in db swap-db-path assoc :pay-token-symbol token-symbol)}))
|
||||
|
||||
(rf/reg-event-fx :trading.swap/set-receive-token
|
||||
(fn [{:keys [db]} [token-symbol]]
|
||||
{:db (update-in db swap-db-path assoc :receive-token-symbol token-symbol)}))
|
||||
|
||||
(rf/reg-event-fx :trading.swap/set-account-address
|
||||
(fn [{:keys [db]} [address]]
|
||||
{:db (update-in db swap-db-path assoc :account-address address)}))
|
||||
|
||||
(rf/reg-event-fx :trading.swap/set-chain-id
|
||||
(fn [{:keys [db]} [chain-id]]
|
||||
{:db (update-in db swap-db-path assoc :chain-id chain-id)}))
|
||||
|
||||
(rf/reg-event-fx :trading.swap/set-max-slippage
|
||||
(fn [{:keys [db]} [max-slippage]]
|
||||
{:db (update-in db swap-db-path assoc :max-slippage (number/parse-float max-slippage))}))
|
||||
|
||||
;; == routes ==
|
||||
|
||||
(rf/reg-event-fx :trading.swap/get-suggested-routes
|
||||
(fn [{:keys [db]} [pay-amount]]
|
||||
(let [{:keys [account-address pay-token-symbol
|
||||
receive-token-symbol chain-id]} (get-in db swap-db-path)
|
||||
disabled-chain-ids (utils/router-disabled-chain-ids db chain-id)
|
||||
amount-in-hex (->> (utils/token-from-symbol db pay-token-symbol)
|
||||
:decimals
|
||||
(money/unit->token pay-amount)
|
||||
money/to-hex)
|
||||
request-uuid (str (random-uuid))
|
||||
route-input-params {:uuid request-uuid
|
||||
:sendType constants/send-type-swap
|
||||
:gasFeeMode constants/gas-rate-medium
|
||||
:addrFrom account-address
|
||||
:addrTo account-address
|
||||
:tokenID pay-token-symbol
|
||||
:toTokenID receive-token-symbol
|
||||
:disabledFromChainIDs disabled-chain-ids
|
||||
:disabledToChainIDs disabled-chain-ids
|
||||
:amountIn (or amount-in-hex "0x0")
|
||||
:amountOut "0x0"
|
||||
:fromLockedAmount {}}]
|
||||
(when (and (seq pay-amount) (not (zero? pay-amount)))
|
||||
(log/info "Requesting Swap route for" pay-amount pay-token-symbol "id: " request-uuid)
|
||||
{:db (update-in db
|
||||
swap-db-path
|
||||
(fn [swap]
|
||||
(-> swap
|
||||
(assoc
|
||||
:requested-route-uuid
|
||||
request-uuid))))
|
||||
:fx [[:dispatch
|
||||
[:wallet.routes/get-routes
|
||||
{:params route-input-params
|
||||
:on-error (fn [error]
|
||||
(rf/dispatch [:trading.swap/suggested-routes-error error]))}]]
|
||||
[:dispatch
|
||||
[:centralized-metrics/track :metric/swap-proposal-start
|
||||
{:network chain-id
|
||||
:pay_token pay-token-symbol
|
||||
:receive_token receive-token-symbol}]]]}))))
|
||||
|
||||
(rf/reg-event-fx :trading.swap/stop-get-routes
|
||||
(fn [{:keys [db]}]
|
||||
{:db (update-in db swap-db-path dissoc :requested-route-uuid)
|
||||
:fx [[:dispatch [:wallet.routes/stop-get-routes]]]}))
|
||||
|
||||
(rf/reg-event-fx :trading.swap/suggested-routes-error
|
||||
(fn [{:keys [db]} [error]]
|
||||
(let [{:keys [requested-route-uuid]} (get-in db swap-db-path)]
|
||||
(log/error "failed to get suggested routes (async)"
|
||||
{:event :trading.swap/get-suggested-routes
|
||||
:error (:message error)
|
||||
:params requested-route-uuid})
|
||||
{:fx [[:dispatch
|
||||
[:centralized-metrics/track :metric/swap-proposal-failed {:error (:code error)}]]]})))
|
||||
|
||||
(rf/reg-event-fx :trading.swap/reset-route
|
||||
(fn [{:keys [db]}]
|
||||
{:db (update-in db swap-db-path dissoc :requested-route-uuid)}))
|
||||
|
||||
(rf/reg-event-fx :trading.swap/flip-tokens
|
||||
(fn [{:keys [db]}]
|
||||
(let [{:keys [network pay-token-symbol
|
||||
receive-token-symbol]} (get-in db swap-db-path)]
|
||||
{:db (update-in db
|
||||
swap-db-path
|
||||
(fn [swap-data]
|
||||
(-> swap-data
|
||||
(assoc
|
||||
:pay-token-symbol receive-token-symbol
|
||||
:receive-token-symbol pay-token-symbol))))
|
||||
:fx [[:dispatch [:trading.swap/reset-route]]
|
||||
[:dispatch
|
||||
[:centralized-metrics/track :metric/swap-asset-to-pay-changed
|
||||
{:network (:chain-id network)
|
||||
:previous_token pay-token-symbol
|
||||
:new_token receive-token-symbol}]]
|
||||
[:dispatch
|
||||
[:centralized-metrics/track :metric/swap-asset-to-receive-changed
|
||||
{:network (:chain-id network)
|
||||
:previous_token receive-token-symbol
|
||||
:new_token pay-token-symbol}]]]})))
|
||||
|
||||
(rf/reg-event-fx :trading.swap/approve-confirmation
|
||||
(fn [{:keys [db]}]
|
||||
(let [{:keys [requested-route-uuid max-slippage]} (get-in db swap-db-path)]
|
||||
{:fx [[:dispatch
|
||||
[:wallet.routes/build-transactions
|
||||
{:request-uuid requested-route-uuid
|
||||
:slippage max-slippage}]]]})))
|
||||
|
||||
(rf/reg-event-fx :trading.swap/on-approval-sent
|
||||
(fn [{:keys [db]} [approval-transaction]]
|
||||
(let [approval-hash (:hash approval-transaction)
|
||||
{:keys [account-address chain-id pay-token-symbol pay-amount]} (get-in db swap-db-path)]
|
||||
(log/info "Swap approval sent" approval-hash)
|
||||
{:db (update-in db
|
||||
(conj swap-db-path :approvals)
|
||||
(fnil into [])
|
||||
[{:transaction-hash approval-hash
|
||||
:account-address account-address
|
||||
:chain-id chain-id
|
||||
:pay-amount pay-amount
|
||||
:pay-token-symbol pay-token-symbol}])})))
|
||||
|
||||
(rf/reg-event-fx :trading.swap/on-approval-finished
|
||||
(fn [{:keys [db]} [approval-status]]
|
||||
(let [{:keys [chain-id
|
||||
pay-token-symbol pay-amount
|
||||
account-address]} (get-in db swap-db-path)
|
||||
route (get-in db [:wallet :route])
|
||||
provider-name (-> route :best-route routes/processor-name)
|
||||
account-name (get-in db [:wallet :accounts account-address :name])
|
||||
toast-label-args {:token-amount pay-amount
|
||||
:token-symbol pay-token-symbol
|
||||
:provider-name provider-name
|
||||
:account-name account-name}]
|
||||
(log/info "Swap approval confirmed for" pay-amount pay-token-symbol)
|
||||
{:fx [(if (= :confirmed approval-status)
|
||||
[:dispatch
|
||||
[:toasts/upsert
|
||||
{:type :positive
|
||||
:text (i18n/label :t/spending-cap-set toast-label-args)}]]
|
||||
[:dispatch
|
||||
[:toasts/upsert
|
||||
{:type :negative
|
||||
:text (i18n/label :t/spending-cap-failed toast-label-args)}]])
|
||||
[:dispatch
|
||||
[:centralized-metrics/track :metric/swap-approval-execution-finished
|
||||
{:network chain-id
|
||||
:pay_token pay-token-symbol
|
||||
:succeeded (= approval-status :confirmed)}]]]})))
|
||||
|
||||
(rf/reg-event-fx :trading.swap/swap-confirmation
|
||||
(fn [{:keys [db]}]
|
||||
(let [{:keys [requested-route-uuid max-slippage]} (get-in db swap-db-path)]
|
||||
{:fx [[:dispatch
|
||||
[:wallet.routes/build-transactions
|
||||
{:request-uuid requested-route-uuid
|
||||
:slippage max-slippage}]]]})))
|
||||
|
||||
(rf/reg-event-fx :trading.swap/on-swap-sent
|
||||
(fn [{:keys [db]} [error]]
|
||||
(let [{:keys [account-address pay-amount
|
||||
pay-token-symbol receive-token-symbol
|
||||
route]} (get-in db swap-db-path)
|
||||
{:keys [decimals whole]} (routes/amount-out route)
|
||||
receive-amount (common.utils/sanitized-token-amount-to-display
|
||||
whole
|
||||
(min decimals
|
||||
constants/min-token-decimals-to-display))]
|
||||
{:fx [[:dispatch [:trading.swap/reset-swap]]
|
||||
[:dispatch-later
|
||||
{:ms 500
|
||||
:dispatch (if error
|
||||
[:toast/upsert
|
||||
{:id :swap-transaction-error
|
||||
:type :negative
|
||||
:text :t/swap-failed}]
|
||||
[:toasts/upsert
|
||||
{:id :swap-transaction-pending
|
||||
:icon :i/info
|
||||
:type :neutral
|
||||
:text (i18n/label :t/swapping-to
|
||||
{:pay-amount pay-amount
|
||||
:pay-token-symbol pay-token-symbol
|
||||
:receive-token-symbol receive-token-symbol
|
||||
:receive-amount receive-amount})}])}]
|
||||
[:dispatch [:shell/change-tab :wallet-stack]]
|
||||
[:dispatch [:wallet/navigate-to-account-within-stack account-address]]
|
||||
[:dispatch [:wallet/select-account-tab :activity]]]})))
|
||||
@@ -1,95 +0,0 @@
|
||||
(ns status-im.contexts.wallet.trading.swap.hooks
|
||||
(:require [react-native.core :as rn]
|
||||
[status-im.common.controlled-input.utils :as controlled-input]
|
||||
[status-im.contexts.wallet.trading.swap.constants :as swap-constants]
|
||||
[status-im.contexts.wallet.trading.swap.utils :as utils]
|
||||
[utils.debounce :as debounce]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn use-init-swap-trading
|
||||
[]
|
||||
(let [view-id (rf/sub [:view-id])
|
||||
swap-initialized? (rf/sub [:trading.swap/initialized?])
|
||||
wallet-loaded? (rf/sub [:wallet/home-tokens-loaded?])]
|
||||
(rn/use-effect (fn []
|
||||
(when (and wallet-loaded?
|
||||
(not swap-initialized?)
|
||||
(= view-id :trading-stack))
|
||||
(rf/dispatch [:trading.swap/init])))
|
||||
[view-id wallet-loaded? swap-initialized?])))
|
||||
|
||||
(defn use-input-validation
|
||||
[pay-amount]
|
||||
(let [pay-token-balance (rf/sub [:trading.swap/pay-token-balance])]
|
||||
{:input-error? (utils/pay-input-error? pay-amount pay-token-balance)
|
||||
:valid-input? (utils/pay-input-valid? pay-amount pay-token-balance)}))
|
||||
|
||||
(defn use-swap-input
|
||||
[default-state]
|
||||
(let [[input-state set-input-state] (rn/use-state (controlled-input/init-value default-state))
|
||||
add-input-char (rn/use-callback (fn [character]
|
||||
(set-input-state
|
||||
#(controlled-input/add-character %
|
||||
character
|
||||
##Inf)))
|
||||
[set-input-state])
|
||||
delete-last-input-char (rn/use-callback (fn []
|
||||
(set-input-state
|
||||
controlled-input/delete-last))
|
||||
[set-input-state])
|
||||
set-input-value (rn/use-callback (fn [value]
|
||||
(set-input-state
|
||||
(fn [input-state]
|
||||
(controlled-input/set-input-value
|
||||
input-state
|
||||
value))))
|
||||
[set-input-state])
|
||||
|
||||
clear-input-value (rn/use-callback (fn []
|
||||
(set-input-state controlled-input/delete-all))
|
||||
[set-input-state])]
|
||||
{:value (controlled-input/input-value input-state)
|
||||
:add-input-char add-input-char
|
||||
:delete-last-input-char delete-last-input-char
|
||||
:set-input-value set-input-value
|
||||
:clear-input-value clear-input-value}))
|
||||
|
||||
(defn- use-ref-value
|
||||
[value]
|
||||
(let [value-ref (rn/use-ref-atom value)]
|
||||
(rn/use-effect
|
||||
(fn [] (reset! value-ref value))
|
||||
[value])
|
||||
|
||||
value-ref))
|
||||
|
||||
(defn use-suggested-routes
|
||||
[input-amount]
|
||||
(let [pay-token-symbol (rf/sub [:trading.swap/pay-token-symbol])
|
||||
receive-token-symbol (rf/sub [:trading.swap/receive-token-symbol])
|
||||
account-address (rf/sub [:trading.swap/account-address])
|
||||
chain-id (rf/sub [:trading.swap/chain-id])
|
||||
{:keys [valid-input?]} (use-input-validation input-amount)
|
||||
valid-input-ref? (use-ref-value valid-input?)]
|
||||
|
||||
(rn/use-effect (fn []
|
||||
(when-not valid-input?
|
||||
(debounce/debounce-and-dispatch [:trading.swap/stop-get-routes]
|
||||
swap-constants/get-suggested-routes-debounce-ms)))
|
||||
[valid-input?])
|
||||
|
||||
;; TODO: add canceling route request
|
||||
(rn/use-effect (fn []
|
||||
(when @valid-input-ref?
|
||||
(debounce/debounce-and-dispatch [:trading.swap/get-suggested-routes input-amount]
|
||||
swap-constants/get-suggested-routes-debounce-ms)))
|
||||
[input-amount pay-token-symbol receive-token-symbol account-address chain-id])))
|
||||
|
||||
(defn use-approval-finished
|
||||
[cb]
|
||||
(let [last-approval-status (rf/sub [:trading.swap/last-approval-status])]
|
||||
(rn/use-effect
|
||||
(fn []
|
||||
(when (#{:confirmed :failed} last-approval-status)
|
||||
(cb)))
|
||||
[last-approval-status])))
|
||||
@@ -1,51 +0,0 @@
|
||||
(ns status-im.contexts.wallet.trading.swap.routes
|
||||
(:require [utils.money :as money]
|
||||
[utils.number :as number]))
|
||||
|
||||
(defn approval-data
|
||||
[route]
|
||||
(let [to-bn (fn [k] (-> route k money/from-hex))]
|
||||
{:required? (:ApprovalRequired route)
|
||||
:nonce (:ApprovalTxNonce route)
|
||||
:contract-address (:ApprovalContractAddress route)
|
||||
:estimated-time (to-bn :ApprovalEstimatedTime)
|
||||
:amount-required (to-bn :ApprovalAmountRequired)}))
|
||||
|
||||
(defn amount-out
|
||||
[route]
|
||||
(let [bn-amount (-> route :AmountOut money/from-hex)
|
||||
token-decimals (-> route :ToToken :decimals)]
|
||||
{:decimals token-decimals
|
||||
:bn bn-amount
|
||||
:whole (number/convert-to-whole-number bn-amount token-decimals)}))
|
||||
|
||||
(defn amount-in
|
||||
[route]
|
||||
(let [bn-amount (-> route :AmountIn money/from-hex)
|
||||
token-decimals (-> route :FromToken money/bignumber)]
|
||||
{:decimals token-decimals
|
||||
:bn bn-amount
|
||||
:whole (number/convert-to-whole-number bn-amount token-decimals)}))
|
||||
|
||||
(defn fees
|
||||
[route]
|
||||
(let [to-bn (fn [k] (-> route k money/from-hex))]
|
||||
{:tx-total-fee (to-bn :TxTotalFee)
|
||||
:approval-fee (to-bn :ApprovalFee)}))
|
||||
|
||||
(defn estimated-time
|
||||
[route]
|
||||
(:TxEstimatedTime route))
|
||||
|
||||
(defn processor-name
|
||||
[route]
|
||||
(get route :ProcessorName))
|
||||
|
||||
(defn find-pending-approval-transaction
|
||||
[transactions]
|
||||
(println transactions)
|
||||
(->> (vals transactions)
|
||||
(some (fn [{:keys [status transaction]}]
|
||||
(when (and (:approvalTx transaction)
|
||||
(= :pending status))
|
||||
transaction)))))
|
||||
@@ -1,52 +0,0 @@
|
||||
(ns status-im.contexts.wallet.trading.swap.style
|
||||
(:require [quo.foundations.colors :as colors]
|
||||
[react-native.safe-area :as safe-area]))
|
||||
|
||||
(defn home-container
|
||||
[]
|
||||
{:margin-top 8
|
||||
:flex 1})
|
||||
|
||||
(defn top-nav-container
|
||||
[]
|
||||
{:margin-top (+ (safe-area/get-top) 0)})
|
||||
|
||||
(defn header-container
|
||||
[theme]
|
||||
{:background-color (colors/theme-colors colors/white colors/neutral-95 theme)})
|
||||
|
||||
(def keyboard-container
|
||||
{:align-self :flex-end
|
||||
:width "100%"})
|
||||
|
||||
(def inputs-container
|
||||
{:padding-top 12
|
||||
:padding-horizontal 20})
|
||||
|
||||
(defn receive-token-swap-input-container
|
||||
[approval-required?]
|
||||
{:margin-top (if approval-required? 3 -9)})
|
||||
|
||||
(defn swap-order-button
|
||||
[approval-required?]
|
||||
{:margin-top (if approval-required? 3 -9)
|
||||
:z-index 2
|
||||
:align-self :center})
|
||||
|
||||
(def alert-banner
|
||||
{:height :auto
|
||||
:min-height 40
|
||||
:max-height 62})
|
||||
|
||||
(def footer-container
|
||||
{:flex 1
|
||||
:justify-content :flex-end})
|
||||
|
||||
(def info-bar
|
||||
{:padding-top 12
|
||||
:padding-horizontal 20})
|
||||
|
||||
(def detail-item
|
||||
{:flex 1
|
||||
:height 36
|
||||
:background-color :transparent})
|
||||
@@ -1,36 +0,0 @@
|
||||
(ns status-im.contexts.wallet.trading.swap.swap-confirmation.style
|
||||
(:require [quo.foundations.colors :as colors]))
|
||||
|
||||
|
||||
(def detail-item
|
||||
{:flex 1
|
||||
:height 36
|
||||
:background-color :transparent})
|
||||
|
||||
(def content-container
|
||||
{:padding-top 12
|
||||
:padding-horizontal 20
|
||||
:padding-bottom 32})
|
||||
|
||||
(def title-container
|
||||
{:margin-right 4})
|
||||
|
||||
(def title-line-with-margin-top
|
||||
{:flex-direction :row
|
||||
:margin-top 4})
|
||||
|
||||
(def details-container
|
||||
{:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:height 52
|
||||
:padding-top 7
|
||||
:margin-bottom 8})
|
||||
|
||||
(def summary-section-container
|
||||
{:padding-horizontal 20
|
||||
:padding-bottom 16})
|
||||
|
||||
(defn section-label
|
||||
[theme]
|
||||
{:margin-bottom 8
|
||||
:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)})
|
||||
@@ -1,158 +0,0 @@
|
||||
(ns status-im.contexts.wallet.trading.swap.swap-confirmation.view
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[status-im.common.standard-authentication.core :as standard-auth]
|
||||
[status-im.contexts.wallet.swap.swap-confirmation.style :as style]
|
||||
[status-im.contexts.wallet.trading.swap.components.info-bar.view :as info-bar]
|
||||
[status-im.contexts.wallet.trading.swap.components.transaction.container :as transaction.container]
|
||||
[status-im.contexts.wallet.trading.swap.components.transaction.provider-footer :as
|
||||
transaction.provider-footer]
|
||||
[status-im.contexts.wallet.trading.swap.components.transaction.title :as transaction.title]
|
||||
[utils.address :as address-utils]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- on-confirm
|
||||
[password]
|
||||
(rf/dispatch [:dismiss-modal :screen/trading.swap-confirmation])
|
||||
(rf/dispatch [:wallet.routes/sign-transactions password]))
|
||||
|
||||
(defn- swap-title
|
||||
[]
|
||||
(let [pay-token-symbol (rf/sub [:trading.swap/pay-token-symbol])
|
||||
receive-token-symbol (rf/sub [:trading.swap/receive-token-symbol])
|
||||
pay-amount (rf/sub [:trading.swap/pay-amount])
|
||||
receive-amount (rf/sub [:trading.swap/formatted-receive-amount])
|
||||
account (rf/sub [:trading.swap/account])]
|
||||
[transaction.title/container
|
||||
[transaction.title/row {:first? true}
|
||||
[transaction.title/text
|
||||
{:label (i18n/label :t/swap)
|
||||
:accessibility-label :title-label}]
|
||||
[quo/summary-tag
|
||||
{:token pay-token-symbol
|
||||
:label (str pay-amount " " pay-token-symbol)
|
||||
:type :token}]]
|
||||
[transaction.title/row
|
||||
[transaction.title/text
|
||||
{:label (i18n/label :t/to)
|
||||
:accessibility-label :title-label}]
|
||||
[quo/summary-tag
|
||||
{:token receive-token-symbol
|
||||
:label (str receive-amount " " receive-token-symbol)
|
||||
:type :token}]]
|
||||
[transaction.title/row
|
||||
[transaction.title/text
|
||||
{:label (i18n/label :t/in)
|
||||
:accessibility-label :send-label}]
|
||||
[quo/summary-tag
|
||||
{:label (:name account)
|
||||
:type :account
|
||||
:emoji (:emoji account)
|
||||
:customization-color (:color account)}]]]))
|
||||
|
||||
(defn- summary-container
|
||||
[{:keys [title accessibility-label]} & children]
|
||||
(let [theme (quo.theme/use-theme)]
|
||||
(into [rn/view {:style style/summary-section-container}
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:style (style/section-label theme)
|
||||
:accessibility-label accessibility-label}
|
||||
title]]
|
||||
children)))
|
||||
|
||||
(defn- format-token-address
|
||||
[address]
|
||||
(when-not (address-utils/zero-address? address)
|
||||
(address-utils/get-shortened-compressed-key address)))
|
||||
|
||||
(defn- pay-section
|
||||
[]
|
||||
(let [pay-token (rf/sub [:trading.swap/pay-token])
|
||||
pay-amount (rf/sub [:trading.swap/pay-amount])
|
||||
pay-token-symbol (:symbol pay-token)
|
||||
pay-token-address (:address pay-token)]
|
||||
[summary-container
|
||||
{:title (i18n/label :t/pay)
|
||||
:accessibility-label :summary-section-pay}
|
||||
[quo/summary-info
|
||||
{:type :token
|
||||
:token-props {:token pay-token-symbol
|
||||
:label (str pay-amount " " pay-token-symbol)
|
||||
:address (format-token-address pay-token-address)
|
||||
:size 32}}]]))
|
||||
|
||||
(defn- receive-section
|
||||
[]
|
||||
(let [receive-token (rf/sub [:trading.swap/receive-token])
|
||||
receive-amount (rf/sub [:trading.swap/receive-amount])
|
||||
receive-token-symbol (:symbol receive-token)
|
||||
receive-token-address (:address receive-token)]
|
||||
[summary-container
|
||||
{:title (i18n/label :t/receive)
|
||||
:accessibility-label :summary-section-receive}
|
||||
[quo/summary-info
|
||||
{:type :token
|
||||
:token-props {:token receive-token-symbol
|
||||
:label (str receive-amount " " receive-token-symbol)
|
||||
:address (format-token-address receive-token-address)
|
||||
:size 32}}]]))
|
||||
|
||||
(defn- network-section
|
||||
[]
|
||||
(let [{:keys [full-name source]} (rf/sub [:trading.swap/network])]
|
||||
[summary-container
|
||||
{:title (i18n/label :t/on)
|
||||
:accessibility-label :summary-section-network}
|
||||
[quo/summary-info
|
||||
{:type :network
|
||||
:network-props {:label full-name
|
||||
:source source
|
||||
:size 32}}]]))
|
||||
|
||||
(defn- transaction-details
|
||||
[]
|
||||
(let [max-fees (rf/sub [:trading.swap/total-fee-fiat])
|
||||
estimated-time (rf/sub [:trading.swap/estimated-time])
|
||||
max-slippage (rf/sub [:trading.swap/max-slippage])]
|
||||
[info-bar/container {:style {:padding-top 7 :margin-bottom 8}}
|
||||
[info-bar/estimated-time {:estimated-time-mins estimated-time}]
|
||||
[info-bar/fiat-max-fee {:fee-amount max-fees}]
|
||||
[info-bar/max-slippage {:slippage max-slippage}]]))
|
||||
|
||||
(defn- slide-button
|
||||
[]
|
||||
(let [transaction-for-signing (rf/sub [:wallet.routes/transactions-for-signing])
|
||||
route (rf/sub [:trading.swap/route])
|
||||
customization-color (rf/sub [:trading.swap/customization-color])
|
||||
sign-on-keycard? (get-in transaction-for-signing
|
||||
[:signingDetails :signOnKeycard])]
|
||||
[standard-auth/slide-button
|
||||
{:size :size-48
|
||||
:track-text (i18n/label :t/slide-to-swap)
|
||||
:container-style {:z-index 2}
|
||||
:customization-color customization-color
|
||||
:disabled? (or (not route)
|
||||
(not transaction-for-signing))
|
||||
:auth-button-label (i18n/label :t/confirm)
|
||||
:on-complete (when sign-on-keycard? #(on-confirm ""))
|
||||
:on-auth-success on-confirm}]))
|
||||
|
||||
(defn footer
|
||||
[]
|
||||
[:<>
|
||||
[transaction-details]
|
||||
[slide-button]
|
||||
[transaction.provider-footer/view]])
|
||||
|
||||
(defn view
|
||||
[]
|
||||
[transaction.container/view {:footer footer}
|
||||
[swap-title]
|
||||
[pay-section]
|
||||
[receive-section]
|
||||
[network-section]])
|
||||
@@ -1,63 +0,0 @@
|
||||
(ns status-im.contexts.wallet.trading.swap.utils
|
||||
(:require [clojure.string :as string]
|
||||
[utils.money :as money]))
|
||||
|
||||
(defn default-account
|
||||
[db]
|
||||
(let [accounts (-> db :wallet :accounts vals)]
|
||||
(->> accounts
|
||||
(filter :operable?)
|
||||
first)))
|
||||
|
||||
(defn- testnet?
|
||||
[db]
|
||||
(-> db :profile/profile :test-networks-enabled?))
|
||||
|
||||
(defn token-from-symbol
|
||||
([db token-symbol]
|
||||
(token-from-symbol db token-symbol 1))
|
||||
([db token-symbol chain-id]
|
||||
(get-in db
|
||||
[:wallet :tokens :normalized-tokens
|
||||
token-symbol chain-id])))
|
||||
|
||||
(defn router-disabled-chain-ids
|
||||
[db chain-id]
|
||||
(let [testnet-key (if (testnet? db) :test :prod)]
|
||||
(->> (get-in db [:wallet :networks testnet-key])
|
||||
(map :chain-id)
|
||||
(filter #(not= % chain-id)))))
|
||||
|
||||
(defn input-empty?
|
||||
[amount]
|
||||
(string/blank? amount))
|
||||
|
||||
(defn pay-input-error?
|
||||
[pay-amount pay-balance]
|
||||
(and (not (input-empty? pay-amount))
|
||||
(money/greater-than
|
||||
(money/bignumber pay-amount)
|
||||
(money/bignumber pay-balance))))
|
||||
|
||||
(defn pay-input-valid?
|
||||
[pay-amount pay-balance]
|
||||
(and (not (input-empty? pay-amount))
|
||||
(money/greater-than (money/bignumber pay-amount)
|
||||
(money/bignumber 0))
|
||||
(not (pay-input-error? pay-amount pay-balance))))
|
||||
|
||||
(defn approval-for-inputs
|
||||
"Finds the relevant approval based on the current inputs"
|
||||
[approvals {:keys [account-address chain-id pay-token-symbol pay-amount]}]
|
||||
(some (fn [approval]
|
||||
(let [same-address? (= account-address (:account-address approval))
|
||||
same-chain? (= chain-id (:chain-id approval))
|
||||
same-pay-token? (= pay-token-symbol (:pay-token-symbol approval))
|
||||
equal-to-approved-amount? (money/equal-to pay-amount (:pay-amount approval))
|
||||
less-than-approved-amount? (money/less-than pay-amount (:pay-amount approval))]
|
||||
(when (and same-address?
|
||||
same-chain?
|
||||
same-pay-token?
|
||||
(or equal-to-approved-amount? less-than-approved-amount?))
|
||||
approval)))
|
||||
approvals))
|
||||
@@ -1,87 +0,0 @@
|
||||
(ns status-im.contexts.wallet.trading.swap.view
|
||||
(:require
|
||||
[oops.core :as oops]
|
||||
[react-native.core :as rn]
|
||||
[status-im.contexts.wallet.routes.hooks :as routes.hooks]
|
||||
[status-im.contexts.wallet.trading.swap.components.exchange-rate.view :as exchange-rate]
|
||||
[status-im.contexts.wallet.trading.swap.components.flip-tokens :as flip-tokens]
|
||||
[status-im.contexts.wallet.trading.swap.components.header-nav :as header-nav]
|
||||
[status-im.contexts.wallet.trading.swap.components.keyboard :as swap-keyboard]
|
||||
[status-im.contexts.wallet.trading.swap.components.pay-input :as pay-input]
|
||||
[status-im.contexts.wallet.trading.swap.components.receive-input :as receive-input]
|
||||
status-im.contexts.wallet.trading.swap.events
|
||||
[status-im.contexts.wallet.trading.swap.hooks :as hooks]
|
||||
[status-im.contexts.wallet.trading.swap.routes :as routes]
|
||||
[status-im.contexts.wallet.trading.swap.style :as style]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- blur-input
|
||||
[input-ref]
|
||||
(some-> @input-ref
|
||||
(oops/ocall "blur")))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [db-pay-amount (rf/sub [:trading.swap/pay-amount])
|
||||
{:keys [clear-input-value] :as pay-input} (hooks/use-swap-input db-pay-amount)
|
||||
input-ref (rn/use-ref-atom nil)
|
||||
pay-amount (:value pay-input)
|
||||
pay-token (rf/sub [:trading.swap/pay-token])
|
||||
pay-input-focused? (rf/sub [:trading.swap/focused?])
|
||||
last-approval-status (rf/sub [:trading.swap/last-approval-status])
|
||||
on-pay-input-focus (rn/use-callback
|
||||
(fn []
|
||||
(rf/dispatch [:trading.swap/focus-input]))
|
||||
[pay-input pay-token])]
|
||||
(hooks/use-init-swap-trading)
|
||||
(hooks/use-suggested-routes pay-amount)
|
||||
|
||||
(rn/use-effect
|
||||
(fn []
|
||||
(if pay-input-focused?
|
||||
(rf/dispatch [:shell/hide-tabs])
|
||||
(rf/dispatch [:shell/show-tabs]))
|
||||
(when-not pay-input-focused?
|
||||
(clear-input-value)
|
||||
(blur-input input-ref)))
|
||||
[pay-input-focused?])
|
||||
|
||||
(routes.hooks/use-transactions-sent
|
||||
(fn [transactions]
|
||||
(let [approval (routes/find-pending-approval-transaction transactions)]
|
||||
(if approval
|
||||
(rf/dispatch [:trading.swap/on-approval-sent approval])
|
||||
(do (clear-input-value)
|
||||
(rf/dispatch [:trading.swap/on-swap-sent]))))))
|
||||
|
||||
(hooks/use-approval-finished
|
||||
(fn []
|
||||
(rf/dispatch [:trading.swap/on-approval-finished last-approval-status])))
|
||||
|
||||
(rn/use-effect
|
||||
(fn []
|
||||
(rf/dispatch [:trading.swap/set-pay-amount pay-amount]))
|
||||
[pay-amount])
|
||||
|
||||
(println :focused? pay-input-focused?)
|
||||
[rn/view {:style (style/home-container)}
|
||||
[header-nav/view]
|
||||
[rn/scroll-view
|
||||
{:style style/inputs-container}
|
||||
[pay-input/view
|
||||
{:input-ref input-ref
|
||||
:pay-input pay-input
|
||||
:pay-input-focused? pay-input-focused?
|
||||
:on-pay-input-focus on-pay-input-focus}]
|
||||
[flip-tokens/view
|
||||
{:pay-input pay-input}]
|
||||
[receive-input/view
|
||||
{:pay-input pay-input}]
|
||||
[exchange-rate/view]]
|
||||
#_[rn/view {:style style/footer-container}
|
||||
(when-not pay-input-focused?
|
||||
[footer/view])]
|
||||
(when pay-input-focused?
|
||||
[swap-keyboard/keyboard-view
|
||||
{:input pay-input
|
||||
:input-token-decimals (:decimals pay-token)}])]))
|
||||
@@ -9,7 +9,6 @@
|
||||
(def app-db
|
||||
{:activity-center {:filter {:status (:filter-status activity-center/defaults)
|
||||
:type (:filter-type activity-center/defaults)}}
|
||||
:shell/bottom-tabs-visible? true
|
||||
:contacts/contacts {}
|
||||
:pairing/installations {}
|
||||
:group/selected-contacts #{}
|
||||
|
||||
@@ -51,7 +51,6 @@
|
||||
status-im.contexts.wallet.common.wizard.events
|
||||
status-im.contexts.wallet.effects
|
||||
status-im.contexts.wallet.events
|
||||
status-im.contexts.wallet.routes.events
|
||||
status-im.contexts.wallet.send.events
|
||||
status-im.contexts.wallet.signals
|
||||
status-im.contexts.wallet.swap.events
|
||||
|
||||
@@ -10,31 +10,29 @@
|
||||
(= "1" (config/get-config k)))
|
||||
|
||||
(def ^:private initial-flags
|
||||
{::community.edit-account-selection (enabled-in-env? :FLAG_EDIT_ACCOUNT_SELECTION_ENABLED)
|
||||
::community.view-token-requirements (enabled-in-env? :FLAG_VIEW_TOKEN_REQUIREMENTS)
|
||||
::app-monitoring.intentional-crash (enabled-in-env? :FLAG_INTENTIONAL_CRASH_ENABLED)
|
||||
{::community.edit-account-selection (enabled-in-env? :FLAG_EDIT_ACCOUNT_SELECTION_ENABLED)
|
||||
::community.view-token-requirements (enabled-in-env? :FLAG_VIEW_TOKEN_REQUIREMENTS)
|
||||
::app-monitoring.intentional-crash (enabled-in-env? :FLAG_INTENTIONAL_CRASH_ENABLED)
|
||||
|
||||
;; Feature toggled (off by default) because the desktop app disabled this
|
||||
;; feature and we want both clients in sync. We keep the code because it
|
||||
;; works and we may re-enable it by default.
|
||||
::profile-pictures-visibility (enabled-in-env? :FLAG_PROFILE_PICTURES_VISIBILITY_ENABLED)
|
||||
::settings.import-all-keypairs (enabled-in-env? :FLAG_WALLET_SETTINGS_IMPORT_ALL_KEYPAIRS)
|
||||
::wallet.add-watched-address (enabled-in-env? :FLAG_ADD_WATCHED_ADDRESS)
|
||||
::wallet.advanced-sending (enabled-in-env? :FLAG_ADVANCED_SENDING)
|
||||
::wallet.assets-modal-hide (enabled-in-env? :FLAG_ASSETS_MODAL_HIDE)
|
||||
::wallet.assets-modal-manage-tokens (enabled-in-env? :FLAG_ASSETS_MODAL_MANAGE_TOKENS)
|
||||
::wallet.bridge-token (enabled-in-env? :FLAG_BRIDGE_TOKEN_ENABLED)
|
||||
::wallet.contacts (enabled-in-env? :FLAG_CONTACTS_ENABLED)
|
||||
::wallet.edit-derivation-path (enabled-in-env? :FLAG_EDIT_DERIVATION_PATH)
|
||||
::wallet.graph (enabled-in-env? :FLAG_GRAPH_ENABLED)
|
||||
::wallet.import-private-key (enabled-in-env? :FLAG_IMPORT_PRIVATE_KEY_ENABLED)
|
||||
::wallet.long-press-watch-only-asset (enabled-in-env? :FLAG_LONG_PRESS_WATCH_ONLY_ASSET_ENABLED)
|
||||
::wallet.saved-addresses (enabled-in-env? :WALLET_SAVED_ADDRESSES)
|
||||
::wallet.wallet-connect (enabled-in-env? :FLAG_WALLET_CONNECT_ENABLED)
|
||||
::wallet.custom-network-amounts (enabled-in-env? :FLAG_WALLET_CUSTOM_NETWORK_AMOUNTS_ENABLED)
|
||||
::wallet.transaction-params (enabled-in-env? :FLAG_WALLET_TRANSACTION_PARAMS_ENABLED)
|
||||
::wallet.trading-tab (enabled-in-env? :FLAG_WALLET_TRADING_TAB)
|
||||
::wallet.swap-redirect-to-trading-tab (enabled-in-env? :FLAG_WALLET_SWAP_REDIRECT_TO_TRADING_TAB)})
|
||||
::profile-pictures-visibility (enabled-in-env? :FLAG_PROFILE_PICTURES_VISIBILITY_ENABLED)
|
||||
::settings.import-all-keypairs (enabled-in-env? :FLAG_WALLET_SETTINGS_IMPORT_ALL_KEYPAIRS)
|
||||
::wallet.add-watched-address (enabled-in-env? :FLAG_ADD_WATCHED_ADDRESS)
|
||||
::wallet.advanced-sending (enabled-in-env? :FLAG_ADVANCED_SENDING)
|
||||
::wallet.assets-modal-hide (enabled-in-env? :FLAG_ASSETS_MODAL_HIDE)
|
||||
::wallet.assets-modal-manage-tokens (enabled-in-env? :FLAG_ASSETS_MODAL_MANAGE_TOKENS)
|
||||
::wallet.bridge-token (enabled-in-env? :FLAG_BRIDGE_TOKEN_ENABLED)
|
||||
::wallet.contacts (enabled-in-env? :FLAG_CONTACTS_ENABLED)
|
||||
::wallet.edit-derivation-path (enabled-in-env? :FLAG_EDIT_DERIVATION_PATH)
|
||||
::wallet.graph (enabled-in-env? :FLAG_GRAPH_ENABLED)
|
||||
::wallet.import-private-key (enabled-in-env? :FLAG_IMPORT_PRIVATE_KEY_ENABLED)
|
||||
::wallet.long-press-watch-only-asset (enabled-in-env? :FLAG_LONG_PRESS_WATCH_ONLY_ASSET_ENABLED)
|
||||
::wallet.saved-addresses (enabled-in-env? :WALLET_SAVED_ADDRESSES)
|
||||
::wallet.wallet-connect (enabled-in-env? :FLAG_WALLET_CONNECT_ENABLED)
|
||||
::wallet.custom-network-amounts (enabled-in-env? :FLAG_WALLET_CUSTOM_NETWORK_AMOUNTS_ENABLED)
|
||||
::wallet.transaction-params (enabled-in-env? :FLAG_WALLET_TRANSACTION_PARAMS_ENABLED)})
|
||||
|
||||
(defonce ^:private feature-flags-config
|
||||
(reagent/atom initial-flags))
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
(ns status-im.navigation.screens
|
||||
(:require
|
||||
[legacy.status-im.ui.screens.screens :as old-screens]
|
||||
@@ -156,10 +155,6 @@
|
||||
[status-im.contexts.wallet.swap.set-spending-cap.view :as wallet-swap-set-spending-cap]
|
||||
[status-im.contexts.wallet.swap.setup-swap.view :as wallet-swap-setup-swap]
|
||||
[status-im.contexts.wallet.swap.swap-confirmation.view :as wallet-swap-confirmation]
|
||||
[status-im.contexts.wallet.trading.swap.approval-confirmation.view :as
|
||||
trading-swap-approval-confirmation]
|
||||
[status-im.contexts.wallet.trading.swap.swap-confirmation.view :as
|
||||
trading-swap-confirmation]
|
||||
[status-im.contexts.wallet.wallet-connect.modals.send-transaction.view :as
|
||||
wallet-connect-send-transaction]
|
||||
[status-im.contexts.wallet.wallet-connect.modals.session-proposal.view :as
|
||||
@@ -170,6 +165,7 @@
|
||||
[status-im.navigation.options :as options]
|
||||
[status-im.navigation.transitions :as transitions]
|
||||
[utils.collection]))
|
||||
|
||||
(def chat-screens
|
||||
[{:name :start-a-new-chat
|
||||
:metrics {:track? true
|
||||
@@ -721,19 +717,6 @@
|
||||
:options {:modalPresentationStyle :overCurrentContext}
|
||||
:component wallet-swap-confirmation/view}])
|
||||
|
||||
(def trading-screens
|
||||
[{:name :screen/trading.swap-approval-confirmation
|
||||
:metrics {:track? true
|
||||
:alias-id :trading.swap-approval-confirmation}
|
||||
:options {:sheet? true}
|
||||
:component trading-swap-approval-confirmation/view}
|
||||
|
||||
{:name :screen/trading.swap-confirmation
|
||||
:metrics {:track? true
|
||||
:alias-id :trading.swap-confirmation}
|
||||
:options {:sheet? true}
|
||||
:component trading-swap-confirmation/view}])
|
||||
|
||||
(def wallet-connect-screens
|
||||
[{:name :screen/wallet.wallet-connect-session-proposal
|
||||
:metrics {:track? true
|
||||
@@ -1140,7 +1123,6 @@
|
||||
settings-screens
|
||||
wallet-settings-screens
|
||||
wallet-screens
|
||||
trading-screens
|
||||
wallet-send-screens
|
||||
wallet-bridge-screens
|
||||
wallet-swap-screens
|
||||
|
||||
@@ -17,13 +17,11 @@
|
||||
status-im.subs.profile
|
||||
status-im.subs.settings
|
||||
status-im.subs.shell
|
||||
status-im.subs.trading.swap
|
||||
status-im.subs.wallet.activities
|
||||
status-im.subs.wallet.buy
|
||||
status-im.subs.wallet.collectibles
|
||||
status-im.subs.wallet.dapps.core
|
||||
status-im.subs.wallet.networks
|
||||
status-im.subs.wallet.routes
|
||||
status-im.subs.wallet.saved-addresses
|
||||
status-im.subs.wallet.send
|
||||
status-im.subs.wallet.swap
|
||||
@@ -193,6 +191,3 @@
|
||||
|
||||
;;keycard
|
||||
(reg-root-key-sub :keycard :keycard)
|
||||
|
||||
;;shell
|
||||
(reg-root-key-sub :shell/bottom-tabs-visible? :shell/bottom-tabs-visible?)
|
||||
|
||||
@@ -1,393 +0,0 @@
|
||||
(ns status-im.subs.trading.swap
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as rf]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.common.utils :as utils]
|
||||
[status-im.contexts.wallet.trading.swap.routes :as routes]
|
||||
[status-im.contexts.wallet.trading.swap.utils :as swap-utils]
|
||||
[utils.money :as money]
|
||||
[utils.number :as number]))
|
||||
|
||||
;; == root keys ==
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/ui-data
|
||||
:<- [:wallet/ui]
|
||||
:-> :trading-swap)
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/focused?
|
||||
:<- [:trading.swap/ui-data]
|
||||
(fn [{:keys [focused?]}]
|
||||
focused?))
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/pay-token-symbol
|
||||
:<- [:trading.swap/ui-data]
|
||||
:-> :pay-token-symbol)
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/receive-token-symbol
|
||||
:<- [:trading.swap/ui-data]
|
||||
:-> :receive-token-symbol)
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/chain-id
|
||||
:<- [:trading.swap/ui-data]
|
||||
:-> :chain-id)
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/max-slippage
|
||||
:<- [:trading.swap/ui-data]
|
||||
:-> :max-slippage)
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/account-address
|
||||
:<- [:trading.swap/ui-data]
|
||||
:-> :account-address)
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/pay-amount
|
||||
:<- [:trading.swap/ui-data]
|
||||
:-> :pay-amount)
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/initialized?
|
||||
:<- [:trading.swap/ui-data]
|
||||
(fn [{:keys [initialized?]}]
|
||||
(or initialized? false)))
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/requested-route-uuid
|
||||
:<- [:trading.swap/ui-data]
|
||||
:-> :requested-route-uuid)
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/approvals
|
||||
:<- [:trading.swap/ui-data]
|
||||
:-> :approvals)
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/route
|
||||
:<- [:wallet.routes/uuid]
|
||||
:<- [:wallet.routes/best-route]
|
||||
:<- [:trading.swap/requested-route-uuid]
|
||||
(fn [[route-uuid best-route requested-route-uuid]]
|
||||
(when (= requested-route-uuid route-uuid)
|
||||
best-route)))
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/route-error
|
||||
:<- [:wallet.routes/error]
|
||||
:<- [:wallet.routes/uuid]
|
||||
:<- [:trading.swap/requested-route-uuid]
|
||||
(fn [[error route-uuid requested-route-uuid]]
|
||||
(when (= requested-route-uuid route-uuid)
|
||||
error)))
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/processing-route?
|
||||
:<- [:wallet.routes/processing-routes?]
|
||||
(fn [processing?]
|
||||
processing?))
|
||||
|
||||
;; =====
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/loading?
|
||||
:<- [:trading.swap/initialized?]
|
||||
:<- [:trading.swap/route]
|
||||
(fn [[initialized? route]]
|
||||
(or (not initialized?) (nil? route))))
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/network
|
||||
:<- [:wallet/network-details]
|
||||
:<- [:trading.swap/chain-id]
|
||||
(fn [[networks chain-id]]
|
||||
(some #(when (= chain-id (:chain-id %)) %) networks)))
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/account
|
||||
:<- [:wallet/accounts-by-address]
|
||||
:<- [:trading.swap/account-address]
|
||||
(fn [[accounts address]]
|
||||
(get accounts address)))
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/customization-color
|
||||
:<- [:trading.swap/account]
|
||||
(fn [account]
|
||||
(:color account)))
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/pay-token
|
||||
:<- [:wallet/normalized-tokens]
|
||||
:<- [:trading.swap/pay-token-symbol]
|
||||
:<- [:trading.swap/chain-id]
|
||||
(fn [[normalized-tokens token-symbol chain-id]]
|
||||
(get-in normalized-tokens [token-symbol chain-id])))
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/receive-token
|
||||
:<- [:wallet/normalized-tokens]
|
||||
:<- [:trading.swap/receive-token-symbol]
|
||||
:<- [:trading.swap/chain-id]
|
||||
(fn [[normalized-tokens token-symbol chain-id]]
|
||||
(get-in normalized-tokens [token-symbol chain-id])))
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/pay-token-balance
|
||||
:<- [:wallet/balances]
|
||||
:<- [:trading.swap/pay-token]
|
||||
:<- [:trading.swap/chain-id]
|
||||
:<- [:trading.swap/account-address]
|
||||
(fn [[balances pay-token chain-id address]]
|
||||
(let [token-symbol (:symbol pay-token)
|
||||
decimals (:decimals pay-token)]
|
||||
(-> balances
|
||||
(get-in [address token-symbol chain-id])
|
||||
:raw-balance
|
||||
(number/convert-to-whole-number decimals)
|
||||
(or "0")))))
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/pay-amount-valid?
|
||||
:<- [:trading.swap/pay-amount]
|
||||
:<- [:trading.swap/pay-token-balance]
|
||||
(fn [[pay-amount pay-balance]]
|
||||
(swap-utils/pay-input-valid? pay-amount pay-balance)))
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/pay-amount-error?
|
||||
:<- [:trading.swap/pay-amount]
|
||||
:<- [:trading.swap/pay-token-balance]
|
||||
(fn [[pay-amount pay-balance]]
|
||||
(swap-utils/pay-input-error? pay-amount pay-balance)))
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/error?
|
||||
:<- [:trading.swap/route-error]
|
||||
:<- [:trading.swap/pay-amount-error?]
|
||||
(fn [[route-error pay-amount-error]]
|
||||
(boolean (or route-error pay-amount-error))))
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/pay-fiat-amount
|
||||
:<- [:trading.swap/pay-token]
|
||||
:<- [:trading.swap/pay-amount]
|
||||
:<- [:wallet/prices-per-token]
|
||||
:<- [:profile/currency]
|
||||
:<- [:profile/currency-symbol]
|
||||
(fn [[pay-token pay-amount prices-per-token currency currency-symbol]]
|
||||
(utils/formatted-token-fiat-value
|
||||
{:currency currency
|
||||
:currency-symbol currency-symbol
|
||||
:balance (or pay-amount 0)
|
||||
:token pay-token
|
||||
:prices-per-token prices-per-token})))
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/pay-fiat-amount
|
||||
:<- [:trading.swap/pay-token]
|
||||
:<- [:trading.swap/pay-amount]
|
||||
:<- [:wallet/prices-per-token]
|
||||
:<- [:profile/currency]
|
||||
:<- [:profile/currency-symbol]
|
||||
(fn [[pay-token pay-amount prices-per-token currency currency-symbol]]
|
||||
(utils/formatted-token-fiat-value
|
||||
{:currency currency
|
||||
:currency-symbol currency-symbol
|
||||
:balance (or pay-amount 0)
|
||||
:token pay-token
|
||||
:prices-per-token prices-per-token})))
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/receive-amount
|
||||
:<- [:trading.swap/route]
|
||||
(fn [route]
|
||||
(when route
|
||||
(-> route
|
||||
routes/amount-out
|
||||
:whole))))
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/receive-fiat-amount
|
||||
:<- [:trading.swap/receive-token]
|
||||
:<- [:trading.swap/receive-amount]
|
||||
:<- [:wallet/prices-per-token]
|
||||
:<- [:profile/currency]
|
||||
:<- [:profile/currency-symbol]
|
||||
(fn [[receive-token receive-amount prices-per-token currency currency-symbol]]
|
||||
(utils/formatted-token-fiat-value
|
||||
{:currency currency
|
||||
:currency-symbol currency-symbol
|
||||
:balance (or receive-amount 0)
|
||||
:token receive-token
|
||||
:prices-per-token prices-per-token})))
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/exchange-rate
|
||||
:<- [:trading.swap/route]
|
||||
:<- [:trading.swap/pay-token]
|
||||
:<- [:profile/currency]
|
||||
:<- [:profile/currency-symbol]
|
||||
:<- [:wallet/prices-per-token]
|
||||
(fn [[route pay-token currency currency-symbol prices-per-token]]
|
||||
(when route
|
||||
(let [pay-amount (-> route routes/amount-in :bn)
|
||||
receive-amount (-> route routes/amount-out :bn)
|
||||
exchange-rate (money/div pay-amount receive-amount)
|
||||
display-decimals (min (:decimals pay-token)
|
||||
constants/min-token-decimals-to-display)
|
||||
exchange-rate (number/to-fixed exchange-rate display-decimals)
|
||||
fiat-exchange-rate (utils/formatted-token-fiat-value
|
||||
{:currency currency
|
||||
:currency-symbol currency-symbol
|
||||
:balance exchange-rate
|
||||
:token pay-token
|
||||
:prices-per-token prices-per-token})]
|
||||
{:crypto exchange-rate
|
||||
:fiat fiat-exchange-rate}))))
|
||||
|
||||
;; === fees ===
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/total-fee-fiat
|
||||
:<- [:trading.swap/route]
|
||||
:<- [:profile/currency]
|
||||
:<- [:wallet/prices-per-token]
|
||||
(fn [[route currency prices-per-token]]
|
||||
(let [native-fee (-> route routes/fees :tx-total-fee money/wei->ether)]
|
||||
(utils/calculate-token-fiat-value
|
||||
{:currency currency
|
||||
:balance native-fee
|
||||
:token {:symbol constants/token-for-fees-symbol}
|
||||
:prices-per-token prices-per-token}))))
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/approval-fee-fiat
|
||||
:<- [:trading.swap/route]
|
||||
:<- [:profile/currency]
|
||||
:<- [:wallet/prices-per-token]
|
||||
(fn [[route currency prices-per-token]]
|
||||
(let [native-fee (-> route routes/fees :approval-fee money/wei->ether)]
|
||||
(utils/calculate-token-fiat-value
|
||||
{:currency currency
|
||||
:balance native-fee
|
||||
:token {:symbol constants/token-for-fees-symbol}
|
||||
:prices-per-token prices-per-token}))))
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/estimated-time
|
||||
:<- [:trading.swap/route]
|
||||
(fn [route]
|
||||
(when route
|
||||
(routes/estimated-time route))))
|
||||
|
||||
;; === formatted values ===
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/formatted-pay-token-balance
|
||||
:<- [:trading.swap/pay-token]
|
||||
:<- [:trading.swap/pay-token-balance]
|
||||
(fn [[{:keys [decimals]} balance]]
|
||||
(utils/sanitized-token-amount-to-display (money/bignumber balance)
|
||||
(min constants/min-token-decimals-to-display decimals))))
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/formatted-receive-amount
|
||||
:<- [:trading.swap/route]
|
||||
(fn [route]
|
||||
(when route
|
||||
(let [{:keys [whole decimals]} (routes/amount-out route)
|
||||
display-decimals (min decimals constants/min-token-decimals-to-display)]
|
||||
(utils/sanitized-token-amount-to-display whole display-decimals)))))
|
||||
|
||||
|
||||
;; === approvals ===
|
||||
|
||||
;; TODO
|
||||
(rf/reg-sub
|
||||
:trading.swap/current-approval
|
||||
:<- [:trading.swap/ui-data]
|
||||
(fn [{:keys [approvals] :as swap-data}]
|
||||
(swap-utils/approval-for-inputs approvals swap-data)))
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/approval-required?
|
||||
:<- [:trading.swap/route]
|
||||
(fn [route]
|
||||
(when route
|
||||
(-> route routes/approval-data :required?))))
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/approval-transaction-id
|
||||
:<- [:trading.swap/current-approval]
|
||||
(fn [approval]
|
||||
(:transaction-hash approval)))
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/approval-status
|
||||
:<- [:wallet.routes/transactions]
|
||||
:<- [:trading.swap/approval-transaction-id]
|
||||
(fn [[transactions approval-transaction-id]]
|
||||
(get-in transactions [approval-transaction-id :status])))
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/last-approval-status
|
||||
:<- [:wallet.routes/transactions]
|
||||
:<- [:trading.swap/approvals]
|
||||
(fn [[transactions approvals]]
|
||||
(->> approvals
|
||||
last
|
||||
:transaction-hash
|
||||
(get transactions)
|
||||
:status)))
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/approval-amount
|
||||
:<- [:trading.swap/route]
|
||||
:<- [:trading.swap/pay-token]
|
||||
:<- [:trading.swap/approval-required?]
|
||||
:<- [:trading.swap/current-approval]
|
||||
(fn [[route {:keys [decimals]} approval-required? approval]]
|
||||
(if approval-required?
|
||||
(-> (routes/approval-data route)
|
||||
:amount-required
|
||||
(number/convert-to-whole-number decimals)
|
||||
(money/bignumber)
|
||||
(number/to-fixed decimals)
|
||||
(utils/sanitized-token-amount-to-display decimals))
|
||||
(:pay-amount approval))))
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/provider
|
||||
:<- [:trading.swap/route]
|
||||
(fn [route]
|
||||
(when route
|
||||
(->> route
|
||||
routes/processor-name
|
||||
string/lower-case
|
||||
keyword
|
||||
(get constants/swap-providers)))))
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/approval-contract-address
|
||||
:<- [:trading.swap/route]
|
||||
:<- [:trading.swap/provider]
|
||||
(fn [[route provider]]
|
||||
(when route
|
||||
(-> route
|
||||
routes/approval-data
|
||||
:contract-address
|
||||
(or (:contract-address provider))))))
|
||||
|
||||
(rf/reg-sub
|
||||
:trading.swap/approval-estimated-time
|
||||
:<- [:trading.swap/route]
|
||||
(fn [route]
|
||||
(when route
|
||||
(-> route
|
||||
routes/approval-data
|
||||
:estimated-time))))
|
||||
@@ -1,42 +0,0 @@
|
||||
(ns status-im.subs.wallet.routes
|
||||
(:require [re-frame.core :as rf]))
|
||||
|
||||
(rf/reg-sub :wallet/route
|
||||
:<- [:wallet]
|
||||
:-> :route)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet.routes/best-route
|
||||
:<- [:wallet/route]
|
||||
:-> :best-route)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet.routes/transactions-for-signing
|
||||
:<- [:wallet/route]
|
||||
:-> :transactions-for-signing)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet.routes/state
|
||||
:<- [:wallet/route]
|
||||
:-> :state)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet.routes/uuid
|
||||
:<- [:wallet/route]
|
||||
:-> :uuid)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet.routes/error
|
||||
:<- [:wallet/route]
|
||||
:-> :error)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet.routes/transactions
|
||||
:<- [:wallet/route]
|
||||
:-> :transactions)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet.routes/processing-routes?
|
||||
:<- [:wallet.routes/state]
|
||||
(fn [state]
|
||||
(= state :requesting-routes)))
|
||||
@@ -90,21 +90,6 @@
|
||||
:<- [:wallet/tokens]
|
||||
:-> :market-values-per-token)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/supported-chains-by-symbol
|
||||
:<- [:wallet/tokens]
|
||||
:-> :supported-chains-by-symbol)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/supported-networks-for-symbol
|
||||
:<- [:wallet/supported-chains-by-symbol]
|
||||
:<- [:wallet/network-details]
|
||||
(fn [[chains-by-symbol network-details] [_ token-symbol]]
|
||||
(println :chain-ids (get chains-by-symbol token-symbol) :symbol token-symbol)
|
||||
(->> (get chains-by-symbol token-symbol)
|
||||
(map (fn [chain-id]
|
||||
(some #(when (= chain-id (:chain-id %)) %) network-details))))))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/tokens-loading
|
||||
:<- [:wallet/ui]
|
||||
@@ -119,15 +104,6 @@
|
||||
(some true?)
|
||||
boolean)))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/home-tokens-loaded?
|
||||
:<- [:wallet/tokens-loading]
|
||||
(fn [tokens-loading]
|
||||
(and (seq tokens-loading)
|
||||
(->> tokens-loading
|
||||
vals
|
||||
(every? false?)))))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/current-viewing-account-tokens-loading?
|
||||
:<- [:wallet/tokens-loading]
|
||||
@@ -404,17 +380,6 @@
|
||||
:<- [:wallet/create-account]
|
||||
:-> :derivation-path-state)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/accounts-by-address
|
||||
:<- [:wallet]
|
||||
:-> :accounts)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/account-by-address
|
||||
:<- [:wallet/accounts-by-address]
|
||||
(fn [accounts [_ address]]
|
||||
(get accounts address)))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/accounts
|
||||
:<- [:wallet]
|
||||
@@ -511,16 +476,6 @@
|
||||
(assoc :balance balance
|
||||
:formatted-balance formatted-balance)))))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/current-viewing-account-address-or-default
|
||||
:<- [:wallet/current-viewing-account-address]
|
||||
:<- [:wallet/accounts]
|
||||
(fn [[current-address accounts]]
|
||||
(or current-address
|
||||
(-> accounts
|
||||
utils/get-default-account
|
||||
:address))))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/current-viewing-account-or-default
|
||||
:<- [:wallet/accounts]
|
||||
@@ -557,17 +512,14 @@
|
||||
(utils/filter-tokens-in-chains tokens chain-ids)))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/account-tokens-filtered
|
||||
:<- [:wallet/current-viewing-account-address]
|
||||
:<- [:wallet/accounts-by-address]
|
||||
:wallet/current-viewing-account-tokens-filtered
|
||||
:<- [:wallet/current-viewing-account-or-default]
|
||||
:<- [:wallet/network-details]
|
||||
:<- [:wallet/wallet-send]
|
||||
:<- [:profile/currency]
|
||||
:<- [:wallet/prices-per-token]
|
||||
(fn [[current-address accounts networks send-data currency price-per-token]
|
||||
[_ {:keys [address query chain-ids hide-token-fn]}]]
|
||||
(fn [[account networks send-data currency price-per-token] [_ {:keys [query chain-ids hide-token-fn]}]]
|
||||
(let [tx-type (:tx-type send-data)
|
||||
account (get accounts (or address current-address))
|
||||
tokens (->> (:tokens account)
|
||||
(map
|
||||
(fn [token]
|
||||
@@ -999,47 +951,3 @@
|
||||
constants/min-token-decimals-to-display)
|
||||
:asset-pay-symbol token-symbol)))
|
||||
accounts))))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/balances
|
||||
:<- [:wallet/accounts-by-address]
|
||||
(fn [accounts]
|
||||
(utils/balances-by-account accounts)))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/balance-for-token
|
||||
:<- [:wallet/balances]
|
||||
(fn [balances [_ address token-symbol chain-id]]
|
||||
(get-in balances [address token-symbol chain-id])))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/normalized-tokens
|
||||
:<- [:wallet/tokens]
|
||||
:-> :normalized-tokens)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/token-for-symbol
|
||||
:<- [:wallet/normalized-tokens]
|
||||
(fn [tokens [_ token-symbol]]
|
||||
(get tokens token-symbol)))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/token-balance
|
||||
:<- [:wallet/normalized-tokens]
|
||||
:<- [:wallet/balances]
|
||||
:<- [:profile/currency]
|
||||
:<- [:profile/currency-symbol]
|
||||
:<- [:wallet/prices-per-token]
|
||||
(fn [[tokens balances currency currency-symbol prices-per-token] [_ address token-symbol chain-id]]
|
||||
(let [token (get-in tokens [token-symbol chain-id])
|
||||
balance-for-chain (get-in balances [address token-symbol chain-id])
|
||||
total-balance (money/token->unit (:raw-balance balance-for-chain) (:decimals token))
|
||||
fiat-value (utils/calculate-token-fiat-value
|
||||
{:currency currency
|
||||
:balance total-balance
|
||||
:token token
|
||||
:prices-per-token prices-per-token})
|
||||
crypto-formatted (utils/get-standard-crypto-format token total-balance prices-per-token)
|
||||
fiat-formatted (utils/fiat-formatted-for-ui currency-symbol fiat-value)]
|
||||
{:crypto (str crypto-formatted " " token-symbol)
|
||||
:fiat fiat-formatted})))
|
||||
|
||||
@@ -820,7 +820,7 @@
|
||||
#(assoc-in % [:wallet :ui :create-account :selected-keypair-uid] "key-uid"))
|
||||
(is (= "key-uid" (rf/sub [sub-name])))))
|
||||
|
||||
(h/deftest-sub :wallet/account-tokens-filtered
|
||||
(h/deftest-sub :wallet/current-viewing-account-tokens-filtered
|
||||
[sub-name]
|
||||
(testing "current viewing tokens filtered"
|
||||
(swap! rf-db/app-db
|
||||
|
||||
@@ -169,12 +169,6 @@
|
||||
(when-let [d (from-decimal decimals)]
|
||||
(.dividedBy bn ^js (bignumber d)))))
|
||||
|
||||
(defn unit->token
|
||||
[n decimals]
|
||||
(when-let [^js bn (bignumber n)]
|
||||
(when-let [d (from-decimal decimals)]
|
||||
(.mul bn ^js (bignumber d)))))
|
||||
|
||||
(defn with-precision
|
||||
[n decimals]
|
||||
(when-let [^js bn (bignumber n)]
|
||||
|
||||
@@ -43,7 +43,7 @@ class TestWalletCollectibles(MultipleSharedDeviceTestCase):
|
||||
self.wallet_view.collectibles_tab.click()
|
||||
self.wallet_view.set_network_in_wallet(self.network_name)
|
||||
collectibles = {
|
||||
"BVL": {"quantity": 2,
|
||||
"BVL": {"quantity": 1,
|
||||
"info": {"Account": "Account 1",
|
||||
"Network": "Base",
|
||||
"category": "Football Player",
|
||||
@@ -102,8 +102,8 @@ class TestWalletCollectibles(MultipleSharedDeviceTestCase):
|
||||
self.wallet_view.collectibles_tab_on_select_token_view.click()
|
||||
time.sleep(5)
|
||||
self.wallet_view.get_collectible_element('BVL').click()
|
||||
self.wallet_view.amount_input_increase_button.click()
|
||||
self.wallet_view.confirm_button.click()
|
||||
# self.wallet_view.amount_input_increase_button.click()
|
||||
# self.wallet_view.confirm_button.click()
|
||||
for text in [self.account_name, self.sender_short_address]:
|
||||
if not self.wallet_view.from_data_container.get_child_element_by_text(text).is_element_displayed():
|
||||
self.errors.append(self.wallet_view,
|
||||
@@ -118,7 +118,7 @@ class TestWalletCollectibles(MultipleSharedDeviceTestCase):
|
||||
data_to_check = {
|
||||
'Est. time': ' min',
|
||||
'Max fees': r"[$]\d+.\d+",
|
||||
'Recipient gets': '2 '
|
||||
'Recipient gets': '1 '
|
||||
}
|
||||
for key, expected_value in data_to_check.items():
|
||||
try:
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 329 KiB After Width: | Height: | Size: 330 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.3 MiB |
Reference in New Issue
Block a user