Compare commits

..
Author SHA1 Message Date
Volodymyr Kozieiev 4db2f93faf Fixed issue when incorrect address details where on the edit page
Data to screen was passed via rf-db and acquired in the screen via
sbuscription. But sometimes subscription wasnt calculated yet and
returned nil value. That nil value was captured by use-state and never
updated after subscription updated.
2025-02-25 10:02:40 +00:00
47 changed files with 341 additions and 666 deletions
+1 -1
View File
@@ -2,7 +2,7 @@ DEBUG_WEBVIEW=0
ETHEREUM_DEV_CLUSTER=0
EXTENSIONS=0
GROUP_CHATS_ENABLED=1
LOG_LEVEL=error
LOG_LEVEL=
MAILSERVER_CONFIRMATIONS_ENABLED=1
MAINNET_WARNING_ENABLED=1
PFS_ENCRYPTION_ENABLED=1
+1 -1
View File
@@ -71,7 +71,7 @@ in stdenv.mkDerivation rec {
};
};
buildInputs = with pkgs; [ nodejs openjdk_headless ];
buildInputs = with pkgs; [ nodejs openjdk ];
nativeBuildInputs = with pkgs; [ bash gradle unzip ]
++ lib.optionals stdenv.isDarwin [ file gnumake ];
+1 -1
View File
@@ -8,7 +8,7 @@ rec {
shell = mkShell {
buildInputs = with pkgs; [
openjdk_headless
openjdk
gradle
lsof # used in start-react-native.sh
flock # used in nix/scripts/node_modules.sh
+1 -1
View File
@@ -38,7 +38,7 @@ stdenv.mkDerivation {
];
};
};
buildInputs = with pkgs; [ clojure nodejs bash git openjdk_headless ];
buildInputs = with pkgs; [ clojure nodejs bash git openjdk];
phases = [
"unpackPhase" "secretsPhase" "patchPhase"
"configurePhase" "buildPhase" "installPhase"
+1 -1
View File
@@ -49,7 +49,7 @@ in {
nodejs = super.nodejs_20;
ruby = super.ruby_3_1;
yarn = super.yarn.override { nodejs = super.nodejs_20; };
openjdk_headless = super.openjdk17_headless;
openjdk = super.openjdk17_headless;
xcodeWrapper = callPackage ./pkgs/xcodeenv/compose-xcodewrapper.nix { } {
versions = ["16.0" "16.1" "16.2"];
};
+2 -2
View File
@@ -1,8 +1,8 @@
{ mkShell, openjdk_headless, androidPkgs }:
{ mkShell, openjdk, androidPkgs }:
mkShell {
name = "android-sdk-shell";
buildInputs = [ openjdk_headless ];
buildInputs = [ openjdk ];
shellHook = ''
export ANDROID_HOME="${androidPkgs.sdk}"
+2 -2
View File
@@ -19,7 +19,7 @@ let
# for calling clojure targets in CI or Makefile
clojure = mkShell {
buildInputs = with pkgs; [
clojure flock maven openjdk_headless
clojure flock maven openjdk
# lint specific utilities
babashka clj-kondo clojure-lsp ripgrep zprint
];
@@ -61,7 +61,7 @@ let
# for 'scripts/generate-keystore.sh'
keytool = mkShell {
buildInputs = with pkgs; [ openjdk_headless apksigner ];
buildInputs = with pkgs; [ openjdk apksigner ];
};
# for targets needing 'adb', 'apkanalyzer' and other SDK/NDK tools
+2 -2
View File
@@ -1,5 +1,5 @@
{ callPackage, lib, buildGoPackage, pkgs
, androidPkgs, openjdk_headless, gomobile, xcodeWrapper, removeReferencesTo
, androidPkgs, openjdk, gomobile, xcodeWrapper, removeReferencesTo
, go-bindata, mockgen, protobuf3_20, protoc-gen-go
, meta
, source
@@ -32,7 +32,7 @@ in buildGoPackage rec {
extraSrcPaths = [ gomobile ];
nativeBuildInputs = [
gomobile removeReferencesTo go-bindata mockgen protoc-gen-go protobuf3_20 fakeGit
] ++ optional isAndroid openjdk_headless
] ++ optional isAndroid openjdk
++ optional isIOS xcodeWrapper;
ldflags = goBuildLdFlags;
+6 -28
View File
@@ -2,41 +2,19 @@
(:require
[legacy.status-im.multiaccounts.update.core :as multiaccounts.update]
[re-frame.core :as re-frame]
[taoensso.timbre :as log]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(rf/defn save-log-level
{:events [:log-level.ui/change-log-level-confirmed]}
[{:keys [db]} log-level]
[{:keys [db] :as cofx} log-level]
(let [old-log-level (get-in db [:profile/profile :log-level])]
(when (not= old-log-level log-level)
(let [need-set-log-enabled? (or (empty? old-log-level) (empty? log-level))
log-enabled? (boolean (seq log-level))
rpc-calls (cond-> []
log-enabled?
(conj {:method "wakuext_setLogLevel"
:params [{:logLevel log-level}]
:on-error #(log/error "Failed to set log level" %)})
need-set-log-enabled?
(conj {:method "wakuext_setLogEnabled"
:params [log-enabled?]
:on-error #(log/error "Failed to set log enabled" %)}))]
{:fx [[:json-rpc/call
(conj (vec (map #(assoc % :on-success nil) (butlast rpc-calls)))
(assoc (last rpc-calls)
:on-success
#(rf/dispatch [:log-level/update-multiaccount log-level])))]]}))))
(rf/defn update-multiaccount
{:events [:log-level/update-multiaccount]}
[cofx log-level]
(multiaccounts.update/multiaccount-update
cofx
:log-level
log-level
{:on-success #(rf/dispatch [:profile/logout])}))
(multiaccounts.update/multiaccount-update
cofx
:log-level
log-level
{:on-success #(re-frame/dispatch [:profile/logout])}))))
(rf/defn show-change-log-level-confirmation
{:events [:log-level.ui/log-level-selected]}
@@ -33,9 +33,6 @@
name]]]]))
(def log-levels
"The status-go log library (zap) doesn't support the trace level, so we remove
the trace option from the UI. When trace is enabled an error will happen while
trying to login (user will see the error 'wrong password')."
[{:name "DISABLED"
:value ""}
{:name "ERROR"
@@ -45,7 +42,9 @@
{:name "INFO"
:value "INFO"}
{:name "DEBUG"
:value "DEBUG"}])
:value "DEBUG"}
{:name "TRACE"
:value "TRACE"}])
(views/defview log-level-settings
[]
@@ -14,43 +14,48 @@
(h/describe "Wallet: Summary Info"
(h/test "Type of `status-account` title renders"
(h/render-with-theme-provider [summary-info/view
{:type :status-account
:networks-to-show {:ethereum 150
:optimism 50
:arbitrum 25}
:account-props status-account-props}])
{:type :status-account
:networks? true
:values {:ethereum 150
:optimism 50
:arbitrum 25}
:account-props status-account-props}])
(h/is-truthy (h/get-by-text "Collectibles vault")))
(h/test "Type of `user` title renders"
(h/render-with-theme-provider [summary-info/view
{:type :user
:networks-to-show {:ethereum 150
:optimism 50
:arbitrum 25}
:account-props {:full-name "M L"
:status-indicator? false
:size :small
:customization-color :blue
:name "Mark Libot"
:address "0x0ah...78b"
:status-account (merge status-account-props
{:size 16})}}])
{:type :user
:networks? true
:values {:ethereum 150
:optimism 50
:arbitrum 25}
:account-props {:full-name "M L"
:status-indicator? false
:size :small
:customization-color :blue
:name "Mark Libot"
:address "0x0ah...78b"
:status-account (merge status-account-props
{:size 16})}}])
(h/is-truthy (h/get-by-text "Mark Libot"))
(h/is-truthy (h/get-by-text "Collectibles vault")))
(h/test "Networks specified render"
(h/test "Networks true render"
(h/render-with-theme-provider [summary-info/view
{:type :status-account
:networks-to-show {:ethereum 150
:optimism 50
:arbitrum 25}
:account-props status-account-props}])
(h/is-truthy (h/get-by-label-text :networks))))
{:type :status-account
:networks? true
:values {:ethereum 150
:optimism 50
:arbitrum 25}
:account-props status-account-props}])
(h/is-truthy (h/get-by-label-text :networks)))
(h/describe "Wallet: network summary info"
(h/test "Type of `network` title renders"
(h/test "Networks false render"
(h/render-with-theme-provider [summary-info/view
{:type :network
:network-props {:full-name "Ethereum"
:network-name :ethereum}}])
(h/is-truthy (h/get-by-text "Ethereum"))))
{:type :status-account
:networks? false
:values {:ethereum 150
:optimism 50
:arbitrum 25}
:account-props status-account-props}])
(h/is-null (h/query-by-label-text :networks))))
@@ -5,9 +5,9 @@
[:catn
[:props
[:map
[:type [:enum :status-account :saved-account :account :user :token :network]]
[:type [:enum :status-account :saved-account :account :user :token]]
[:account-props {:optional true} [:maybe :map]]
[:network-props {:optional true} [:maybe :map]]
[:token-props {:optional true} [:maybe :map]]
[:networks-to-show {:optional true} [:maybe :map]]]]]
[:networks? {:optional true} [:maybe :boolean]]
[:values {:optional true} [:maybe :map]]]]]
:any])
@@ -3,13 +3,13 @@
[quo.foundations.colors :as colors]))
(defn container
[networks-to-show? theme]
[networks? theme]
{:width "100%"
:height (if networks-to-show? 90 56)
:height (if networks? 90 56)
:border-radius 16
:border-width 1
:border-color (colors/theme-colors colors/neutral-10 colors/neutral-80 theme)
:margin-bottom (if networks-to-show? 4 8)})
:margin-bottom (if networks? 4 8)})
(def info-container
{:flex-direction :row
@@ -39,7 +39,3 @@
:height 32
:flex-direction :row
:align-items :center})
(def network-icon
{:width 32
:height 32})
@@ -28,35 +28,50 @@
[rn/view
{:style (style/dot-divider theme)}])])
(def ^:private default-token-symbols
{:ethereum "ETH"
:optimism "OP"
:arbitrum "ARB"
:base "ETH"})
(defn networks
[networks-to-show theme]
(->> networks-to-show
(map-indexed
(fn [i [k {:keys [amount token-symbol]}]]
(when (or (pos? amount)
(= amount "<0.01"))
[network-amount
{:network k
:amount (str amount " " (or token-symbol (get default-token-symbols k)))
:divider? (not= (dec i) (-> networks-to-show keys count))
:theme theme}])))
(remove nil?)
(into [rn/view
{:style style/networks-container
:accessibility-label :networks}])))
[values theme]
(let [{:keys [ethereum optimism arbitrum base]} values
show-optimism? (and optimism
(or (pos? (:amount optimism))
(= (:amount optimism) "<0.01")))
show-arbitrum? (and arbitrum
(or (pos? (:amount arbitrum))
(= (:amount arbitrum) "<0.01")))
show-base? (and base
(or (pos? (:amount base))
(= (:amount base) "<0.01")))]
[rn/view
{:style style/networks-container
:accessibility-label :networks}
(when (and ethereum (pos? (:amount ethereum)))
[network-amount
{:network :ethereum
:amount (str (:amount ethereum) " " (or (:token-symbol ethereum) "ETH"))
:divider? (or show-arbitrum? show-optimism?)
:theme theme}])
(when show-optimism?
[network-amount
{:network :optimism
:amount (str (:amount optimism) " " (or (:token-symbol optimism) "OETH"))
:divider? show-arbitrum?
:theme theme}])
(when show-arbitrum?
[network-amount
{:network :arbitrum
:amount (str (:amount arbitrum) " " (or (:token-symbol arbitrum) "ARB"))
:theme theme}])
(when show-base?
[network-amount
{:network :base
:amount (str (:amount base) " " (or (:token-symbol base) "ETH"))
:theme theme}])]))
(defn- view-internal
[{:keys [type account-props network-props token-props networks-to-show]}]
[{:keys [type account-props token-props networks? values]}]
(let [theme (quo.theme/use-theme)
address (or (:address account-props) (:address token-props))]
[rn/view
{:style (style/container (seq? networks-to-show) theme)}
{:style (style/container networks? theme)}
[rn/view
{:style style/info-container}
(case type
@@ -67,26 +82,16 @@
(assoc account-props
:size :size-32
:neutral? true)]
:network [rn/image
{:source (resources/get-network (:network-name network-props))
:style style/network-icon}]
[user-avatar/user-avatar account-props])
[rn/view {:style {:margin-left 8}}
(when (not (some #{type} [:account :network]))
[text/text
{:weight :semi-bold}
(or (:name account-props) (:label token-props))])
(when (= type :network)
[text/text
{:weight :semi-bold}
(:full-name network-props)])
(when (not= type :account)
[text/text {:weight :semi-bold} (or (:name account-props) (:label token-props))])
[rn/view
{:style {:flex-direction :row
:align-items :center}}
(when (= type :user)
[:<>
[rn/view {:style {:margin-right 4}}
[account-avatar/view (:status-account account-props)]]
[rn/view {:style {:margin-right 4}} [account-avatar/view (:status-account account-props)]]
[text/text
{:size :paragraph-2
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}}
@@ -100,10 +105,10 @@
:style {:color (when (not= type :account)
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme))}}
address])]]]
(when networks-to-show
(when networks?
[:<>
[rn/view
{:style (style/line-divider theme)}]
[networks networks-to-show theme]])]))
[networks values theme]])]))
(def view (schema/instrument #'view-internal summary-info-schema/?schema))
@@ -88,10 +88,3 @@
(def gradient-end
(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-token-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]]
[:container-style {:optional true} [:maybe :map]]]]]
:any])
@@ -53,7 +52,7 @@
[{: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?
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)
pay? (= type :pay)
disabled? (= status :disabled)
@@ -173,13 +172,11 @@
(when-not loading?
[:<>
(when pay?
(if max-loading?
[rn/view {:style (style/button-loader theme)}]
[rn/pressable {:on-press on-max-press}
[network-tag/view
(assoc network-tag-props
:status
(if error? :error :default))]]))
[rn/pressable {:on-press on-max-press}
[network-tag/view
(assoc network-tag-props
:status
(if error? :error :default))]])
(when fiat-value
[text/text
{:size :paragraph-2
-6
View File
@@ -492,16 +492,10 @@
(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-pending "Pending")
(def ^:const transaction-status-failed "Failed")
(def ^:const eth-send-amount-decimal 4)
(def ^:const min-token-decimals-to-display 6)
(def ^:const swap-proposal-refresh-interval-ms 15000)
+15 -26
View File
@@ -23,7 +23,6 @@
(defn view
[]
(let [error (rf/sub [:keycard/application-info-error])
logged-in? (rf/sub [:multiaccount/logged-in?])
{:keys [title description]} (get titles error)]
[:<>
[quo/page-nav
@@ -38,31 +37,21 @@
[quo/section-label
{:section (i18n/label :t/what-you-can-do) :container-style {:padding-vertical 8}}]
(if (= error :keycard/error.keycard-empty)
(if logged-in?
[quo/settings-item
{:title (i18n/label :t/use-backup-keycard)
:image :icon
:image-props :i/placeholder
:action :arrow
:description :text
:description-props {:text (i18n/label :t/create-backup-profile-keycard)}
:on-press (fn []
(rf/dispatch [:show-bottom-sheet
{:content
(fn []
[backup.view/sheet
{:on-continue
(rf/dispatch
[:keycard/backup.create-or-enter-pin])}])}]))}]
[quo/settings-item
{:title (i18n/label :t/create-new-profile)
:image :icon
:image-props :i/profile
:action :arrow
:description :text
:description-props {:text (i18n/label :t/new-key-pair-keycard)}
:on-press (fn []
(rf/dispatch [:keycard/create.get-phrase]))}])
[quo/settings-item
{:title (i18n/label :t/use-backup-keycard)
:image :icon
:image-props :i/placeholder
:action :arrow
:description :text
:description-props {:text (i18n/label :t/create-backup-profile-keycard)}
:on-press (fn []
(rf/dispatch [:show-bottom-sheet
{:content
(fn []
[backup.view/sheet
{:on-continue
(rf/dispatch
[:keycard/backup.create-or-enter-pin])}])}]))}]
[:<>
(when (or (= error :keycard/error.keycard-frozen)
(= error :keycard/error.keycard-locked))
@@ -12,15 +12,17 @@
:options [{:key :status-account}
{:key :user}
{:key :saved-account}
{:key :account}]}])
{:key :account}]}
{:key :networks? :type :boolean}])
(defn view
[]
(let [state (reagent/atom {:type :status-account
:networks-to-show {:ethereum {:amount 150}
:optimism {:amount 50}
:arbitrum {:amount 25}}})
(let [state (reagent/atom {:type :status-account
:networks? true
:values {:ethereum {:amount 150}
:optimism {:amount 50}
:arbitrum {:amount 25}}})
status-account-props {:customization-color :purple
:size 32
:emoji "🍑"
@@ -164,15 +164,12 @@
on-press-continue (rn/use-callback
(fn []
(rf/dispatch
[:wallet/set-address-to-save
[:open-modal :screen/settings.save-address
{:address address
:ens (when ens-name? address-or-ens)
:ens? ens-name?}])
(rf/dispatch
[:open-modal :screen/settings.save-address]))
:ens? ens-name?}]))
[address ens-name? address-or-ens])]
(rn/use-unmount #(rf/dispatch [:wallet/clean-scanned-address]))
(rn/use-mount #(rf/dispatch [:wallet/clear-address-to-save]))
[quo/overlay {:type :shell}
[floating-button-page/view
{:footer-container-padding 0
@@ -143,18 +143,6 @@
(rf/reg-event-fx :wallet/add-saved-address-failed add-saved-address-failed)
(defn set-address-to-save
[{:keys [db]} [args]]
{:db (assoc-in db [:wallet :ui :saved-address] args)})
(rf/reg-event-fx :wallet/set-address-to-save set-address-to-save)
(defn clear-address-to-save
[{:keys [db]}]
{:db (update-in db [:wallet :ui] dissoc :saved-address)})
(rf/reg-event-fx :wallet/clear-address-to-save clear-address-to-save)
(defn check-remaining-capacity-for-saved-addresses
[{:keys [db]} [{:keys [on-success on-error]}]]
(let [test-networks-enabled? (boolean (get-in db [:profile/profile :test-networks-enabled?]))]
@@ -17,50 +17,48 @@
(defn view
[]
(let [{:keys [edit?]} (rf/sub [:get-screen-params])
{:keys [address name customization-color ens ens?]}
(rf/sub [:wallet/saved-address])
(let [{:keys [address name customization-color ens
ens? edit?]} (rf/sub [:get-screen-params])
[address-label set-address-label] (rn/use-state (or name ""))
[address-color set-address-color] (rn/use-state (or customization-color
(rand-nth colors/account-colors)))
placeholder (i18n/label :t/address-name)
address-text (rn/use-callback
(fn []
[quo/address-text
{:full-address? true
:address address
:format :long}])
[address])
on-press-save (rn/use-callback
(fn []
(rf/dispatch [:wallet/save-address
{:on-success
(if edit?
[:wallet/edit-saved-address-success]
[:wallet/add-saved-address-success
(i18n/label :t/address-saved)])
:on-error
[:wallet/add-saved-address-failed]
:name address-label
:ens (when ens? ens)
:address address
:customization-color address-color}]))
[address address-label
address-color])
data-item-props (rn/use-memo
#(cond-> {:status :default
:size :default
:subtitle-type :default
:label :none
:blur? true
:card? true
:title (i18n/label :t/address)
:subtitle ens
:custom-subtitle address-text
:container-style style/data-item}
ens?
(dissoc :custom-subtitle))
[ens ens? address-text])]
placeholder (i18n/label :t/address-name)
address-text (rn/use-callback
(fn []
[quo/address-text
{:full-address? true
:address address
:format :long}])
[address])
on-press-save (rn/use-callback
(fn []
(rf/dispatch [:wallet/save-address
{:on-success
(if edit?
[:wallet/edit-saved-address-success]
[:wallet/add-saved-address-success
(i18n/label :t/address-saved)])
:on-error
[:wallet/add-saved-address-failed]
:name address-label
:ens (when ens? ens)
:address address
:customization-color address-color}]))
[address address-label
address-color])
data-item-props (rn/use-memo
#(cond-> {:status :default
:size :default
:subtitle-type :default
:blur? true
:card? true
:title (i18n/label :t/address)
:subtitle ens
:custom-subtitle address-text
:container-style style/data-item}
ens?
(dissoc :custom-subtitle))
[ens ens? address-text])]
[quo/overlay {:type :shell}
[floating-button-page/view
{:footer-container-padding (if edit? (+ (safe-area/get-bottom) 12) 0)
@@ -9,7 +9,7 @@
[utils.re-frame :as rf]))
(defn view
[{:keys [name address customization-color] :as opts}]
[{:keys [name address customization-color] :as address-details}]
(let [open-send-flow (rn/use-callback
(fn []
(rf/dispatch [:wallet/init-send-flow-for-address
@@ -62,19 +62,20 @@
{:theme :dark
:shell? true
:content (fn []
[remove-address/view opts])}])
[opts])
[remove-address/view address-details])}])
[address-details])
open-show-address-qr (rn/use-callback
#(rf/dispatch [:open-modal
:screen/settings.share-saved-address opts])
[opts])
:screen/settings.share-saved-address
address-details])
[address-details])
open-edit-saved-address (rn/use-callback
(fn []
(rf/dispatch [:wallet/set-address-to-save opts])
(rf/dispatch [:open-modal
:screen/settings.edit-saved-address
{:edit? true}]))
[opts])]
(merge {:edit? true}
address-details)]))
[address-details])]
[quo/action-drawer
[[{:icon :i/arrow-up
:label (i18n/label :t/send-to-user {:user name})
@@ -2,7 +2,6 @@
(:require [quo.core :as quo]
[status-im.contexts.wallet.send.utils :as send-utils]
[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]
[utils.i18n :as i18n]
[utils.money :as money]
@@ -79,34 +78,34 @@
(defn token-value-drawer
[token watch-only? entry-point]
(let [token-symbol (:token token)
token-data (rf/sub [:wallet/token-by-symbol-from-first-available-account-with-balance
token-symbol])
selected-account (rf/sub [:wallet/current-viewing-account-address])
token-owners (rf/sub [:wallet/operable-addresses-with-token-symbol token-symbol])
testnet-mode? (rf/sub [:profile/test-networks-enabled?])
account-owns-token? (rf/sub [:wallet/current-account-owns-token token-symbol])
network-details (rf/sub [:wallet/network-details])
token-owned? (if selected-account account-owns-token? (seq token-owners))
asset-to-receive (rf/sub [:wallet/token-by-symbol-from-first-available-account-with-balance
(swap-utils/default-asset-to-receive token-symbol)])
unique-owner? (= (count token-owners) 1)
params (cond-> {:start-flow? true
:owners token-owners
:testnet-mode? testnet-mode?}
selected-account
(assoc :token token-data
:stack-id :screen/wallet.accounts
:has-balance? (-> (get-in token [:values :fiat-unformatted-value])
money/above-zero?))
(and (not selected-account) unique-owner?)
(assoc :token-symbol token-symbol
:token token-data
:stack-id :wallet-stack)
(let [token-symbol (:token token)
token-data (rf/sub [:wallet/token-by-symbol-from-first-available-account-with-balance
token-symbol])
selected-account (rf/sub [:wallet/current-viewing-account-address])
token-owners (rf/sub [:wallet/operable-addresses-with-token-symbol token-symbol])
testnet-mode? (rf/sub [:profile/test-networks-enabled?])
account-owns-token? (rf/sub [:wallet/current-account-owns-token token-symbol])
network-details (rf/sub [:wallet/network-details])
receive-token-symbol (if (= token-symbol "SNT") "ETH" "SNT")
token-owned? (if selected-account account-owns-token? (seq token-owners))
asset-to-receive (rf/sub [:wallet/token-by-symbol receive-token-symbol])
unique-owner? (= (count token-owners) 1)
params (cond-> {:start-flow? true
:owners token-owners
:testnet-mode? testnet-mode?}
selected-account
(assoc :token token-data
:stack-id :screen/wallet.accounts
:has-balance? (-> (get-in token [:values :fiat-unformatted-value])
money/above-zero?))
(and (not selected-account) unique-owner?)
(assoc :token-symbol token-symbol
:token token-data
:stack-id :wallet-stack)
(and (not selected-account) (not unique-owner?))
(assoc :token-symbol token-symbol
:stack-id :wallet-stack))]
(and (not selected-account) (not unique-owner?))
(assoc :token-symbol token-symbol
:stack-id :wallet-stack))]
[quo/action-drawer
[(cond->> [(when (ff/enabled? ::ff/wallet.assets-modal-manage-tokens)
(action-manage-tokens watch-only?))
@@ -182,22 +182,12 @@
[amount display-decimals]
(let [number (or (money/bignumber amount)
(money/bignumber 0))
amount-fixed-decimals (-> number
(number/format-decimal-fixed display-decimals)
(number/remove-trailing-zeroes))]
amount-fixed-decimals (number/to-fixed number display-decimals)]
(if (and (= amount-fixed-decimals "0")
(money/above-zero? amount))
(number/small-number-threshold display-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
"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,
@@ -490,25 +480,3 @@
(filter (fn [{:keys [tokens]}]
(some positive-balance-in-any-chain? tokens))
operable-account))))
(defn calculate-max-safe-send-amount
"Calculates the max ETH that can be sent while reserving enough for gas fees.
- Ensures a minimum of 0.0001 ETH and a max of 0.01 ETH for gas.
- Uses 20% of the value as an estimated fee, clamped within this range.
- In Desktop it's 10% but after some more test, we found 20% is better option.
- Prevents sending the full balance to avoid transaction failures.
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.00001 3) "<0.001"))
(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 nil 2) "0"))
(is (= (utils/sanitized-token-amount-to-display "invalid" 2) "0"))))
@@ -375,14 +375,3 @@
{:symbol "DAI"}
{:symbol "ETH"}]]
(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
transforms/json->clj
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)))
+40 -2
View File
@@ -12,6 +12,7 @@
[taoensso.timbre :as log]
[utils.address]
[utils.i18n :as i18n]
[utils.money :as utils.money]
[utils.number]
[utils.re-frame :as rf]
[utils.security.core :as security]))
@@ -622,6 +623,43 @@
{:event :wallet/stop-get-suggested-routes
: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
:wallet/handle-suggested-routes
(fn [{:keys [db]} [data]]
@@ -647,8 +685,8 @@
(cond
(and failure? swap?) [:wallet/swap-proposal-error error]
failure? [:wallet/suggested-routes-error error-message]
swap? [:wallet/swap-proposal-success (data-store/fix-routes data)]
:else [:wallet/suggested-routes-success (data-store/fix-routes data)
swap? [:wallet/swap-proposal-success (fix-routes data)]
:else [:wallet/suggested-routes-success (fix-routes data)
enough-assets?])]]}))))))
(rf/reg-event-fx
@@ -28,7 +28,3 @@
[theme]
{:margin-bottom 8
:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)})
(def summary-container
{:padding-horizontal 20
:padding-bottom 16})
@@ -135,7 +135,9 @@
:saved-address :saved-account
:account :status-account
summary-type)]
[rn/view {:style style/summary-container}
[rn/view
{:style {:padding-horizontal 20
:padding-bottom 16}}
[quo/text
{:size :paragraph-2
:weight :medium
@@ -143,32 +145,17 @@
:accessibility-label accessibility-label}
label]
[quo/summary-info
{:type summary-info-type
:networks-to-show (when bridge-tx?
(send-utils/network-values-for-ui network-values))
:account-props (cond-> account-props
(and account-to? (not bridge-tx?))
(assoc
:size 32
:name (:label recipient)
:full-name (:label recipient)
:emoji (:emoji recipient)
:customization-color (:customization-color recipient)))}]]))
(defn- network-summary
[{:keys [theme label accessibility-label]}]
(let [network (rf/sub [:wallet/send-selected-network])]
(when network
[rn/view {:style style/summary-container}
[quo/text
{:size :paragraph-2
:weight :medium
:style (style/section-label theme)
:accessibility-label accessibility-label}
label]
[quo/summary-info
{:type :network
:network-props network}]])))
{:type summary-info-type
:networks? true
:values (send-utils/network-values-for-ui network-values)
:account-props (cond-> account-props
(and account-to? (not bridge-tx?))
(assoc
:size 32
:name (:label recipient)
:full-name (:label recipient)
:emoji (:emoji recipient)
:customization-color (:customization-color recipient)))}]]))
(defn- data-item
[{:keys [title subtitle]}]
@@ -313,7 +300,6 @@
:accessibility-label :summary-from-label
:label (i18n/label :t/from-capitalized)
:account-props from-account-props
:bridge-tx? (= transaction-type :tx/bridge)
:theme theme}]
[user-summary
{:summary-type (if (= transaction-type :tx/bridge)
@@ -327,8 +313,4 @@
:recipient recipient
:bridge-tx? (= transaction-type :tx/bridge)
:account-to? true
:theme theme}]
(when-not (= transaction-type :tx/bridge)
[network-summary
{:label (i18n/label :t/on-capitalized)
:theme theme}])]]]))
:theme theme}]]]]))
@@ -24,7 +24,7 @@
{:size :paragraph-2
:weight :medium
:style style/on}
(i18n/label :t/on-capitalized)]
(i18n/label :t/on-uppercase)]
[quo/context-tag
{:type :network
:network-logo (:logo-url provider)
+3 -92
View File
@@ -2,7 +2,6 @@
(:require [re-frame.core :as rf]
[status-im.constants :as constants]
[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.sheets.network-selection.view :as network-selection]
[status-im.contexts.wallet.swap.utils :as swap-utils]
@@ -29,15 +28,6 @@
:account account
:test-networks-enabled? test-networks-enabled?
: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
(count)
(> 1))
@@ -46,7 +36,7 @@
start-point (if open-new-screen? :action-menu :swap-button)]
{:db (-> db
(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 :launch-screen] view-id)
(assoc-in [:wallet :ui :swap :start-point] start-point))
@@ -63,7 +53,7 @@
[:centralized-metrics/track :metric/swap-start
{:network (:chain-id network)
:pay_token (:symbol asset-to-pay)
:receive_token (:symbol received-asset)
:receive_token (:symbol asset-to-receive)
:start_point start-point
:launch_screen view-id}]]
[:dispatch [:wallet.swap/set-default-slippage]]]
@@ -77,7 +67,7 @@
(rf/dispatch
[:wallet.swap/start
{:asset-to-pay asset-to-pay
:asset-to-receive received-asset
:asset-to-receive asset-to-receive
:network network
:open-new-screen?
open-new-screen?
@@ -587,82 +577,3 @@
[:dispatch
[:navigate-to-within-stack
[: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.asset-list.view :as asset-list]
[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.re-frame :as rf]))
@@ -21,11 +20,11 @@
(defn- assets-view
[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)
asset-to-receive (rf/sub [:wallet/token-by-symbol
(swap-utils/default-asset-to-receive
pay-token-symbol)])]
asset-to-receive (if (= pay-token-symbol "SNT") eth-token snt-token)]
(rf/dispatch [:wallet.swap/start
{:asset-to-pay {:symbol pay-token-symbol}
:asset-to-receive asset-to-receive
@@ -115,7 +115,6 @@
pay-token-symbol (rf/sub [:wallet/swap-asset-to-pay-symbol])
pay-token-decimals (rf/sub [:wallet/swap-asset-to-pay-decimals])
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])
approval-required (rf/sub [:wallet/swap-proposal-approval-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])
approved-amount (rf/sub [:wallet/swap-approved-amount])
error-response (rf/sub [:wallet/swap-error-response])
eth-proposal? (= pay-token-symbol "ETH")
overlay-shown? (boolean (:sheets (rf/sub [:bottom-sheet])))
input-ref (rn/use-ref-atom nil)
set-input-ref (rn/use-callback (fn [ref] (reset! input-ref ref)))
@@ -133,16 +131,12 @@
(:chain-id network)])
pay-token-fiat-value (rf/sub [:wallet/swap-asset-to-pay-amount-in-fiat
pay-input-num-value])
available-crypto-limit (rf/sub [:wallet/swap-available-crypto-limit])
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
available-crypto-limit (money/bignumber
pay-token-balance-selected-chain)
total-crypto-limit-display (utils/sanitized-token-amount-to-display
total-crypto-limit
display-decimals)
display-decimals (min pay-token-decimals
constants/min-token-decimals-to-display)
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
(number/to-fixed (number/hex->whole
approval-amount-required
@@ -163,36 +157,14 @@
pay-input-amount))
(> pay-input-amount 0)
(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
(fn []
(fetch-swap-proposal
{:amount pay-input-amount
:valid-input? valid-pay-input?
:clean-approval-transaction? true}))
[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?])]
[pay-input-amount])]
(rn/use-unmount #(rf/dispatch [:wallet/clean-swap]))
(rn/use-effect
(fn []
(when eth-proposal?
(request-swap-proposal-fee)))
[eth-proposal?])
(rn/use-effect
(fn []
(request-fetch-swap-proposal))
@@ -224,13 +196,12 @@
input-focused? :typing
:else :disabled)
:on-token-press on-token-press
:on-max-press on-max-balance-press
:max-loading? loading-swap-proposal-fee?
:on-max-press #(on-max-press (str pay-token-balance-selected-chain))
:on-input-focus on-input-focus
:value pay-input-amount
:fiat-value pay-token-fiat-value
:network-tag-props {:title (i18n/label :t/max-token
{:number total-crypto-limit-display
{:number available-crypto-limit-display
:token-symbol pay-token-symbol})
:networks [{:source (:source network)}]}
:approval-label-props {:status (case approval-transaction-status
@@ -331,16 +302,16 @@
(defn- action-button
[{:keys [on-press]}]
(let [account-color (rf/sub [:wallet/current-viewing-account-color])
swap-proposal-received-amount (rf/sub [:wallet/swap-proposal-amount-out])
error-response (rf/sub [:wallet/swap-error-response])
loading-swap-proposal? (rf/sub [:wallet/swap-loading-swap-proposal?])
approval-required? (rf/sub [:wallet/swap-proposal-approval-required])
approval-transaction-status (rf/sub [:wallet/swap-approval-transaction-status])]
(let [account-color (rf/sub [:wallet/current-viewing-account-color])
swap-proposal (rf/sub [:wallet/swap-proposal-without-fees])
error-response (rf/sub [:wallet/swap-error-response])
loading-swap-proposal? (rf/sub [:wallet/swap-loading-swap-proposal?])
approval-required? (rf/sub [:wallet/swap-proposal-approval-required])
approval-transaction-status (rf/sub [:wallet/swap-approval-transaction-status])]
[quo/bottom-actions
{:actions :one-action
: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
(and approval-required?
(not= approval-transaction-status :confirmed))
@@ -75,13 +75,14 @@
:accessibility-label title-accessibility-label}
label]
[quo/summary-info
{:type :token
:token-props {:token token-symbol
:label (str amount " " token-symbol)
:address (when token-address
(address-utils/get-shortened-compressed-key token-address))
:size 32}
:networks-to-show (send-utils/network-values-for-ui network-values)}]]))
{:type :token
:networks? true
:values (send-utils/network-values-for-ui network-values)
:token-props {:token token-symbol
:label (str amount " " token-symbol)
:address (when token-address
(address-utils/get-shortened-compressed-key token-address))
:size 32}}]]))
(defn- pay-section
[]
@@ -62,9 +62,3 @@
[{:keys [networks]}]
(when (= (count networks) 1)
(first networks)))
(defn default-asset-to-receive
[pay-token-symbol]
(cond (= pay-token-symbol "SNT") "ETH"
(= pay-token-symbol "ETH") "USDC"
:else "SNT"))
+3 -3
View File
@@ -164,9 +164,9 @@
theme)})
options
(when sheet?
options/sheet-options))}}]}})))
(state/navigation-state-push {:id component
:type :modal})))
options/sheet-options))}}]}})
(state/navigation-state-push {:id component
:type :modal})))))
(rf/reg-fx :open-modal-fx open-modal)
-9
View File
@@ -71,12 +71,3 @@
{:amount amount-fixed :token-symbol token-symbol})))
{}
network-values))))
(re-frame/reg-sub
:wallet/send-selected-network
:<- [:wallet/wallet-send]
(fn [{:keys [to-values-by-chain]}]
(-> to-values-by-chain
keys
first
network-utils/get-network-details)))
-30
View File
@@ -142,11 +142,6 @@
:<- [:wallet/swap]
:-> :loading-swap-proposal?)
(rf/reg-sub
:wallet/swap-loading-swap-proposal-fee?
:<- [:wallet/swap]
:-> :loading-swap-proposal-fee?)
(rf/reg-sub
:wallet/swap-transaction-for-signing
:<- [:wallet/swap]
@@ -378,28 +373,3 @@
:token asset-to-pay
:prices-per-token prices-per-token})]
(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))))
-10
View File
@@ -246,13 +246,3 @@
(schema/=> format-amount
[:=> [:cat [:maybe :int]]
[: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]
(let [decimal-part (second (string/split (str num) #"\."))]
(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 (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>",
"owner": "status-im",
"repo": "status-go",
"version": "v10.8.0",
"commit-sha1": "ba8fd51958686aea45e34e684ac925a4e65927f8",
"src-sha256": "0kqn5rkfsn7aqc2n2flqvkm6cc53ssk0mc1l84f4czg0paci0717"
"version": "v10.6.0",
"commit-sha1": "c5e4eb1a56ea7641efcc7cc677be7fd5d3f92225",
"src-sha256": "0n8x03c4dqxwcl27y8x6hmn6wbfpq3llkj15hhjxc4baaqwrhy8i"
}
@@ -36,12 +36,11 @@ class TestWalletCollectibles(MultipleSharedDeviceTestCase):
'').lower()
self.receiver_short_address = self.receiver['wallet_address'].replace(self.receiver['wallet_address'][6:-3],
'').lower()
self.network_name = 'Base'
@marks.testrail_id(741839)
def test_wallet_collectibles_balance(self):
self.wallet_view.collectibles_tab.click()
self.wallet_view.set_network_in_wallet(self.network_name)
self.wallet_view.set_network_in_wallet('Base')
collectibles = {
"BVL": {"quantity": 2,
"info": {"Account": "Account 1",
@@ -104,17 +103,15 @@ class TestWalletCollectibles(MultipleSharedDeviceTestCase):
self.wallet_view.get_collectible_element('BVL').click()
self.wallet_view.amount_input_increase_button.click()
self.wallet_view.confirm_button.click()
for text in [self.account_name, self.sender_short_address]:
expected_text = '2 BVL #47'
for text in [self.account_name, self.sender_short_address, expected_text]:
if not self.wallet_view.from_data_container.get_child_element_by_text(text).is_element_displayed():
self.errors.append(self.wallet_view,
"Text %s is not shown inside 'From' container on the Review Send page" % text)
if not self.wallet_view.to_data_container.get_child_element_by_text(
self.receiver_short_address).is_element_displayed():
self.errors.append(self.wallet_view,
"Text %s is not shown inside 'To' container on the Review Send page" % text)
if not self.wallet_view.on_data_container.get_child_element_by_text(self.network_name).is_element_displayed():
self.errors.append(self.wallet_view,
"Text %s is not shown inside 'On' container on the Review Send page" % text)
"Text %s is not shown in 'From' container on the Review Send page" % text)
for text in [self.receiver_short_address, expected_text]:
if not self.wallet_view.to_data_container.get_child_element_by_text(text).is_element_displayed():
self.errors.append(self.wallet_view,
"Text %s is not shown in 'To' container on the Review Send page" % text)
data_to_check = {
'Est. time': ' min',
'Max fees': r"[$]\d+.\d+",
@@ -151,17 +148,15 @@ class TestWalletCollectibles(MultipleSharedDeviceTestCase):
self.wallet_view.send_from_collectible_info_button.click()
self.wallet_view.address_text_input.send_keys(self.receiver['wallet_address'])
self.wallet_view.continue_button.click()
for text in [self.account_name, self.sender_short_address]:
expected_text = '1 Glitch Punks #3422'
for text in [self.account_name, self.sender_short_address, expected_text]:
if not self.wallet_view.from_data_container.get_child_element_by_text(text).is_element_displayed():
self.errors.append(self.wallet_view,
"Text %s is not shown in 'From' container on the Review Send page" % text)
if not self.wallet_view.to_data_container.get_child_element_by_text(
self.receiver_short_address).is_element_displayed():
self.errors.append(self.wallet_view,
"Text %s is not shown in 'To' container on the Review Send page" % text)
if not self.wallet_view.on_data_container.get_child_element_by_text(self.network_name).is_element_displayed():
self.errors.append(self.wallet_view,
"Text %s is not shown inside 'On' container on the Review Send page" % text)
for text in [self.receiver_short_address, expected_text]:
if not self.wallet_view.to_data_container.get_child_element_by_text(text).is_element_displayed():
self.errors.append(self.wallet_view,
"Text %s is not shown in 'To' container on the Review Send page" % text)
data_to_check = {
'Est. time': ' min',
'Max fees': r"[$]\d+.\d+",
@@ -99,32 +99,28 @@ class TestWalletOneDevice(MultipleSharedDeviceTestCase):
self.wallet_view.confirm_button.click()
self.wallet_view.just_fyi("Checking Review Send page for %s on %s" % (asset, network))
expected_amount = "%s %s" % (data['amount'], 'ETH' if asset == 'Ether' else 'SNT')
sender_short_address = self.sender['wallet_address'].replace(self.sender['wallet_address'][6:-3],
'').lower()
receiver_short_address = self.receiver['wallet_address'].replace(self.receiver['wallet_address'][6:-3],
'').lower()
for text in [self.account_name, sender_short_address]:
for text in [self.account_name, sender_short_address, expected_amount]:
if not self.wallet_view.from_data_container.get_child_element_by_text(text).is_element_displayed():
self.errors.append(
self.wallet_view,
"%s on %s: text %s is not shown in 'From' container on the Review Send page" % (
asset, network, text))
if not self.wallet_view.to_data_container.get_child_element_by_text(
receiver_short_address).is_element_displayed():
self.errors.append(
self.wallet_view,
"%s on %s: text %s is not shown in 'To' container on the Review Send page" % (
asset, network, text))
if not self.wallet_view.on_data_container.get_child_element_by_text(network).is_element_displayed():
self.errors.append(
self.wallet_view,
"%s on %s: network %s is not shown in 'On' container on the Review Send page" % (
asset, network, text))
for text in [receiver_short_address, expected_amount]:
if not self.wallet_view.to_data_container.get_child_element_by_text(text).is_element_displayed():
self.errors.append(
self.wallet_view,
"%s on %s: text %s is not shown in 'To' container on the Review Send page" % (
asset, network, text))
data_to_check = {
'Est. time': ' min',
'Max fees': r"[$]\d+.\d+",
'Recipient gets': "%s %s" % (data['amount'], 'ETH' if asset == 'Ether' else 'SNT')
'Recipient gets': expected_amount
}
for key, expected_value in data_to_check.items():
try:
@@ -309,6 +305,17 @@ class TestWalletOneDevice(MultipleSharedDeviceTestCase):
self.wallet_view,
"%s to %s: Text %s is not shown in the '%s' data container on the Review Bridge screen"
% (network_from, network_to, text, name))
amount_text = container.amount_text
if name == 'from' and amount_text != amount + ' ETH':
self.errors.append(
self.wallet_view,
"%s to %s: amount %s in the 'from' data container doesn't match expected %s ETH"
% (network_from, network_to, amount_text, amount))
if name == 'to' and not re.findall(r"0.000\d+ ETH", amount_text):
self.errors.append(
self.wallet_view,
"%s to %s: amount %s in the 'to' data container is not a number"
% (network_from, network_to, amount_text))
except TimeoutException:
self.errors.append(self.wallet_view, "%s to %s: data '%s' is not shown in Review Bridge screen" %
(network_from, network_to, name))
+3 -4
View File
@@ -81,7 +81,7 @@ class ActivityElement(BaseElement):
class ConfirmationViewInfoContainer(BaseElement):
def __init__(self, driver, label_name: str):
self.locator = "//*[@text='%s']/following-sibling::android.view.ViewGroup[1]" % label_name
self.locator = "//*[@content-desc='summary-%s-label']/following-sibling::android.view.ViewGroup[1]" % label_name
super().__init__(driver, xpath=self.locator)
@property
@@ -139,9 +139,8 @@ class WalletView(BaseView):
self.amount_input_increase_button = Button(self.driver, accessibility_id='amount-input-inc-button')
# Review Send and Review Bridge screens
self.from_data_container = ConfirmationViewInfoContainer(self.driver, label_name='From')
self.to_data_container = ConfirmationViewInfoContainer(self.driver, label_name='To')
self.on_data_container = ConfirmationViewInfoContainer(self.driver, label_name='On')
self.from_data_container = ConfirmationViewInfoContainer(self.driver, label_name='from')
self.to_data_container = ConfirmationViewInfoContainer(self.driver, label_name='to')
# Swap flow
self.approve_swap_button = Button(self.driver, accessibility_id='Approve')
+1
View File
@@ -1892,6 +1892,7 @@
"on-keycard": "On Keycard",
"on-status-tree": "On Status tree",
"on-the-web": "On the web",
"on-uppercase": "On",
"once-enabled-share-metadata": "Once enabled, links posted in the chat may share your metadata with the site",
"one-day": "One day",
"one-month": "One month",