Screens for editing transaction settings

This commit is contained in:
Volodymyr Kozieiev 2024-12-17 15:25:01 +00:00
parent a85ca5bd3d
commit dd4e08a11a
No known key found for this signature in database
GPG Key ID: 82B04968DF4C0535
21 changed files with 587 additions and 152 deletions

View File

@ -133,7 +133,7 @@
[variant-colors] [variant-colors]
{:color (:label variant-colors)}) {:color (:label variant-colors)})
(def counter-container (def right-label-container
{:flex 1 {:flex 1
:align-items :flex-end}) :align-items :flex-end})

View File

@ -7,8 +7,8 @@
[react-native.core :as rn] [react-native.core :as rn]
[react-native.platform :as platform])) [react-native.platform :as platform]))
(defn- label-&-counter (defn- label-line
[{:keys [label current-chars char-limit variant-colors theme]}] [{:keys [label label-right current-chars char-limit variant-colors theme]}]
[rn/view [rn/view
{:accessibility-label :input-labels {:accessibility-label :input-labels
:style style/texts-container} :style style/texts-container}
@ -18,17 +18,25 @@
:weight :medium :weight :medium
:size :paragraph-2} :size :paragraph-2}
label]] label]]
(when-let [count-text (some->> char-limit (when label-right
(str current-chars "/"))] [rn/view {:style style/right-label-container}
[rn/view {:style style/counter-container}
[text/text [text/text
{:style (style/counter-color {:current-chars current-chars {:style (style/label-color variant-colors)
:char-limit char-limit
:variant-colors variant-colors
:theme theme})
:weight :regular :weight :regular
:size :paragraph-2} :size :paragraph-2}
count-text]])]) label-right]])
(when char-limit
(when-let [count-text (some->> char-limit
(str current-chars "/"))]
[rn/view {:style style/right-label-container}
[text/text
{:style (style/counter-color {:current-chars current-chars
:char-limit char-limit
:variant-colors variant-colors
:theme theme})
:weight :regular
:size :paragraph-2}
count-text]]))])
(defn- left-accessory (defn- left-accessory
[{:keys [variant-colors small? icon-name]}] [{:keys [variant-colors small? icon-name]}]
@ -65,7 +73,7 @@
(defn- base-input (defn- base-input
[{:keys [blur? error? right-icon left-icon disabled? small? button [{:keys [blur? error? right-icon left-icon disabled? small? button
label char-limit multiline? clearable? on-focus on-blur container-style input-container-style label char-limit multiline? clearable? on-focus on-blur container-style input-container-style
on-change-text on-char-limit-reach weight default-value on-clear placeholder] on-change-text on-char-limit-reach weight default-value on-clear placeholder label-right]
:as props}] :as props}]
(let [theme (quo.theme/use-theme) (let [theme (quo.theme/use-theme)
ref (rn/use-ref-atom nil) ref (rn/use-ref-atom nil)
@ -115,10 +123,11 @@
;; https://github.com/facebook/react-native/issues/27687 ;; https://github.com/facebook/react-native/issues/27687
modified-placeholder (if platform/android? (str "\u2009" placeholder) placeholder)] modified-placeholder (if platform/android? (str "\u2009" placeholder) placeholder)]
[rn/view {:style container-style} [rn/view {:style container-style}
(when (or label char-limit) (when (or label char-limit label-right)
[label-&-counter [label-line
{:variant-colors variant-colors {:variant-colors variant-colors
:label label :label label
:label-right label-right
:current-chars char-count :current-chars char-count
:char-limit char-limit :char-limit char-limit
:theme theme}]) :theme theme}])
@ -199,6 +208,7 @@
- :on-clear - Function executed when the clear button is pressed. - :on-clear - Function executed when the clear button is pressed.
- :button - Map containing `:on-press` & `:text` keys, if provided renders a button - :button - Map containing `:on-press` & `:text` keys, if provided renders a button
- :label - A string to set as label for this input. - :label - A string to set as label for this input.
- :label-right - Additional label aligned to the right
- :char-limit - A number to set a maximum char limit for this input. - :char-limit - A number to set a maximum char limit for this input.
- :on-char-limit-reach - Function executed each time char limit is reached or exceeded. - :on-char-limit-reach - Function executed each time char limit is reached or exceeded.
- :default-shown? - boolean to show password input initially - :default-shown? - boolean to show password input initially

View File

@ -32,8 +32,8 @@
:padding-bottom 2}) :padding-bottom 2})
(defn title-style (defn title-style
[{:keys [status theme]}] [{:keys [status theme networks-shown?]}]
{:padding-left 4 {:padding-left (if networks-shown? 4 0)
:margin-top -1 :margin-top -1
:color (when (= status :error) :color (when (= status :error)
(colors/theme-colors (colors/theme-colors

View File

@ -14,14 +14,16 @@
:theme theme :theme theme
:blur? blur?}) :blur? blur?})
container-style)} container-style)}
[preview-list/view (when networks
{:type :network [preview-list/view
:number (count networks) {:type :network
:size :size-16} :number (count networks)
networks] :size :size-16}
networks])
[text/text [text/text
{:weight :medium {:weight :medium
:size :paragraph-2 :size :paragraph-2
:style (style/title-style {:status status :style (style/title-style {:status status
:theme theme})} :theme theme
:networks-shown? networks})}
title]])) title]]))

View File

@ -9,9 +9,11 @@
[:currency-symbol [:maybe [:or :string :keyword]]] [:currency-symbol [:maybe [:or :string :keyword]]]
[:hint-component {:optional true} [:maybe :schema.common/hiccup]] [:hint-component {:optional true} [:maybe :schema.common/hiccup]]
[:on-token-press {:optional true} [:maybe fn?]] [:on-token-press {:optional true} [:maybe fn?]]
[:on-swap [:maybe fn?]] [:on-swap {:optional true} [:maybe fn?]]
[:container-style {:optional true} [:maybe :map]] [:container-style {:optional true} [:maybe :map]]
[:error? [:maybe :boolean]] [:error? [:maybe :boolean]]
[:show-token-icon? {:optional true} [:maybe :boolean]]
[:value [:maybe :string]] [:value [:maybe :string]]
[:converted-value [:maybe :string]]]]] [:converted-value {:optional true} [:maybe :string]]
[:swappable? {:optional true} [:maybe :boolean]]]]]
:any]) :any])

View File

@ -23,9 +23,8 @@
{:flex-direction :row {:flex-direction :row
:align-items :flex-end}) :align-items :flex-end})
(defn input-container (def input-container
[window-width] {:flex 1
{:width (- window-width 120)
:margin-left 8 :margin-left 8
:margin-right 8 :margin-right 8
:flex-direction :row :flex-direction :row

View File

@ -20,17 +20,18 @@
(string/upper-case (or (clj->js text) ""))]) (string/upper-case (or (clj->js text) ""))])
(defn input-section (defn input-section
[{:keys [token-symbol on-token-press value error? on-swap currency-symbol]}] [{:keys [token-symbol on-token-press value error? on-swap currency-symbol show-token-icon?
(let [theme (quo.theme/use-theme) swappable?]}]
window-width (:width (rn/get-window))] (let [theme (quo.theme/use-theme)]
[rn/pressable [rn/pressable
{:style {:width "100%" {:style {:width "100%"
:flex-direction :row} :flex-direction :row}
:on-press on-token-press} :on-press on-token-press}
[token/view (when show-token-icon?
{:token token-symbol [token/view
:size :size-32}] {:token token-symbol
[rn/view {:style (style/input-container window-width)} :size :size-32}])
[rn/view {:style style/input-container}
[rn/text-input [rn/text-input
{:style (style/text-input theme error?) {:style (style/text-input theme error?)
:placeholder-text-color (style/placeholder-text theme) :placeholder-text-color (style/placeholder-text theme)
@ -39,14 +40,15 @@
:editable false :editable false
:value value}] :value value}]
[token-name-text theme currency-symbol]] [token-name-text theme currency-symbol]]
[button/button (when swappable?
{:icon true [button/button
:icon-only? true {:icon true
:size 32 :icon-only? true
:on-press #(when on-swap (on-swap)) :size 32
:type :outline :on-press #(when on-swap (on-swap))
:accessibility-label :reorder} :type :outline
:i/reorder]])) :accessibility-label :reorder}
:i/reorder])]))
(defn- view-internal (defn- view-internal
[{:keys [token-symbol [{:keys [token-symbol
@ -57,26 +59,33 @@
on-swap on-swap
converted-value converted-value
hint-component hint-component
currency-symbol]}] show-token-icon?
currency-symbol
swappable?]
:or {show-token-icon? true
swappable? true}}]
(let [theme (quo.theme/use-theme) (let [theme (quo.theme/use-theme)
width (:width (rn/get-window))] width (:width (rn/get-window))]
[rn/view {:style (merge (style/main-container width) container-style)} [rn/view {:style (merge (style/main-container width) container-style)}
[rn/view {:style style/amount-container} [rn/view {:style style/amount-container}
[input-section [input-section
{:theme theme {:theme theme
:token-symbol token-symbol :token-symbol token-symbol
:on-token-press on-token-press :on-token-press on-token-press
:value value :value value
:error? error? :error? error?
:on-swap on-swap :on-swap on-swap
:currency-symbol currency-symbol}]] :currency-symbol currency-symbol
:show-token-icon? show-token-icon?
:swappable? swappable?}]]
[divider-line/view {:container-style (style/divider theme)}] [divider-line/view {:container-style (style/divider theme)}]
[rn/view {:style style/data-container} [rn/view {:style style/data-container}
hint-component hint-component
[text/text (when swappable?
{:size :paragraph-2 [text/text
:weight :medium {:size :paragraph-2
:style (style/converted-amount theme)} :weight :medium
converted-value]]])) :style (style/converted-amount theme)}
converted-value])]]))
(def view (schema/instrument #'view-internal component-schema/?schema)) (def view (schema/instrument #'view-internal component-schema/?schema))

View File

@ -54,7 +54,7 @@
(when (money/bignumber? (value-bn state)) (when (money/bignumber? (value-bn state))
(money/greater-than (value-bn state) (upper-limit-bn state))))) (money/greater-than (value-bn state) (upper-limit-bn state)))))
(defn- lower-limit-exceeded? (defn lower-limit-exceeded?
[state] [state]
(and (lower-limit state) (and (lower-limit state)
(when (money/bignumber? (value-bn state)) (when (money/bignumber? (value-bn state))
@ -78,16 +78,19 @@
(defn set-upper-limit (defn set-upper-limit
[state limit] [state limit]
(when limit (if limit
(-> state (-> state
(assoc :upper-limit limit) (assoc :upper-limit limit)
recheck-errorness))) recheck-errorness)
state))
(defn set-lower-limit (defn set-lower-limit
[state limit] [state limit]
(-> state (if limit
(assoc :lower-limit limit) (-> state
recheck-errorness)) (assoc :lower-limit limit)
recheck-errorness)
state))
(defn increase (defn increase
[state] [state]

View File

@ -23,29 +23,31 @@
:key :title} :key :title}
{:type :select {:type :select
:key :networks :key :networks
:options [{:key 1} :options [{:key 0}
{:key 1}
{:key 2} {:key 2}
{:key 3}]} {:key 3}]}
{:type :boolean {:type :boolean
:key :blur?}]) :key :blur?}])
(defn view (defn view
[] []
(let [state (reagent/atom {:title "Tag" (let [state (reagent/atom {:title "Tag"
:status :default :status :default
:networks 3})] :networks 3})]
(fn [] (fn []
[preview/preview-container (let [selected-networks-id (dec (:networks @state))]
{:state state [preview/preview-container
:descriptor descriptor {:state state
:blur? (:blur? @state) :descriptor descriptor
:show-blur-background? true} :blur? (:blur? @state)
[rn/view :show-blur-background? true}
{:style {:align-self :center [rn/view
:justify-content :center {:style {:align-self :center
:flex 1}} :justify-content :center
[quo/network-tags :flex 1}}
(assoc @state [quo/network-tags
:networks (assoc @state
(nth community-networks (dec (:networks @state))))]]]))) :networks
(when (pos? selected-networks-id)
(nth community-networks selected-networks-id)))]]]))))

View File

@ -22,21 +22,29 @@
[{:key :token-symbol [{:key :token-symbol
:type :select :type :select
:options [{:key :eth} :options [{:key :eth}
{:key :snt}]} {:key :snt}
{:key :gwei}
{:key :units}]}
{:key :currency {:key :currency
:type :select :type :select
:options [{:key "$"} :options [{:key "$"}
{:key "€"}]} {:key "€"}]}
{:key :error? {:key :error?
:type :boolean}
{:key :show-token-icon?
:type :boolean}
{:key :swappable?
:type :boolean}]) :type :boolean}])
(defn view (defn view
[] []
(let [state (reagent/atom {:token-symbol :eth (let [state (reagent/atom {:token-symbol :eth
:currency "$" :currency "$"
:crypto? true :crypto? true
:error? false})] :error? false
:show-token-icon? true
:swappable? true})]
(fn [] (fn []
(let [{:keys [currency token-symbol crypto? error?]} @state (let [{:keys [currency token-symbol crypto? error?]} @state
[input-state set-input-state] (rn/use-state controlled-input/init-state) [input-state set-input-state] (rn/use-state controlled-input/init-state)
@ -67,18 +75,20 @@
:component-container-style {:flex 1 :component-container-style {:flex 1
:justify-content :space-between}} :justify-content :space-between}}
[quo/token-input [quo/token-input
{:token-symbol token-symbol {:token-symbol token-symbol
:currency-symbol (if crypto? token-symbol currency) :currency-symbol (if crypto? token-symbol currency)
:error? error? :error? error?
:value input-amount :value input-amount
:converted-value converted-value :converted-value converted-value
:on-swap (fn [] :on-swap (fn []
(swap! state assoc :crypto? (not crypto?)) (swap! state assoc :crypto? (not crypto?))
(swap-between-fiat-and-crypto)) (swap-between-fiat-and-crypto))
:hint-component [quo/network-tags :hint-component [quo/network-tags
{:networks networks {:networks networks
:title title :title title
:status (when (:error? @state) :error)}]}] :status (when (:error? @state) :error)}]
:show-token-icon? (:show-token-icon? @state)
:swappable? (:swappable? @state)}]
[quo/numbered-keyboard [quo/numbered-keyboard
{:container-style {:padding-bottom (safe-area/get-top)} {:container-style {:padding-bottom (safe-area/get-top)}
:left-action :dot :left-action :dot

View File

@ -768,3 +768,41 @@
:always (update-in [:wallet :ui :send] dissoc :amount :route) :always (update-in [:wallet :ui :send] dissoc :amount :route)
(not keep-tx-data?) (update-in [:wallet :ui :send] dissoc :tx-type)) (not keep-tx-data?) (update-in [:wallet :ui :send] dissoc :tx-type))
:fx [[:dispatch [:navigate-back]]]}))) :fx [[:dispatch [:navigate-back]]]})))
(rf/reg-event-fx
:wallet/init-tx-settings
(fn [{db :db}]
{:db (assoc-in db
[:wallet :ui :send :tx-settings]
{:max-base-fee {:low 5
:current 8.2
:high 9}
:priority-fee {:low 0.6
:high 5.1
:current 1.1}
:max-gas-amount {:low 30000
:current 31000}
:nonce {:last-transaction 21
:current 22}})}))
(rf/reg-event-fx
:wallet/set-max-base-fee
(fn [{db :db} [value]]
{:db (assoc-in db [:wallet :ui :send :tx-settings :max-base-fee :current] value)}))
(rf/reg-event-fx
:wallet/set-priority-fee
(fn [{db :db} [value]]
{:db (assoc-in db [:wallet :ui :send :tx-settings :priority-fee :current] value)}))
(rf/reg-event-fx
:wallet/set-max-gas-amount
(fn [{db :db} [value]]
{:db (assoc-in db [:wallet :ui :send :tx-settings :max-gas-amount :current] value)}))
(rf/reg-event-fx
:wallet/set-nonce
(fn [{db :db} [value]]
{:db (assoc-in db [:wallet :ui :send :tx-settings :nonce :current] value)}))
#_(rf/dispatch [:wallet/init-tx-settings])

View File

@ -262,6 +262,11 @@
first-route) first-route)
(rf/dispatch [:wallet/build-transaction-for-collectible-route]))) (rf/dispatch [:wallet/build-transaction-for-collectible-route])))
[first-route]) [first-route])
;; Until we getting transaction params from status-go, we use placeholder values
(rn/use-mount
(fn []
(when (ff/enabled? ::ff/wallet.transaction-params)
(rf/dispatch [:wallet/init-tx-settings]))))
[rn/view {:style {:flex 1}} [rn/view {:style {:flex 1}}
[floating-button-page/view [floating-button-page/view
{:footer-container-padding 0 {:footer-container-padding 0

View File

@ -0,0 +1,30 @@
(ns status-im.contexts.wallet.send.transaction-settings.gas-amount.view
(:require
[quo.theme]
[status-im.contexts.wallet.send.transaction-settings.view :as transaction-settings]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn gas-amount-hint-text
[{:keys [current]} lower-limit-exceeded? _upper-limit-exceeded?]
(cond
lower-limit-exceeded? (i18n/label :t/gas-amount-lower {:current current})
:else (i18n/label :t/current-units {:current current})))
(defn view
[]
(let [suggested-values (rf/sub [:wallet/tx-settings-max-gas-amount])
hint-text (partial gas-amount-hint-text suggested-values)]
[transaction-settings/custom-setting-screen
{:screen-title (i18n/label :t/max-gas-amount)
:token-symbol :units
:hint-text-fn hint-text
:suggested-values suggested-values
:info-title (i18n/label :t/gas-amount)
:info-content (i18n/label :t/about-gas-amount)
:on-save (fn [new-val]
(rf/dispatch [:wallet/set-max-gas-amount new-val])
(rf/dispatch [:navigate-back])
(rf/dispatch [:show-bottom-sheet
{:content transaction-settings/custom-settings-sheet}]))
:with-decimals? false}]))

View File

@ -0,0 +1,30 @@
(ns status-im.contexts.wallet.send.transaction-settings.max-fee.view
(:require
[quo.theme]
[status-im.contexts.wallet.send.transaction-settings.view :as transaction-settings]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn max-base-fee-hint-text
[current lower-limit-exceeded? upper-limit-exceeded?]
(cond
upper-limit-exceeded? (i18n/label :t/max-base-fee-higher {:current current})
lower-limit-exceeded? (i18n/label :t/max-base-fee-lower {:current current})
:else (i18n/label :t/fee-current-gwei {:current current})))
(defn view
[]
(let [suggested-values (rf/sub [:wallet/tx-settings-max-base-fee])
hint-text (partial max-base-fee-hint-text (:current suggested-values))]
[transaction-settings/custom-setting-screen
{:screen-title (i18n/label :t/max-base-fee)
:token-sybmol :gwei
:hint-text-fn hint-text
:suggested-values suggested-values
:info-title (i18n/label :t/max-base-fee)
:info-content (i18n/label :t/about-max-base-fee)
:on-save (fn [new-val]
(rf/dispatch [:wallet/set-max-base-fee new-val])
(rf/dispatch [:navigate-back])
(rf/dispatch [:show-bottom-sheet
{:content transaction-settings/custom-settings-sheet}]))}]))

View File

@ -0,0 +1,78 @@
(ns status-im.contexts.wallet.send.transaction-settings.nonce.view
(:require
[quo.core :as quo]
[quo.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[status-im.common.controlled-input.utils :as controlled-input]
[status-im.contexts.wallet.send.transaction-settings.view :as transaction-settings]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn view
[]
(let [{:keys [last-transaction current]} (rf/sub [:wallet/tx-settings-nonce])
suggested-nonce (inc last-transaction)
[input-state set-input-state] (rn/use-state (controlled-input/set-value-numeric
controlled-input/init-state
current))
input-value (controlled-input/input-value input-state)
warning? (> (controlled-input/value-numeric input-state)
suggested-nonce)]
[rn/view
{:style {:flex 1}}
[quo/page-nav
{:type :title
:title (i18n/label :t/nonce)
:text-align :center
:right-side [{:icon-name :i/info
:on-press #(rf/dispatch [:show-bottom-sheet
{:content (fn [] [transaction-settings/info-sheet
(i18n/label :t/nonce)
(i18n/label :t/about-nonce)])}])}]
:icon-name :i/arrow-left
:on-press (fn []
(rf/dispatch [:navigate-back])
(rf/dispatch [:show-bottom-sheet
{:content transaction-settings/custom-settings-sheet}]))}]
[rn/view
{:style {:padding-horizontal 20
:gap 8}}
[quo/input
{:type :text
:label (i18n/label :t/type-nonce)
:label-right (i18n/label :t/last-transaction-is {:number last-transaction})
:editable false
:default-value input-value
:clearable? true
:error? warning?
:on-clear (fn []
(set-input-state controlled-input/delete-all))}]
(when warning?
[quo/text
{:style {:color colors/warning-50}
:weight :regular
:size :paragraph-2}
(i18n/label :t/nonce-higher {:number suggested-nonce})])]
[rn/view {:style {:flex 1}}]
[quo/bottom-actions
{:actions :one-action
:button-one-label (i18n/label :t/save-changes)
:button-one-props {:disabled? (controlled-input/empty-value? input-state)
:on-press (fn []
(rf/dispatch [:wallet/set-nonce
(controlled-input/value-numeric input-state)])
(rf/dispatch [:navigate-back])
(rf/dispatch [:show-bottom-sheet
{:content
transaction-settings/custom-settings-sheet}]))}}]
[quo/numbered-keyboard
{:container-style {:padding-bottom (safe-area/get-bottom)}
:left-action :none
:delete-key? true
:on-press (fn [c]
(set-input-state #(controlled-input/add-character % c)))
:on-delete (fn []
(set-input-state controlled-input/delete-last))
:on-long-press-delete (fn []
(set-input-state controlled-input/delete-all))}]]))

View File

@ -0,0 +1,30 @@
(ns status-im.contexts.wallet.send.transaction-settings.priority-fee.view
(:require
[quo.theme]
[status-im.contexts.wallet.send.transaction-settings.view :as transaction-settings]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn priority-fee-hint-text
[{:keys [current low high]} lower-limit-exceeded? upper-limit-exceeded?]
(cond
upper-limit-exceeded? (i18n/label :t/priority-fee-higher {:low low :high high})
lower-limit-exceeded? (i18n/label :t/priority-fee-lower {:low low :high high})
:else (i18n/label :t/fee-current-gwei {:current current})))
(defn view
[]
(let [suggested-values (rf/sub [:wallet/tx-settings-priority-fee])
hint-text (partial priority-fee-hint-text suggested-values)]
[transaction-settings/custom-setting-screen
{:screen-title (i18n/label :t/priority-fee)
:token-sybmol :gwei
:hint-text-fn hint-text
:suggested-values suggested-values
:info-title (i18n/label :t/priority-fee)
:info-content (i18n/label :t/about-priority-fee)
:on-save (fn [new-val]
(rf/dispatch [:wallet/set-priority-fee new-val])
(rf/dispatch [:navigate-back])
(rf/dispatch [:show-bottom-sheet
{:content transaction-settings/custom-settings-sheet}]))}]))

View File

@ -2,53 +2,68 @@
(:require (:require
[quo.core :as quo] [quo.core :as quo]
[react-native.core :as rn] [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]
[utils.i18n :as i18n] [utils.i18n :as i18n]
[utils.re-frame :as rf])) [utils.re-frame :as rf]))
(defn custom-settings-sheet (defn custom-settings-sheet
[_] [_]
[rn/view (let [max-base-fee (:current (rf/sub [:wallet/tx-settings-max-base-fee]))
[quo/drawer-top priority-fee (:current (rf/sub [:wallet/tx-settings-priority-fee]))
{:title "Custom"}] max-gas-amount (:current (rf/sub [:wallet/tx-settings-max-gas-amount]))
[quo/category nonce (:current (rf/sub [:wallet/tx-settings-nonce]))]
{:list-type :settings [rn/view
:data [{:title "Max base fee" [quo/drawer-top
:description-props {:text "8.2 GWEI - €1.45"} {:title "Custom"}]
:image :none [quo/category
:description :text {:list-type :settings
:action :arrow :data [{:title (i18n/label :t/max-base-fee)
:on-press #() :description-props {:text (str max-base-fee " GWEI")}
:label :text :image :none
:preview-size :size-32} :description :text
{:title "Priority fee" :action :arrow
:description-props {:text "0.06 GWEI - €0.03"} :on-press #(rf/dispatch [:navigate-to-within-stack
:image :none [:screen/wallet.tx-settings-max-fee
:description :text :screen/wallet.transaction-confirmation]])
:action :arrow :label :text
:on-press #() :preview-size :size-32}
:label :text {:title (i18n/label :t/priority-fee)
:preview-size :size-32} :description-props {:text (str priority-fee " GWEI")}
{:title "Gas amount" :image :none
:description-props {:text "31,500 UNITS"} :description :text
:image :none :action :arrow
:description :text :on-press #(rf/dispatch [:navigate-to-within-stack
:action :arrow [:screen/wallet.tx-settings-priority-fee
:on-press #() :screen/wallet.transaction-confirmation]])
:label :text :label :text
:preview-size :size-32} :preview-size :size-32}
{:title "Nonce" {:title (i18n/label :t/max-gas-amount)
:description-props {:text "22"} :description-props {:text (str max-gas-amount " UNITS")}
:image :none :image :none
:description :text :description :text
:action :arrow :action :arrow
:on-press #() :on-press #(rf/dispatch [:navigate-to-within-stack
:label :text [:screen/wallet.tx-settings-gas-amount
:preview-size :size-32}]}] :screen/wallet.transaction-confirmation]])
[quo/bottom-actions :label :text
{:actions :one-action :preview-size :size-32}
:button-one-props {:on-press #(rf/dispatch [:hide-bottom-sheet])} {:title (i18n/label :t/nonce)
:button-one-label (i18n/label :t/confirm)}]]) :description-props {:text nonce}
:image :none
:description :text
:action :arrow
:on-press #(rf/dispatch [:navigate-to-within-stack
[:screen/wallet.tx-settings-nonce
:screen/wallet.transaction-confirmation]])
:label :text
:preview-size :size-32}]}]
[quo/bottom-actions
{:actions :one-action
:button-one-props {:on-press #(rf/dispatch [:hide-bottom-sheet])}
:button-one-label (i18n/label :t/confirm)}]]))
(defn settings-sheet (defn settings-sheet
[_] [_]
@ -58,18 +73,27 @@
{:title "Transaction settings"}] {:title "Transaction settings"}]
[quo/category [quo/category
{:list-type :settings {:list-type :settings
:data [{:title "Normal ~60s" :data [{:title (str (i18n/label :t/normal) "~60s")
:image-props "🍿" :image-props
:description-props {:text "€1.45"} "🍿"
:image :emoji :description-props
:description :text {:text "€1.45"}
:action :selector :image
:action-props {:type :radio :emoji
:checked? (= :normal selected-id)} :description
:on-press #(set-selected-id :normal) :text
:label :text :action
:preview-size :size-32} :selector
{:title "Fast ~40s" :action-props
{:type :radio
:checked? (= :normal selected-id)}
:on-press
#(set-selected-id :normal)
:label
:text
:preview-size
:size-32}
{:title (str (i18n/label :t/fast) "~40s")
:image-props "🚗" :image-props "🚗"
:description-props {:text "€1.65"} :description-props {:text "€1.65"}
:image :emoji :image :emoji
@ -80,7 +104,7 @@
:on-press #(set-selected-id :fast) :on-press #(set-selected-id :fast)
:label :text :label :text
:preview-size :size-32} :preview-size :size-32}
{:title "Urgent ~15s" {:title (str (i18n/label :t/urgent) "~15s")
:image-props "🚀" :image-props "🚀"
:description-props {:text "€1.85"} :description-props {:text "€1.85"}
:image :emoji :image :emoji
@ -91,7 +115,7 @@
:on-press #(set-selected-id :urgent) :on-press #(set-selected-id :urgent)
:label :text :label :text
:preview-size :size-32} :preview-size :size-32}
{:title "Custom" {:title (i18n/label :t/custom)
:image-props :i/edit :image-props :i/edit
:description-props {:text "Set your own fees and nonce"} :description-props {:text "Set your own fees and nonce"}
:image :icon :image :icon
@ -106,3 +130,91 @@
{:actions :one-action {:actions :one-action
:button-one-props {:on-press #(rf/dispatch [:hide-bottom-sheet])} :button-one-props {:on-press #(rf/dispatch [:hide-bottom-sheet])}
:button-one-label (i18n/label :t/confirm)}]])) :button-one-label (i18n/label :t/confirm)}]]))
(defn- hint
[{:keys [error? text]}]
[quo/network-tags
{:title text
:status (when error? :error)}])
(defn info-sheet
[info-title info-content]
[quo/documentation-drawers
{:title info-title
:shell? true}
[rn/view
[quo/text {:size :paragraph-2} info-content]
[quo/button
{:type :outline
:size 24
:icon-right :i/info
:container-style {:padding-top 21
:padding-bottom (if platform/ios? 14 24)
:align-self :flex-start
:justify-content :center}
:on-press #()}
(i18n/label :t/read-more)]]])
(defn custom-setting-screen
[{:keys [screen-title token-symbol hint-text-fn suggested-values info-title info-content on-save
with-decimals?]
:or {with-decimals? true}}]
(let [[input-state set-input-state] (rn/use-state (controlled-input/set-value-numeric
controlled-input/init-state
(:current suggested-values)))
input-value (controlled-input/input-value input-state)
out-of-limits? (controlled-input/input-error input-state)
valid-input? (not (or (controlled-input/empty-value? input-state)
out-of-limits?))]
(rn/use-mount
(fn []
(set-input-state (fn [state]
(-> state
(controlled-input/set-upper-limit (:high suggested-values))
(controlled-input/set-lower-limit (:low suggested-values)))))))
[rn/view
{:style {:flex 1}}
[quo/page-nav
{:type :title
:title screen-title
:text-align :center
:right-side [{:icon-name :i/info
:on-press #(rf/dispatch [:show-bottom-sheet
{:content (fn [] [info-sheet info-title
info-content])}])}]
:icon-name :i/arrow-left
:on-press (fn []
(rf/dispatch [:navigate-back])
(rf/dispatch [:show-bottom-sheet
{:content custom-settings-sheet}]))}]
[quo/token-input
{:token-symbol token-symbol
:swappable? false
:show-token-icon? false
:value input-value
:error? out-of-limits?
:currency-symbol token-symbol
:hint-component [hint
{:error? out-of-limits?
:text (hint-text-fn
(controlled-input/lower-limit-exceeded? input-state)
(controlled-input/upper-limit-exceeded? input-state))}]}]
[rn/view {:style {:flex 1}}]
[quo/bottom-actions
{:actions :one-action
:button-one-label (i18n/label :t/save-changes)
:button-one-props {:disabled? (not valid-input?)
:on-press #(on-save (controlled-input/value-numeric input-state))}}]
[quo/numbered-keyboard
{:container-style {:padding-bottom (safe-area/get-bottom)}
:left-action (if with-decimals? :dot :none)
:delete-key? true
:on-press (fn [c]
(set-input-state #(controlled-input/add-character % c)))
:on-delete (fn []
(set-input-state controlled-input/delete-last))
:on-long-press-delete (fn []
(set-input-state controlled-input/delete-all))}]]))

View File

@ -30,8 +30,9 @@
(rf/defn navigate-to-within-stack (rf/defn navigate-to-within-stack
{:events [:navigate-to-within-stack]} {:events [:navigate-to-within-stack]}
[{:keys [db]} comp-id screen-params] [{:keys [db]} comp-id screen-params]
{:db (all-screens-params db (first comp-id) screen-params) {:db (all-screens-params db (first comp-id) screen-params)
:fx [[:navigate-to-within-stack (conj comp-id (:theme db))]]}) :dispatch-n [[:hide-bottom-sheet]]
:fx [[:navigate-to-within-stack (conj comp-id (:theme db))]]})
(re-frame/reg-event-fx :open-modal (re-frame/reg-event-fx :open-modal
(fn [{:keys [db]} [component screen-params]] (fn [{:keys [db]} [component screen-params]]

View File

@ -138,6 +138,12 @@
[status-im.contexts.wallet.send.send-amount.view :as wallet-send-input-amount] [status-im.contexts.wallet.send.send-amount.view :as wallet-send-input-amount]
[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.send.transaction-settings.gas-amount.view :as
wallet-tx-settings-gas-amount]
[status-im.contexts.wallet.send.transaction-settings.max-fee.view :as wallet-tx-settings-max-fee]
[status-im.contexts.wallet.send.transaction-settings.nonce.view :as wallet-tx-settings-nonce]
[status-im.contexts.wallet.send.transaction-settings.priority-fee.view :as
wallet-tx-settings-priority-fee]
[status-im.contexts.wallet.swap.select-account.view :as wallet-swap-select-account] [status-im.contexts.wallet.swap.select-account.view :as wallet-swap-select-account]
[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.set-spending-cap.view :as wallet-swap-set-spending-cap]
@ -623,7 +629,31 @@
:metrics {:track? true :metrics {:track? true
:alias-id :wallet-send.select-collectible-amount} :alias-id :wallet-send.select-collectible-amount}
:options {:insets {:top? true}} :options {:insets {:top? true}}
:component wallet-select-collectible-amount/view}]) :component wallet-select-collectible-amount/view}
{:name :screen/wallet.tx-settings-max-fee
:metrics {:track? true
:alias-id :wallet-send.tx-settings-max-fee}
:options {:insets {:top? true}}
:component wallet-tx-settings-max-fee/view}
{:name :screen/wallet.tx-settings-priority-fee
:metrics {:track? true
:alias-id :wallet-send.tx-settings-priority-fee}
:options {:insets {:top? true}}
:component wallet-tx-settings-priority-fee/view}
{:name :screen/wallet.tx-settings-gas-amount
:metrics {:track? true
:alias-id :wallet-send.tx-settings-gas-amount}
:options {:insets {:top? true}}
:component wallet-tx-settings-gas-amount/view}
{:name :screen/wallet.tx-settings-nonce
:metrics {:track? true
:alias-id :wallet-send.tx-settings-nonce}
:options {:insets {:top? true}}
:component wallet-tx-settings-nonce/view}])
(def wallet-bridge-screens (def wallet-bridge-screens
[{:name :screen/wallet.bridge-select-asset [{:name :screen/wallet.bridge-select-asset

View File

@ -173,3 +173,28 @@
(= (:chain-id network) bridge-to-chain-id) (= (:chain-id network) bridge-to-chain-id)
network)) network))
networks)))) networks))))
(rf/reg-sub
:wallet/tx-settings
:<- [:wallet/wallet-send]
:-> :tx-settings)
(rf/reg-sub
:wallet/tx-settings-max-base-fee
:<- [:wallet/tx-settings]
:-> :max-base-fee)
(rf/reg-sub
:wallet/tx-settings-priority-fee
:<- [:wallet/tx-settings]
:-> :priority-fee)
(rf/reg-sub
:wallet/tx-settings-max-gas-amount
:<- [:wallet/tx-settings]
:-> :max-gas-amount)
(rf/reg-sub
:wallet/tx-settings-nonce
:<- [:wallet/tx-settings]
:-> :nonce)

View File

@ -1,10 +1,14 @@
{ {
"about": "About", "about": "About",
"about-app": "About", "about-app": "About",
"about-gas-amount": "AKA gas limit. Refers to the maximum number of computational steps (or units of gas) that a transaction can consume. It represents the complexity or amount of work required to execute a transaction or smart contract.\n\nThe gas limit is a cap on how much work the transaction can do on the blockchain. If the gas limit is set too low, the transaction may fail due to insufficient gas.",
"about-key-storage-content": "Status will never access your private key. Be sure to backup your seed phrase. If you lose your phone it is the only way to access your keys.", "about-key-storage-content": "Status will never access your private key. Be sure to backup your seed phrase. If you lose your phone it is the only way to access your keys.",
"about-key-storage-title": "About key storage", "about-key-storage-title": "About key storage",
"about-max-base-fee": "When your transaction gets included in the block, any difference between your max base fee and the actual base fee will be refunded.",
"about-names-content": "No one can pretend to be you! Youre anonymous by default and never have to reveal your real name. You can register a custom name for a small fee.", "about-names-content": "No one can pretend to be you! Youre anonymous by default and never have to reveal your real name. You can register a custom name for a small fee.",
"about-names-title": "Names cant be changed", "about-names-title": "Names cant be changed",
"about-nonce": "Transaction counter ensuring transactions from your account are processed in the correct order and cant be replayed. Each new transaction increments the nonce by 1, ensuring uniqueness and preventing double-spending.\n\nIf a transaction with a lower nonce is pending, higher nonce transactions will remain in the queue until the earlier one is confirmed.",
"about-priority-fee": "AKA miner tip. A voluntary fee you can add to incentivise miners or validators to prioritise your transaction.\n\nThe higher the tip, the faster your transaction is likely to be processed, especially curing periods of higher network congestion.",
"about-sharing-data": "About sharing data", "about-sharing-data": "About sharing data",
"accent-colour": "Accent colour", "accent-colour": "Accent colour",
"accent-colour-updated": "Accent colour updated", "accent-colour-updated": "Accent colour updated",
@ -653,6 +657,7 @@
"current-password": "Current password", "current-password": "Current password",
"current-pin": "Enter 6-digit passcode", "current-pin": "Enter 6-digit passcode",
"current-pin-description": "Enter your 6-digit passcode to proceed", "current-pin-description": "Enter your 6-digit passcode to proceed",
"current-units": "Current: {{current}} UNITS",
"custom": "Custom", "custom": "Custom",
"custom-node": "You are using custom RPC endpoint. Your local transfers history might be incomplete.", "custom-node": "You are using custom RPC endpoint. Your local transfers history might be incomplete.",
"custom-seed-phrase": "Invalid seed phrase", "custom-seed-phrase": "Invalid seed phrase",
@ -1044,6 +1049,7 @@
"featured": "Featured", "featured": "Featured",
"feb": "Feb", "feb": "Feb",
"fee-cap": "Fee cap", "fee-cap": "Fee cap",
"fee-current-gwei": "Current: {{current}} GWEI",
"fee-explanation": "Maximum overall price for the transaction. If the block base fee exceeds this, it will be included in a following block with a lower base fee.", "fee-explanation": "Maximum overall price for the transaction. If the block base fee exceeds this, it will be included in a following block with a lower base fee.",
"fee-options": "Suggested fee options", "fee-options": "Suggested fee options",
"fees": "Fees", "fees": "Fees",
@ -1085,7 +1091,9 @@
"from-all-profiles-on-device": "From all profiles on device", "from-all-profiles-on-device": "From all profiles on device",
"from-capitalized": "From", "from-capitalized": "From",
"from-label": "From", "from-label": "From",
"gas-amount": "Gas amount",
"gas-amount-limit": "Gas amount limit", "gas-amount-limit": "Gas amount limit",
"gas-amount-lower": "Too low. Recommended: {{current}} UNITS",
"gas-limit": "Gas limit", "gas-limit": "Gas limit",
"gas-price": "Gas price", "gas-price": "Gas price",
"gas-used": "Gas used", "gas-used": "Gas used",
@ -1445,6 +1453,7 @@
"language-and-currency": "Language and currency", "language-and-currency": "Language and currency",
"last-backup-performed": "Last backup performed:", "last-backup-performed": "Last backup performed:",
"last-transaction": "Last transaction", "last-transaction": "Last transaction",
"last-transaction-is": "Last transaction: {{number}}",
"layer-2": "Layer 2", "layer-2": "Layer 2",
"learn-more": "Learn more", "learn-more": "Learn more",
"learn-more-about-keycard": "Learn more about Keycard", "learn-more-about-keycard": "Learn more about Keycard",
@ -1551,8 +1560,12 @@
"master-account": "Master account", "master-account": "Master account",
"max": "Max: {{number}}", "max": "Max: {{number}}",
"max-2-decimals": "Max. 2 decimals", "max-2-decimals": "Max. 2 decimals",
"max-base-fee": "Max base fee",
"max-base-fee-higher": "Higher than necessary. Current: {{current}} GWEI",
"max-base-fee-lower": "Too low. Current: {{current}} GWEI ",
"max-fee": "Max fee", "max-fee": "Max fee",
"max-fees": "Max fees", "max-fees": "Max fees",
"max-gas-amount": "Max gas amount",
"max-priority-fee": "Max priority fee", "max-priority-fee": "Max priority fee",
"max-slippage": "Max slippage", "max-slippage": "Max slippage",
"max-token": "Max: {{number}} {{token-symbol}}", "max-token": "Max: {{number}} {{token-symbol}}",
@ -1796,6 +1809,7 @@
"non-archival-node": "RPC endpoint doesn't support archival requests. Your local transfers history might be incomplete.", "non-archival-node": "RPC endpoint doesn't support archival requests. Your local transfers history might be incomplete.",
"non-contacts": "Non contacts", "non-contacts": "Non contacts",
"nonce": "Nonce", "nonce": "Nonce",
"nonce-higher": "Higher than suggested nonce of {{number}}",
"none": "None", "none": "None",
"normal": "Normal", "normal": "Normal",
"not-a-chatkey": "This is not a chatkey", "not-a-chatkey": "This is not a chatkey",
@ -2022,6 +2036,9 @@
"price-impact-too-high": "Price impact too high. Lower token amount or try again later.", "price-impact-too-high": "Price impact too high. Lower token amount or try again later.",
"principles": "Principles", "principles": "Principles",
"priority": "Priority", "priority": "Priority",
"priority-fee": "Priority fee",
"priority-fee-higher": "More than necessary. Current: {{low}} - {{high}} GWEI",
"priority-fee-lower": "Too low. Current: {{low}} - {{high}} GWEI",
"privacy": "Privacy", "privacy": "Privacy",
"privacy-and-security": "Privacy and security", "privacy-and-security": "Privacy and security",
"privacy-photos": "Profile Photo Privacy", "privacy-photos": "Profile Photo Privacy",
@ -2672,6 +2689,7 @@
"type": "Type", "type": "Type",
"type-a-message": "Message", "type-a-message": "Message",
"type-nickname": "Type nickname", "type-nickname": "Type nickname",
"type-nonce": "Type nonce",
"type-pairing-code": "Type or paste pairing code", "type-pairing-code": "Type or paste pairing code",
"type-slippage": "Type slippage", "type-slippage": "Type slippage",
"type-some-chat-key": "zQ3...1sgt5N", "type-some-chat-key": "zQ3...1sgt5N",
@ -2728,6 +2746,7 @@
"updates-to-tos": "Updates to Terms of Use", "updates-to-tos": "Updates to Terms of Use",
"updates-to-tos-desc": "Before you continue, please review the Terms of Use and confirm you take full responsibility for how you use the app.", "updates-to-tos-desc": "Before you continue, please review the Terms of Use and confirm you take full responsibility for how you use the app.",
"upvote-it": "upvote it", "upvote-it": "upvote it",
"urgent": "Urgent",
"url": "URL", "url": "URL",
"usage-data-shared-from-all-profiles": "Usage data will be shared from all profiles added to device. ", "usage-data-shared-from-all-profiles": "Usage data will be shared from all profiles added to device. ",
"usd-currency": "USD", "usd-currency": "USD",