feat(swap): trigger swap transactions (#21134)
Signed-off-by: Brian Sztamfater <brian@status.im>
This commit is contained in:
parent
3ae500ff68
commit
e2d597401c
|
@ -9,6 +9,7 @@
|
|||
[:token-value :string]
|
||||
[:token-symbol :string]
|
||||
[:container-style {:optional true} [:maybe :map]]
|
||||
[:show-view-button? {:optional true} [:maybe :boolean]]
|
||||
[:button-props {:optional true} [:maybe :map]]
|
||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]]]]
|
||||
:any])
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
(defn- view-internal
|
||||
[{:keys [status token-value token-symbol
|
||||
container-style button-props]
|
||||
container-style button-props show-view-button?]
|
||||
:as props}]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
customization-color (or (:customization-color props) :blue)
|
||||
|
@ -56,7 +56,9 @@
|
|||
(i18n/label (status-message status)
|
||||
{:amount token-value
|
||||
:symbol token-symbol})]]
|
||||
(when button-props
|
||||
(when (and button-props
|
||||
(or (= status :approve)
|
||||
(and (not= status :approve) show-view-button?)))
|
||||
[button/button
|
||||
(merge {:type (if (= status :approve) :primary :grey)
|
||||
:background (when-not (= status :approve) :blur)
|
||||
|
|
|
@ -565,6 +565,7 @@
|
|||
(def ^:const bridge-name-erc-721-transfer "ERC721Transfer")
|
||||
(def ^:const bridge-name-erc-1155-transfer "ERC1155Transfer")
|
||||
(def ^:const bridge-name-hop "Hop")
|
||||
(def ^:const bridge-name-paraswap "Paraswap")
|
||||
|
||||
(def ^:const bridge-assets #{"ETH" "USDT" "USDC" "DAI"})
|
||||
|
||||
|
@ -605,3 +606,5 @@
|
|||
(def ^:const transaction-status-success "Success")
|
||||
(def ^:const transaction-status-pending "Pending")
|
||||
(def ^:const transaction-status-failed "Failed")
|
||||
|
||||
(def ^:const min-token-decimals-to-display 6)
|
||||
|
|
|
@ -407,7 +407,8 @@
|
|||
:TransferTx tx-data}))
|
||||
|
||||
(defn transaction-path
|
||||
[{:keys [from-address to-address token-id token-address route data eth-transfer?]}]
|
||||
[{:keys [from-address to-address token-id-from token-address token-id-to route data
|
||||
slippage-percentage eth-transfer?]}]
|
||||
(let [{:keys [bridge-name amount-in bonder-fees from
|
||||
to]} route
|
||||
tx-data (transaction-data {:from-address from-address
|
||||
|
@ -425,14 +426,14 @@
|
|||
(assoc :ERC721TransferTx
|
||||
(assoc tx-data
|
||||
:Recipient to-address
|
||||
:TokenID token-id
|
||||
:TokenID token-id-from
|
||||
:ChainID to-chain-id))
|
||||
|
||||
(= bridge-name constants/bridge-name-erc-1155-transfer)
|
||||
(assoc :ERC1155TransferTx
|
||||
(assoc tx-data
|
||||
:Recipient to-address
|
||||
:TokenID token-id
|
||||
:TokenID token-id-from
|
||||
:ChainID to-chain-id
|
||||
:Amount amount-in))
|
||||
|
||||
|
@ -444,18 +445,27 @@
|
|||
(assoc tx-data
|
||||
:ChainID from-chain-id
|
||||
:ChainIDTo to-chain-id
|
||||
:Symbol token-id
|
||||
:Symbol token-id-from
|
||||
:Recipient to-address
|
||||
:Amount amount-in
|
||||
:BonderFee bonder-fees))
|
||||
|
||||
(= bridge-name constants/bridge-name-paraswap)
|
||||
(assoc :SwapTx
|
||||
(assoc tx-data
|
||||
:ChainID from-chain-id
|
||||
:ChainIDTo to-chain-id
|
||||
:TokenIDFrom token-id-from
|
||||
:TokenIDTo token-id-to
|
||||
:SlippagePercentage slippage-percentage))
|
||||
|
||||
(not (or (= bridge-name constants/bridge-name-erc-721-transfer)
|
||||
(= bridge-name constants/bridge-name-transfer)
|
||||
(= bridge-name constants/bridge-name-hop)))
|
||||
(assoc :CbridgeTx
|
||||
(assoc tx-data
|
||||
:ChainID to-chain-id
|
||||
:Symbol token-id
|
||||
:Symbol token-id-from
|
||||
:Recipient to-address
|
||||
:Amount amount-in)))))
|
||||
|
||||
|
|
|
@ -618,7 +618,7 @@
|
|||
:from-address from-address
|
||||
:route route
|
||||
:token-address token-address
|
||||
:token-id (if collectible
|
||||
:token-id-from (if collectible
|
||||
(utils.hex/number-to-hex
|
||||
token-id)
|
||||
token-id)
|
||||
|
|
|
@ -20,10 +20,22 @@
|
|||
(= tx-status constants/transaction-status-failed)
|
||||
:failed)
|
||||
swap-approval-transaction-id (get-in db [:wallet :ui :swap :approval-transaction-id])
|
||||
swap-approval-transaction? (= swap-approval-transaction-id tx-hash)]
|
||||
swap-approval-transaction? (= swap-approval-transaction-id tx-hash)
|
||||
swap-transaction-ids (get-in db [:wallet :swap-transaction-ids])
|
||||
swap-transaction? (and swap-transaction-ids
|
||||
(contains? swap-transaction-ids tx-hash))]
|
||||
(cond-> {:db (update-in db [:wallet :transactions tx-hash] assoc :status status)}
|
||||
swap-approval-transaction?
|
||||
(assoc :fx [[:dispatch [:wallet.swap/approve-transaction-update status]]])))))
|
||||
(assoc :fx
|
||||
[[:dispatch
|
||||
[:wallet.swap/approve-transaction-update
|
||||
{:status status}]]])
|
||||
swap-transaction?
|
||||
(assoc :fx
|
||||
[[:dispatch
|
||||
[:wallet.swap/swap-transaction-update
|
||||
{:tx-hash tx-hash
|
||||
:status status}]]])))))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/signal-received
|
||||
|
|
|
@ -7,8 +7,11 @@
|
|||
[status-im.contexts.wallet.sheets.network-selection.view :as network-selection]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.address :as address]
|
||||
[utils.debounce :as debounce]
|
||||
[utils.hex :as hex]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.number]))
|
||||
[utils.number]
|
||||
[utils.number :as number]))
|
||||
|
||||
(rf/reg-event-fx :wallet.swap/start
|
||||
(fn [{:keys [_db]}]
|
||||
|
@ -95,6 +98,7 @@
|
|||
:fromLockedAmount from-locked-amount}
|
||||
amount-in (assoc :amountIn amount-in-hex)
|
||||
amount-out (assoc :amountOut amount-out-hex))]]
|
||||
|
||||
(when-let [amount (or amount-in amount-out)]
|
||||
{:db (update-in db
|
||||
[:wallet :ui :swap]
|
||||
|
@ -165,30 +169,38 @@
|
|||
|
||||
(rf/reg-event-fx :wallet/swap-transaction
|
||||
(fn [{:keys [db]} [sha3-pwd]]
|
||||
(let [wallet-address (get-in db [:wallet :current-viewing-account-address])
|
||||
{:keys [asset-to-pay swap-proposal network
|
||||
approval-transaction-id]} (get-in db [:wallet :ui :swap])
|
||||
(let [wallet-address (get-in db
|
||||
[:wallet
|
||||
:current-viewing-account-address])
|
||||
{:keys [asset-to-pay asset-to-receive
|
||||
swap-proposal network amount
|
||||
approval-transaction-id
|
||||
max-slippage]} (get-in db [:wallet :ui :swap])
|
||||
transactions (get-in db [:wallet :transactions])
|
||||
approval-transaction (when approval-transaction-id
|
||||
(get transactions approval-transaction-id))
|
||||
already-approved? (and approval-transaction
|
||||
(= (:status approval-transaction) :confirmed))
|
||||
(= (:status approval-transaction)
|
||||
:confirmed))
|
||||
approval-required? (and (:approval-required swap-proposal)
|
||||
(not already-approved?))
|
||||
multi-transaction-type constants/multi-transaction-type-swap
|
||||
swap-chain-id (:chain-id network)
|
||||
token-id (:symbol asset-to-pay)
|
||||
erc20-transfer? (and asset-to-pay (not= token-id "ETH"))
|
||||
token-id-from (:symbol asset-to-pay)
|
||||
token-id-to (:symbol asset-to-receive)
|
||||
erc20-transfer? (and asset-to-pay (not= token-id-from "ETH"))
|
||||
eth-transfer? (and asset-to-pay (not erc20-transfer?))
|
||||
token-address (when erc20-transfer?
|
||||
(get-in asset-to-pay
|
||||
[:balances-per-chain swap-chain-id :address]))
|
||||
[:balances-per-chain swap-chain-id
|
||||
:address]))
|
||||
data (when erc20-transfer?
|
||||
(native-module/encode-transfer
|
||||
(address/normalized-hex wallet-address)
|
||||
(:amount-in swap-proposal)))
|
||||
transaction-paths (if approval-required?
|
||||
[(utils/approval-path {:route swap-proposal
|
||||
[(utils/approval-path
|
||||
{:route swap-proposal
|
||||
:token-address token-address
|
||||
:from-address wallet-address
|
||||
:to-address wallet-address})]
|
||||
|
@ -197,18 +209,23 @@
|
|||
:from-address wallet-address
|
||||
:route swap-proposal
|
||||
:token-address token-address
|
||||
:token-id token-id
|
||||
:token-id-from token-id-from
|
||||
:token-id-to token-id-to
|
||||
:data data
|
||||
:slippage-percentage max-slippage
|
||||
:eth-transfer? eth-transfer?})])
|
||||
request-params [(utils/multi-transaction-command
|
||||
{:from-address wallet-address
|
||||
:to-address wallet-address
|
||||
:from-asset token-id
|
||||
:to-asset token-id
|
||||
:from-asset token-id-from
|
||||
:to-asset (if approval-required?
|
||||
token-id-from
|
||||
token-id-to)
|
||||
:amount-out (if eth-transfer?
|
||||
(:amount-out swap-proposal)
|
||||
"0x0")
|
||||
:multi-transaction-type multi-transaction-type})
|
||||
:multi-transaction-type
|
||||
multi-transaction-type})
|
||||
transaction-paths
|
||||
sha3-pwd]]
|
||||
(log/info "multi transaction called")
|
||||
|
@ -216,12 +233,49 @@
|
|||
:params request-params
|
||||
:on-success (fn [result]
|
||||
(when result
|
||||
(let [receive-token-decimals (:decimals asset-to-receive)
|
||||
amount-out (:amount-out swap-proposal)
|
||||
decimals-to-display
|
||||
(min
|
||||
receive-token-decimals
|
||||
constants/min-token-decimals-to-display)
|
||||
receive-amount (when amount-out
|
||||
(number/remove-trailing-zeroes
|
||||
(.toFixed (number/convert-to-whole-number
|
||||
(native-module/hex-to-number
|
||||
(hex/normalize-hex
|
||||
amount-out))
|
||||
receive-token-decimals)
|
||||
decimals-to-display)))]
|
||||
(rf/dispatch [:wallet.swap/add-authorized-transaction
|
||||
{:transaction result
|
||||
:approval-transaction? approval-required?}])
|
||||
(cond-> {:transaction result
|
||||
:approval-transaction?
|
||||
approval-required?}
|
||||
(not approval-required?)
|
||||
(assoc :swap-data
|
||||
{:pay-token-symbol token-id-from
|
||||
:pay-amount amount
|
||||
:receive-token-symbol token-id-to
|
||||
:receive-amount receive-amount}))])
|
||||
(rf/dispatch [:hide-bottom-sheet])
|
||||
(rf/dispatch [:dismiss-modal
|
||||
:screen/wallet.swap-set-spending-cap])
|
||||
(rf/dispatch [:hide-bottom-sheet])))
|
||||
(if approval-required?
|
||||
:screen/wallet.swap-set-spending-cap
|
||||
:screen/wallet.swap-confirmation)])
|
||||
(when-not approval-required?
|
||||
(rf/dispatch [:wallet/select-account-tab :activity])
|
||||
(debounce/debounce-and-dispatch [:wallet/clean-swap] 1000)
|
||||
(debounce/debounce-and-dispatch
|
||||
[:toasts/upsert
|
||||
{:id :swap-transaction-pending
|
||||
:icon :i/info
|
||||
:type :neutral
|
||||
:text (i18n/label :t/swapping-to
|
||||
{:pay-amount amount
|
||||
:pay-token-symbol token-id-from
|
||||
:receive-token-symbol token-id-to
|
||||
:receive-amount receive-amount})}]
|
||||
500)))))
|
||||
:on-error (fn [error]
|
||||
(log/error "failed swap transaction"
|
||||
{:event :wallet/swap-transaction
|
||||
|
@ -233,20 +287,30 @@
|
|||
:text (:message error)}]))}]})))
|
||||
|
||||
(rf/reg-event-fx :wallet.swap/add-authorized-transaction
|
||||
(fn [{:keys [db]} [{:keys [transaction approval-transaction?]}]]
|
||||
(let [transaction-batch-id (:id transaction)
|
||||
(fn [{:keys [db]} [{:keys [transaction swap-data approval-transaction?]}]]
|
||||
(let [transactions (get-in db [:wallet :transactions] {})
|
||||
transaction-batch-id (:id transaction)
|
||||
transaction-hashes (:hashes transaction)
|
||||
transaction-ids (flatten (vals transaction-hashes))
|
||||
transaction-details (send-utils/map-multitransaction-by-ids transaction-batch-id
|
||||
transaction-hashes)]
|
||||
transaction-id (first transaction-ids)
|
||||
transaction-details (cond-> (send-utils/map-multitransaction-by-ids transaction-batch-id
|
||||
transaction-hashes)
|
||||
:always (assoc-in [transaction-id :tx-type] :swap)
|
||||
swap-data (assoc-in [transaction-id :swap-data] swap-data))
|
||||
swap-transaction-ids (get-in db [:wallet :swap-transaction-ids])]
|
||||
{:db (cond-> db
|
||||
:always (assoc-in [:wallet :transactions] transaction-details)
|
||||
:always (assoc-in [:wallet :transactions]
|
||||
(merge transactions transaction-details))
|
||||
:always (assoc-in [:wallet :ui :swap :transaction-ids] transaction-ids)
|
||||
approval-transaction? (assoc-in [:wallet :ui :swap :approval-transaction-id]
|
||||
(first transaction-ids)))})))
|
||||
transaction-id)
|
||||
(not approval-transaction?) (assoc-in [:wallet :swap-transaction-ids]
|
||||
(if swap-transaction-ids
|
||||
(conj swap-transaction-ids transaction-id)
|
||||
(hash-set transaction-id))))})))
|
||||
|
||||
(rf/reg-event-fx :wallet.swap/approve-transaction-update
|
||||
(fn [{:keys [db]} [status]]
|
||||
(fn [{:keys [db]} [{:keys [status]}]]
|
||||
(let [{:keys [amount asset-to-pay swap-proposal]} (get-in db [:wallet :ui :swap])
|
||||
provider-name (:bridge-name swap-proposal)
|
||||
token-symbol (:symbol asset-to-pay)
|
||||
|
@ -276,3 +340,27 @@
|
|||
:account-name account-name}))}]]]}
|
||||
(not transaction-confirmed?)
|
||||
(assoc :db (update-in db [:wallet :ui :swap] dissoc :approval-transaction-id)))))))
|
||||
|
||||
(rf/reg-event-fx :wallet.swap/swap-transaction-update
|
||||
(fn [{:keys [db]} [{:keys [tx-hash status]}]]
|
||||
(let [{:keys [pay-amount pay-token-symbol
|
||||
receive-amount receive-token-symbol]} (get-in db
|
||||
[:wallet :transactions tx-hash
|
||||
:swap-data])
|
||||
transaction-confirmed-or-failed? (#{:confirmed :failed} status)
|
||||
transaction-confirmed? (= status :confirmed)]
|
||||
(when transaction-confirmed-or-failed?
|
||||
{:db (-> db
|
||||
(update-in [:wallet :swap-transaction-ids] disj tx-hash)
|
||||
(update-in [:wallet :transactions] dissoc tx-hash))
|
||||
:fx [[:dispatch
|
||||
[:toasts/upsert
|
||||
{:id :swap-transaction-update
|
||||
:type (if transaction-confirmed? :positive :negative)
|
||||
:text (if transaction-confirmed?
|
||||
(i18n/label :t/swapped-to
|
||||
{:pay-amount pay-amount
|
||||
:pay-token-symbol pay-token-symbol
|
||||
:receive-token-symbol receive-token-symbol
|
||||
:receive-amount receive-amount})
|
||||
(i18n/label :t/swap-failed))}]]]}))))
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
[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 "SNT"])]
|
||||
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)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
(ns status-im.contexts.wallet.swap.set-spending-cap.view
|
||||
(:require
|
||||
[native-module.core :as native-module]
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.resources :as resources]
|
||||
[quo.theme :as quo.theme]
|
||||
|
@ -12,26 +11,17 @@
|
|||
[status-im.contexts.wallet.common.utils.external-links :as external-links]
|
||||
[status-im.contexts.wallet.swap.set-spending-cap.style :as style]
|
||||
[utils.address :as address-utils]
|
||||
[utils.hex :as hex]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.number :as number]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.security.core :as security]))
|
||||
|
||||
(defn- swap-title
|
||||
[]
|
||||
(let [asset-to-pay (rf/sub [:wallet/swap-asset-to-pay])
|
||||
amount-in (rf/sub [:wallet/swap-proposal-amount-in])
|
||||
pay-amount (rf/sub [:wallet/swap-pay-amount])
|
||||
account (rf/sub [:wallet/current-viewing-account])
|
||||
provider (rf/sub [:wallet/swap-proposal-provider])
|
||||
pay-token-symbol (:symbol asset-to-pay)
|
||||
pay-token-decimals (:decimals asset-to-pay)
|
||||
pay-amount (when amount-in
|
||||
(number/convert-to-whole-number
|
||||
(native-module/hex-to-number
|
||||
(hex/normalize-hex
|
||||
amount-in))
|
||||
pay-token-decimals))]
|
||||
pay-token-symbol (:symbol asset-to-pay)]
|
||||
[rn/view {:style style/content-container}
|
||||
[rn/view {:style {:flex-direction :row}}
|
||||
[quo/text
|
||||
|
@ -74,15 +64,8 @@
|
|||
[]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
asset-to-pay (rf/sub [:wallet/swap-asset-to-pay])
|
||||
amount-in (rf/sub [:wallet/swap-proposal-amount-in])
|
||||
pay-token-symbol (:symbol asset-to-pay)
|
||||
pay-token-decimals (:decimals asset-to-pay)
|
||||
pay-amount (when amount-in
|
||||
(number/convert-to-whole-number
|
||||
(native-module/hex-to-number
|
||||
(hex/normalize-hex
|
||||
amount-in))
|
||||
pay-token-decimals))]
|
||||
pay-amount (rf/sub [:wallet/swap-pay-amount])
|
||||
pay-token-symbol (:symbol asset-to-pay)]
|
||||
[rn/view {:style style/summary-section-container}
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
|
@ -100,16 +83,9 @@
|
|||
[]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
asset-to-pay (rf/sub [:wallet/swap-asset-to-pay])
|
||||
amount-in (rf/sub [:wallet/swap-proposal-amount-in])
|
||||
account (rf/sub [:wallet/current-viewing-account])
|
||||
pay-token-symbol (:symbol asset-to-pay)
|
||||
pay-token-decimals (:decimals asset-to-pay)
|
||||
pay-amount (when amount-in
|
||||
(number/convert-to-whole-number
|
||||
(native-module/hex-to-number
|
||||
(hex/normalize-hex
|
||||
amount-in))
|
||||
pay-token-decimals))]
|
||||
pay-amount (rf/sub [:wallet/swap-pay-amount])
|
||||
pay-token-symbol (:symbol asset-to-pay)]
|
||||
[rn/view {:style style/summary-section-container}
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
|
@ -216,14 +192,14 @@
|
|||
{:title (i18n/label :t/network)
|
||||
:subtitle (:full-name network)
|
||||
:network-image (:source network)}]
|
||||
[data-item
|
||||
{:title (i18n/label :t/est-time)
|
||||
:subtitle (i18n/label :t/time-in-mins {:minutes (str estimated-time)})}]
|
||||
[data-item
|
||||
{:title (i18n/label :t/max-fees)
|
||||
:subtitle max-fees
|
||||
:loading? loading-fees?
|
||||
:size :small}]]]))
|
||||
:size :small}]
|
||||
[data-item
|
||||
{:title (i18n/label :t/est-time)
|
||||
:subtitle (i18n/label :t/time-in-mins {:minutes (str estimated-time)})}]]]))
|
||||
|
||||
(defn- slide-button
|
||||
[]
|
||||
|
@ -234,7 +210,7 @@
|
|||
(security/safe-unmask-data %)]))]
|
||||
[standard-auth/slide-button
|
||||
{:size :size-48
|
||||
:track-text (i18n/label :t/slide-to-swap)
|
||||
:track-text (i18n/label :t/slide-to-sign)
|
||||
:container-style {:z-index 2}
|
||||
:customization-color (:color account)
|
||||
:disabled? loading-fees?
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
[native-module.core :as native-module]
|
||||
[quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[status-im.common.controlled-input.utils :as controlled-input]
|
||||
[status-im.common.events-helper :as events-helper]
|
||||
|
@ -17,7 +18,6 @@
|
|||
[utils.re-frame :as rf]
|
||||
[utils.string :as utils.string]))
|
||||
|
||||
(def ^:private min-token-decimals-to-display 6)
|
||||
(def ^:private default-text-for-unfocused-input "0.00")
|
||||
|
||||
(defn- on-close
|
||||
|
@ -94,7 +94,7 @@
|
|||
(.toFixed (money/bignumber
|
||||
pay-token-balance-selected-chain)
|
||||
(min pay-token-decimals
|
||||
min-token-decimals-to-display)))
|
||||
constants/min-token-decimals-to-display)))
|
||||
approval-amount-required-num (when approval-amount-required
|
||||
(str (number/convert-to-whole-number
|
||||
(native-module/hex-to-number
|
||||
|
@ -128,13 +128,14 @@
|
|||
:customization-color :blue
|
||||
:show-approval-label? (and swap-proposal approval-required)
|
||||
:auto-focus? true
|
||||
:show-keyboard? false
|
||||
:status (cond
|
||||
(and loading-swap-proposal? (not input-focused?)) :loading
|
||||
input-focused? :typing
|
||||
:else :disabled)
|
||||
:currency-symbol currency-symbol
|
||||
:on-token-press on-token-press
|
||||
:on-max-press on-max-press
|
||||
:on-max-press #(on-max-press available-crypto-limit)
|
||||
:on-input-focus on-input-focus
|
||||
:value pay-input-amount
|
||||
:fiat-value pay-token-fiat-value
|
||||
|
@ -177,7 +178,8 @@
|
|||
amount-out))
|
||||
receive-token-decimals))
|
||||
amount-out-num (if amount-out-whole-number
|
||||
(str amount-out-whole-number)
|
||||
(number/remove-trailing-zeroes
|
||||
(.toFixed amount-out-whole-number receive-token-decimals))
|
||||
default-text-for-unfocused-input)
|
||||
receive-token-fiat-value (str (utils/calculate-token-fiat-value
|
||||
{:currency currency
|
||||
|
@ -191,6 +193,7 @@
|
|||
:show-approval-label? false
|
||||
:enable-swap? true
|
||||
:input-disabled? true
|
||||
:show-keyboard? false
|
||||
:status (cond
|
||||
(and loading-swap-proposal? (not input-focused?)) :loading
|
||||
input-focused? :typing
|
||||
|
@ -226,17 +229,16 @@
|
|||
(let [[pay-input-state set-pay-input-state] (rn/use-state controlled-input/init-state)
|
||||
[pay-input-focused? set-pay-input-focused?] (rn/use-state true)
|
||||
error-response (rf/sub [:wallet/swap-error-response])
|
||||
network (rf/sub [:wallet/swap-network])
|
||||
loading-swap-proposal? (rf/sub [:wallet/swap-loading-swap-proposal?])
|
||||
swap-proposal (rf/sub [:wallet/swap-proposal])
|
||||
asset-to-pay (rf/sub [:wallet/swap-asset-to-pay])
|
||||
pay-input-amount (controlled-input/input-value pay-input-state)
|
||||
pay-token-decimals (:decimals asset-to-pay)
|
||||
network-chain-id (:chain-id network)
|
||||
pay-token-balance-selected-chain (get-in asset-to-pay
|
||||
[:balances-per-chain network-chain-id
|
||||
:balance]
|
||||
0)
|
||||
on-review-swap-press (rn/use-callback
|
||||
(fn []
|
||||
(rf/dispatch [:navigate-to-within-stack
|
||||
[:screen/wallet.swap-confirmation
|
||||
:screen/wallet.setup-swap]])))
|
||||
on-press (rn/use-callback
|
||||
(fn [c]
|
||||
(let
|
||||
|
@ -256,7 +258,14 @@
|
|||
(fn []
|
||||
(set-pay-input-state
|
||||
controlled-input/delete-last)
|
||||
(rf/dispatch [:wallet/clean-swap-proposal])))]
|
||||
(rf/dispatch [:wallet/clean-swap-proposal])))
|
||||
on-max-press (rn/use-callback
|
||||
(fn [max-value]
|
||||
(set-pay-input-state
|
||||
(fn [input-state]
|
||||
(controlled-input/set-input-value
|
||||
input-state
|
||||
max-value)))))]
|
||||
[rn/view {:style style/container}
|
||||
[account-switcher/view
|
||||
{:on-press on-close
|
||||
|
@ -266,11 +275,13 @@
|
|||
[rn/view {:style style/inputs-container}
|
||||
[pay-token-input
|
||||
{:input-state pay-input-state
|
||||
:on-max-press #(set-pay-input-state pay-token-balance-selected-chain)
|
||||
:on-max-press on-max-press
|
||||
:input-focused? pay-input-focused?
|
||||
:on-token-press #(js/alert "Token Pressed")
|
||||
:on-approve-press #(rf/dispatch [:open-modal :screen/wallet.swap-set-spending-cap])
|
||||
:on-input-focus #(set-pay-input-focused? true)}]
|
||||
:on-input-focus (fn []
|
||||
(when platform/android? (rf/dispatch [:dismiss-keyboard]))
|
||||
(set-pay-input-focused? true))}]
|
||||
[swap-order-button {:on-press #(js/alert "Swap Order Pressed")}]
|
||||
[receive-token-input
|
||||
{:input-focused? (not pay-input-focused?)
|
||||
|
@ -283,8 +294,7 @@
|
|||
:text (i18n/label :t/something-went-wrong-please-try-again-later)}])
|
||||
(when (or loading-swap-proposal? swap-proposal)
|
||||
[transaction-details])
|
||||
[action-button
|
||||
{:on-press #(js/alert "Review swap pressed")}]]
|
||||
[action-button {:on-press on-review-swap-press}]]
|
||||
[quo/numbered-keyboard
|
||||
{:container-style style/keyboard-container
|
||||
:left-action :dot
|
||||
|
|
|
@ -37,3 +37,7 @@
|
|||
(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)})
|
||||
|
|
|
@ -1,23 +1,31 @@
|
|||
(ns status-im.contexts.wallet.swap.swap-confirmation.view
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[status-im.common.floating-button-page.view :as floating-button-page]
|
||||
[status-im.common.standard-authentication.core :as standard-auth]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.swap.swap-confirmation.style :as style]
|
||||
[utils.address :as address-utils]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
[utils.re-frame :as rf]
|
||||
[utils.security.core :as security]))
|
||||
|
||||
(defn- on-close-action
|
||||
[]
|
||||
(rf/dispatch [:navigate-back]))
|
||||
|
||||
(defn- swap-title
|
||||
[{:keys [pay-token-symbol pay-amount receive-token-symbol receive-amount account]}]
|
||||
[]
|
||||
(let [asset-to-pay (rf/sub [:wallet/swap-asset-to-pay])
|
||||
asset-to-receive (rf/sub [:wallet/swap-asset-to-receive])
|
||||
account (rf/sub [:wallet/current-viewing-account])
|
||||
receive-amount (rf/sub [:wallet/swap-receive-amount])
|
||||
pay-amount (rf/sub [:wallet/swap-pay-amount])
|
||||
pay-token-symbol (:symbol asset-to-pay)
|
||||
receive-token-symbol (:symbol asset-to-receive)]
|
||||
[rn/view {:style style/content-container}
|
||||
[rn/view {:style {:flex-direction :row}}
|
||||
[quo/text
|
||||
|
@ -52,7 +60,7 @@
|
|||
{:label (:name account)
|
||||
:type :account
|
||||
:emoji (:emoji account)
|
||||
:customization-color (:color account)}]]])
|
||||
:customization-color (:color account)}]]]))
|
||||
|
||||
(defn- summary-section
|
||||
[{:keys [theme label title-accessibility-label amount token-symbol token-address network]}]
|
||||
|
@ -74,6 +82,44 @@
|
|||
:address (address-utils/get-shortened-compressed-key token-address)
|
||||
:size 32}}]]))
|
||||
|
||||
(defn- pay-section
|
||||
[]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
asset-to-pay (rf/sub [:wallet/swap-asset-to-pay])
|
||||
network (rf/sub [:wallet/swap-network])
|
||||
pay-amount (rf/sub [:wallet/swap-pay-amount])
|
||||
network-chain-id (:chain-id network)
|
||||
network-name (:network-name network)
|
||||
pay-token-symbol (:symbol asset-to-pay)
|
||||
pay-token-address (get-in asset-to-pay [:balances-per-chain network-chain-id :address])]
|
||||
[summary-section
|
||||
{:title-accessibility-label :summary-section-pay
|
||||
:label (i18n/label :t/pay)
|
||||
:token-symbol pay-token-symbol
|
||||
:amount pay-amount
|
||||
:token-address pay-token-address
|
||||
:network network-name
|
||||
:theme theme}]))
|
||||
|
||||
(defn- receive-section
|
||||
[]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
asset-to-receive (rf/sub [:wallet/swap-asset-to-receive])
|
||||
network (rf/sub [:wallet/swap-network])
|
||||
receive-amount (rf/sub [:wallet/swap-receive-amount])
|
||||
network-chain-id (:chain-id network)
|
||||
network-name (:network-name network)
|
||||
receive-token-symbol (:symbol asset-to-receive)
|
||||
receive-token-address (get-in asset-to-receive [:balances-per-chain network-chain-id :address])]
|
||||
[summary-section
|
||||
{:title-accessibility-label :summary-section-receive
|
||||
:label (i18n/label :t/receive)
|
||||
:token-symbol receive-token-symbol
|
||||
:amount receive-amount
|
||||
:token-address receive-token-address
|
||||
:network network-name
|
||||
:theme theme}]))
|
||||
|
||||
(defn- data-item
|
||||
[{:keys [title subtitle loading?]}]
|
||||
[quo/data-item
|
||||
|
@ -86,64 +132,59 @@
|
|||
:subtitle subtitle}])
|
||||
|
||||
(defn- transaction-details
|
||||
[{:keys [estimated-time-min max-fees max-slippage loading-fees?]}]
|
||||
[]
|
||||
(let [max-fees (rf/sub [:wallet/wallet-swap-proposal-fee-fiat-formatted
|
||||
constants/token-for-fees-symbol])
|
||||
estimated-time (rf/sub [:wallet/swap-proposal-estimated-time])
|
||||
loading-fees? (rf/sub [:wallet/swap-loading-fees?])
|
||||
max-slippage (rf/sub [:wallet/swap-max-slippage])]
|
||||
[rn/view {:style style/details-container}
|
||||
[:<>
|
||||
[data-item
|
||||
{:title (i18n/label :t/est-time)
|
||||
:subtitle (i18n/label :t/time-in-mins {:minutes (str estimated-time-min)})}]
|
||||
:subtitle (i18n/label :t/time-in-mins {:minutes (str estimated-time)})}]
|
||||
[data-item
|
||||
{:title (i18n/label :t/max-fees)
|
||||
:subtitle max-fees
|
||||
:loading? loading-fees?}]
|
||||
[data-item
|
||||
{:title (i18n/label :t/max-slippage)
|
||||
:subtitle (str max-slippage "%")}]]])
|
||||
:subtitle (str max-slippage "%")}]]]))
|
||||
|
||||
(defn footer
|
||||
[{:keys [estimated-time-min native-currency-symbol max-slippage theme account-color provider
|
||||
loading-fees?]}]
|
||||
(let [fee-formatted (rf/sub [:wallet/wallet-send-fee-fiat-formatted native-currency-symbol])]
|
||||
[:<>
|
||||
[transaction-details
|
||||
{:estimated-time-min estimated-time-min
|
||||
:max-fees fee-formatted
|
||||
:max-slippage max-slippage
|
||||
:loading-fees? loading-fees?
|
||||
:theme theme}]
|
||||
(defn- slide-button
|
||||
[]
|
||||
(let [loading-fees? (rf/sub [:wallet/swap-loading-fees?])
|
||||
account (rf/sub [:wallet/current-viewing-account])
|
||||
account-color (:color account)
|
||||
on-auth-success (rn/use-callback #(rf/dispatch
|
||||
[:wallet/swap-transaction
|
||||
(security/safe-unmask-data %)]))]
|
||||
[standard-auth/slide-button
|
||||
{:size :size-48
|
||||
:track-text (i18n/label :t/slide-to-swap)
|
||||
:container-style {:z-index 2}
|
||||
:customization-color account-color
|
||||
:disabled? loading-fees?
|
||||
:auth-button-label (i18n/label :t/confirm)}]
|
||||
:auth-button-label (i18n/label :t/confirm)
|
||||
:on-auth-success on-auth-success}]))
|
||||
|
||||
(defn footer
|
||||
[]
|
||||
(let [provider (rf/sub [:wallet/swap-proposal-provider])
|
||||
theme (quo.theme/use-theme)]
|
||||
[:<>
|
||||
[transaction-details]
|
||||
[slide-button]
|
||||
[rn/view {:style style/providers-container}
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:style {:color (colors/theme-colors colors/neutral-80-opa-40
|
||||
colors/white-opa-70
|
||||
theme)}}
|
||||
(i18n/label :t/swaps-powered-by {:provider (:name provider)})]]]))
|
||||
:style (style/swaps-powered-by theme)}
|
||||
(i18n/label :t/swaps-powered-by {:provider (:full-name provider)})]]]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
swap-transaction-data (rf/sub [:wallet/swap])
|
||||
{:keys [asset-to-pay max-slippage network
|
||||
pay-amount providers swap-proposal
|
||||
loading-fees?]} swap-transaction-data
|
||||
receive-amount (:receive-amount swap-proposal)
|
||||
receive-token (:receive-token swap-proposal)
|
||||
receive-token-symbol (:symbol receive-token)
|
||||
receive-token-address (:address receive-token)
|
||||
estimated-time-min (:estimated-time swap-proposal)
|
||||
pay-token-symbol (:symbol asset-to-pay)
|
||||
pay-token-address (:address asset-to-pay)
|
||||
native-currency-symbol (get-in swap-proposal [:from :native-currency-symbol])
|
||||
account (rf/sub [:wallet/current-viewing-account])
|
||||
account-color (:color account)
|
||||
provider (first providers)]
|
||||
(let [account (rf/sub [:wallet/current-viewing-account])
|
||||
account-color (:color account)]
|
||||
[rn/view {:style {:flex 1}}
|
||||
[floating-button-page/view
|
||||
{:footer-container-padding 0
|
||||
|
@ -153,36 +194,10 @@
|
|||
:margin-top (safe-area/get-top)
|
||||
:background :blur
|
||||
:accessibility-label :top-bar}]
|
||||
:footer [footer
|
||||
{:estimated-time-min estimated-time-min
|
||||
:native-currency-symbol native-currency-symbol
|
||||
:max-slippage max-slippage
|
||||
:account-color account-color
|
||||
:provider provider
|
||||
:loading-fees? loading-fees?
|
||||
:theme theme}]
|
||||
:footer [footer]
|
||||
:gradient-cover? true
|
||||
:customization-color account-color}
|
||||
[rn/view
|
||||
[swap-title
|
||||
{:pay-token-symbol pay-token-symbol
|
||||
:pay-amount pay-amount
|
||||
:receive-token-symbol receive-token-symbol
|
||||
:receive-amount receive-amount
|
||||
:account account}]
|
||||
[summary-section
|
||||
{:title-accessibility-label :summary-section-pay
|
||||
:label (i18n/label :t/pay)
|
||||
:token-symbol pay-token-symbol
|
||||
:amount pay-amount
|
||||
:token-address pay-token-address
|
||||
:network (:network-name network)
|
||||
:theme theme}]
|
||||
[summary-section
|
||||
{:title-accessibility-label :summary-section-receive
|
||||
:label (i18n/label :t/receive)
|
||||
:token-symbol receive-token-symbol
|
||||
:amount receive-amount
|
||||
:token-address receive-token-address
|
||||
:network (:network-name network)
|
||||
:theme theme}]]]]))
|
||||
[swap-title]
|
||||
[pay-section]
|
||||
[receive-section]]]]))
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
(ns status-im.subs.wallet.swap
|
||||
(:require [clojure.string :as string]
|
||||
[native-module.core :as native-module]
|
||||
[re-frame.core :as rf]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.common.utils :as utils]
|
||||
[status-im.contexts.wallet.send.utils :as send-utils]
|
||||
[utils.money :as money]))
|
||||
[utils.hex :as hex]
|
||||
[utils.money :as money]
|
||||
[utils.number :as number]))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/swap
|
||||
|
@ -112,6 +115,44 @@
|
|||
:<- [:wallet/swap-proposal]
|
||||
:-> :amount-in)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/swap-receive-amount
|
||||
:<- [:wallet/swap-proposal-amount-out]
|
||||
:<- [:wallet/swap-asset-to-receive]
|
||||
(fn [[amount-out asset-to-receive]]
|
||||
(let [receive-token-decimals (:decimals asset-to-receive)
|
||||
receive-amount (when amount-out
|
||||
(number/convert-to-whole-number
|
||||
(native-module/hex-to-number
|
||||
(hex/normalize-hex
|
||||
amount-out))
|
||||
receive-token-decimals))
|
||||
receive-amount (when amount-out
|
||||
(number/remove-trailing-zeroes
|
||||
(.toFixed receive-amount
|
||||
(min receive-token-decimals
|
||||
constants/min-token-decimals-to-display))))]
|
||||
(or receive-amount 0))))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/swap-pay-amount
|
||||
:<- [:wallet/swap-proposal-amount-in]
|
||||
:<- [:wallet/swap-asset-to-pay]
|
||||
(fn [[amount-in asset-to-pay]]
|
||||
(let [pay-token-decimals (:decimals asset-to-pay)
|
||||
pay-amount (when amount-in
|
||||
(number/convert-to-whole-number
|
||||
(native-module/hex-to-number
|
||||
(hex/normalize-hex
|
||||
amount-in))
|
||||
pay-token-decimals))
|
||||
pay-amount (when amount-in
|
||||
(number/remove-trailing-zeroes
|
||||
(.toFixed pay-amount
|
||||
(min pay-token-decimals
|
||||
constants/min-token-decimals-to-display))))]
|
||||
(or pay-amount 0))))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/swap-proposal-provider
|
||||
:<- [:wallet/swap-proposal]
|
||||
|
|
|
@ -2368,6 +2368,9 @@
|
|||
"sun": "Sun",
|
||||
"swap": "Swap",
|
||||
"swap-details": "Swap details",
|
||||
"swap-failed": "Swap failed",
|
||||
"swapped-to": "Swapped {{pay-amount}} {{pay-token-symbol}} to {{receive-amount}} {{receive-token-symbol}}",
|
||||
"swapping-to": "Swapping {{pay-amount}} {{pay-token-symbol}} to {{receive-amount}} {{receive-token-symbol}}",
|
||||
"swaps-powered-by": "Swaps powered by {{provider}}",
|
||||
"switch-to-simple-interface": "Switch to simple interface",
|
||||
"symbol": "Symbol",
|
||||
|
|
Loading…
Reference in New Issue