Compare commits

..
Author SHA1 Message Date
Mohamed Javid 73d5cb24f8 fix(wallet)_: Address or ENS - Paste button behaviour
Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2025-03-04 17:32:03 +05:30
Mohamed JavidandYevheniia Berdnyk 614eeafde9 feat(wallet)_: Add base chain indicator (#22215)
* feat(wallet)_: Add base chain indicator

Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>

* e2e: updated Base network name

---------

Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
Co-authored-by: Yevheniia Berdnyk <ie.berdnyk@gmail.com>
2025-03-03 20:24:22 +00:00
Parvesh Monu 1dc4ea3a51 fix Some of the message longtap options disappear until relogin after unmuting chat (#22220) 2025-03-03 22:54:25 +05:30
dbef1c9edc Fix slide-button not resetting (#22210)
* nix: use openjdk_headless to avoid pulling GTK

This saves a whole bunch of downloading.

Signed-off-by: Jakub Sokołowski <jakub@status.im>

* fix_: no log file (#22122)

* fix_: no log file

https://github.com/status-im/status-go/compare/c5e4eb1a...388fce10

* chore_: fix lint issue

* chore_: set error level for release build

https://github.com/status-im/status-go/compare/c5e4eb1a...ba8fd519

* nix: replace yet another openjdk with headless version

Signed-off-by: Jakub Sokołowski <jakub@status.im>

* fix: moved slide-button reset from standard-auth to quo

---------

Signed-off-by: Jakub Sokołowski <jakub@status.im>
Co-authored-by: Jakub Sokołowski <jakub@status.im>
Co-authored-by: frank <lovefree103@gmail.com>
2025-03-03 10:46:40 +00:00
Mohsen 4853cde20b [#22206] fix: swap proposal keep sending update either after clean up (#22212) 2025-03-03 10:28:20 +00:00
Volodymyr Kozieiev 4c5f3282c4 Incorporated latest changes in status-go release branch
https://github.com/status-im/status-go/compare/c5e4eb1a...595dc68e
2025-02-28 14:54:17 +00:00
frank 376493b0b3 fix_: no log file (#22201) 2025-02-27 14:33:24 +00:00
Ulises Manuel 886f7b43d1 fix(keycard): light theme on "ready to scan" sheet (#22196) 2025-02-27 13:39:34 +00:00
Volodymyr Kozieiev c8c785f136 Switched to udpated release status-go branch. Log-related changes.
https://github.com/status-im/status-go/compare/c5e4eb1a...927f0c2b
2025-02-27 12:20:24 +00:00
Volodymyr Kozieiev b2602ba15e _TEMPORARY_ enabled all logging in release for testing purposes (#22192) 2025-02-26 11:36:41 +00:00
Volodymyr Kozieiev 4b0a983d68 swtiched to status-go version v10.7.0
https://github.com/status-im/status-go/compare/c5e4eb1a...6935cf11
2025-02-26 10:35:02 +00:00
Volodymyr Kozieiev af5c613cc0 Bump version to 2.33.0 2025-02-26 09:34:52 +00:00
50 changed files with 355 additions and 476 deletions
+2 -2
View File
@@ -2,7 +2,7 @@ DEBUG_WEBVIEW=0
ETHEREUM_DEV_CLUSTER=0 ETHEREUM_DEV_CLUSTER=0
EXTENSIONS=0 EXTENSIONS=0
GROUP_CHATS_ENABLED=1 GROUP_CHATS_ENABLED=1
LOG_LEVEL=error LOG_LEVEL=debug
MAILSERVER_CONFIRMATIONS_ENABLED=1 MAILSERVER_CONFIRMATIONS_ENABLED=1
MAINNET_WARNING_ENABLED=1 MAINNET_WARNING_ENABLED=1
PFS_ENCRYPTION_ENABLED=1 PFS_ENCRYPTION_ENABLED=1
@@ -20,6 +20,6 @@ FAST_CREATE_COMMUNITY_ENABLED=0
TEST_NETWORKS_ENABLED=0 TEST_NETWORKS_ENABLED=0
STATUS_PROXY_STAGE_NAME=prod STATUS_PROXY_STAGE_NAME=prod
FLAG_WALLET_CONNECT_ENABLED=1 FLAG_WALLET_CONNECT_ENABLED=1
API_LOGGING_ENABLED=0 API_LOGGING_ENABLED=1
SENTRY_ENABLED=1 SENTRY_ENABLED=1
SENTRY_ENVIRONMENT=production SENTRY_ENVIRONMENT=production
+1 -1
View File
@@ -1 +1 @@
2.32.0 2.33.0
@@ -1,15 +1,15 @@
(ns quo.components.buttons.slide-button.constants) (ns quo.components.buttons.slide-button.constants)
(def track-padding 4) (def ^:constant small-dimensions
(def small-dimensions
{:track-height 40 {:track-height 40
:thumb 32}) :thumb 32})
(def large-dimensions (def ^:constant large-dimensions
{:track-height 48 {:track-height 48
:thumb 40}) :thumb 40})
(def disable-opacity 0.3) (def ^:constant track-padding 4)
(def ^:constant disable-opacity 0.3)
(def ^:constant default-width 300)
(def default-width 300) (def ^:constant reset-timeout-ms 500)
@@ -27,7 +27,8 @@
(when (and reached-end? (not sliding-complete?)) (when (and reached-end? (not sliding-complete?))
(set-sliding-complete true) (set-sliding-complete true)
(when on-complete (when on-complete
(on-complete reset-fn)))))) (js/setTimeout reset-fn constants/reset-timeout-ms)
(on-complete))))))
(gesture/on-end (fn [event] (gesture/on-end (fn [event]
(let [x-translation (oops/oget event "translationX") (let [x-translation (oops/oget event "translationX")
reached-end? (>= x-translation track-width)] reached-end? (>= x-translation track-width)]
@@ -55,10 +56,9 @@
on-track-layout (rn/use-callback on-track-layout (rn/use-callback
#(set-track-width (oops/oget % "nativeEvent.layout.width"))) #(set-track-width (oops/oget % "nativeEvent.layout.width")))
reset-fn (rn/use-callback reset-fn (rn/use-callback
(fn [keep-at-end-after-slide?] (fn []
(set-sliding-complete false) (set-sliding-complete false)
(when-not keep-at-end-after-slide? (animations/reset-track-position x-pos)))
(animations/reset-track-position x-pos))))
dimensions (rn/use-callback dimensions (rn/use-callback
(partial utils/get-dimensions (partial utils/get-dimensions
(or track-width constants/default-width) (or track-width constants/default-width)
@@ -0,0 +1,13 @@
(ns quo.components.common.new-feature-dot
(:require [quo.components.common.new-feature-gradient :as new-feature-gradient]))
(def ^:const size 8)
(defn view
[{:keys [style accessibility-label]}]
[new-feature-gradient/view
{:style (merge {:width size
:height size
:border-radius (/ size 2)}
style)
:accessibility-label accessibility-label}])
@@ -0,0 +1,16 @@
(ns quo.components.common.new-feature-gradient
(:require [quo.foundations.colors :as colors]
[quo.theme]
[react-native.linear-gradient :as linear-gradient]))
(defn view
[{:keys [style accessibility-label]}]
(let [theme (quo.theme/use-theme)]
[linear-gradient/linear-gradient
{:style style
:accessibility-label accessibility-label
:colors [(colors/resolve-color :yellow theme)
colors/new-feature-gradient-pink]
:use-angle true
:angle 78
:angle-center {:x 0.5 :y 0.5}}]))
@@ -33,4 +33,12 @@
networks-list]) networks-list])
(h/is-truthy (h/query-by-label-text :network-dropdown)) (h/is-truthy (h/query-by-label-text :network-dropdown))
(h/fire-event :press (h/query-by-label-text :network-dropdown)) (h/fire-event :press (h/query-by-label-text :network-dropdown))
(h/was-not-called on-press)))) (h/was-not-called on-press)))
(h/test "Should display new chain indicator"
(h/render [network-dropdown/view
{:state :default
:show-new-chain-indicator? true}
networks-list])
(h/is-truthy (h/query-by-label-text :network-dropdown))
(h/is-truthy (h/query-by-label-text :new-chain-indicator))))
@@ -23,3 +23,7 @@
:opacity (if (= state :disabled) 0.3 1) :opacity (if (= state :disabled) 0.3 1)
:border-color (container-border-color props) :border-color (container-border-color props)
:align-items :center}) :align-items :center})
(def new-chain-indicator
{:position :absolute
:right 0})
@@ -1,12 +1,13 @@
(ns quo.components.dropdowns.network-dropdown.view (ns quo.components.dropdowns.network-dropdown.view
(:require (:require
[quo.components.common.new-feature-dot :as new-feature-dot]
[quo.components.dropdowns.network-dropdown.style :as style] [quo.components.dropdowns.network-dropdown.style :as style]
[quo.components.list-items.preview-list.view :as preview-list] [quo.components.list-items.preview-list.view :as preview-list]
[quo.theme :as quo.theme] [quo.theme :as quo.theme]
[react-native.core :as rn])) [react-native.core :as rn]))
(defn view (defn view
[{:keys [on-press state] :as props} networks] [{:keys [on-press state show-new-chain-indicator?] :as props} networks]
(let [theme (quo.theme/use-theme) (let [theme (quo.theme/use-theme)
[pressed? set-pressed] (rn/use-state false) [pressed? set-pressed] (rn/use-state false)
on-press-in (rn/use-callback #(set-pressed true)) on-press-in (rn/use-callback #(set-pressed true))
@@ -18,6 +19,10 @@
:on-press on-press :on-press on-press
:on-press-in on-press-in :on-press-in on-press-in
:on-press-out on-press-out} :on-press-out on-press-out}
(when show-new-chain-indicator?
[new-feature-dot/view
{:style style/new-chain-indicator
:accessibility-label :new-chain-indicator}])
[preview-list/view [preview-list/view
{:type :network {:type :network
:list-size (count networks) :list-size (count networks)
@@ -200,12 +200,15 @@
shown-name]])) shown-name]]))
(defn- wallet-networks-center (defn- wallet-networks-center
[{:keys [networks networks-on-press background center-content-container-style]}] [{:keys [networks networks-on-press show-new-chain-indicator? background
center-content-container-style]}]
[reanimated/view {:style center-content-container-style} [reanimated/view {:style center-content-container-style}
[network-dropdown/view [network-dropdown/view
{:state :default {:state :default
:on-press networks-on-press :on-press networks-on-press
:blur? (= background :blur)} networks]]) :blur? (= background :blur)
:show-new-chain-indicator? show-new-chain-indicator?}
networks]])
(defn page-nav (defn page-nav
"Props: "Props:
@@ -64,3 +64,20 @@
{:margin-top 7 {:margin-top 7
:margin-bottom 2 :margin-bottom 2
:margin-left -1}) :margin-left -1})
(def new-feature-tag-container
{:margin-left 6
:border-radius 12
:justify-content :center})
(def new-feature-tag-gradient
{:border-radius 12
:position :absolute
:left 0
:right 0
:top 0
:bottom 0})
(def new-feature-tag-text
{:color colors/white
:margin-horizontal 5})
@@ -4,6 +4,7 @@
[quo.components.avatars.icon-avatar :as icon-avatar] [quo.components.avatars.icon-avatar :as icon-avatar]
[quo.components.avatars.user-avatar.view :as user-avatar] [quo.components.avatars.user-avatar.view :as user-avatar]
[quo.components.buttons.button.view :as button] [quo.components.buttons.button.view :as button]
[quo.components.common.new-feature-gradient :as new-feature-gradient]
[quo.components.icon :as icon] [quo.components.icon :as icon]
[quo.components.list-items.preview-list.view :as preview-list] [quo.components.list-items.preview-list.view :as preview-list]
[quo.components.markdown.text :as text] [quo.components.markdown.text :as text]
@@ -115,7 +116,9 @@
nil)]) nil)])
(defn view (defn view
[{:keys [title on-press action-props accessibility-label blur? container-style content] :as props}] [{:keys [title show-new-feature-tag? on-press action-props accessibility-label blur? container-style
content]
:as props}]
[rn/pressable [rn/pressable
{:style (merge style/container container-style) {:style (merge style/container container-style)
:on-press (or on-press (:on-change action-props)) :on-press (or on-press (:on-change action-props))
@@ -126,10 +129,19 @@
[rn/view {:style (style/left-sub-container props)} [rn/view {:style (style/left-sub-container props)}
[image-component props] [image-component props]
[rn/view {:style (style/left-container (:image props))} [rn/view {:style (style/left-container (:image props))}
[text/text [rn/view {:flex-direction :row}
{:weight :medium [text/text
:style {:color (when blur? colors/white)}} {:weight :medium
title] :style {:color (when blur? colors/white)}}
title]
(when show-new-feature-tag?
[rn/view {:style style/new-feature-tag-container}
[new-feature-gradient/view {:style style/new-feature-tag-gradient}]
[text/text
{:weight :semi-bold
:size :label
:style style/new-feature-tag-text}
(string/upper-case (i18n/label :t/new))]])]
[description-component props] [description-component props]
[tag-component props]]] [tag-component props]]]
[rn/view {:style (style/sub-container (:alignment action-props))} [rn/view {:style (style/sub-container (:alignment action-props))}
@@ -88,10 +88,3 @@
(def gradient-end (def gradient-end
(assoc gradient-common :right 0)) (assoc gradient-common :right 0))
(defn button-loader
[theme]
{:width 100
:height 22
:border-radius 6
:background-color (loader-color theme)})
@@ -40,7 +40,6 @@
[:on-input-focus {:optional true} [:maybe fn?]] [:on-input-focus {:optional true} [:maybe fn?]]
[:on-token-press {:optional true} [:maybe fn?]] [:on-token-press {:optional true} [:maybe fn?]]
[:on-max-press {:optional true} [:maybe fn?]] [:on-max-press {:optional true} [:maybe fn?]]
[:max-loading? {:optional true} [:maybe :boolean]]
[:customization-color {:optional true} [:maybe :schema.common/customization-color]] [:customization-color {:optional true} [:maybe :schema.common/customization-color]]
[:container-style {:optional true} [:maybe :map]]]]] [:container-style {:optional true} [:maybe :map]]]]]
:any]) :any])
@@ -53,7 +52,7 @@
[{:keys [type status token value fiat-value show-approval-label? error? network-tag-props [{:keys [type status token value fiat-value show-approval-label? error? network-tag-props
approval-label-props default-value auto-focus? input-disabled? enable-swap? approval-label-props default-value auto-focus? input-disabled? enable-swap?
currency-symbol on-change-text show-keyboard? get-ref currency-symbol on-change-text show-keyboard? get-ref
container-style on-swap-press on-token-press on-max-press max-loading? on-input-focus]}] container-style on-swap-press on-token-press on-max-press on-input-focus]}]
(let [theme (quo.theme/use-theme) (let [theme (quo.theme/use-theme)
pay? (= type :pay) pay? (= type :pay)
disabled? (= status :disabled) disabled? (= status :disabled)
@@ -173,13 +172,11 @@
(when-not loading? (when-not loading?
[:<> [:<>
(when pay? (when pay?
(if max-loading? [rn/pressable {:on-press on-max-press}
[rn/view {:style (style/button-loader theme)}] [network-tag/view
[rn/pressable {:on-press on-max-press} (assoc network-tag-props
[network-tag/view :status
(assoc network-tag-props (if error? :error :default))]])
:status
(if error? :error :default))]]))
(when fiat-value (when fiat-value
[text/text [text/text
{:size :paragraph-2 {:size :paragraph-2
@@ -18,5 +18,6 @@
[:dropdown-on-press {:optional true} [:maybe fn?]] [:dropdown-on-press {:optional true} [:maybe fn?]]
[:networks {:optional true} [:networks {:optional true}
[:maybe [:sequential [:map [:source [:maybe :schema.common/image-source]]]]]] [:maybe [:sequential [:map [:source [:maybe :schema.common/image-source]]]]]]
[:dropdown-state {:optional true} [:maybe [:enum :default :disabled]]]]]] [:dropdown-state {:optional true} [:maybe [:enum :default :disabled]]]
[:show-new-chain-indicator? {:optional true} [:maybe :boolean]]]]]
:any]) :any])
@@ -25,7 +25,7 @@
bars)) bars))
(defn- view-info-top (defn- view-info-top
[{:keys [state balance networks dropdown-on-press dropdown-state]}] [{:keys [state balance networks dropdown-on-press dropdown-state show-new-chain-indicator?]}]
(let [theme (quo.theme/use-theme)] (let [theme (quo.theme/use-theme)]
[rn/view {:style style/container-info-top} [rn/view {:style style/container-info-top}
(if (= state :loading) (if (= state :loading)
@@ -36,9 +36,10 @@
:style (style/style-text-heading theme)} :style (style/style-text-heading theme)}
balance]) balance])
[network-dropdown/view [network-dropdown/view
{:state (or dropdown-state :default) {:state (or dropdown-state :default)
:blur? true :blur? true
:on-press dropdown-on-press} :on-press dropdown-on-press
:show-new-chain-indicator? show-new-chain-indicator?}
networks]])) networks]]))
(defn- view-metrics (defn- view-metrics
+2
View File
@@ -315,6 +315,8 @@
networks-short-name networks-short-name
socials)) socials))
(def new-feature-gradient-pink "#FF33A3")
(defn hex-string? (defn hex-string?
[s] [s]
(and (string? s) (string/starts-with? s "#"))) (and (string? s) (string/starts-with? s "#")))
@@ -26,8 +26,7 @@
:auth-button-label auth-button-label}])) :auth-button-label auth-button-label}]))
(vec (conj dependencies on-auth-success on-auth-fail))) (vec (conj dependencies on-auth-success on-auth-fail)))
on-slider-complete (rn/use-callback on-slider-complete (rn/use-callback
(fn [reset-slider-fn] (fn []
(js/setTimeout #(reset-slider-fn false) 500)
(if (fn? on-complete) (if (fn? on-complete)
(on-complete) (on-complete)
(on-complete-callback))) (on-complete-callback)))
-6
View File
@@ -492,16 +492,10 @@
(def ^:const token-for-fees-symbol "ETH") (def ^:const token-for-fees-symbol "ETH")
;; The 15% buffer accounts for Ethereum's EIP-1559 fee mechanism, where the base fee can increase
;; by up to 12.5% per block in periods of high congestion. The extra 2.5% provides additional
;; safety to prevent failed transactions due to rapid gas price fluctuations.
(def ^:const eth-max-fee-buffer-percent 15)
(def ^:const transaction-status-success "Success") (def ^:const transaction-status-success "Success")
(def ^:const transaction-status-pending "Pending") (def ^:const transaction-status-pending "Pending")
(def ^:const transaction-status-failed "Failed") (def ^:const transaction-status-failed "Failed")
(def ^:const eth-send-amount-decimal 4)
(def ^:const min-token-decimals-to-display 6) (def ^:const min-token-decimals-to-display 6)
(def ^:const swap-proposal-refresh-interval-ms 15000) (def ^:const swap-proposal-refresh-interval-ms 15000)
+2 -1
View File
@@ -275,7 +275,8 @@
{:events [:chat/unmute-chat-community]} {:events [:chat/unmute-chat-community]}
[{:keys [db]} chat-id] [{:keys [db]} chat-id]
(let [{:keys [community-id]} (get-in db [:chats chat-id])] (let [{:keys [community-id]} (get-in db [:chats chat-id])]
{:db (assoc-in db [:communities community-id :muted] false)})) (when community-id
{:db (assoc-in db [:communities community-id :muted] false)})))
(rf/defn mute-chat-failed (rf/defn mute-chat-failed
{:events [:chat/mute-failed]} {:events [:chat/mute-failed]}
@@ -18,11 +18,16 @@
:padding-horizontal 36 :padding-horizontal 36
:padding-vertical 30 :padding-vertical 30
:background-color (colors/theme-colors colors/white colors/neutral-95 theme)}} :background-color (colors/theme-colors colors/white colors/neutral-95 theme)}}
[rn/text {:style {:font-size 26 :color "#9F9FA5" :margin-bottom 36}} [rn/text
{:style {:font-size 26
:color (colors/theme-colors "#8F8E94" "#9F9FA5" theme)
:margin-bottom 36}}
(i18n/label :t/ready-to-scan)] (i18n/label :t/ready-to-scan)]
[rn/image [rn/image {:source (resources/get-image :nfc-prompt)}]
{:source (resources/get-image :nfc-prompt)}] [rn/text
[rn/text {:style {:font-size 16 :color :white :margin-vertical 36}} {:style {:font-size 16
:color (colors/theme-colors "#09101C" :white theme)
:margin-vertical 36}}
(if connected? (if connected?
(i18n/label :t/connected-dont-move) (i18n/label :t/connected-dont-move)
(i18n/label :t/hold-phone-near-keycard))] (i18n/label :t/hold-phone-near-keycard))]
@@ -32,6 +37,12 @@
(rf/dispatch [:keycard/hide-connection-sheet])) (rf/dispatch [:keycard/hide-connection-sheet]))
:style {:flex-direction :row}} :style {:flex-direction :row}}
[rn/view [rn/view
{:style {:background-color "#8E8E93" :flex 1 :align-items :center :padding 18 :border-radius 10}} {:style {:background-color (colors/theme-colors "#D5D4DB" "#8E8E93" theme)
[rn/text {:style {:color :white :font-size 16}} :flex 1
:align-items :center
:padding 18
:border-radius 10}}
[rn/text
{:style {:color (colors/theme-colors "#09101C" :white theme)
:font-size 16}}
(i18n/label :t/cancel)]]]]])) (i18n/label :t/cancel)]]]]]))
@@ -7,6 +7,7 @@
[react-native.safe-area :as safe-area] [react-native.safe-area :as safe-area]
[status-im.common.floating-button-page.view :as floating-button-page] [status-im.common.floating-button-page.view :as floating-button-page]
[status-im.contexts.settings.wallet.saved-addresses.add-address-to-save.style :as style] [status-im.contexts.settings.wallet.saved-addresses.add-address-to-save.style :as style]
[status-im.contexts.wallet.common.utils :as utils]
[status-im.contexts.wallet.common.validation :as validation] [status-im.contexts.wallet.common.validation :as validation]
[utils.address :as utils-address] [utils.address :as utils-address]
[utils.debounce :as debounce] [utils.debounce :as debounce]
@@ -159,7 +160,7 @@
(fn [clipboard-text] (fn [clipboard-text]
(when-not (string/blank? clipboard-text) (when-not (string/blank? clipboard-text)
(-> clipboard-text (-> clipboard-text
utils-address/extract-address-without-chains-info utils/on-paste-address-or-ens
on-change-text))))) on-change-text)))))
on-press-continue (rn/use-callback on-press-continue (rn/use-callback
(fn [] (fn []
@@ -7,6 +7,7 @@
[reagent.core :as reagent] [reagent.core :as reagent]
[status-im.common.floating-button-page.view :as floating-button-page] [status-im.common.floating-button-page.view :as floating-button-page]
[status-im.contexts.wallet.add-account.add-address-to-watch.style :as style] [status-im.contexts.wallet.add-account.add-address-to-watch.style :as style]
[status-im.contexts.wallet.common.utils :as utils]
[status-im.contexts.wallet.common.validation :as validation] [status-im.contexts.wallet.common.validation :as validation]
[status-im.subs.wallet.add-account.address-to-watch] [status-im.subs.wallet.add-account.address-to-watch]
[utils.address :as utils-address] [utils.address :as utils-address]
@@ -42,7 +43,7 @@
paste-on-input #(clipboard/get-string paste-on-input #(clipboard/get-string
(fn [clipboard-text] (fn [clipboard-text]
(-> clipboard-text (-> clipboard-text
utils.address/extract-address-without-chains-info utils/on-paste-address-or-ens
on-change-text)))] on-change-text)))]
(rn/use-effect (fn [] (rn/use-effect (fn []
(when-not (string/blank? scanned-address) (when-not (string/blank? scanned-address)
@@ -1,6 +1,7 @@
(ns status-im.contexts.wallet.common.account-switcher.view (ns status-im.contexts.wallet.common.account-switcher.view
(:require (:require
[quo.core :as quo] [quo.core :as quo]
[react-native.core :as rn]
[status-im.contexts.wallet.sheets.account-options.view :as account-options] [status-im.contexts.wallet.sheets.account-options.view :as account-options]
[status-im.contexts.wallet.sheets.network-filter.view :as network-filter] [status-im.contexts.wallet.sheets.network-filter.view :as network-filter]
[status-im.contexts.wallet.sheets.select-account.view :as select-account] [status-im.contexts.wallet.sheets.select-account.view :as select-account]
@@ -30,25 +31,33 @@
type :no-title}}] type :no-title}}]
(let [{:keys [color emoji watch-only?]} (rf/sub [:wallet/current-viewing-account]) (let [{:keys [color emoji watch-only?]} (rf/sub [:wallet/current-viewing-account])
networks (rf/sub [:wallet/selected-network-details]) networks (rf/sub [:wallet/selected-network-details])
sending-collectible? (rf/sub [:wallet/sending-collectible?])] sending-collectible? (rf/sub [:wallet/sending-collectible?])
show-new-chain-indicator? (rf/sub [:wallet/show-new-chain-indicator?])
on-press-networks (rn/use-callback
(fn []
(rf/dispatch [:wallet/hide-new-chain-indicator])
(rf/dispatch [:show-bottom-sheet
{:content network-filter/view}])))]
[quo/page-nav [quo/page-nav
{:type type {:type type
:icon-name icon-name :icon-name icon-name
:margin-top margin-top :margin-top margin-top
:background :blur :background :blur
:on-press on-press :on-press on-press
:accessibility-label accessibility-label :accessibility-label accessibility-label
:networks networks :networks networks
:align-center? true :align-center? true
:networks-on-press #(rf/dispatch [:show-bottom-sheet {:content network-filter/view}]) :networks-on-press on-press-networks
:right-side [(when (and (ff/enabled? ::ff/wallet.wallet-connect) :show-new-chain-indicator? show-new-chain-indicator?
(not watch-only?) :right-side [(when (and (ff/enabled? ::ff/wallet.wallet-connect)
show-dapps-button?) (not watch-only?)
{:icon-name :i/dapps show-dapps-button?)
:on-press #(rf/dispatch [:navigate-to :screen/wallet.connected-dapps])}) {:icon-name :i/dapps
(when-not sending-collectible? :on-press #(rf/dispatch [:navigate-to
{:content-type :account-switcher :screen/wallet.connected-dapps])})
:customization-color color (when-not sending-collectible?
:on-press #(on-switcher-press switcher-type params) {:content-type :account-switcher
:emoji emoji :customization-color color
:type (when watch-only? :watch-only)})]}])) :on-press #(on-switcher-press switcher-type params)
:emoji emoji
:type (when watch-only? :watch-only)})]}]))
@@ -2,7 +2,6 @@
(:require [quo.core :as quo] (:require [quo.core :as quo]
[status-im.contexts.wallet.send.utils :as send-utils] [status-im.contexts.wallet.send.utils :as send-utils]
[status-im.contexts.wallet.sheets.buy-token.view :as buy-token] [status-im.contexts.wallet.sheets.buy-token.view :as buy-token]
[status-im.contexts.wallet.swap.utils :as swap-utils]
[status-im.feature-flags :as ff] [status-im.feature-flags :as ff]
[utils.i18n :as i18n] [utils.i18n :as i18n]
[utils.money :as money] [utils.money :as money]
@@ -79,34 +78,34 @@
(defn token-value-drawer (defn token-value-drawer
[token watch-only? entry-point] [token watch-only? entry-point]
(let [token-symbol (:token token) (let [token-symbol (:token token)
token-data (rf/sub [:wallet/token-by-symbol-from-first-available-account-with-balance token-data (rf/sub [:wallet/token-by-symbol-from-first-available-account-with-balance
token-symbol]) token-symbol])
selected-account (rf/sub [:wallet/current-viewing-account-address]) selected-account (rf/sub [:wallet/current-viewing-account-address])
token-owners (rf/sub [:wallet/operable-addresses-with-token-symbol token-symbol]) token-owners (rf/sub [:wallet/operable-addresses-with-token-symbol token-symbol])
testnet-mode? (rf/sub [:profile/test-networks-enabled?]) testnet-mode? (rf/sub [:profile/test-networks-enabled?])
account-owns-token? (rf/sub [:wallet/current-account-owns-token token-symbol]) account-owns-token? (rf/sub [:wallet/current-account-owns-token token-symbol])
network-details (rf/sub [:wallet/network-details]) network-details (rf/sub [:wallet/network-details])
token-owned? (if selected-account account-owns-token? (seq token-owners)) receive-token-symbol (if (= token-symbol "SNT") "ETH" "SNT")
asset-to-receive (rf/sub [:wallet/token-by-symbol-from-first-available-account-with-balance token-owned? (if selected-account account-owns-token? (seq token-owners))
(swap-utils/default-asset-to-receive token-symbol)]) asset-to-receive (rf/sub [:wallet/token-by-symbol receive-token-symbol])
unique-owner? (= (count token-owners) 1) unique-owner? (= (count token-owners) 1)
params (cond-> {:start-flow? true params (cond-> {:start-flow? true
:owners token-owners :owners token-owners
:testnet-mode? testnet-mode?} :testnet-mode? testnet-mode?}
selected-account selected-account
(assoc :token token-data (assoc :token token-data
:stack-id :screen/wallet.accounts :stack-id :screen/wallet.accounts
:has-balance? (-> (get-in token [:values :fiat-unformatted-value]) :has-balance? (-> (get-in token [:values :fiat-unformatted-value])
money/above-zero?)) money/above-zero?))
(and (not selected-account) unique-owner?) (and (not selected-account) unique-owner?)
(assoc :token-symbol token-symbol (assoc :token-symbol token-symbol
:token token-data :token token-data
:stack-id :wallet-stack) :stack-id :wallet-stack)
(and (not selected-account) (not unique-owner?)) (and (not selected-account) (not unique-owner?))
(assoc :token-symbol token-symbol (assoc :token-symbol token-symbol
:stack-id :wallet-stack))] :stack-id :wallet-stack))]
[quo/action-drawer [quo/action-drawer
[(cond->> [(when (ff/enabled? ::ff/wallet.assets-modal-manage-tokens) [(cond->> [(when (ff/enabled? ::ff/wallet.assets-modal-manage-tokens)
(action-manage-tokens watch-only?)) (action-manage-tokens watch-only?))
+22 -46
View File
@@ -4,6 +4,7 @@
[status-im.common.qr-codes.view :as qr-codes] [status-im.common.qr-codes.view :as qr-codes]
[status-im.constants :as constants] [status-im.constants :as constants]
[status-im.contexts.wallet.common.utils.networks :as network-utils] [status-im.contexts.wallet.common.utils.networks :as network-utils]
[utils.address]
[utils.money :as money] [utils.money :as money]
[utils.number :as number] [utils.number :as number]
[utils.string])) [utils.string]))
@@ -182,22 +183,12 @@
[amount display-decimals] [amount display-decimals]
(let [number (or (money/bignumber amount) (let [number (or (money/bignumber amount)
(money/bignumber 0)) (money/bignumber 0))
amount-fixed-decimals (-> number amount-fixed-decimals (number/to-fixed number display-decimals)]
(number/format-decimal-fixed display-decimals)
(number/remove-trailing-zeroes))]
(if (and (= amount-fixed-decimals "0") (if (and (= amount-fixed-decimals "0")
(money/above-zero? amount)) (money/above-zero? amount))
(number/small-number-threshold display-decimals) (number/small-number-threshold display-decimals)
(str amount-fixed-decimals)))) (str amount-fixed-decimals))))
(defn token-balance-for-network
"Returns the token balance for a specific chain"
[token chain-id]
(let [token-decimals (:decimals token)]
(-> (get-in token [:balances-per-chain chain-id :raw-balance] 0)
(number/convert-to-whole-number token-decimals)
money/bignumber)))
(defn token-balance-display-for-network (defn token-balance-display-for-network
"Formats a token balance for a specific chain and rounds it to a specified number of decimals. "Formats a token balance for a specific chain and rounds it to a specified number of decimals.
If the balance is less than the smallest representable value based on rounding decimals, If the balance is less than the smallest representable value based on rounding decimals,
@@ -334,20 +325,19 @@
(defn make-network-item (defn make-network-item
"This function generates props for quo/category component item" "This function generates props for quo/category component item"
[{:keys [network-name color on-change networks state label-props type blur?]}] [{:keys [network-name color on-change networks label-props type blur?]}]
(cond-> {:title (string/capitalize (name network-name)) (cond-> {:title (string/capitalize (name network-name))
:image :icon-avatar :image :icon-avatar
:image-props {:icon (resources/get-network network-name) :image-props {:icon (resources/get-network network-name)
:size :size-20} :size :size-20}
:action :selector ;; Remove the following line for v2.35
:action-props {:type (or type :show-new-feature-tag? (= network-name constants/base-network-name)
(if (= :default state) :action :selector
:filled-checkbox :action-props {:type (or type :checkbox)
:checkbox)) :blur? blur?
:blur? blur? :customization-color color
:customization-color color :checked? (contains? networks network-name)
:checked? (contains? networks network-name) :on-change on-change}}
:on-change on-change}}
label-props label-props
(assoc :label :text (assoc :label :text
@@ -491,24 +481,10 @@
(some positive-balance-in-any-chain? tokens)) (some positive-balance-in-any-chain? tokens))
operable-account)))) operable-account))))
(defn calculate-max-safe-send-amount (defn on-paste-address-or-ens
"Calculates the max ETH that can be sent while reserving enough for gas fees. "Check if the clipboard has any valid address and extract the address without any chain info.
If it does not contain an valid address or it is ENS, return the clipboard text as it is"
- Ensures a minimum of 0.0001 ETH and a max of 0.01 ETH for gas. [clipboard-text]
- Uses 20% of the value as an estimated fee, clamped within this range. (if (utils.address/supported-address? clipboard-text)
- In Desktop it's 10% but after some more test, we found 20% is better option. (utils.address/extract-address-without-chains-info clipboard-text)
- Prevents sending the full balance to avoid transaction failures. clipboard-text))
Aligned with the desktop logic for consistency.
https://github.com/status-im/status-desktop/blob/f320abb5c498ac260a1a4a9db046485b88af81e7/ui/app/AppLayouts/Wallet/WalletUtils.qml#L44"
[value]
(if (or (nil? value) (zero? value))
"0"
(let [raw-fee (money/mul (money/bignumber value) 0.2)
clamped-fee (money/maximum (money/bignumber 0.0001)
(money/minimum (money/bignumber 0.01) raw-fee))
result (money/sub (money/bignumber value) clamped-fee)]
(-> result
(money/maximum 0)
(number/format-decimal-fixed constants/eth-send-amount-decimal)
(number/remove-trailing-zeroes)))))
@@ -202,7 +202,7 @@
(is (= (utils/sanitized-token-amount-to-display 0.0001 3) "<0.001")) (is (= (utils/sanitized-token-amount-to-display 0.0001 3) "<0.001"))
(is (= (utils/sanitized-token-amount-to-display 0.00001 3) "<0.001")) (is (= (utils/sanitized-token-amount-to-display 0.00001 3) "<0.001"))
(is (= (utils/sanitized-token-amount-to-display 0 2) "0")) (is (= (utils/sanitized-token-amount-to-display 0 2) "0"))
(is (= (utils/sanitized-token-amount-to-display 123.456789 4) "123.4567")) (is (= (utils/sanitized-token-amount-to-display 123.456789 4) "123.4568"))
(is (= (utils/sanitized-token-amount-to-display 0.00000123 6) "0.000001")) (is (= (utils/sanitized-token-amount-to-display 0.00000123 6) "0.000001"))
(is (= (utils/sanitized-token-amount-to-display nil 2) "0")) (is (= (utils/sanitized-token-amount-to-display nil 2) "0"))
(is (= (utils/sanitized-token-amount-to-display "invalid" 2) "0")))) (is (= (utils/sanitized-token-amount-to-display "invalid" 2) "0"))))
@@ -375,14 +375,3 @@
{:symbol "DAI"} {:symbol "DAI"}
{:symbol "ETH"}]] {:symbol "ETH"}]]
(is (= (utils/sort-tokens-by-name tokens) expected))))) (is (= (utils/sort-tokens-by-name tokens) expected)))))
(deftest calculate-max-safe-send-amount-test
(testing "Calculates the max ETH sendable while reserving fees"
(is (= "0" (utils/calculate-max-safe-send-amount nil)))
(is (= "0" (utils/calculate-max-safe-send-amount 0)))
(is (= "0" (utils/calculate-max-safe-send-amount 0.00009)))
(is (= "0" (utils/calculate-max-safe-send-amount 0.0001)))
(is (= "0.008" (utils/calculate-max-safe-send-amount 0.01)))
(is (= "0.99" (utils/calculate-max-safe-send-amount 1.0)))
(is (= "9.99" (utils/calculate-max-safe-send-amount 10.0)))
(is (= "99.99" (utils/calculate-max-safe-send-amount 100.0)))))
@@ -313,40 +313,3 @@
(-> collectible (-> collectible
transforms/json->clj transforms/json->clj
transform-collectible)) transform-collectible))
(defn- bridge-amount-greater-than-bonder-fees?
[{{token-decimals :decimals} :from-token
bonder-fees :tx-bonder-fees
amount-in :amount-in}]
(let [bonder-fees (utils.money/token->unit bonder-fees token-decimals)
amount-to-bridge (utils.money/token->unit amount-in token-decimals)]
(> amount-to-bridge bonder-fees)))
(defn- remove-multichain-routes
[routes]
(if (> (count routes) 1)
[] ;; if route is multichain, we remove it
routes))
(defn- remove-invalid-bonder-fees-routes
[routes]
(filter bridge-amount-greater-than-bonder-fees? routes))
(defn- ->old-route-paths
[routes]
(map new->old-route-path routes))
(def ^:private best-routes-fix
(comp ->old-route-paths
remove-invalid-bonder-fees-routes
remove-multichain-routes))
(def ^:private candidates-fix
(comp ->old-route-paths remove-invalid-bonder-fees-routes))
(defn fix-routes
[data]
(-> data
(rpc->suggested-routes)
(update :best best-routes-fix)
(update :candidates candidates-fix)))
@@ -3,6 +3,7 @@
[clojure.string :as string] [clojure.string :as string]
[native-module.core :as native-module] [native-module.core :as native-module]
[promesa.core :as promesa] [promesa.core :as promesa]
[react-native.async-storage :as async-storage]
[status-im.common.json-rpc.events :as json-rpc] [status-im.common.json-rpc.events :as json-rpc]
[status-im.contexts.profile.recover.effects :as profile.recover.effects] [status-im.contexts.profile.recover.effects :as profile.recover.effects]
[status-im.contexts.wallet.rpc :as wallet-rpc] [status-im.contexts.wallet.rpc :as wallet-rpc]
@@ -130,3 +131,14 @@
(-> (wallet-rpc/sign-message message address (security/safe-unmask-data password)) (-> (wallet-rpc/sign-message message address (security/safe-unmask-data password))
(promesa/then on-success) (promesa/then on-success)
(promesa/catch on-error)))) (promesa/catch on-error))))
(rf/reg-fx
:effects.wallet/retrieve-base-chain-indicator-shown
(fn []
(async-storage/get-item :base-chain-indicator-shown
#(rf/dispatch [:wallet/retrieve-new-chain-indicator (not %)]))))
(rf/reg-fx
:effects.wallet/set-base-chain-indicator-shown
(fn [flag]
(async-storage/set-item! :base-chain-indicator-shown flag)))
+11
View File
@@ -797,3 +797,14 @@
:wallet.swap/transaction-success :wallet.swap/transaction-success
:wallet/transaction-success) :wallet/transaction-success)
sent-transactions])]]}))) sent-transactions])]]})))
(rf/reg-event-fx
:wallet/retrieve-new-chain-indicator
(fn [{:keys [db]} [flag]]
{:db (assoc-in db [:wallet :ui :show-new-chain-indicator?] flag)}))
(rf/reg-event-fx
:wallet/hide-new-chain-indicator
(fn [{:keys [db]}]
{:db (assoc-in db [:wallet :ui :show-new-chain-indicator?] false)
:fx [[:effects.wallet/set-base-chain-indicator-shown true]]}))
+15 -8
View File
@@ -135,7 +135,13 @@
cards (conj account-cards-data (new-account-card-data)) cards (conj account-cards-data (new-account-card-data))
[init-loaded? set-init-loaded] (rn/use-state false) [init-loaded? set-init-loaded] (rn/use-state false)
{:keys [formatted-balance]} (rf/sub [:wallet/aggregated-token-values-and-balance]) {:keys [formatted-balance]} (rf/sub [:wallet/aggregated-token-values-and-balance])
theme (quo.theme/use-theme)] theme (quo.theme/use-theme)
show-new-chain-indicator? (rf/sub [:wallet/show-new-chain-indicator?])
on-press-network-selector (rn/use-callback
(fn []
(rf/dispatch [:wallet/hide-new-chain-indicator])
(rf/dispatch [:show-bottom-sheet
{:content network-filter/view}])))]
(rn/use-effect (fn [] (rn/use-effect (fn []
(when (and @account-list-ref (pos? (count cards))) (when (and @account-list-ref (pos? (count cards)))
(.scrollToOffset ^js @account-list-ref (.scrollToOffset ^js @account-list-ref
@@ -157,13 +163,14 @@
:on-refresh #(rf/dispatch [:wallet/get-accounts])}] :on-refresh #(rf/dispatch [:wallet/get-accounts])}]
:header [rn/view {:style (style/header-container theme)} :header [rn/view {:style (style/header-container theme)}
[quo/wallet-overview [quo/wallet-overview
{:state (if tokens-loading? :loading :default) {:state (if tokens-loading? :loading :default)
:time-frame :none :time-frame :none
:metrics :none :metrics :none
:balance formatted-balance :balance formatted-balance
:networks networks :networks networks
:dropdown-on-press #(rf/dispatch [:show-bottom-sheet :dropdown-on-press on-press-network-selector
{:content network-filter/view}])}] :show-new-chain-indicator? (when (not-empty networks)
show-new-chain-indicator?)}]
(when (ff/enabled? ::ff/wallet.graph) (when (ff/enabled? ::ff/wallet.graph)
[quo/wallet-graph {:time-frame :empty}]) [quo/wallet-graph {:time-frame :empty}])
[render-cards cards account-list-ref] [render-cards cards account-list-ref]
+40 -2
View File
@@ -12,6 +12,7 @@
[taoensso.timbre :as log] [taoensso.timbre :as log]
[utils.address] [utils.address]
[utils.i18n :as i18n] [utils.i18n :as i18n]
[utils.money :as utils.money]
[utils.number] [utils.number]
[utils.re-frame :as rf] [utils.re-frame :as rf]
[utils.security.core :as security])) [utils.security.core :as security]))
@@ -622,6 +623,43 @@
{:event :wallet/stop-get-suggested-routes {:event :wallet/stop-get-suggested-routes
:error error}))}]]]})) :error error}))}]]]}))
(defn- bridge-amount-greater-than-bonder-fees?
[{{token-decimals :decimals} :from-token
bonder-fees :tx-bonder-fees
amount-in :amount-in}]
(let [bonder-fees (utils.money/token->unit bonder-fees token-decimals)
amount-to-bridge (utils.money/token->unit amount-in token-decimals)]
(> amount-to-bridge bonder-fees)))
(defn- remove-multichain-routes
[routes]
(if (> (count routes) 1)
[] ;; if route is multichain, we remove it
routes))
(defn- remove-invalid-bonder-fees-routes
[routes]
(filter bridge-amount-greater-than-bonder-fees? routes))
(defn- ->old-route-paths
[routes]
(map data-store/new->old-route-path routes))
(def ^:private best-routes-fix
(comp ->old-route-paths
remove-invalid-bonder-fees-routes
remove-multichain-routes))
(def ^:private candidates-fix
(comp ->old-route-paths remove-invalid-bonder-fees-routes))
(defn- fix-routes
[data]
(-> data
(data-store/rpc->suggested-routes)
(update :best best-routes-fix)
(update :candidates candidates-fix)))
(rf/reg-event-fx (rf/reg-event-fx
:wallet/handle-suggested-routes :wallet/handle-suggested-routes
(fn [{:keys [db]} [data]] (fn [{:keys [db]} [data]]
@@ -647,8 +685,8 @@
(cond (cond
(and failure? swap?) [:wallet/swap-proposal-error error] (and failure? swap?) [:wallet/swap-proposal-error error]
failure? [:wallet/suggested-routes-error error-message] failure? [:wallet/suggested-routes-error error-message]
swap? [:wallet/swap-proposal-success (data-store/fix-routes data)] swap? [:wallet/swap-proposal-success (fix-routes data)]
:else [:wallet/suggested-routes-success (data-store/fix-routes data) :else [:wallet/suggested-routes-success (fix-routes data)
enough-assets?])]]})))))) enough-assets?])]]}))))))
(rf/reg-event-fx (rf/reg-event-fx
@@ -18,6 +18,7 @@
:network-name :mainnet :network-name :mainnet
:chain-id 1 :chain-id 1
:related-chain-id 5}] :related-chain-id 5}]
:wallet/show-new-chain-indicator? false
:wallet/current-viewing-account-address "0x1" :wallet/current-viewing-account-address "0x1"
:wallet/current-viewing-account {:path "m/44'/60'/0'/0/1" :wallet/current-viewing-account {:path "m/44'/60'/0'/0/1"
:emoji "💎" :emoji "💎"
@@ -61,7 +61,7 @@
(fn [clipboard] (fn [clipboard]
(when-not (empty? clipboard) (when-not (empty? clipboard)
(-> clipboard (-> clipboard
utils-address/extract-address-without-chains-info utils/on-paste-address-or-ens
on-change))))) on-change)))))
:ens-regex constants/regx-ens :ens-regex constants/regx-ens
:scanned-value (or (when recipient-plain-address? send-address) scanned-address) :scanned-value (or (when recipient-plain-address? send-address) scanned-address)
@@ -8,41 +8,26 @@
(defn view (defn view
[] []
(let [selected-networks (rf/sub [:wallet/selected-networks]) (let [selected-networks (rf/sub [:wallet/selected-networks])
selector-state (rf/sub [:wallet/network-filter-selector-state])
color (rf/sub [:profile/customization-color]) color (rf/sub [:profile/customization-color])
network-details (rf/sub [:wallet/network-details]) network-details (rf/sub [:wallet/network-details])]
viewing-account? (rf/sub [:wallet/viewing-account?])
balance-per-chain (if viewing-account?
(rf/sub [:wallet/current-viewing-account-fiat-balance-per-chain])
(rf/sub [:wallet/aggregated-fiat-balance-per-chain]))
mainnet (first network-details)
layer-2-networks (rest network-details)]
[:<> [:<>
[quo/drawer-top {:title (i18n/label :t/select-networks)}] [quo/drawer-top {:title (i18n/label :t/select-networks)}]
[quo/information-box
{:type :informative
:icon :i/info
:blur? false
:style {:margin-horizontal 20
:margin-bottom 4}}
(i18n/label :t/base-chain-available-info)]
[quo/category [quo/category
{:list-type :settings {:list-type :settings
:data [(utils/make-network-item
{:state selector-state
:network-name (:network-name mainnet)
:color color
:networks selected-networks
:label-props (get balance-per-chain (:chain-id mainnet))
:on-change #(rf/dispatch
[:wallet/update-selected-networks
(:network-name
mainnet)])})]}]
[quo/category
{:list-type :settings
:label (i18n/label :t/layer-2)
:data (mapv (fn [network] :data (mapv (fn [network]
(utils/make-network-item (utils/make-network-item
{:state selector-state {:network-name (:network-name network)
:network-name (:network-name network)
:color color :color color
:networks selected-networks :networks selected-networks
:label-props (get balance-per-chain (:chain-id network))
:on-change #(rf/dispatch :on-change #(rf/dispatch
[:wallet/update-selected-networks [:wallet/update-selected-networks
(:network-name (:network-name
network)])})) network)])}))
layer-2-networks)}]])) network-details)}]]))
+10 -101
View File
@@ -2,7 +2,6 @@
(:require [re-frame.core :as rf] (:require [re-frame.core :as rf]
[status-im.constants :as constants] [status-im.constants :as constants]
[status-im.contexts.wallet.common.utils :as utils] [status-im.contexts.wallet.common.utils :as utils]
[status-im.contexts.wallet.data-store :as data-store]
[status-im.contexts.wallet.send.utils :as send-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.sheets.network-selection.view :as network-selection]
[status-im.contexts.wallet.swap.utils :as swap-utils] [status-im.contexts.wallet.swap.utils :as swap-utils]
@@ -29,15 +28,6 @@
:account account :account account
:test-networks-enabled? test-networks-enabled? :test-networks-enabled? test-networks-enabled?
:token-symbol (get-in data [:asset-to-pay :symbol])})) :token-symbol (get-in data [:asset-to-pay :symbol])}))
received-asset (if-not (nil? asset-to-receive)
asset-to-receive
(swap-utils/select-asset-to-pay-by-symbol
{:wallet wallet
:account account
:test-networks-enabled? test-networks-enabled?
:token-symbol (if (= (:symbol asset-to-pay) "SNT")
"ETH"
"SNT")}))
multi-account-balance? (-> available-accounts multi-account-balance? (-> available-accounts
(count) (count)
(> 1)) (> 1))
@@ -46,7 +36,7 @@
start-point (if open-new-screen? :action-menu :swap-button)] start-point (if open-new-screen? :action-menu :swap-button)]
{:db (-> db {:db (-> db
(assoc-in [:wallet :ui :swap :asset-to-pay] asset-to-pay) (assoc-in [:wallet :ui :swap :asset-to-pay] asset-to-pay)
(assoc-in [:wallet :ui :swap :asset-to-receive] received-asset) (assoc-in [:wallet :ui :swap :asset-to-receive] asset-to-receive)
(assoc-in [:wallet :ui :swap :network] network') (assoc-in [:wallet :ui :swap :network] network')
(assoc-in [:wallet :ui :swap :launch-screen] view-id) (assoc-in [:wallet :ui :swap :launch-screen] view-id)
(assoc-in [:wallet :ui :swap :start-point] start-point)) (assoc-in [:wallet :ui :swap :start-point] start-point))
@@ -63,7 +53,7 @@
[:centralized-metrics/track :metric/swap-start [:centralized-metrics/track :metric/swap-start
{:network (:chain-id network) {:network (:chain-id network)
:pay_token (:symbol asset-to-pay) :pay_token (:symbol asset-to-pay)
:receive_token (:symbol received-asset) :receive_token (:symbol asset-to-receive)
:start_point start-point :start_point start-point
:launch_screen view-id}]] :launch_screen view-id}]]
[:dispatch [:wallet.swap/set-default-slippage]]] [:dispatch [:wallet.swap/set-default-slippage]]]
@@ -77,7 +67,7 @@
(rf/dispatch (rf/dispatch
[:wallet.swap/start [:wallet.swap/start
{:asset-to-pay asset-to-pay {:asset-to-pay asset-to-pay
:asset-to-receive received-asset :asset-to-receive asset-to-receive
:network network :network network
:open-new-screen? :open-new-screen?
open-new-screen? open-new-screen?
@@ -259,15 +249,13 @@
(rf/reg-event-fx :wallet/stop-get-swap-proposal (rf/reg-event-fx :wallet/stop-get-swap-proposal
(fn [{:keys [db]}] (fn [{:keys [db]}]
(let [route-request-ongoing? (some? (get-in db [:wallet :ui :swap :last-request-uuid]))] {:db (update-in db [:wallet :ui :swap] dissoc :last-request-uuid)
(when route-request-ongoing? :json-rpc/call [{:method "wallet_stopSuggestedRoutesAsyncCalculation"
{:db (update-in db [:wallet :ui :swap] dissoc :last-request-uuid) :params []
:json-rpc/call [{:method "wallet_stopSuggestedRoutesAsyncCalculation" :on-error (fn [error]
:params [] (log/error "failed to stop fetching swap proposals"
:on-error (fn [error] {:event :wallet/stop-get-swap-proposal
(log/error "failed to stop fetching swap proposals" :error error}))}]}))
{:event :wallet/stop-get-swap-proposal
:error error}))}]}))))
(rf/reg-event-fx (rf/reg-event-fx
:wallet/clean-swap-proposal :wallet/clean-swap-proposal
@@ -587,82 +575,3 @@
[:dispatch [:dispatch
[:navigate-to-within-stack [:navigate-to-within-stack
[:screen/wallet.swap-select-asset-to-pay :screen/wallet.swap-select-account]]]])}))) [:screen/wallet.swap-select-asset-to-pay :screen/wallet.swap-select-account]]]])})))
(rf/reg-event-fx :wallet/get-swap-proposal-fee
(fn [{:keys [db]} [{:keys [amount-in amount-out]}]]
(let [wallet-address (get-in db [:wallet :current-viewing-account-address])
{:keys [asset-to-pay asset-to-receive
network]} (get-in db [:wallet :ui :swap])
test-networks-enabled? (get-in db [:profile/profile :test-networks-enabled?])
networks ((if test-networks-enabled? :test :prod)
(get-in db [:wallet :networks]))
network-chain-ids (map :chain-id networks)
pay-token-decimal (:decimals asset-to-pay)
pay-token-id (:symbol asset-to-pay)
receive-token-id (:symbol asset-to-receive)
receive-token-decimals (:decimals asset-to-receive)
gas-rates constants/gas-rate-medium
amount-in-hex (if amount-in
(send-utils/amount-in-hex amount-in pay-token-decimal)
0)
amount-out-hex (when amount-out
(send-utils/amount-in-hex amount-out receive-token-decimals))
to-address wallet-address
from-address wallet-address
swap-chain-id (:chain-id network)
disabled-to-chain-ids (filter #(not= % swap-chain-id) network-chain-ids)
disabled-from-chain-ids (filter #(not= % swap-chain-id) network-chain-ids)
from-locked-amount {}
send-type constants/send-type-swap
request-uuid (str (random-uuid))
params [(cond->
{:uuid request-uuid
:sendType send-type
:addrFrom from-address
:addrTo to-address
:tokenID pay-token-id
:toTokenID receive-token-id
:disabledFromChainIDs disabled-from-chain-ids
:disabledToChainIDs disabled-to-chain-ids
:gasFeeMode gas-rates
:fromLockedAmount from-locked-amount
:amountOut (or amount-out-hex "0x0")}
amount-in (assoc :amountIn amount-in-hex))]]
{:db (assoc-in db [:wallet :ui :swap :loading-swap-proposal-fee?] true)
:json-rpc/call [{:method "wallet_getSuggestedRoutes"
:params params
:on-success (fn [data]
(let [swap-proposal (data-store/fix-routes data)]
(rf/dispatch [:wallet/swap-proposal-fee-success
swap-proposal])))
:on-error (fn [error]
(rf/dispatch [:wallet/swap-proposal-fee-error])
(log/error "failed to get suggested routes"
{:event :wallet/get-swap-proposal-fee
:error (:message error)
:params params}))}]})))
(rf/reg-event-fx
:wallet/swap-proposal-fee-success
(fn [{:keys [db]} [swap-proposal]]
(let [best-routes (:best swap-proposal)
selected-route (first best-routes)
relevant-fee-fields [:gas-amount :gas-fees :token-fees :approval-required
:approval-fee :approval-l-1-fee :bonder-fees]
fee-data (select-keys selected-route relevant-fee-fields)]
{:db (update-in db
[:wallet :ui :swap]
assoc
:loading-swap-proposal-fee? false
:swap-proposal
(when-not (empty? best-routes)
fee-data))})))
(rf/reg-event-fx
:wallet/swap-proposal-fee-error
(fn [{:keys [db]}]
{:db (update-in db
[:wallet :ui :swap]
assoc
:loading-swap-proposal-fee?
false)}))
@@ -5,7 +5,6 @@
[status-im.contexts.wallet.common.account-switcher.view :as account-switcher] [status-im.contexts.wallet.common.account-switcher.view :as account-switcher]
[status-im.contexts.wallet.common.asset-list.view :as asset-list] [status-im.contexts.wallet.common.asset-list.view :as asset-list]
[status-im.contexts.wallet.swap.select-asset-to-pay.style :as style] [status-im.contexts.wallet.swap.select-asset-to-pay.style :as style]
[status-im.contexts.wallet.swap.utils :as swap-utils]
[utils.i18n :as i18n] [utils.i18n :as i18n]
[utils.re-frame :as rf])) [utils.re-frame :as rf]))
@@ -21,11 +20,11 @@
(defn- assets-view (defn- assets-view
[search-text on-change-text] [search-text on-change-text]
(let [on-token-press (fn [token] (let [snt-token (rf/sub [:wallet/token-by-symbol "SNT"])
eth-token (rf/sub [:wallet/token-by-symbol "ETH"])
on-token-press (fn [token]
(let [pay-token-symbol (:symbol token) (let [pay-token-symbol (:symbol token)
asset-to-receive (rf/sub [:wallet/token-by-symbol asset-to-receive (if (= pay-token-symbol "SNT") eth-token snt-token)]
(swap-utils/default-asset-to-receive
pay-token-symbol)])]
(rf/dispatch [:wallet.swap/start (rf/dispatch [:wallet.swap/start
{:asset-to-pay {:symbol pay-token-symbol} {:asset-to-pay {:symbol pay-token-symbol}
:asset-to-receive asset-to-receive :asset-to-receive asset-to-receive
@@ -115,7 +115,6 @@
pay-token-symbol (rf/sub [:wallet/swap-asset-to-pay-symbol]) pay-token-symbol (rf/sub [:wallet/swap-asset-to-pay-symbol])
pay-token-decimals (rf/sub [:wallet/swap-asset-to-pay-decimals]) pay-token-decimals (rf/sub [:wallet/swap-asset-to-pay-decimals])
loading-swap-proposal? (rf/sub [:wallet/swap-loading-swap-proposal?]) loading-swap-proposal? (rf/sub [:wallet/swap-loading-swap-proposal?])
loading-swap-proposal-fee? (rf/sub [:wallet/swap-loading-swap-proposal-fee?])
swap-proposal (rf/sub [:wallet/swap-proposal-without-fees]) swap-proposal (rf/sub [:wallet/swap-proposal-without-fees])
approval-required (rf/sub [:wallet/swap-proposal-approval-required]) approval-required (rf/sub [:wallet/swap-proposal-approval-required])
approval-amount-required (rf/sub [:wallet/swap-proposal-approval-amount-required]) approval-amount-required (rf/sub [:wallet/swap-proposal-approval-amount-required])
@@ -123,7 +122,6 @@
approval-transaction-id (rf/sub [:wallet/swap-approval-transaction-id]) approval-transaction-id (rf/sub [:wallet/swap-approval-transaction-id])
approved-amount (rf/sub [:wallet/swap-approved-amount]) approved-amount (rf/sub [:wallet/swap-approved-amount])
error-response (rf/sub [:wallet/swap-error-response]) error-response (rf/sub [:wallet/swap-error-response])
eth-proposal? (= pay-token-symbol "ETH")
overlay-shown? (boolean (:sheets (rf/sub [:bottom-sheet]))) overlay-shown? (boolean (:sheets (rf/sub [:bottom-sheet])))
input-ref (rn/use-ref-atom nil) input-ref (rn/use-ref-atom nil)
set-input-ref (rn/use-callback (fn [ref] (reset! input-ref ref))) set-input-ref (rn/use-callback (fn [ref] (reset! input-ref ref)))
@@ -133,16 +131,12 @@
(:chain-id network)]) (:chain-id network)])
pay-token-fiat-value (rf/sub [:wallet/swap-asset-to-pay-amount-in-fiat pay-token-fiat-value (rf/sub [:wallet/swap-asset-to-pay-amount-in-fiat
pay-input-num-value]) pay-input-num-value])
available-crypto-limit (rf/sub [:wallet/swap-available-crypto-limit]) available-crypto-limit (money/bignumber
display-decimals (min pay-token-decimals
(if eth-proposal?
constants/eth-send-amount-decimal
constants/min-token-decimals-to-display))
total-crypto-limit (money/bignumber
pay-token-balance-selected-chain) pay-token-balance-selected-chain)
total-crypto-limit-display (utils/sanitized-token-amount-to-display display-decimals (min pay-token-decimals
total-crypto-limit constants/min-token-decimals-to-display)
display-decimals) available-crypto-limit-display (rf/sub [:wallet/swap-asset-to-pay-balance-for-chain-ui
(:chain-id network)])
approval-amount-required-num (when approval-amount-required approval-amount-required-num (when approval-amount-required
(number/to-fixed (number/hex->whole (number/to-fixed (number/hex->whole
approval-amount-required approval-amount-required
@@ -163,36 +157,14 @@
pay-input-amount)) pay-input-amount))
(> pay-input-amount 0) (> pay-input-amount 0)
(not pay-input-error?)) (not pay-input-error?))
request-swap-proposal-fee (rn/use-callback
(fn []
(let [safe-send-amount (utils/calculate-max-safe-send-amount
pay-token-balance-selected-chain)]
(rf/dispatch [:wallet/get-swap-proposal-fee
{:amount-in safe-send-amount}])))
[pay-token-balance-selected-chain])
request-fetch-swap-proposal (rn/use-callback request-fetch-swap-proposal (rn/use-callback
(fn [] (fn []
(fetch-swap-proposal (fetch-swap-proposal
{:amount pay-input-amount {:amount pay-input-amount
:valid-input? valid-pay-input? :valid-input? valid-pay-input?
:clean-approval-transaction? true})) :clean-approval-transaction? true}))
[pay-input-amount]) [pay-input-amount])]
on-max-balance-press (rn/use-callback
(fn []
(let [max-value (if eth-proposal?
(number/format-decimal-fixed
available-crypto-limit
constants/eth-send-amount-decimal)
(money/to-string available-crypto-limit))]
(when (money/greater-than max-value 0)
(on-max-press max-value))))
[available-crypto-limit eth-proposal?])]
(rn/use-unmount #(rf/dispatch [:wallet/clean-swap])) (rn/use-unmount #(rf/dispatch [:wallet/clean-swap]))
(rn/use-effect
(fn []
(when eth-proposal?
(request-swap-proposal-fee)))
[eth-proposal?])
(rn/use-effect (rn/use-effect
(fn [] (fn []
(request-fetch-swap-proposal)) (request-fetch-swap-proposal))
@@ -224,13 +196,12 @@
input-focused? :typing input-focused? :typing
:else :disabled) :else :disabled)
:on-token-press on-token-press :on-token-press on-token-press
:on-max-press on-max-balance-press :on-max-press #(on-max-press (str pay-token-balance-selected-chain))
:max-loading? loading-swap-proposal-fee?
:on-input-focus on-input-focus :on-input-focus on-input-focus
:value pay-input-amount :value pay-input-amount
:fiat-value pay-token-fiat-value :fiat-value pay-token-fiat-value
:network-tag-props {:title (i18n/label :t/max-token :network-tag-props {:title (i18n/label :t/max-token
{:number total-crypto-limit-display {:number available-crypto-limit-display
:token-symbol pay-token-symbol}) :token-symbol pay-token-symbol})
:networks [{:source (:source network)}]} :networks [{:source (:source network)}]}
:approval-label-props {:status (case approval-transaction-status :approval-label-props {:status (case approval-transaction-status
@@ -331,16 +302,16 @@
(defn- action-button (defn- action-button
[{:keys [on-press]}] [{:keys [on-press]}]
(let [account-color (rf/sub [:wallet/current-viewing-account-color]) (let [account-color (rf/sub [:wallet/current-viewing-account-color])
swap-proposal-received-amount (rf/sub [:wallet/swap-proposal-amount-out]) swap-proposal (rf/sub [:wallet/swap-proposal-without-fees])
error-response (rf/sub [:wallet/swap-error-response]) error-response (rf/sub [:wallet/swap-error-response])
loading-swap-proposal? (rf/sub [:wallet/swap-loading-swap-proposal?]) loading-swap-proposal? (rf/sub [:wallet/swap-loading-swap-proposal?])
approval-required? (rf/sub [:wallet/swap-proposal-approval-required]) approval-required? (rf/sub [:wallet/swap-proposal-approval-required])
approval-transaction-status (rf/sub [:wallet/swap-approval-transaction-status])] approval-transaction-status (rf/sub [:wallet/swap-approval-transaction-status])]
[quo/bottom-actions [quo/bottom-actions
{:actions :one-action {:actions :one-action
:button-one-label (i18n/label :t/review-swap) :button-one-label (i18n/label :t/review-swap)
:button-one-props {:disabled? (or (not swap-proposal-received-amount) :button-one-props {:disabled? (or (not swap-proposal)
error-response error-response
(and approval-required? (and approval-required?
(not= approval-transaction-status :confirmed)) (not= approval-transaction-status :confirmed))
@@ -62,9 +62,3 @@
[{:keys [networks]}] [{:keys [networks]}]
(when (= (count networks) 1) (when (= (count networks) 1)
(first networks))) (first networks)))
(defn default-asset-to-receive
[pay-token-symbol]
(cond (= pay-token-symbol "SNT") "ETH"
(= pay-token-symbol "ETH") "USDC"
:else "SNT"))
+3 -1
View File
@@ -78,4 +78,6 @@
;;app starting flow continues in get-profiles-overview ;;app starting flow continues in get-profiles-overview
:profile/get-profiles-overview #(rf/dispatch [:profile/get-profiles-overview-success %]) :profile/get-profiles-overview #(rf/dispatch [:profile/get-profiles-overview-success %])
:effects.font/get-font-file-for-initials-avatar :effects.font/get-font-file-for-initials-avatar
#(rf/dispatch [:font/init-font-file-for-initials-avatar %])})) #(rf/dispatch [:font/init-font-file-for-initials-avatar %])
;; show new chain indicator to highlight base chain. This will be be removed in v2.35.
:effects.wallet/retrieve-base-chain-indicator-shown nil}))
-30
View File
@@ -142,11 +142,6 @@
:<- [:wallet/swap] :<- [:wallet/swap]
:-> :loading-swap-proposal?) :-> :loading-swap-proposal?)
(rf/reg-sub
:wallet/swap-loading-swap-proposal-fee?
:<- [:wallet/swap]
:-> :loading-swap-proposal-fee?)
(rf/reg-sub (rf/reg-sub
:wallet/swap-transaction-for-signing :wallet/swap-transaction-for-signing
:<- [:wallet/swap] :<- [:wallet/swap]
@@ -378,28 +373,3 @@
:token asset-to-pay :token asset-to-pay
:prices-per-token prices-per-token})] :prices-per-token prices-per-token})]
(utils/fiat-formatted-for-ui currency-symbol fiat-value))))) (utils/fiat-formatted-for-ui currency-symbol fiat-value)))))
(rf/reg-sub :wallet/max-swap-fee
:<- [:wallet/swap-proposal-approval-required]
:<- [:wallet/swap-approval-fee]
:<- [:wallet/swap-proposal]
(fn [[approval-required swap-approval-fee swap-proposal]]
(let [wallet-swap-proposal-fee (send-utils/full-route-gas-fee [swap-proposal])]
(if approval-required
(money/add swap-approval-fee wallet-swap-proposal-fee)
wallet-swap-proposal-fee))))
(rf/reg-sub :wallet/swap-available-crypto-limit
:<- [:wallet/swap-network]
:<- [:wallet/swap-asset-to-pay-balance-for-chain-data]
:<- [:wallet/max-swap-fee]
:<- [:wallet/swap-asset-to-pay-symbol]
(fn [[network asset-to-pay-with-current-account-balance max-swap-fee pay-token-symbol]]
(let [pay-token-balance (utils/token-balance-for-network
asset-to-pay-with-current-account-balance
(:chain-id network))]
(if (= pay-token-symbol constants/token-for-fees-symbol)
(let [buffered-fee (money/mul max-swap-fee
(inc (/ constants/eth-max-fee-buffer-percent 100)))]
(money/sub pay-token-balance buffered-fee))
pay-token-balance))))
+5
View File
@@ -47,6 +47,11 @@
:<- [:wallet/ui] :<- [:wallet/ui]
:-> :last-updates-per-address) :-> :last-updates-per-address)
(rf/reg-sub
:wallet/show-new-chain-indicator?
:<- [:wallet/ui]
:-> :show-new-chain-indicator?)
(rf/reg-sub (rf/reg-sub
:wallet/latest-update :wallet/latest-update
:<- [:wallet/last-updates-per-address] :<- [:wallet/last-updates-per-address]
-10
View File
@@ -246,13 +246,3 @@
(schema/=> format-amount (schema/=> format-amount
[:=> [:cat [:maybe :int]] [:=> [:cat [:maybe :int]]
[:maybe :string]]) [:maybe :string]])
(defn maximum
[n1 n2]
(when-let [[^js bn1 ^js bn2] (->bignumbers n1 n2)]
(if (greater-than-or-equals bn1 bn2) bn1 bn2)))
(defn minimum
[n1 n2]
(when-let [[^js bn1 ^js bn2] (->bignumbers n1 n2)]
(if (less-than bn1 bn2) bn1 bn2)))
-15
View File
@@ -97,18 +97,3 @@
[num decimal-count] [num decimal-count]
(let [decimal-part (second (string/split (str num) #"\."))] (let [decimal-part (second (string/split (str num) #"\."))]
(or (nil? decimal-part) (<= (count decimal-part) decimal-count)))) (or (nil? decimal-part) (<= (count decimal-part) decimal-count))))
(defn format-decimal-fixed
"Formats a number `n` to `decimal-places` without rounding.
- Ensures the exact number of decimal places (including trailing zeros).
- Does not round up or down, just trims excess decimals."
[n decimal-places]
(let [bn (money/bignumber n)
scale (money/bignumber (money/from-decimal decimal-places))
truncated (if (money/less-than bn 0)
(Math/ceil (money/mul bn scale))
(Math/floor (money/mul bn scale)))]
(-> truncated
(money/bignumber)
(money/div scale)
(money/to-fixed decimal-places))))
-16
View File
@@ -88,19 +88,3 @@
(is (true? (utils.number/valid-decimal-count? 1234567890.12 2))) (is (true? (utils.number/valid-decimal-count? 1234567890.12 2)))
(is (false? (utils.number/valid-decimal-count? 1234567890.12345 3))))) (is (false? (utils.number/valid-decimal-count? 1234567890.12345 3)))))
(deftest format-decimal-fixed-test
(testing "Format decimal numbers correctly without rounding"
(is (= "123.45" (utils.number/format-decimal-fixed "123.456" 2)))
(is (= "123.456" (utils.number/format-decimal-fixed "123.456" 3)))
(is (= "123.45600" (utils.number/format-decimal-fixed "123.456" 5)))
(is (= "123.000" (utils.number/format-decimal-fixed "123.000" 3)))
(is (= "123" (utils.number/format-decimal-fixed "123.999" 0)))
(is (= "-123.4" (utils.number/format-decimal-fixed "-123.456" 1)))
(is (= "-123.45" (utils.number/format-decimal-fixed "-123.456" 2)))
(is (= "0.0006" (utils.number/format-decimal-fixed "0.000650462672354754" 4)))
(is (= "999999999.999" (utils.number/format-decimal-fixed "999999999.999999" 3)))))
+3 -3
View File
@@ -3,7 +3,7 @@
"_comment": "Instead use: scripts/update-status-go.sh <rev>", "_comment": "Instead use: scripts/update-status-go.sh <rev>",
"owner": "status-im", "owner": "status-im",
"repo": "status-go", "repo": "status-go",
"version": "v10.8.0", "version": "v10.7.0+hotfix.2",
"commit-sha1": "ba8fd51958686aea45e34e684ac925a4e65927f8", "commit-sha1": "595dc68e9ff5e6e57364818098616a97b83eabd5",
"src-sha256": "0kqn5rkfsn7aqc2n2flqvkm6cc53ssk0mc1l84f4czg0paci0717" "src-sha256": "04dsmz70h3i738bj3i3ba8bckpw61vxb56m8sc4qw8agc9pdaxc0"
} }
@@ -41,7 +41,7 @@ class TestWalletCollectibles(MultipleSharedDeviceTestCase):
@marks.testrail_id(741839) @marks.testrail_id(741839)
def test_wallet_collectibles_balance(self): def test_wallet_collectibles_balance(self):
self.wallet_view.collectibles_tab.click() self.wallet_view.collectibles_tab.click()
self.wallet_view.set_network_in_wallet(self.network_name) self.wallet_view.set_network_in_wallet(self.network_name + ', NEW')
collectibles = { collectibles = {
"BVL": {"quantity": 2, "BVL": {"quantity": 2,
"info": {"Account": "Account 1", "info": {"Account": "Account 1",
@@ -52,7 +52,7 @@ class TestWalletOneDevice(MultipleSharedDeviceTestCase):
'Mainnet': self.mainnet_balance, 'Mainnet': self.mainnet_balance,
'Arbitrum': self.arb_balance, 'Arbitrum': self.arb_balance,
'Optimism': self.optimism_balance, 'Optimism': self.optimism_balance,
'Base': self.base_balance 'Base, NEW': self.base_balance
} }
for network in expected_balances: for network in expected_balances:
+1 -1
View File
@@ -182,7 +182,7 @@ class WalletView(BaseView):
def set_network_in_wallet(self, network_name: str): def set_network_in_wallet(self, network_name: str):
self.network_drop_down.click() self.network_drop_down.click()
Button(self.driver, accessibility_id="%s, label-component" % network_name.capitalize()).click() Button(self.driver, accessibility_id="%s, label-component" % network_name).click()
self.network_drop_down.click() self.network_drop_down.click()
def get_account_element(self, account_name: str = 'Account 1'): def get_account_element(self, account_name: str = 'Account 1'):
+1
View File
@@ -200,6 +200,7 @@
"bad-fees-description": "Your priority fee is below our suggested parameters.", "bad-fees-description": "Your priority fee is below our suggested parameters.",
"balance": "Balance", "balance": "Balance",
"base": "Base", "base": "Base",
"base-chain-available-info": "Base chain is now on Status - view your assets, interact with dApps and swap tokens",
"be-safe-with-secure-cold-wallet": "Be safe with secure cold wallet", "be-safe-with-secure-cold-wallet": "Be safe with secure cold wallet",
"begin-set-up": "Begin setup", "begin-set-up": "Begin setup",
"below-base-fee": "max fee below base fee", "below-base-fee": "max fee below base fee",