feat(swap): set spending cap screen (#20727)

Signed-off-by: Brian Sztamfater <brian@status.im>
This commit is contained in:
Brian Sztamfater 2024-07-22 08:50:29 -03:00 committed by GitHub
parent 3b446963ef
commit 4b7c906df2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 314 additions and 3 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -28,6 +28,7 @@
{:type :spending-cap {:type :spending-cap
:label "Spending Cap" :label "Spending Cap"
:button-label "Edit" :button-label "Edit"
:button-icon :i/options
:on-button-press on-button-press :on-button-press on-button-press
:avatar-props {:image "image"}}]) :avatar-props {:image "image"}}])
(h/fire-event :press (h/get-by-text "Edit")) (h/fire-event :press (h/get-by-text "Edit"))

View File

@ -107,7 +107,7 @@
:style (style/description blur? theme)} :style (style/description blur? theme)}
description])] description])]
(when (= type :account) [tiny-tag/view {:label tag-label}]) (when (= type :account) [tiny-tag/view {:label tag-label}])
(when (= type :spending-cap) (when (and (= type :spending-cap) button-icon)
[button/button [button/button
{:type :outline {:type :outline
:size 24 :size 24

View File

@ -43,6 +43,7 @@
:gnosis (js/require "../resources/images/networks/Gnosis.png") :gnosis (js/require "../resources/images/networks/Gnosis.png")
:hermez (js/require "../resources/images/networks/Hermez.png") :hermez (js/require "../resources/images/networks/Hermez.png")
:optimism (js/require "../resources/images/networks/Optimism.png") :optimism (js/require "../resources/images/networks/Optimism.png")
:paraswap (js/require "../resources/images/networks/Paraswap.png")
:polygon (js/require "../resources/images/networks/Polygon.png") :polygon (js/require "../resources/images/networks/Polygon.png")
:scroll (js/require "../resources/images/networks/Scroll.png") :scroll (js/require "../resources/images/networks/Scroll.png")
:taiko (js/require "../resources/images/networks/Taiko.png") :taiko (js/require "../resources/images/networks/Taiko.png")

View File

@ -579,5 +579,8 @@
(def ^:const max-recommended-slippage 5) (def ^:const max-recommended-slippage 5)
(def ^:const max-slippage-decimal-places 2) (def ^:const max-slippage-decimal-places 2)
(def ^:const swap-default-provider (def ^:const swap-default-provider
{:name "Paraswap" {:name :paraswap
:full-name "Paraswap"
:color :blue
:contract-address "0xdef171fe48cf0115b1d80b88dc8eab59176fee57"
:terms-and-conditions-url "https://files.paraswap.io/tos_v4.pdf"}) :terms-and-conditions-url "https://files.paraswap.io/tos_v4.pdf"})

View File

@ -0,0 +1,40 @@
(ns status-im.contexts.wallet.swap.set-spending-cap.style
(:require [quo.foundations.colors :as colors]))
(def container
{:flex 1
:margin-top -20})
(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-horizontal 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
:padding-horizontal 1
: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)})

View File

@ -0,0 +1,253 @@
(ns status-im.contexts.wallet.swap.set-spending-cap.view
(:require
[quo.core :as quo]
[quo.foundations.resources :as resources]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[status-im.common.floating-button-page.view :as floating-button-page]
[status-im.common.standard-authentication.core :as standard-auth]
[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.i18n :as i18n]
[utils.navigation :as navigation]
[utils.re-frame :as rf]))
(defn- swap-title
[{:keys [pay-token-symbol pay-amount account provider]}]
[rn/view {:style style/content-container}
[rn/view {:style {:flex-direction :row}}
[quo/text
{:size :heading-1
:weight :semi-bold
:style style/title-container
:accessibility-label :set-spending-cap-of}
(i18n/label :t/set-spending-cap-of)]]
[rn/view {:style style/title-line-with-margin-top}
[quo/summary-tag
{:token pay-token-symbol
:label (str pay-amount " " pay-token-symbol)
:type :token}]
[quo/text
{:size :heading-1
:weight :semi-bold
:style style/title-container
:accessibility-label :for}
(i18n/label :t/for)]]
[rn/view {:style style/title-line-with-margin-top}
[quo/summary-tag
{:label (:full-name provider)
:type :network
:image-source (resources/get-network (:name provider))
:customization-color (:color provider)}]
[quo/text
{:size :heading-1
:weight :semi-bold
:style style/title-container
:accessibility-label :on}
(i18n/label :t/on)]]
[rn/view {:style style/title-line-with-margin-top}
[quo/summary-tag
{:label (:name account)
:type :account
:emoji (:emoji account)
:customization-color (:color account)}]]])
(defn- spending-cap-section
[{:keys [theme amount token-symbol]}]
[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)]
[quo/approval-info
{:type :spending-cap
:unlimited-icon? false
:label (str amount " " token-symbol)
:avatar-props {:token token-symbol}}]])
(defn- account-section
[{:keys [theme account pay-token-symbol pay-token-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)]
[quo/approval-info
{:type :account
:unlimited-icon? false
:label (:name account)
:description (address-utils/get-short-wallet-address (:address account))
:tag-label (str pay-token-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
[{:keys [theme token-address token-symbol network-chain-id]}]
[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)]
[quo/approval-info
{:type :token-contract
:option-icon :i/options
:on-option-press #(on-option-press {:chain-id network-chain-id
:contract-address token-address})
:unlimited-icon? false
:label token-symbol
:description (address-utils/get-short-wallet-address token-address)
:avatar-props {:token token-symbol}}]])
(defn- spender-contract-section
[{:keys [theme provider network-chain-id]}]
[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)]
[quo/approval-info
{:type :token-contract
:option-icon :i/options
:on-option-press #(on-option-press {:chain-id network-chain-id
:contract-address (:contract-address provider)})
:unlimited-icon? false
:label (:full-name provider)
:description (address-utils/get-short-wallet-address (:contract-address provider))
:avatar-props {:image (resources/get-network (:name provider))}}]])
(defn- data-item
[{:keys [network-image title subtitle size loading?]}]
[quo/data-item
{:container-style style/detail-item
:blur? false
:card? false
:network-image network-image
:subtitle-type (if network-image :network :default)
:status (if loading? :loading :default)
:title title
:subtitle subtitle
:size size}])
(defn- transaction-details
[{:keys [estimated-time-min max-fees network loading-fees?]}]
[rn/view {:style style/details-container}
[:<>
[data-item
{: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-min)})}]
[data-item
{:title (i18n/label :t/max-fees)
:subtitle max-fees
:loading? loading-fees?
:size :small}]]])
(defn footer
[{:keys [estimated-time-min native-currency-symbol network theme account-color loading-fees?]}]
(let [native-token (when native-currency-symbol
(rf/sub [:wallet/token-by-symbol
native-currency-symbol]))
fee-formatted (rf/sub [:wallet/wallet-send-fee-fiat-formatted
native-token])
on-auth-success (rn/use-callback #(js/alert "Not implemented yet"))]
[rn/view {:style {:margin-bottom -10}}
[transaction-details
{:estimated-time-min estimated-time-min
:max-fees fee-formatted
:network network
:loading-fees? loading-fees?
:theme theme}]
[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?
:on-auth-success on-auth-success
:auth-button-label (i18n/label :t/confirm)}]]))
(defn view
[]
(let [theme (quo.theme/use-theme)
swap-transaction-data (rf/sub [:wallet/swap])
{:keys [asset-to-pay network pay-amount
providers swap-proposal
loading-fees?]} swap-transaction-data
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)]
[rn/view {:style style/container}
[floating-button-page/view
{:footer-container-padding 0
:header [quo/page-nav
{:icon-name :i/close
:on-press navigation/navigate-back
:margin-top 8
:background :blur
:accessibility-label :top-bar}]
:footer [footer
{:estimated-time-min estimated-time-min
:native-currency-symbol native-currency-symbol
:network network
:account-color account-color
:provider provider
:loading-fees? loading-fees?
:theme theme}]
:gradient-cover? true
:customization-color account-color}
[:<>
[swap-title
{:pay-token-symbol pay-token-symbol
:pay-amount pay-amount
:account account
:provider provider}]
[spending-cap-section
{:token-symbol pay-token-symbol
:amount pay-amount
:theme theme}]
[account-section
{:account account
:pay-token-symbol pay-token-symbol
:pay-token-amount pay-amount
:theme theme}]
[token-section
{:token-symbol pay-token-symbol
:token-address pay-token-address
:network-chain-id (:chain-id network)
:theme theme}]
[spender-contract-section
{:provider provider
:network-chain-id (:chain-id network)
:theme theme}]]]]))

View File

@ -16,4 +16,7 @@
[quo/button [quo/button
{:on-press #(rf/dispatch [:navigate-to-within-stack {:on-press #(rf/dispatch [:navigate-to-within-stack
[:screen/wallet.swap-confirmation :screen/wallet.swap-propasal]])} [:screen/wallet.swap-confirmation :screen/wallet.swap-propasal]])}
"Swap confirmation"]])) "Swap confirmation"]
[quo/button
{:on-press #(rf/dispatch [:open-modal :screen/wallet.swap-set-spending-cap])}
"Set spending cap"]]))

View File

@ -118,6 +118,7 @@
[status-im.contexts.wallet.send.transaction-confirmation.view :as wallet-transaction-confirmation] [status-im.contexts.wallet.send.transaction-confirmation.view :as wallet-transaction-confirmation]
[status-im.contexts.wallet.send.transaction-progress.view :as wallet-transaction-progress] [status-im.contexts.wallet.send.transaction-progress.view :as wallet-transaction-progress]
[status-im.contexts.wallet.swap.select-asset-to-pay.view :as wallet-swap-select-asset-to-pay] [status-im.contexts.wallet.swap.select-asset-to-pay.view :as wallet-swap-select-asset-to-pay]
[status-im.contexts.wallet.swap.set-spending-cap.view :as wallet-swap-set-spending-cap]
[status-im.contexts.wallet.swap.swap-confirmation.view :as wallet-swap-confirmation] [status-im.contexts.wallet.swap.swap-confirmation.view :as wallet-swap-confirmation]
[status-im.contexts.wallet.swap.swap-proposal.view :as wallet-swap-propasal] [status-im.contexts.wallet.swap.swap-proposal.view :as wallet-swap-propasal]
[status-im.contexts.wallet.wallet-connect.modals.send-transaction.view :as [status-im.contexts.wallet.wallet-connect.modals.send-transaction.view :as
@ -526,6 +527,10 @@
:options {:modalPresentationStyle :overCurrentContext} :options {:modalPresentationStyle :overCurrentContext}
:component wallet-swap-confirmation/view} :component wallet-swap-confirmation/view}
{:name :screen/wallet.swap-set-spending-cap
:options {:sheet? true}
:component wallet-swap-set-spending-cap/view}
{:name :scan-profile-qr-code {:name :scan-profile-qr-code
:options (merge :options (merge
options/dark-screen options/dark-screen

View File

@ -18,6 +18,7 @@
"accepted": "Accepted", "accepted": "Accepted",
"access-existing-keys": "Access existing keys", "access-existing-keys": "Access existing keys",
"access-key": "Access key", "access-key": "Access key",
"account": "Account",
"account-added": "Account added", "account-added": "Account added",
"account-color": "Account color", "account-color": "Account color",
"account-content": "You can compare accounts in Status to bank accounts. Like a bank account, an account typically has an address and a balance; You use this account to transact on Ethereum. You can have multiple accounts in your wallet. All accessed by unlocking Status.", "account-content": "You can compare accounts in Status to bank accounts. Like a bank account, an account typically has an address and a balance; You use this account to transact on Ethereum. You can have multiple accounts in your wallet. All accessed by unlocking Status.",
@ -1016,6 +1017,7 @@
"fleet-settings": "Fleet settings", "fleet-settings": "Fleet settings",
"follow": "Follow", "follow": "Follow",
"follow-your-interests": "Jump into a public chat and meet new people", "follow-your-interests": "Jump into a public chat and meet new people",
"for": "for",
"for-airdrops": "For airdrops", "for-airdrops": "For airdrops",
"forgot-password": "Forgot password?", "forgot-password": "Forgot password?",
"forgot-your-password-info-create-new-password": "Create a new password", "forgot-your-password-info-create-new-password": "Create a new password",
@ -2189,6 +2191,7 @@
"set-dapp-access-permissions": "Set DApp access permissions", "set-dapp-access-permissions": "Set DApp access permissions",
"set-max": "Set max", "set-max": "Set max",
"set-nickname-toast": "You have renamed {{primary-name}} as {{nickname}}", "set-nickname-toast": "You have renamed {{primary-name}} as {{nickname}}",
"set-spending-cap-of": "Set spending cap of",
"set-up-sync": "Set up sync", "set-up-sync": "Set up sync",
"settings": "Settings", "settings": "Settings",
"setup-group-chat": "Setup group chat", "setup-group-chat": "Setup group chat",
@ -2285,6 +2288,8 @@
"specify-network-id": "Specify network id", "specify-network-id": "Specify network id",
"specify-server-public-key": "Enter server public key", "specify-server-public-key": "Enter server public key",
"specify-symbol": "Specify a symbol", "specify-symbol": "Specify a symbol",
"spender-contract": "Spender contract",
"spending-cap": "Spending cap",
"start-chat": "Start chat", "start-chat": "Start chat",
"start-conversation": "Start conversation", "start-conversation": "Start conversation",
"start-group-chat": "Start group chat", "start-group-chat": "Start group chat",