Compare commits

..
77 changed files with 196 additions and 3130 deletions
@@ -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
+4 -9
View File
@@ -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))
+3 -6
View File
@@ -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]
+2 -1
View File
@@ -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])]]]))
+1 -4
View File
@@ -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
View File
@@ -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]]))
-1
View File
@@ -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))
-2
View File
@@ -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))))
+2 -3
View File
@@ -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
+20 -26
View File
@@ -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))
+12 -16
View File
@@ -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)]]]}
+38 -56
View File
@@ -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)]]))
@@ -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)}])]))
-1
View File
@@ -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 #{}
-1
View File
@@ -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
+19 -21
View File
@@ -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 -19
View File
@@ -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
-5
View File
@@ -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?)
-393
View File
@@ -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))))
-42
View File
@@ -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)))
+3 -95
View File
@@ -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})))
+1 -1
View File
@@ -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
-6
View File
@@ -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