Swaps: Asset to Pay / Asset to Receive (#21140)
* Select assets to pay/receive * Fixes * Fixes * Updates * Fixes * Fixes * Fixes * Fixes * Small test fix
This commit is contained in:
parent
93f00c442e
commit
7bbd476cf6
|
@ -0,0 +1,13 @@
|
|||
(ns quo.components.list-items.token-info.component-spec
|
||||
(:require
|
||||
[quo.components.list-items.token-info.view :as token-info]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(h/describe "List Items: Token Info"
|
||||
(h/test "Token label renders"
|
||||
(h/render-with-theme-provider [token-info/view
|
||||
{:token :snt
|
||||
:label "Status"
|
||||
:state :default
|
||||
:customization-color :blue}])
|
||||
(h/is-truthy (h/get-by-text "Status"))))
|
|
@ -0,0 +1,12 @@
|
|||
(ns quo.components.list-items.token-info.schema)
|
||||
|
||||
(def ?schema
|
||||
[:=>
|
||||
[:cat
|
||||
[:map
|
||||
[:token [:or :string :keyword]]
|
||||
[:label :string]
|
||||
[:on-press {:optional true} [:maybe fn?]]
|
||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
|
||||
[:state {:optional true} [:maybe [:enum :default :active :selected :disabled]]]]]
|
||||
:any])
|
|
@ -0,0 +1,42 @@
|
|||
(ns quo.components.list-items.token-info.style
|
||||
(:require [quo.foundations.colors :as colors]))
|
||||
|
||||
(defn- background-color
|
||||
[state customization-color theme]
|
||||
(cond
|
||||
(= state :pressed) (colors/resolve-color customization-color theme 5)
|
||||
(= state :active) (colors/resolve-color customization-color theme 10)
|
||||
(= state :selected) (colors/resolve-color customization-color theme 5)
|
||||
:else :transparent))
|
||||
|
||||
(defn container
|
||||
[state customization-color theme]
|
||||
{:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:align-items :center
|
||||
:padding-horizontal 12
|
||||
:padding-vertical 8
|
||||
:border-radius 12
|
||||
:height 56
|
||||
:opacity (when (= state :disabled) 0.3)
|
||||
:background-color (background-color state customization-color theme)})
|
||||
|
||||
(def info
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:width "70%"})
|
||||
|
||||
(def token-info
|
||||
{:height 40
|
||||
:flex 1})
|
||||
|
||||
(defn token-description-label
|
||||
[theme]
|
||||
{:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)})
|
||||
|
||||
(def token-image
|
||||
{:border-width 1
|
||||
:border-radius 16
|
||||
:border-color colors/neutral-80-opa-5
|
||||
:margin-right 8
|
||||
:background-color colors/neutral-80-opa-5})
|
|
@ -0,0 +1,50 @@
|
|||
(ns quo.components.list-items.token-info.view
|
||||
(:require
|
||||
[quo.components.list-items.token-info.schema :as component-schema]
|
||||
[quo.components.list-items.token-info.style :as style]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.components.utilities.token.view :as token]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[schema.core :as schema]))
|
||||
|
||||
(defn- info
|
||||
[{:keys [token label]}]
|
||||
(let [theme (quo.theme/use-theme)]
|
||||
[rn/view {:style style/info}
|
||||
(when token
|
||||
[token/view
|
||||
{:style style/token-image
|
||||
:size :size-32
|
||||
:token token}])
|
||||
[rn/view {:style style/token-info}
|
||||
[text/text
|
||||
{:weight :semi-bold
|
||||
:number-of-lines 1}
|
||||
(if-not (empty? label) label "-")]
|
||||
[text/text
|
||||
{:weight :medium
|
||||
:size :paragraph-2
|
||||
:style (style/token-description-label theme)
|
||||
:number-of-lines 1}
|
||||
token]]]))
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [on-press state customization-color]
|
||||
:as props
|
||||
:or {customization-color :blue}}]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
[pressed? set-pressed] (rn/use-state false)
|
||||
on-press-in (rn/use-callback #(set-pressed true))
|
||||
on-press-out (rn/use-callback #(set-pressed false))
|
||||
internal-state (if pressed? :pressed state)]
|
||||
[rn/pressable
|
||||
{:style (style/container internal-state customization-color theme)
|
||||
:on-press-in on-press-in
|
||||
:on-press-out on-press-out
|
||||
:on-press on-press
|
||||
:disabled (= state :disabled)
|
||||
:accessibility-label :token}
|
||||
[info props]]))
|
||||
|
||||
(def view (schema/instrument #'view-internal component-schema/?schema))
|
|
@ -97,6 +97,7 @@
|
|||
quo.components.list-items.quiz-item.view
|
||||
quo.components.list-items.saved-address.view
|
||||
quo.components.list-items.saved-contact-address.view
|
||||
quo.components.list-items.token-info.view
|
||||
quo.components.list-items.token-network.view
|
||||
quo.components.list-items.token-value.view
|
||||
quo.components.list-items.user
|
||||
|
@ -348,6 +349,7 @@
|
|||
(def quiz-item quo.components.list-items.quiz-item.view/view)
|
||||
(def saved-address quo.components.list-items.saved-address.view/view)
|
||||
(def saved-contact-address quo.components.list-items.saved-contact-address.view/view)
|
||||
(def token-info quo.components.list-items.token-info.view/view)
|
||||
(def token-network quo.components.list-items.token-network.view/view)
|
||||
(def token-value quo.components.list-items.token-value.view/view)
|
||||
(def user quo.components.list-items.user/user)
|
||||
|
|
|
@ -63,6 +63,7 @@
|
|||
quo.components.list-items.quiz-item.component-spec
|
||||
quo.components.list-items.saved-address.component-spec
|
||||
quo.components.list-items.saved-contact-address.component-spec
|
||||
quo.components.list-items.token-info.component-spec
|
||||
quo.components.list-items.token-network.component-spec
|
||||
quo.components.list-items.token-value.component-spec
|
||||
quo.components.loaders.skeleton-list.component-spec
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
(defn enabled? [v] (= "1" v))
|
||||
|
||||
(goog-define INFURA_TOKEN "")
|
||||
(goog-define INFURA_TOKEN "62f3cee52dbb484198e7339837e263f3")
|
||||
(goog-define POKT_TOKEN "3ef2018191814b7e1009b8d9")
|
||||
(goog-define STATUS_BUILD_PROXY_USER "")
|
||||
(goog-define STATUS_BUILD_PROXY_PASSWORD "")
|
||||
|
|
|
@ -601,6 +601,8 @@
|
|||
:terms-and-conditions-url "https://files.paraswap.io/tos_v4.pdf"})
|
||||
(def ^:const swap-providers
|
||||
{:paraswap swap-provider-paraswap})
|
||||
(def ^:const swap-tokens-my :my)
|
||||
(def ^:const swap-tokens-popular :popular)
|
||||
|
||||
(def ^:const token-for-fees-symbol "ETH")
|
||||
|
||||
|
|
|
@ -104,8 +104,6 @@
|
|||
[:profile.settings/get-profile-picture key-uid]
|
||||
(when (ff/enabled? ::ff/wallet.wallet-connect)
|
||||
[:dispatch [:wallet-connect/init]])
|
||||
(when (ff/enabled? ::ff/wallet.swap)
|
||||
[:dispatch [:wallet.tokens/get-token-list]])
|
||||
(when notifications-enabled?
|
||||
[:effects/push-notifications-enable])]})))
|
||||
|
||||
|
|
|
@ -60,7 +60,9 @@
|
|||
(rf/dispatch [:wallet/clean-send-data])
|
||||
(rf/dispatch [:wallet/start-bridge]))
|
||||
:swap-action (when (ff/enabled? ::ff/wallet.swap)
|
||||
#(rf/dispatch [:wallet.swap/start]))}])
|
||||
(fn []
|
||||
(rf/dispatch [:wallet.tokens/get-token-list])
|
||||
(rf/dispatch [:open-modal :screen/wallet.swap-select-asset-to-pay])))}])
|
||||
[quo/tabs
|
||||
{:style style/tabs
|
||||
:size 32
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
(defn view
|
||||
[{:keys [content-container-style search-text on-token-press preselected-token-symbol]
|
||||
:or {content-container-style {:padding-horizontal 8}}}]
|
||||
(let [filtered-tokens (rf/sub [:wallet/current-viewing-account-tokens-filtered search-text])
|
||||
(let [filtered-tokens (rf/sub [:wallet/current-viewing-account-tokens-filtered {:query search-text}])
|
||||
currency (rf/sub [:profile/currency])
|
||||
currency-symbol (rf/sub [:profile/currency-symbol])]
|
||||
[gesture/flat-list
|
||||
|
|
|
@ -73,7 +73,7 @@
|
|||
[token watch-only? entry-point]
|
||||
(let [token-symbol (:token token)
|
||||
token-data (first (rf/sub [:wallet/current-viewing-account-tokens-filtered
|
||||
token-symbol]))
|
||||
{:query token-symbol}]))
|
||||
fiat-unformatted-value (get-in token [:values :fiat-unformatted-value])
|
||||
has-balance? (money/greater-than fiat-unformatted-value (money/bignumber "0"))
|
||||
selected-account? (rf/sub [:wallet/current-viewing-account-address])
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
[quo.foundations.resources :as resources]
|
||||
[status-im.common.qr-codes.view :as qr-codes]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.common.utils.networks :as network-utils]
|
||||
[utils.hex :as utils.hex]
|
||||
[utils.money :as money]
|
||||
[utils.number :as number]
|
||||
|
@ -478,3 +479,17 @@
|
|||
:toAsset to-asset
|
||||
:fromAmount amount-out
|
||||
:type multi-transaction-type})
|
||||
|
||||
(defn sort-tokens-by-name
|
||||
[tokens]
|
||||
(let [priority #(get constants/token-sort-priority (:symbol %) ##Inf)]
|
||||
(sort-by (juxt :symbol priority) tokens)))
|
||||
|
||||
(defn tokens-with-balance
|
||||
[tokens networks chain-ids]
|
||||
(map (fn [token]
|
||||
(assoc token
|
||||
:networks (network-utils/network-list token networks)
|
||||
:available-balance (calculate-total-token-balance token)
|
||||
:total-balance (calculate-total-token-balance token chain-ids)))
|
||||
tokens))
|
||||
|
|
|
@ -189,3 +189,14 @@
|
|||
nil)
|
||||
(when $
|
||||
(assoc $ :chain-id chain-id))))
|
||||
|
||||
(defn sorted-networks-with-details
|
||||
[networks]
|
||||
(->> networks
|
||||
(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))))
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
[status-im.contexts.wallet.db :as db]
|
||||
[status-im.contexts.wallet.item-types :as item-types]
|
||||
[status-im.contexts.wallet.tokens.events]
|
||||
[status-im.feature-flags :as ff]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.collection]
|
||||
[utils.ethereum.chain :as chain]
|
||||
|
@ -344,7 +345,9 @@
|
|||
:Prod
|
||||
data-store/rpc->network)
|
||||
data)}]
|
||||
{:db (assoc-in db [:wallet :networks] network-data)})))
|
||||
{:fx [(when (ff/enabled? ::ff/wallet.swap)
|
||||
[:dispatch [:wallet.tokens/get-token-list]])]
|
||||
:db (assoc-in db [:wallet :networks] network-data)})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/find-ens
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
(ns status-im.contexts.wallet.sheets.select-asset.asset-list.style)
|
|
@ -0,0 +1,111 @@
|
|||
(ns status-im.contexts.wallet.sheets.select-asset.asset-list.view
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[react-native.gesture :as gesture]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.common.utils :as utils]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- my-token-component
|
||||
[{token-symbol :symbol
|
||||
token-name :name
|
||||
total-balance :total-balance
|
||||
bridge-disabled? :bridge-disabled?
|
||||
:as token}
|
||||
{:keys [currency currency-symbol on-token-press disable-token-fn preselected-token-symbol]}]
|
||||
(let [fiat-value (utils/calculate-token-fiat-value
|
||||
{:currency currency
|
||||
:balance total-balance
|
||||
:token token})
|
||||
crypto-formatted (utils/get-standard-crypto-format token total-balance)
|
||||
fiat-formatted (utils/get-standard-fiat-format crypto-formatted currency-symbol fiat-value)]
|
||||
[rn/view {:style {:padding-horizontal 8}}
|
||||
[quo/token-network
|
||||
{:token token-symbol
|
||||
:label token-name
|
||||
:token-value (str crypto-formatted " " token-symbol)
|
||||
:fiat-value fiat-formatted
|
||||
:networks (seq (:networks token))
|
||||
:on-press #(on-token-press token)
|
||||
:state (cond
|
||||
(or bridge-disabled?
|
||||
(when disable-token-fn
|
||||
(disable-token-fn constants/swap-tokens-my token)))
|
||||
:disabled
|
||||
|
||||
(= preselected-token-symbol token-symbol)
|
||||
:selected)}]]))
|
||||
|
||||
(defn- popular-token-component
|
||||
[{token-symbol :symbol
|
||||
token-name :name
|
||||
:as token}
|
||||
{:keys [on-token-press disable-token-fn]}]
|
||||
[rn/view {:style {:padding-horizontal 8}}
|
||||
[quo/token-info
|
||||
{:token token-symbol
|
||||
:label token-name
|
||||
:state (when (and disable-token-fn (disable-token-fn constants/swap-tokens-popular token))
|
||||
:disabled)
|
||||
:on-press #(on-token-press token)}]])
|
||||
|
||||
(defn- list-component
|
||||
[{:keys [type] :as token} _ _ render-data]
|
||||
(if (= type constants/swap-tokens-popular)
|
||||
[popular-token-component token render-data]
|
||||
[my-token-component token render-data]))
|
||||
|
||||
(defn section-header
|
||||
[{:keys [title]}]
|
||||
[quo/divider-label
|
||||
{:container-style {:padding-horizontal 20
|
||||
:margin-top 12
|
||||
:margin-bottom 8}
|
||||
:tight? false}
|
||||
title])
|
||||
|
||||
(defn view
|
||||
[{:keys [search-text on-token-press preselected-token-symbol network hide-token-fn
|
||||
disable-token-fn]}]
|
||||
(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
|
||||
{:query search-text
|
||||
:chain-ids #{(:chain-id network)}
|
||||
:hide-token-fn hide-token-fn}])
|
||||
currency (rf/sub [:profile/currency])
|
||||
currency-symbol (rf/sub [:profile/currency-symbol])
|
||||
sectioned-data (cond-> []
|
||||
(pos? (count my-tokens))
|
||||
(conj {:title (i18n/label :t/your-assets-on-network
|
||||
{:network (:full-name network)})
|
||||
:data (map #(assoc % :type constants/swap-tokens-my)
|
||||
my-tokens)})
|
||||
|
||||
(pos? (count popular-tokens))
|
||||
(conj {:title (i18n/label :t/popular-assets-on-network
|
||||
{:network (:full-name network)})
|
||||
:data (map #(assoc % :type constants/swap-tokens-popular)
|
||||
popular-tokens)}))
|
||||
render-data {:currency currency
|
||||
:currency-symbol currency-symbol
|
||||
:on-token-press on-token-press
|
||||
:preselected-token-symbol preselected-token-symbol
|
||||
:disable-token-fn disable-token-fn}]
|
||||
[gesture/section-list
|
||||
{:data sectioned-data
|
||||
:sections sectioned-data
|
||||
:render-data render-data
|
||||
:render-fn list-component
|
||||
:sticky-section-headers-enabled false
|
||||
:render-section-header-fn section-header
|
||||
:style {:flex 1}
|
||||
:content-container-style {:padding-bottom 20}
|
||||
:keyboard-should-persist-taps :handled
|
||||
:key-fn (fn [{:keys [type title] :as token}]
|
||||
(str (:symbol token) "-" type "-" title))
|
||||
:on-scroll-to-index-failed identity}]))
|
|
@ -0,0 +1,24 @@
|
|||
(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
|
||||
:padding-top (when platform/android? (navigation/status-bar-height))})
|
||||
|
||||
(def search-input-container
|
||||
{:padding-horizontal 20
|
||||
:padding-vertical 8})
|
||||
|
||||
(def subheader-container
|
||||
{:justify-content :flex-start
|
||||
:align-items :center
|
||||
:flex-direction :row
|
||||
:flex-wrap :wrap
|
||||
:gap 4
|
||||
:padding-horizontal 20
|
||||
:margin-bottom 8})
|
|
@ -0,0 +1,92 @@
|
|||
(ns status-im.contexts.wallet.sheets.select-asset.view
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[status-im.contexts.wallet.sheets.select-asset.asset-list.view :as asset-list]
|
||||
[status-im.contexts.wallet.sheets.select-asset.style :as style]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- search-input
|
||||
[search-text on-change-text]
|
||||
[rn/view {:style style/search-input-container}
|
||||
[quo/input
|
||||
{:small? true
|
||||
:placeholder (i18n/label :t/search-assets)
|
||||
:icon-name :i/search
|
||||
:value search-text
|
||||
:on-change-text on-change-text}]])
|
||||
|
||||
(defn- assets-view
|
||||
[{: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
|
||||
{:search-text search-text
|
||||
:on-token-press (fn [token]
|
||||
(when on-select
|
||||
(on-select token))
|
||||
(rf/dispatch [:hide-bottom-sheet]))
|
||||
:network network
|
||||
:hide-token-fn hide-token-fn
|
||||
:disable-token-fn disable-token-fn}]])
|
||||
|
||||
(defn- account-view
|
||||
[{:keys [emoji name color]}]
|
||||
(let [theme (quo.theme/use-theme)]
|
||||
[quo/context-tag
|
||||
{:theme theme
|
||||
:type :account
|
||||
:size 24
|
||||
:account-name name
|
||||
:emoji emoji
|
||||
:customization-color color}]))
|
||||
|
||||
(defn- network-view
|
||||
[{:keys [full-name source]}]
|
||||
[quo/context-tag
|
||||
{:size 24
|
||||
:network-logo source
|
||||
:network-name full-name
|
||||
:type :network}])
|
||||
|
||||
(defn- subheader-view
|
||||
[{:keys [account network]}]
|
||||
[rn/view {:style style/subheader-container}
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium}
|
||||
(i18n/label :t/select-asset-on)]
|
||||
[account-view account]
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium}
|
||||
(i18n/label :t/select-asset-via)]
|
||||
[network-view network]])
|
||||
|
||||
(defn view
|
||||
[{:keys [title on-select hide-token-fn disable-token-fn]}]
|
||||
(let [account (rf/sub [:wallet/current-viewing-account])
|
||||
{:keys [network]} (rf/sub [:wallet/swap])
|
||||
[search-text set-search-text] (rn/use-state "")
|
||||
window-height (:height (rn/get-window))]
|
||||
[rn/safe-area-view {:style (style/container window-height)}
|
||||
[quo/page-nav
|
||||
{:type :no-title
|
||||
:icon-name :i/close
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:hide-bottom-sheet]))}]
|
||||
[quo/page-top
|
||||
{:title title
|
||||
:title-accessibility-label :title-label}]
|
||||
[subheader-view
|
||||
{:account account
|
||||
:network network}]
|
||||
[assets-view
|
||||
{:search-text search-text
|
||||
:on-change-text #(set-search-text %)
|
||||
:on-select on-select
|
||||
:network network
|
||||
:hide-token-fn hide-token-fn
|
||||
:disable-token-fn disable-token-fn}]]))
|
|
@ -5,6 +5,7 @@
|
|||
[status-im.contexts.wallet.common.utils :as utils]
|
||||
[status-im.contexts.wallet.send.utils :as send-utils]
|
||||
[status-im.contexts.wallet.sheets.network-selection.view :as network-selection]
|
||||
[status-im.contexts.wallet.swap.utils :as swap-utils]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.address :as address]
|
||||
[utils.debounce :as debounce]
|
||||
|
@ -13,32 +14,58 @@
|
|||
[utils.number :as number]))
|
||||
|
||||
(rf/reg-event-fx :wallet.swap/start
|
||||
(fn [{:keys [_db]}]
|
||||
{:fx [[:dispatch [:open-modal :screen/wallet.swap-select-asset-to-pay]]]}))
|
||||
(fn [{:keys [db]} [{:keys [asset-to-pay asset-to-receive network]}]]
|
||||
(let [asset-to-receive' (or asset-to-receive
|
||||
(swap-utils/select-asset-to-receive
|
||||
(:wallet db)
|
||||
(:profile/profile db)
|
||||
asset-to-pay))
|
||||
network' (or network
|
||||
(swap-utils/select-network asset-to-pay))]
|
||||
{: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'))
|
||||
:fx (if network'
|
||||
[[:dispatch
|
||||
[:navigate-to-within-stack
|
||||
[:screen/wallet.setup-swap :screen/wallet.swap-select-asset-to-pay]]]
|
||||
[: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}]))}])}]]])})))
|
||||
|
||||
(rf/reg-event-fx :wallet.swap/select-asset-to-pay
|
||||
(fn [{:keys [db]} [{:keys [token network]}]]
|
||||
{:db (-> db
|
||||
(assoc-in [:wallet :ui :swap :asset-to-pay] token)
|
||||
(assoc-in [:wallet :ui :swap :network] network))
|
||||
:fx (if network
|
||||
[[:dispatch
|
||||
[:navigate-to-within-stack
|
||||
[:screen/wallet.setup-swap :screen/wallet.swap-select-asset-to-pay]]]
|
||||
[:dispatch [:wallet.swap/set-default-slippage]]]
|
||||
[[:dispatch
|
||||
[:show-bottom-sheet
|
||||
{:content (fn []
|
||||
[network-selection/view
|
||||
{:token-symbol (:symbol token)
|
||||
:on-select-network (fn [network]
|
||||
(rf/dispatch [:hide-bottom-sheet])
|
||||
(rf/dispatch
|
||||
[:wallet.swap/select-asset-to-pay
|
||||
{:token token
|
||||
:network network
|
||||
:stack-id
|
||||
:screen/wallet.swap-select-asset-to-pay}]))}])}]]])}))
|
||||
(fn [{:keys [db]} [{:keys [token]}]]
|
||||
{:db (update-in db
|
||||
[:wallet :ui :swap]
|
||||
#(-> %
|
||||
(assoc :asset-to-pay token)
|
||||
(dissoc :amount
|
||||
:amount-hex
|
||||
:last-request-uuid
|
||||
:swap-proposal
|
||||
:error-response
|
||||
:loading-swap-proposal?
|
||||
:approval-transaction-id
|
||||
:approved-amount)))}))
|
||||
|
||||
(rf/reg-event-fx :wallet.swap/select-asset-to-receive
|
||||
(fn [{:keys [db]} [{:keys [token]}]]
|
||||
{:db (update-in db
|
||||
[:wallet :ui :swap]
|
||||
#(-> %
|
||||
(assoc :asset-to-receive token)
|
||||
(assoc :loading-swap-proposal? true)))}))
|
||||
|
||||
(rf/reg-event-fx :wallet.swap/set-default-slippage
|
||||
(fn [{:keys [db]}]
|
||||
|
@ -48,10 +75,6 @@
|
|||
(fn [{:keys [db]} [max-slippage]]
|
||||
{:db (assoc-in db [:wallet :ui :swap :max-slippage] (number/parse-float max-slippage))}))
|
||||
|
||||
(rf/reg-event-fx :wallet.swap/select-asset-to-receive
|
||||
(fn [{:keys [db]} [{:keys [token]}]]
|
||||
{:db (assoc-in db [:wallet :ui :swap :asset-to-receive] token)}))
|
||||
|
||||
(rf/reg-event-fx :wallet/start-get-swap-proposal
|
||||
(fn [{:keys [db]} [{:keys [amount-in amount-out clean-approval-transaction?]}]]
|
||||
(let [wallet-address (get-in db [:wallet :current-viewing-account-address])
|
||||
|
|
|
@ -21,15 +21,7 @@
|
|||
(defn- assets-view
|
||||
[search-text on-change-text]
|
||||
(let [on-token-press (fn [token]
|
||||
(let [token-networks (:networks token)
|
||||
asset-to-receive (rf/sub [:wallet/token-by-symbol "DAI"])]
|
||||
(rf/dispatch [:wallet.swap/select-asset-to-pay
|
||||
{:token token
|
||||
:network (when (= (count token-networks) 1)
|
||||
(first token-networks))
|
||||
:stack-id :screen/wallet.swap-select-asset-to-pay}])
|
||||
(rf/dispatch [:wallet.swap/select-asset-to-receive
|
||||
{:token asset-to-receive}])))]
|
||||
(rf/dispatch [:wallet.swap/start {:asset-to-pay token}]))]
|
||||
[:<>
|
||||
[search-input search-text on-change-text]
|
||||
[asset-list/view
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
[status-im.contexts.wallet.common.account-switcher.view :as account-switcher]
|
||||
[status-im.contexts.wallet.common.utils :as utils]
|
||||
[status-im.contexts.wallet.sheets.buy-token.view :as buy-token]
|
||||
[status-im.contexts.wallet.sheets.select-asset.view :as select-asset]
|
||||
[status-im.contexts.wallet.sheets.slippage-settings.view :as slippage-settings]
|
||||
[status-im.contexts.wallet.swap.setup-swap.style :as style]
|
||||
[status-im.contexts.wallet.swap.utils :as swap-utils]
|
||||
|
@ -271,6 +272,31 @@
|
|||
:customization-color account-color
|
||||
:on-press on-press}}]))
|
||||
|
||||
(defn- pay-token-bottom-sheet
|
||||
[]
|
||||
(let [asset-to-receive (rf/sub [:wallet/swap-asset-to-receive])]
|
||||
[select-asset/view
|
||||
{:title (i18n/label :t/select-asset-to-pay)
|
||||
:on-select (fn [token]
|
||||
(rf/dispatch [:wallet.swap/select-asset-to-pay {:token token}]))
|
||||
:hide-token-fn (fn [type {:keys [available-balance]}]
|
||||
(and (= type constants/swap-tokens-my)
|
||||
(= available-balance 0)))
|
||||
:disable-token-fn (fn [_ token]
|
||||
(= (:symbol token)
|
||||
(:symbol asset-to-receive)))}]))
|
||||
|
||||
(defn- receive-token-bottom-sheet
|
||||
[]
|
||||
(let [asset-to-pay (rf/sub [:wallet/swap-asset-to-pay])]
|
||||
[select-asset/view
|
||||
{:title (i18n/label :t/select-asset-to-receive)
|
||||
:on-select (fn [token]
|
||||
(rf/dispatch [:wallet.swap/select-asset-to-receive {:token token}]))
|
||||
:disable-token-fn (fn [_ token]
|
||||
(= (:symbol token)
|
||||
(:symbol asset-to-pay)))}]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [[pay-input-state set-pay-input-state] (rn/use-state controlled-input/init-state)
|
||||
|
@ -280,6 +306,7 @@
|
|||
loading-swap-proposal? (rf/sub [:wallet/swap-loading-swap-proposal?])
|
||||
swap-proposal (rf/sub [:wallet/swap-proposal-without-fees])
|
||||
asset-to-pay (rf/sub [:wallet/swap-asset-to-pay])
|
||||
asset-to-receive (rf/sub [:wallet/swap-asset-to-receive])
|
||||
network (rf/sub [:wallet/swap-network])
|
||||
pay-input-amount (controlled-input/input-value pay-input-state)
|
||||
pay-token-decimals (:decimals asset-to-pay)
|
||||
|
@ -360,7 +387,7 @@
|
|||
:clean-approval-transaction? false}))))
|
||||
[valid-pay-input? loading-swap-proposal?
|
||||
pay-input-amount])
|
||||
on-asset-to-pay-change (fn []
|
||||
refetch-swap-proposal (fn []
|
||||
(when valid-pay-input?
|
||||
(fetch-swap-proposal
|
||||
{:amount pay-input-amount
|
||||
|
@ -394,8 +421,11 @@
|
|||
(controlled-input/set-input-value
|
||||
input-state
|
||||
swap-amount)))
|
||||
(on-asset-to-pay-change)))))
|
||||
(refetch-swap-proposal)))))
|
||||
[asset-to-pay])
|
||||
(rn/use-effect
|
||||
refetch-swap-proposal
|
||||
[asset-to-receive])
|
||||
[rn/view {:style style/container}
|
||||
[account-switcher/view
|
||||
{:on-press on-close
|
||||
|
@ -407,7 +437,7 @@
|
|||
{:input-state pay-input-state
|
||||
:on-max-press on-max-press
|
||||
:input-focused? pay-input-focused?
|
||||
:on-token-press #(js/alert "Token Pressed")
|
||||
:on-token-press #(rf/dispatch [:show-bottom-sheet {:content pay-token-bottom-sheet}])
|
||||
:on-approve-press #(rf/dispatch [:open-modal :screen/wallet.swap-set-spending-cap])
|
||||
:on-input-focus (fn []
|
||||
(when platform/android? (rf/dispatch [:dismiss-keyboard]))
|
||||
|
@ -420,7 +450,7 @@
|
|||
(rf/dispatch [:wallet.swap/flip-assets]))}]
|
||||
[receive-token-input
|
||||
{:input-focused? (not pay-input-focused?)
|
||||
:on-token-press #(js/alert "Token Pressed")
|
||||
:on-token-press #(rf/dispatch [:show-bottom-sheet {:content receive-token-bottom-sheet}])
|
||||
:on-input-focus #(set-pay-input-focused? false)}]]
|
||||
[rn/view {:style style/footer-container}
|
||||
[alert-banner {:pay-input-error? pay-input-error?}]
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
(ns status-im.contexts.wallet.swap.swap-proposal.view
|
||||
(:require [quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[status-im.contexts.wallet.sheets.slippage-settings.view :as slippage-settings]
|
||||
[status-im.contexts.wallet.swap.swap-proposal.style :as style]
|
||||
[utils.re-frame :as rf]))
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[status-im.contexts.wallet.sheets.slippage-settings.view :as slippage-settings]
|
||||
[status-im.contexts.wallet.swap.swap-proposal.style :as style]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
(ns status-im.contexts.wallet.swap.utils
|
||||
(:require [status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.common.utils :as utils]
|
||||
[status-im.contexts.wallet.common.utils.networks :as network-utils]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(defn error-message-from-code
|
||||
|
@ -27,3 +29,23 @@
|
|||
(i18n/label :t/not-enough-assets-to-pay-gas-fees)
|
||||
:else
|
||||
(i18n/label :t/something-went-wrong-please-try-again-later)))
|
||||
|
||||
(defn select-asset-to-receive
|
||||
[wallet profile asset-to-pay]
|
||||
(let [wallet-address (get-in wallet [:current-viewing-account-address])
|
||||
account (-> wallet
|
||||
:accounts
|
||||
vals
|
||||
(utils/get-account-by-address wallet-address))
|
||||
test-networks-enabled? (get profile :test-networks-enabled?)
|
||||
networks (-> (get-in wallet
|
||||
[:wallet :networks (if test-networks-enabled? :test :prod)])
|
||||
(network-utils/sorted-networks-with-details))]
|
||||
(->> (utils/tokens-with-balance (:tokens account) networks nil)
|
||||
(remove #(= (:symbol %) (:symbol asset-to-pay)))
|
||||
first)))
|
||||
|
||||
(defn select-network
|
||||
[{:keys [networks]}]
|
||||
(when (= (count networks) 1)
|
||||
(first networks)))
|
||||
|
|
|
@ -10,12 +10,13 @@
|
|||
(rf/reg-event-fx
|
||||
:wallet.tokens/get-token-list
|
||||
(fn [{:keys [db]}]
|
||||
{:db (assoc-in db [:wallet :ui :loading :token-list] true)
|
||||
:fx [[:json-rpc/call
|
||||
[{:method "wallet_getTokenList"
|
||||
:params []
|
||||
:on-success [:wallet.tokens/store-token-list]
|
||||
:on-error [:wallet.tokens/get-token-list-failed]}]]]}))
|
||||
(when-not (get-in db [:wallet :tokens])
|
||||
{:db (assoc-in db [:wallet :ui :loading :token-list] true)
|
||||
:fx [[:json-rpc/call
|
||||
[{:method "wallet_getTokenList"
|
||||
:params []
|
||||
:on-success [:wallet.tokens/store-token-list]
|
||||
:on-error [:wallet.tokens/get-token-list-failed]}]]]})))
|
||||
|
||||
(defn store-token-list
|
||||
[{:keys [db]} [{:keys [data]}]]
|
||||
|
|
|
@ -21,14 +21,7 @@
|
|||
:wallet/network-details
|
||||
:<- [:wallet/networks-by-mode]
|
||||
(fn [networks]
|
||||
(->> networks
|
||||
(map
|
||||
(fn [{:keys [chain-id related-chain-id layer]}]
|
||||
(assoc (network-utils/get-network-details chain-id)
|
||||
:chain-id chain-id
|
||||
:related-chain-id related-chain-id
|
||||
:layer layer)))
|
||||
(sort-by (juxt :layer :short-name)))))
|
||||
(network-utils/sorted-networks-with-details networks)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet/network-details-by-network-name
|
||||
|
|
|
@ -39,6 +39,11 @@
|
|||
:<- [:wallet/ui]
|
||||
:-> :scanned-address)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/tokens
|
||||
:<- [:wallet]
|
||||
:-> :tokens)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/tokens-loading
|
||||
:<- [:wallet/ui]
|
||||
|
@ -418,19 +423,26 @@
|
|||
:<- [:wallet/current-viewing-account]
|
||||
:<- [:wallet/network-details]
|
||||
:<- [:wallet/wallet-send]
|
||||
(fn [[account networks send-data] [_ query chain-ids]]
|
||||
(prn send-data)
|
||||
(fn [[account networks send-data] [_ {:keys [query chain-ids hide-token-fn]}]]
|
||||
(let [tx-type (:tx-type send-data)
|
||||
tokens (map (fn [token]
|
||||
(assoc token
|
||||
:bridge-disabled? (and (= tx-type :tx/bridge)
|
||||
(send-utils/bridge-disabled? (:symbol
|
||||
token)))
|
||||
:networks (network-utils/network-list token networks)
|
||||
:available-balance (utils/calculate-total-token-balance token)
|
||||
:total-balance (utils/calculate-total-token-balance token
|
||||
chain-ids)))
|
||||
(:tokens account))
|
||||
tokens (->> (:tokens account)
|
||||
(map
|
||||
(fn [token]
|
||||
(assoc token
|
||||
:bridge-disabled? (and (= tx-type :tx/bridge)
|
||||
(send-utils/bridge-disabled? (:symbol
|
||||
token)))
|
||||
:networks (cond->> (network-utils/network-list token
|
||||
networks)
|
||||
chain-ids
|
||||
(filter #(some #{(:chain-id %)} chain-ids)))
|
||||
:available-balance (utils/calculate-total-token-balance token)
|
||||
:total-balance (utils/calculate-total-token-balance
|
||||
token
|
||||
chain-ids))))
|
||||
(filter (fn [{:keys [networks]}]
|
||||
(pos? (count networks))))
|
||||
(remove #(when hide-token-fn (hide-token-fn constants/swap-tokens-my %))))
|
||||
sorted-tokens (utils/sort-tokens tokens)]
|
||||
(if query
|
||||
(let [query-string (string/lower-case query)]
|
||||
|
@ -439,22 +451,38 @@
|
|||
sorted-tokens))
|
||||
sorted-tokens))))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/tokens-filtered
|
||||
:<- [:wallet/tokens]
|
||||
(fn [{:keys [by-symbol market-values-per-token details-per-token]}
|
||||
[_ {:keys [query chain-ids hide-token-fn]}]]
|
||||
(let [tokens (->> by-symbol
|
||||
(map (fn [token]
|
||||
(-> token
|
||||
(assoc :market-values
|
||||
(get market-values-per-token (:symbol token)))
|
||||
(assoc :details (get details-per-token (:symbol token))))))
|
||||
(filter (fn [{:keys [chain-id]}]
|
||||
(some #{chain-id} chain-ids)))
|
||||
(remove #(when hide-token-fn
|
||||
(hide-token-fn constants/swap-tokens-popular %))))
|
||||
sorted-tokens (utils/sort-tokens-by-name tokens)]
|
||||
(if query
|
||||
(let [query-string (string/lower-case query)]
|
||||
(filter #(or (string/starts-with? (string/lower-case (:name %)) query-string)
|
||||
(string/starts-with? (string/lower-case (:symbol %)) query-string))
|
||||
sorted-tokens))
|
||||
sorted-tokens))))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/token-by-symbol
|
||||
:<- [:wallet/current-viewing-account]
|
||||
:<- [:wallet/network-details]
|
||||
(fn [[account networks] [_ token-symbol chain-ids]]
|
||||
(let [tokens (map (fn [token]
|
||||
(assoc token
|
||||
:networks (network-utils/network-list token networks)
|
||||
:available-balance (utils/calculate-total-token-balance token)
|
||||
:total-balance (utils/calculate-total-token-balance token
|
||||
chain-ids)))
|
||||
(:tokens account))
|
||||
token (first (filter #(= (string/lower-case (:symbol %))
|
||||
(string/lower-case token-symbol))
|
||||
tokens))]
|
||||
token)))
|
||||
(fn [[{:keys [tokens]} networks] [_ token-symbol chain-ids]]
|
||||
(->> (utils/tokens-with-balance tokens networks chain-ids)
|
||||
(filter #(= (string/lower-case (:symbol %))
|
||||
(string/lower-case token-symbol)))
|
||||
first)))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/accounts-without-current-viewing-account
|
||||
|
|
|
@ -887,7 +887,7 @@
|
|||
(assoc :currencies currencies)
|
||||
(assoc-in [:profile/profile :currency] :usd)))
|
||||
(is (match? (count (rf/sub [sub-name ""])) 2))
|
||||
(is (match? (count (rf/sub [sub-name "et"])) 1))))
|
||||
(is (match? (count (rf/sub [sub-name "et"])) 2))))
|
||||
|
||||
(h/deftest-sub :wallet/selected-networks->chain-ids
|
||||
[sub-name]
|
||||
|
|
|
@ -1929,6 +1929,7 @@
|
|||
},
|
||||
"pinned-messages-empty": "Pinned messages will appear here. To pin a message, press and hold it and tap `Pin`",
|
||||
"podcasts": "Podcasts",
|
||||
"popular-assets-on-network": "Popular assets on {{network}}",
|
||||
"popular-currencies": "Popular currencies",
|
||||
"positive": "Positive",
|
||||
"powered-by-paraswap": "Powered by Paraswap",
|
||||
|
@ -2187,7 +2188,10 @@
|
|||
"select-account-first": "Select an account first",
|
||||
"select-another-account": "Select another account",
|
||||
"select-asset": "Select asset",
|
||||
"select-asset-on": "On",
|
||||
"select-asset-to-pay": "Select asset to pay",
|
||||
"select-asset-to-receive": "Select asset to receive",
|
||||
"select-asset-via": "via",
|
||||
"select-chat": "Select chat to start messaging",
|
||||
"select-network": "Select network",
|
||||
"select-networks": "Select networks",
|
||||
|
@ -2833,6 +2837,7 @@
|
|||
"you-will-start-from-scratch": "You will start from scratch with a new set of keys",
|
||||
"your-addresses": "Your addresses",
|
||||
"your-answer": "Your answer",
|
||||
"your-assets-on-network": "Your assets on {{network}}",
|
||||
"your-card-is-frozen": "Your Keycard is frozen. Reset card access",
|
||||
"your-contact-code": "Granting access authorizes this DApp to retrieve your chat key",
|
||||
"your-data-belongs-to-you": "If you lose your seed phrase you lose your data and funds",
|
||||
|
|
Loading…
Reference in New Issue