Compare commits

...
Author SHA1 Message Date
Volodymyr Kozieiev d2eb401a16 wip 2025-01-26 16:36:48 +00:00
Volodymyr Kozieiev c568a51c60 Before modifying signing order 2025-01-24 16:55:15 +00:00
Yevheniia Berdnyk f474edf67d e2e: fix for saving logs 2025-01-22 16:03:54 +02:00
Volodymyr Kozieiev dfd90617bf Backend server doc added to readme (#21966) 2025-01-21 12:14:27 +00:00
Yevheniia Berdnyk 9782ba2ac3 e2e: added verifications to fallback test 2025-01-21 11:54:44 +02:00
Brian Sztamfater f0e0c95fe0 feat: integrate base chain (#21876)
Signed-off-by: Brian Sztamfater <brian@status.im>
2025-01-21 01:44:02 -03:00
Mohsen ef7d977299 [#21305] fix: sort assets by value and collectibles by name (#21908)
* [#21305] fix: sort assets by value and collectibles by name

* [#21305] fix: use seq to check name is nil or empty

* [#21305] fix: normalize text to sort properly
2025-01-20 19:41:40 +03:00
Parvesh Monu 70a5ed255f fix keycard sign up ui issues (#21938) 2025-01-20 17:22:13 +05:30
flexsurfer be1347346c [#21578] Keycard - Factory reset a Keycard (#21914) 2025-01-20 12:35:06 +01:00
Volodymyr Kozieiev 803e83ae02 Screens for editing transaction settings (#21838)
* Screens for editing transaction settings

* extra lines removed

* review notes fixed
2025-01-20 11:21:55 +00:00
Yevheniia Berdnyk 64748c939b e2e: fix for test_community_mentions_push_notification 2025-01-20 03:33:27 +02:00
Sean Hagstrom 64fb344197 chore: add support for remote devices with re-frisk server (#21805)
This changes adds support for connecting remotely to re-frisk when running the app on a mobile device. This change is essentially aimed towards better support for introspecting on iOS devices, but these changes should also work for Android devices too. Note, that running in the Android simulator may still require port-forwarding with `adb reverse`.
2025-01-18 05:57:17 +00:00
Sean Hagstrom f27b402205 chore: update status-go with identity images fixes (#21931)
This change integrates status-go changes that fix an underlying issue with generating identity images. Now identity images will be generated with a populated `clock` field, so we no longer need our existing workaround.
2025-01-18 05:37:37 +00:00
Icaro Motta b22744f81e fix(settings): Show current mailserver in legacy settings (#21901)
A regression removed more code than we wanted in
https://github.com/status-im/status-mobile/pull/20730 and the result was
broken functionality in the Legacy settings.

We now show the current mailserver correctly. The data is kept in sync via
signals, just as the original code.

Fixes https://github.com/status-im/status-mobile/issues/21375
2025-01-17 14:26:20 -03:00
Mohamed Javid 174e44c77d fix(wallet)_: Dismiss collectible details screen after a is TX placed (#21909)
This commit fixes the user is not taken to the activity tab after the TX is placed if the user enters the send flow from collectible details screen (inside the account)

Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2025-01-16 21:57:06 +05:30
90 changed files with 1400 additions and 531 deletions
+4 -2
View File
@@ -267,9 +267,11 @@ run-metro: export TARGET := clojure
run-metro: ##@run Start Metro to build React Native changes
@scripts/run-metro.sh
export RE_FRISK_PORT ?= 4567
run-re-frisk: export TARGET := clojure
run-re-frisk: ##@run Start re-frisk server
yarn shadow-cljs run re-frisk-remote.core/start
yarn shadow-cljs run re-frisk-remote.core/start ${RE_FRISK_PORT}
# TODO: Migrate this to a Nix recipe, much the same way as nix/mobile/android/targets/release-android.nix
run-android: export TARGET := android
@@ -443,7 +445,7 @@ android-ports: export RCT_METRO_PORT ?= 8081
android-ports: ##@other Add proxies to Android Device/Simulator
adb reverse tcp:$(RCT_METRO_PORT) tcp:$(RCT_METRO_PORT) && \
adb reverse tcp:3449 tcp:3449 && \
adb reverse tcp:4567 tcp:4567 && \
adb reverse tcp:$(RE_FRISK_PORT) tcp:$(RE_FRISK_PORT) && \
adb reverse tcp:$(FLOWSTORM_PORT) tcp:$(FLOWSTORM_PORT) && \
adb forward tcp:5561 tcp:5561
+1
View File
@@ -16,6 +16,7 @@
- [Patching](patching.md)
- [Creating a pixel perfect UI](pixel-perfection.md)
- [Contributing to status-go](status-go-changes.md)
- [Status Backend Server](use-status-backend-server.md)
- [Malli schemas (recorded demo)](https://www.youtube.com/watch?v=SlRio70aYVI) ([slides](files/forging-code-with-schemas-sep-2023-slides.pdf))
## Testing
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 156 KiB

+2
View File
@@ -37,6 +37,8 @@ SECRETS_ENV_VARS=(
'ALCHEMY_ARBITRUM_SEPOLIA_TOKEN'
'ALCHEMY_OPTIMISM_MAINNET_TOKEN'
'ALCHEMY_OPTIMISM_SEPOLIA_TOKEN'
'ALCHEMY_BASE_MAINNET_TOKEN'
'ALCHEMY_BASE_SEPOLIA_TOKEN'
'RARIBLE_MAINNET_API_KEY'
'RARIBLE_TESTNET_API_KEY'
'INFURA_TOKEN'
+9 -3
View File
@@ -58,7 +58,7 @@
:preloads [;; The official recommendation is to
;; load the debugger preload first.
flow-storm.api
re-frisk-remote.preload
dev.re-frisk-preload
status-im.setup.schema-preload
;; In order to use component test helpers in the REPL we need to
;; preload namespaces that are not normally required by
@@ -87,7 +87,9 @@
status-im.config/ALCHEMY_ARBITRUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ARBITRUM_MAINNET_TOKEN"
status-im.config/ALCHEMY_ARBITRUM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_ARBITRUM_SEPOLIA_TOKEN"
status-im.config/ALCHEMY_OPTIMISM_MAINNET_TOKEN #shadow/env "ALCHEMY_OPTIMISM_MAINNET_TOKEN"
status-im.config/ALCHEMY_OPTIMISM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_OPTIMISM_SEPOLIA_TOKEN"}
status-im.config/ALCHEMY_OPTIMISM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_OPTIMISM_SEPOLIA_TOKEN"
status-im.config/ALCHEMY_BASE_MAINNET_TOKEN #shadow/env "ALCHEMY_BASE_MAINNET_TOKEN"
status-im.config/ALCHEMY_BASE_SEPOLIA_TOKEN #shadow/env "ALCHEMY_BASE_SEPOLIA_TOKEN"}
:compiler-options {:output-feature-set :es5
;; We disable `:fn-deprecated` warnings because we
;; are managing deprecation via clj-kondo and we
@@ -123,7 +125,9 @@
status-im.config/ALCHEMY_ARBITRUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ARBITRUM_MAINNET_TOKEN"
status-im.config/ALCHEMY_ARBITRUM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_ARBITRUM_SEPOLIA_TOKEN"
status-im.config/ALCHEMY_OPTIMISM_MAINNET_TOKEN #shadow/env "ALCHEMY_OPTIMISM_MAINNET_TOKEN"
status-im.config/ALCHEMY_OPTIMISM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_OPTIMISM_SEPOLIA_TOKEN"}
status-im.config/ALCHEMY_OPTIMISM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_OPTIMISM_SEPOLIA_TOKEN"
status-im.config/ALCHEMY_BASE_MAINNET_TOKEN #shadow/env "ALCHEMY_BASE_MAINNET_TOKEN"
status-im.config/ALCHEMY_BASE_SEPOLIA_TOKEN #shadow/env "ALCHEMY_BASE_SEPOLIA_TOKEN"}
:compiler-options {:output-feature-set :es6
;;disable for android build as there
;;is an intermittent warning with deftype
@@ -165,6 +169,8 @@
status-im.config/ALCHEMY_ARBITRUM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_ARBITRUM_SEPOLIA_TOKEN"
status-im.config/ALCHEMY_OPTIMISM_MAINNET_TOKEN #shadow/env "ALCHEMY_OPTIMISM_MAINNET_TOKEN"
status-im.config/ALCHEMY_OPTIMISM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_OPTIMISM_SEPOLIA_TOKEN"
status-im.config/ALCHEMY_BASE_MAINNET_TOKEN #shadow/env "ALCHEMY_BASE_MAINNET_TOKEN"
status-im.config/ALCHEMY_BASE_SEPOLIA_TOKEN #shadow/env "ALCHEMY_BASE_SEPOLIA_TOKEN"
status-im.config/WALLET_CONNECT_PROJECT_ID #shadow/env "WALLET_CONNECT_PROJECT_ID"}
:compiler-options
{;; needed because we override require and it
+5
View File
@@ -0,0 +1,5 @@
(ns dev.re-frisk-preload
(:require [re-frisk-remote.core :as re-frisk-remote]
[status-im.config]))
(re-frisk-remote/enable {:host (str status-im.config/re-frisk-host ":" status-im.config/re-frisk-port)})
+43
View File
@@ -0,0 +1,43 @@
(ns ^{:doc "Mailserver events and API"} legacy.status-im.mailserver.core
(:require
[legacy.status-im.multiaccounts.update.core :as multiaccounts.update]
[taoensso.timbre :as log]
[utils.re-frame :as rf]))
(rf/defn handle-mailserver-changed
[{:keys [db]} ms]
(when (seq ms)
{:db (assoc db :mailserver/current-id (keyword ms))}))
(rf/defn handle-mailserver-available
[{:keys [db]} ms]
{:db (assoc db :mailserver/current-id (keyword ms))})
(rf/defn toggle-use-mailservers
[_ value]
{:json-rpc/call
[{:method "wakuext_toggleUseMailservers"
:params [value]
:on-success #(log/info "successfully toggled use-mailservers" value)
:on-error #(log/error "failed to toggle use-mailserver" value %)}]})
(rf/defn update-use-mailservers
{:events [:mailserver.ui/use-history-switch-pressed]}
[cofx use-mailservers?]
(rf/merge cofx
(multiaccounts.update/optimistic :use-mailservers? use-mailservers?)
(toggle-use-mailservers use-mailservers?)))
(defn add-mailservers
[db mailservers]
(reduce (fn [db {:keys [fleet id name] :as mailserver}]
(let [updated-mailserver
(-> mailserver
(update :id keyword)
(assoc :name (if (seq name) name id))
(dissoc :fleet))]
(assoc-in db
[:mailserver/mailservers (keyword fleet) (keyword id)]
updated-mailserver)))
db
mailservers))
@@ -1,6 +1,5 @@
(ns legacy.status-im.subs.mailservers
(:require
[legacy.status-im.fleet.core :as fleet]
[re-frame.core :as re-frame]))
(re-frame/reg-sub
@@ -17,10 +16,3 @@
:<- [:mailserver/mailservers]
(fn [[current-fleet mailservers]]
(current-fleet mailservers)))
(re-frame/reg-sub
:mailserver/preferred-id
:<- [:profile/profile]
(fn [multiaccount]
(get-in multiaccount
[:pinned-mailservers (fleet/current-fleet-sub multiaccount)])))
-5
View File
@@ -38,11 +38,6 @@
;;mailserver
(reg-root-key-sub :mailserver/current-id :mailserver/current-id)
(reg-root-key-sub :mailserver/mailservers :mailserver/mailservers)
(reg-root-key-sub :mailserver.edit/mailserver :mailserver.edit/mailserver)
(reg-root-key-sub :mailserver/state :mailserver/state)
(reg-root-key-sub :mailserver/pending-requests :mailserver/pending-requests)
(reg-root-key-sub :mailserver/request-error? :mailserver/request-error)
(reg-root-key-sub :mailserver/fetching-gaps-in-progress :mailserver/fetching-gaps-in-progress)
;;contacts
(reg-root-key-sub :contacts/contacts-raw :contacts/contacts)
@@ -1,41 +0,0 @@
(ns legacy.status-im.ui.screens.offline-messaging-settings.styles
(:require
[legacy.status-im.ui.components.colors :as colors]
[legacy.status-im.utils.styles :as styles]))
(def wrapper
{:flex 1})
(styles/defn mailserver-item
[]
{:flex-direction :row
:align-items :center
:justify-content :space-between
:padding-horizontal 16
:ios {:height 64}
:android {:height 56}})
(def mailserver-item-name-text
{:typography :title})
(def switch-container
{:height 52})
(def automatic-selection-container
{:border-top-width 1
:border-top-color colors/gray-lighter
:margin-top 16})
(def explanation-text
{:color colors/gray})
(def use-history-explanation-text-container
{:margin-right 16
:margin-left 16
:margin-top 8
:margin-bottom 16})
(def history-nodes-label
{:color colors/gray
:padding-horizontal 16
:margin-top 48})
@@ -1,88 +0,0 @@
(ns legacy.status-im.ui.screens.offline-messaging-settings.views
(:require-macros [legacy.status-im.utils.views :as views])
(:require
[legacy.status-im.ui.components.colors :as colors]
[legacy.status-im.ui.components.core :as quo]
[legacy.status-im.ui.components.icons.icons :as icons]
[legacy.status-im.ui.components.list.views :as list]
[legacy.status-im.ui.components.react :as react]
[legacy.status-im.ui.components.topbar :as topbar]
[legacy.status-im.ui.screens.offline-messaging-settings.styles :as styles]
[legacy.status-im.ui.screens.profile.components.views :as profile.components]
[re-frame.core :as re-frame]
[utils.i18n :as i18n]))
(defn pinned-state
[pinned?]
[react/view {:style styles/automatic-selection-container}
[react/view {:style styles/switch-container}
[profile.components/settings-switch-item
{:label-kw :t/mailserver-automatic
:value (not pinned?)
:action-fn #(if pinned?
(re-frame/dispatch [:mailserver.ui/unpin-pressed])
(re-frame/dispatch [:mailserver.ui/pin-pressed]))}]]
[react/view {:style {:padding-horizontal 16}}
[react/text {:style styles/explanation-text}
(i18n/label :t/mailserver-automatic-switch-explanation)]]])
(defn render-row
[{:keys [name id custom]} _ _ {:keys [current-mailserver-id preferred-mailserver-id]}]
(let [pinned? preferred-mailserver-id
connected? (= id current-mailserver-id)
visible? (or pinned? ; show everything when auto selection is turned off
(and (not pinned?) ; auto selection turned on
(= current-mailserver-id id)))] ; show only the selected server
(when visible?
[react/touchable-highlight
{:on-press (when pinned?
#(if custom
(re-frame/dispatch [:mailserver.ui/custom-mailserver-selected id])
(re-frame/dispatch [:mailserver.ui/default-mailserver-selected id])))
:accessibility-label :mailserver-item}
[react/view (styles/mailserver-item)
[react/text {:style styles/mailserver-item-name-text}
name]
(if pinned?
[quo/radio {:value connected?}]
[icons/icon :check {:color colors/blue}])]])))
(views/defview offline-messaging-settings
[]
(views/letsubs [current-mailserver-id [:mailserver/current-id]
preferred-mailserver-id [:mailserver/preferred-id]
mailservers [:mailserver/fleet-mailservers]
{:keys [use-mailservers?]} [:profile/profile]]
[react/view {:style styles/wrapper}
[topbar/topbar
{:title (i18n/label :t/history-nodes)
:right-accessories
[{:icon :main-icons/add-circle
:on-press #(re-frame/dispatch [:mailserver.ui/add-pressed])}]}]
[react/scroll-view
[react/view {:style styles/switch-container}
[profile.components/settings-switch-item
{:label-kw :t/offline-messaging-use-history-nodes
:value use-mailservers?
:action-fn #(re-frame/dispatch [:mailserver.ui/use-history-switch-pressed
(not use-mailservers?)])}]]
[react/view {:style styles/use-history-explanation-text-container}
[react/text {:style styles/explanation-text}
(i18n/label :t/offline-messaging-use-history-explanation)]]
(when use-mailservers?
[:<>
[pinned-state preferred-mailserver-id]
[react/text {:style styles/history-nodes-label}
(i18n/label :t/history-nodes)]
[list/flat-list
{:data (vals mailservers)
:default-separator? false
:key-fn :name
:render-data {:current-mailserver-id current-mailserver-id
:preferred-mailserver-id preferred-mailserver-id}
:render-fn render-row}]])]]))
@@ -12,7 +12,6 @@
[legacy.status-im.ui.screens.help-center.views :as help-center]
[legacy.status-im.ui.screens.log-level-settings.views :as log-level-settings]
[legacy.status-im.ui.screens.notifications-settings.views :as notifications-settings]
[legacy.status-im.ui.screens.offline-messaging-settings.views :as offline-messaging-settings]
[legacy.status-im.ui.screens.pairing.views :as pairing]
[legacy.status-im.ui.screens.peers-stats :as peers-stats]
[legacy.status-im.ui.screens.profile.seed.views :as profile.seed]
@@ -113,9 +112,6 @@
:options {:topBar (topbar-options (i18n/label :t/devices))
:insets {:top? true}}
:component pairing/installations}
{:name :offline-messaging-settings
:options {:insets {:top? true}}
:component offline-messaging-settings/offline-messaging-settings}
{:name :rpc-usage-info
:options {:topBar (topbar-options :t/rpc-usage-info)
:insets {:top? true}}
@@ -7,6 +7,7 @@
[legacy.status-im.ui.components.react :as react]
[quo.core :as quo]
[re-frame.core :as re-frame]
[react-native.clipboard :as clipboard]
[status-im.constants :as constants]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -67,10 +68,10 @@
{:size :small
:accessibility-label :offline-messages-settings-button
:title (i18n/label :t/history-nodes)
:on-press #(re-frame/dispatch [:navigate-to :offline-messaging-settings])
:on-press (fn []
(clipboard/set-string current-mailserver-name))
:accessory :text
:accessory-text (when use-mailservers? current-mailserver-name)
:chevron true}]
:accessory-text (when use-mailservers? current-mailserver-name)}]
;; TODO(Ferossgp): Devider componemt
[react/view
{:height 1
+1 -1
View File
@@ -131,7 +131,7 @@
[variant-colors]
{:color (:label variant-colors)})
(def counter-container
(def right-label-container
{:flex 1
:align-items :flex-end})
+22 -13
View File
@@ -7,8 +7,8 @@
[react-native.core :as rn]
[react-native.platform :as platform]))
(defn- label-&-counter
[{:keys [label current-chars char-limit variant-colors theme]}]
(defn- label-line
[{:keys [label label-right current-chars char-limit variant-colors theme]}]
[rn/view
{:accessibility-label :input-labels
:style style/texts-container}
@@ -18,17 +18,24 @@
:weight :medium
:size :paragraph-2}
label]]
(when-let [count-text (some->> char-limit
(str current-chars "/"))]
[rn/view {:style style/counter-container}
(when label-right
[rn/view {:style style/right-label-container}
[text/text
{:style (style/counter-color {:current-chars current-chars
:char-limit char-limit
:variant-colors variant-colors
:theme theme})
{:style (style/label-color variant-colors)
:weight :regular
:size :paragraph-2}
count-text]])])
label-right]])
(when char-limit
(let [count-text (str current-chars "/" char-limit)]
[rn/view {:style style/right-label-container}
[text/text
{:style (style/counter-color {:current-chars current-chars
:char-limit char-limit
:variant-colors variant-colors
:theme theme})
:weight :regular
:size :paragraph-2}
count-text]]))])
(defn- left-accessory
[{:keys [variant-colors small? icon-name]}]
@@ -65,7 +72,7 @@
(defn- base-input
[{:keys [blur? error? right-icon left-icon disabled? small? button
label char-limit multiline? clearable? on-focus on-blur container-style input-container-style
on-change-text on-char-limit-reach weight default-value on-clear placeholder]
on-change-text on-char-limit-reach weight default-value on-clear placeholder label-right]
:as props}]
(let [theme (quo.theme/use-theme)
ref (rn/use-ref-atom nil)
@@ -115,10 +122,11 @@
;; https://github.com/facebook/react-native/issues/27687
modified-placeholder (if platform/android? (str "\u2009" placeholder) placeholder)]
[rn/view {:style container-style}
(when (or label char-limit)
[label-&-counter
(when (or label char-limit label-right)
[label-line
{:variant-colors variant-colors
:label label
:label-right label-right
:current-chars char-count
:char-limit char-limit
:theme theme}])
@@ -199,6 +207,7 @@
- :on-clear - Function executed when the clear button is pressed.
- :button - Map containing `:on-press` & `:text` keys, if provided renders a button
- :label - A string to set as label for this input.
- :label-right - Additional label aligned to the right
- :char-limit - A number to set a maximum char limit for this input.
- :on-char-limit-reach - Function executed each time char limit is reached or exceeded.
- :default-shown? - boolean to show password input initially
@@ -35,7 +35,7 @@
subtitle]]])
(defn- main-variant
[{:keys [title subtitle button-label image max-height accessibility-label on-press]}]
[{:keys [title subtitle button-label image max-height accessibility-label on-press button-type]}]
[rn/view {:style style/main-variant}
[rn/view {:style style/main-variant-text-container}
[text/text
@@ -58,7 +58,7 @@
[button/button
{:on-press on-press
:accessibility-label accessibility-label
:type :grey
:type (or button-type :grey)
:size 40
:container-style style/main-button
:theme :dark
@@ -66,7 +66,7 @@
button-label]])
(defn small-option-card
[{:keys [variant title subtitle button-label image max-height on-press accessibility-label]
[{:keys [variant title subtitle button-label image max-height on-press accessibility-label button-type]
:or {variant :main accessibility-label :small-option-card}}]
(let [main-variant? (= variant :main)
card-component (if main-variant? main-variant icon-variant)
@@ -82,4 +82,5 @@
:on-press on-press
:accessibility-label accessibility-label
:image image
:max-height max-height}]]))
:max-height max-height
:button-type button-type}]]))
@@ -32,8 +32,8 @@
:padding-bottom 2})
(defn title-style
[{:keys [status theme]}]
{:padding-left 4
[{:keys [status theme networks-shown?]}]
{:padding-left (if networks-shown? 4 0)
:margin-top -1
:color (when (= status :error)
(colors/resolve-color :danger theme))})
@@ -14,14 +14,16 @@
:theme theme
:blur? blur?})
container-style)}
[preview-list/view
{:type :network
:number (count networks)
:size :size-16}
networks]
(when networks
[preview-list/view
{:type :network
:number (count networks)
:size :size-16}
networks])
[text/text
{:weight :medium
:size :paragraph-2
:style (style/title-style {:status status
:theme theme})}
:style (style/title-style {:status status
:theme theme
:networks-shown? networks})}
title]]))
@@ -30,13 +30,16 @@
(defn networks
[values theme]
(let [{:keys [ethereum optimism arbitrum]} 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")))]
(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}
@@ -56,6 +59,11 @@
[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
@@ -9,9 +9,11 @@
[:currency-symbol [:maybe [:or :string :keyword]]]
[:hint-component {:optional true} [:maybe :schema.common/hiccup]]
[:on-token-press {:optional true} [:maybe fn?]]
[:on-swap [:maybe fn?]]
[:on-swap {:optional true} [:maybe fn?]]
[:container-style {:optional true} [:maybe :map]]
[:error? [:maybe :boolean]]
[:show-token-icon? {:optional true} [:maybe :boolean]]
[:value [:maybe :string]]
[:converted-value [:maybe :string]]]]]
[:converted-value {:optional true} [:maybe :string]]
[:swappable? {:optional true} [:maybe :boolean]]]]]
:any])
@@ -19,9 +19,8 @@
{:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)
:padding-bottom 3})
(defn input-container
[window-width]
{:width (- window-width 120)
(def input-container
{:flex 1
:margin-left 8
:margin-right 8
:flex-direction :row
+37 -28
View File
@@ -20,17 +20,18 @@
(string/upper-case (or (clj->js text) ""))])
(defn input-section
[{:keys [token-symbol on-token-press value error? on-swap currency-symbol]}]
(let [theme (quo.theme/use-theme)
window-width (:width (rn/get-window))]
[{:keys [token-symbol on-token-press value error? on-swap currency-symbol show-token-icon?
swappable?]}]
(let [theme (quo.theme/use-theme)]
[rn/pressable
{:style {:width "100%"
:flex-direction :row}
:on-press on-token-press}
[token/view
{:token token-symbol
:size :size-32}]
[rn/view {:style (style/input-container window-width)}
(when show-token-icon?
[token/view
{:token token-symbol
:size :size-32}])
[rn/view {:style style/input-container}
[rn/text-input
{:style (style/text-input theme error?)
:placeholder-text-color (style/placeholder-text theme)
@@ -39,14 +40,15 @@
:editable false
:value value}]
[token-name-text theme currency-symbol]]
[button/button
{:icon true
:icon-only? true
:size 32
:on-press #(when on-swap (on-swap))
:type :outline
:accessibility-label :reorder}
:i/reorder]]))
(when swappable?
[button/button
{:icon true
:icon-only? true
:size 32
:on-press #(when on-swap (on-swap))
:type :outline
:accessibility-label :reorder}
:i/reorder])]))
(defn- view-internal
[{:keys [token-symbol
@@ -57,26 +59,33 @@
on-swap
converted-value
hint-component
currency-symbol]}]
show-token-icon?
currency-symbol
swappable?]
:or {show-token-icon? true
swappable? true}}]
(let [theme (quo.theme/use-theme)
width (:width (rn/get-window))]
[rn/view {:style (merge (style/main-container width) container-style)}
[rn/view {:style style/amount-container}
[input-section
{:theme theme
:token-symbol token-symbol
:on-token-press on-token-press
:value value
:error? error?
:on-swap on-swap
:currency-symbol currency-symbol}]]
{:theme theme
:token-symbol token-symbol
:on-token-press on-token-press
:value value
:error? error?
:on-swap on-swap
:currency-symbol currency-symbol
:show-token-icon? show-token-icon?
:swappable? swappable?}]]
[divider-line/view {:container-style (style/divider theme)}]
[rn/view {:style style/data-container}
hint-component
[text/text
{:size :paragraph-2
:weight :medium
:style (style/converted-amount theme)}
converted-value]]]))
(when swappable?
[text/text
{:size :paragraph-2
:weight :medium
:style (style/converted-amount theme)}
converted-value])]]))
(def view (schema/instrument #'view-internal component-schema/?schema))
+1
View File
@@ -44,6 +44,7 @@
:hermez (js/require "../resources/images/networks/Hermez.png")
:optimism (js/require "../resources/images/networks/Optimism.png")
:paraswap (js/require "../resources/images/networks/Paraswap.png")
:base (js/require "../resources/images/networks/Base.png")
:polygon (js/require "../resources/images/networks/Polygon.png")
:scroll (js/require "../resources/images/networks/Scroll.png")
:taiko (js/require "../resources/images/networks/Taiko.png")
@@ -54,7 +54,7 @@
(when (money/bignumber? (value-bn state))
(money/greater-than (value-bn state) (upper-limit-bn state)))))
(defn- lower-limit-exceeded?
(defn lower-limit-exceeded?
[state]
(and (lower-limit state)
(when (money/bignumber? (value-bn state))
@@ -78,16 +78,19 @@
(defn set-upper-limit
[state limit]
(when limit
(if limit
(-> state
(assoc :upper-limit limit)
recheck-errorness)))
recheck-errorness)
state))
(defn set-lower-limit
[state limit]
(-> state
(assoc :lower-limit limit)
recheck-errorness))
(if limit
(-> state
(assoc :lower-limit limit)
recheck-errorness)
state))
(defn increase
[state]
+1 -1
View File
@@ -17,7 +17,7 @@
:music (js/require "../resources/images/ui2/music.png")
:podcasts (js/require "../resources/images/ui2/podcasts.png")
:generate-keys (js/require "../resources/images/ui2/generate-keys.png")
:generate-keys1 (js/require "../resources/images/ui2/generating-keys-1.png")
:add-key-to-keycard (js/require "../resources/images/ui2/add-key-to-keycard.png")
:ethereum-address (js/require "../resources/images/ui2/ethereum-address.png")
:use-keycard (js/require "../resources/images/ui2/keycard.png")
:use-recovery-phrase (js/require "../resources/images/ui2/recovery-phrase.png")
+7
View File
@@ -1,6 +1,7 @@
(ns status-im.common.signals.events
(:require
[legacy.status-im.chat.models.message :as models.message]
[legacy.status-im.mailserver.core :as mailserver]
[legacy.status-im.visibility-status-updates.core :as visibility-status-updates]
[oops.core :as oops]
[status-im.common.pairing.events :as pairing]
@@ -63,6 +64,12 @@
"messages.new"
(messages.transport/sanitize-messages-and-process-response cofx event-js true)
"mailserver.changed"
(mailserver/handle-mailserver-changed cofx (oops/oget event-js :id))
"mailserver.available"
(mailserver/handle-mailserver-available cofx (oops/oget event-js :id))
"discovery.summary"
(summary cofx (transforms/js->clj event-js))
@@ -11,28 +11,28 @@
[{:keys [track-text customization-color auth-button-label on-auth-success on-auth-fail
auth-button-icon-left size blur? container-style disabled? dependencies on-complete]
:or {container-style {:flex 1}}}]
(let [theme (quo.theme/use-theme)
auth-method (rf/sub [:auth-method])
biometric-auth? (= auth-method constants/auth-method-biometric)
on-complete-callback (rn/use-callback
(fn []
(rf/dispatch [:standard-auth/authorize
{:auth-button-icon-left auth-button-icon-left
:theme theme
:blur? blur?
:biometric-auth? biometric-auth?
:on-auth-success on-auth-success
:on-auth-fail on-auth-fail
:auth-button-label auth-button-label}]))
(vec (conj dependencies on-auth-success on-auth-fail)))
on-slider-complete (rn/use-callback
(fn [reset-slider-fn]
(js/setTimeout #(reset-slider-fn false) 500)
(if (fn? on-complete)
(on-complete)
(on-complete-callback)))
[on-complete on-complete-callback])
biometric-type (rf/sub [:biometrics/supported-type])]
(let [theme (quo.theme/use-theme)
auth-method (rf/sub [:auth-method])
biometric-auth? (= auth-method constants/auth-method-biometric)
authorization-callback (rn/use-callback
(fn []
(rf/dispatch [:standard-auth/authorize
{:auth-button-icon-left auth-button-icon-left
:theme theme
:blur? blur?
:biometric-auth? biometric-auth?
:on-auth-success on-auth-success
:on-auth-fail on-auth-fail
:auth-button-label auth-button-label}]))
(vec (conj dependencies on-auth-success on-auth-fail)))
on-slider-complete (rn/use-callback
(fn [reset-slider-fn]
(js/setTimeout #(reset-slider-fn false) 500)
(if (fn? on-complete)
(on-complete)
(authorization-callback)))
[on-complete authorization-callback])
biometric-type (rf/sub [:biometrics/supported-type])]
[quo/slide-button
{:container-style container-style
:size size
+7
View File
@@ -23,6 +23,8 @@
(goog-define ALCHEMY_ARBITRUM_SEPOLIA_TOKEN "")
(goog-define ALCHEMY_OPTIMISM_MAINNET_TOKEN "")
(goog-define ALCHEMY_OPTIMISM_SEPOLIA_TOKEN "")
(goog-define ALCHEMY_BASE_MAINNET_TOKEN "")
(goog-define ALCHEMY_BASE_SEPOLIA_TOKEN "")
(goog-define WALLET_CONNECT_PROJECT_ID "87815d72a81d739d2a7ce15c2cfdefb3")
(goog-define MIXPANEL_APP_ID "3350627")
(goog-define MIXPANEL_TOKEN "5c73bda2d36a9f688a5ee45641fb6775")
@@ -38,9 +40,11 @@
(def mainnet-tx-details-base-link "https://etherscan.io/tx")
(def optimism-mainnet-tx-details-base-link "https://optimistic.etherscan.io/tx")
(def arbitrum-mainnet-tx-details-base-link "https://arbiscan.io/tx")
(def base-mainnet-tx-details-base-link "https://basescan.org/tx")
(def mainnet-sepolia-tx-details-base-link "https://sepolia.etherscan.io/tx")
(def optimism-sepolia-tx-details-base-link "https://sepolia-optimistic.etherscan.io/tx")
(def arbitrum-sepolia-tx-details-base-link "https://sepolia.arbiscan.io/tx")
(def base-sepolia-tx-details-base-link "https://sepolia.basescan.org/tx")
(def opensea-link "https://opensea.io")
(def opensea-tesnet-link "https://testnets.opensea.io")
@@ -124,3 +128,6 @@
(goog-define STATUS_BACKEND_SERVER_ROOT_DATA_DIR "")
;; if you're using android simulator, I suggest set the env variable to "http://10.0.2.2:"
(goog-define STATUS_BACKEND_SERVER_IMAGE_SERVER_URI_PREFIX "https://localhost:")
(def re-frisk-host (get-config :RE_FRISK_HOST "localhost"))
(def re-frisk-port (get-config :RE_FRISK_PORT "4567"))
+13 -3
View File
@@ -396,29 +396,34 @@
(def ^:const arbitrum-sepolia-chain-id 421614)
(def ^:const optimism-mainnet-chain-id 10)
(def ^:const optimism-sepolia-chain-id 11155420)
(def ^:const base-mainnet-chain-id 8453)
(def ^:const base-sepolia-chain-id 84532)
(def opensea-url-names
{:ethereum "ethereum"
:sepolia "sepolia"})
(def ^:const mainnet-chain-ids
#{ethereum-mainnet-chain-id arbitrum-mainnet-chain-id optimism-mainnet-chain-id})
#{ethereum-mainnet-chain-id arbitrum-mainnet-chain-id optimism-mainnet-chain-id base-mainnet-chain-id})
(def ^:const sepolia-chain-ids
#{ethereum-sepolia-chain-id arbitrum-sepolia-chain-id optimism-sepolia-chain-id})
#{ethereum-sepolia-chain-id arbitrum-sepolia-chain-id optimism-sepolia-chain-id base-sepolia-chain-id})
(def ^:const mainnet-short-name "eth")
(def ^:const ethereum-short-name "eth")
(def ^:const optimism-short-name "oeth")
(def ^:const arbitrum-short-name "arb1")
(def ^:const base-short-name "base")
(def ^:const mainnet-abbreviated-name "Eth.")
(def ^:const optimism-abbreviated-name "Oeth.")
(def ^:const arbitrum-abbreviated-name "Arb1.")
(def ^:const base-abbreviated-name "Base")
(def ^:const mainnet-full-name "Mainnet")
(def ^:const optimism-full-name "Optimism")
(def ^:const arbitrum-full-name "Arbitrum")
(def ^:const base-full-name "Base")
(def ^:const sepolia-full-name "Sepolia")
@@ -426,11 +431,13 @@
(def ^:const ethereum-network-name :ethereum)
(def ^:const optimism-network-name :optimism)
(def ^:const arbitrum-network-name :arbitrum)
(def ^:const base-network-name :base)
(def ^:const layer-1-network 1)
(def ^:const layer-2-network 2)
(def ^:const default-network-names [mainnet-network-name optimism-network-name arbitrum-network-name])
(def ^:const default-network-names
[mainnet-network-name optimism-network-name arbitrum-network-name base-network-name])
(def ^:const default-network-count (count default-network-names))
@@ -441,7 +448,10 @@
(def ^:const wallet-account-name-max-length 20)
(def ^:const gas-rate-low 0)
(def ^:const gas-rate-medium 1)
(def ^:const gas-rate-high 2)
(def ^:const gas-rate-custom 3)
(def ^:const send-type-transfer 0)
(def ^:const send-type-bridge 5)
(def ^:const send-type-erc-721-transfer 6)
@@ -2,7 +2,9 @@
(:require [quo.core :as quo]
[react-native.core :as rn]
[status-im.common.events-helper :as events-helper]
[status-im.common.not-implemented :as not-implemented]
[status-im.common.resources :as resources]
[status-im.config :as config]
[status-im.constants :as constants]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -43,20 +45,23 @@
[]
[:<>
[quo/page-nav
{:icon-name :i/arrow-left
:on-press events-helper/navigate-back}]
{:icon-name :i/close
:on-press events-helper/navigate-back
:right-side [(when config/show-not-implemented-features?
{:icon-name :i/info
:on-press not-implemented/alert})]}]
[quo/page-top
{:title (i18n/label :t/ready-add-keypair-keycard)
:description :text
:description-text ""}]
[rn/view {:style {:flex 1 :align-items :center :justify-content :center}}
[rn/image
{:resize-mode :contain
:source (resources/get-image :generate-keys1)}]]
[rn/image
{:resize-mode :contain
:style {:flex 1 :align-self :center :margin-vertical 37}
:source (resources/get-image :add-key-to-keycard)}]
[quo/divider-label (i18n/label :t/tips-scan-keycard)]
[quo/markdown-list {:description (i18n/label :t/remove-phone-case)}]
[quo/markdown-list {:description (i18n/label :t/keep-card-steady)}]
[quo/bottom-actions
{:actions :one-action
:button-one-label (i18n/label :t/ready-to-scan)
:button-one-label (i18n/label :t/scan-keycard)
:button-one-props {:on-press #(rf/dispatch [:keycard/create.start])}}]])
@@ -0,0 +1,21 @@
(ns status-im.contexts.keycard.different-card.view
(:require [quo.core :as quo]
[react-native.core :as rn]
[status-im.common.events-helper :as events-helper]
[utils.i18n :as i18n]))
(defn view
[]
[:<>
[quo/page-nav
{:icon-name :i/close
:on-press events-helper/navigate-back}]
[quo/page-top
{:title (i18n/label :t/different-keycard)
:description :text
:description-text (i18n/label :t/scan-previous-keycard)}]
[rn/view {:style {:flex 1}}]
[rn/view {:style {:padding-horizontal 20}}
[quo/button {:on-press events-helper/navigate-back}
(i18n/label :t/try-again)]]])
@@ -52,6 +52,10 @@
(fn [args]
(keycard/export-key (keycard.utils/wrap-handlers args))))
(rf/reg-fx :effects.keycard/factory-reset
(fn [args]
(keycard/factory-reset (keycard.utils/wrap-handlers args))))
(rf/reg-fx :effects.keycard/sign
(fn [args]
(-> (keycard/sign args)
@@ -25,6 +25,7 @@
:button-label (i18n/label :t/lets-go)
:accessibility-label :create-new-profile-keycard
:image (resources/get-image :keycard-buy)
:button-type :primary
:on-press #(rf/dispatch [:keycard/create.get-phrase])}]]
[quo/information-box
{:type :default
+15 -4
View File
@@ -2,6 +2,7 @@
(:require [quo.core :as quo]
[react-native.core :as rn]
[status-im.common.events-helper :as events-helper]
[status-im.contexts.keycard.factory-reset.view :as factory-reset]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -31,7 +32,17 @@
:description-text description}]
[rn/view {:style {:margin-horizontal 20}}
[quo/keycard {:holder-name ""}]
[quo/information-box
{:type :default
:style {:margin-top 20}}
(i18n/label :t/unlock-reset-instructions)]]]))
(when (not= :keycard/error.keycard-blank error)
[:<>
[quo/section-label
{:section (i18n/label :t/what-you-can-do) :container-style {:padding-vertical 8}}]
[quo/settings-item
{:title (i18n/label :t/factory-reset)
:image :icon
:image-props :i/placeholder
:action :arrow
:description :text
:description-props {:text (i18n/label :t/remove-keycard-content)}
:on-press (fn []
(rf/dispatch [:show-bottom-sheet
{:content factory-reset/sheet}]))}]])]]))
@@ -68,6 +68,10 @@
(fn [_ [data]]
{:effects.keycard/export-key data}))
(rf/reg-event-fx :keycard/factory-reset
(fn [_ [data]]
{:effects.keycard/factory-reset data}))
(rf/reg-event-fx :keycard/connect-derive-address-and-add-account
(fn [_ [{:keys [pin derivation-path key-uid account-preferences]}]]
{:fx [[:dispatch
@@ -0,0 +1,96 @@
(ns status-im.contexts.keycard.factory-reset.view
(:require [quo.core :as quo]
[react-native.core :as rn]
[status-im.common.events-helper :as events-helper]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- reset-card
[]
(rf/dispatch
[:keycard/factory-reset
{:on-success (fn []
(rf/dispatch [:navigate-back])
(rf/dispatch [:keycard/disconnect])
(rf/dispatch [:open-modal :screen/keycard.factory-reset.success]))
:on-failure (fn []
(rf/dispatch [:navigate-back])
(rf/dispatch [:keycard/disconnect])
(rf/dispatch [:open-modal :screen/keycard.factory-reset.fail]))}]))
(defn- connect-and-reset
[key-uid]
(rf/dispatch
[:keycard/connect
{:key-uid key-uid
:on-success reset-card
:on-error (fn [error]
(if (or (= error :keycard/error.keycard-frozen)
(= error :keycard/error.keycard-locked)
(= error :keycard/error.keycard-unpaired))
(reset-card)
(do
(rf/dispatch [:navigate-back])
(if (= error :keycard/error.keycard-wrong-profile)
(do
(rf/dispatch [:keycard/disconnect])
(rf/dispatch [:open-modal :screen/keycard.different-card]))
(rf/dispatch [:keycard/on-application-info-error error])))))}]))
(defn success-view
[]
[:<>
[quo/page-nav
{:icon-name :i/close
:on-press events-helper/navigate-back}]
[quo/page-top
{:title (i18n/label :t/keycard-reset-success)
:description :text
:description-text (i18n/label :t/keycard-empty-ready)}]
[rn/view {:style {:flex 1}}]
[rn/view {:style {:padding-horizontal 20}}
[quo/button {:on-press events-helper/navigate-back}
(i18n/label :t/done)]]])
(defn failed-view
[]
[:<>
[quo/page-nav
{:icon-name :i/close
:on-press events-helper/navigate-back}]
[quo/page-top
{:title (i18n/label :t/keycard-reset-failed)}]
[rn/view {:style {:flex 1}}]
[rn/view {:style {:padding-horizontal 20}}
[quo/button {:on-press events-helper/navigate-back}
(i18n/label :t/try-again)]]])
(defn sheet
[]
(let [customization-color (rf/sub [:profile/customization-color])
key-uid (rf/sub [:keycard/key-uid])
[checked? set-checked] (rn/use-state false)]
[:<>
[quo/drawer-top {:title (i18n/label :t/factory-reset-keycard)}]
[quo/text
{:style {:padding-horizontal 20
:padding-top 8
:padding-bottom 8}}
(i18n/label :t/factory-reset-warning)]
[quo/disclaimer
{:checked? checked?
:container-style {:margin-horizontal 20}
:on-change #(set-checked (not checked?))}
(i18n/label :t/key-pair-erased)]
[quo/bottom-actions
{:actions :two-actions
:button-one-label (i18n/label :t/continue)
:button-one-props {:disabled? (not checked?)
:customization-color customization-color
:on-press (fn []
(rf/dispatch [:hide-bottom-sheet])
(connect-and-reset key-uid))}
:button-two-label (i18n/label :t/cancel)
:button-two-props {:type :grey
:on-press (fn []
(rf/dispatch [:hide-bottom-sheet]))}}]]))
@@ -19,6 +19,6 @@
[rn/image
{:resize-mode :contain
:source (resources/get-image :not-keycard)}]]
[rn/view {:padding-horizontal 20}
[rn/view {:style {:padding-horizontal 20}}
[quo/button {:on-press events-helper/navigate-back}
(i18n/label :t/try-again)]]])
@@ -23,29 +23,31 @@
:key :title}
{:type :select
:key :networks
:options [{:key 1}
:options [{:key 0}
{:key 1}
{:key 2}
{:key 3}]}
{:type :boolean
:key :blur?}])
(defn view
[]
(let [state (reagent/atom {:title "Tag"
:status :default
:networks 3})]
(fn []
[preview/preview-container
{:state state
:descriptor descriptor
:blur? (:blur? @state)
:show-blur-background? true}
[rn/view
{:style {:align-self :center
:justify-content :center
:flex 1}}
[quo/network-tags
(assoc @state
:networks
(nth community-networks (dec (:networks @state))))]]])))
(let [selected-networks-id (dec (:networks @state))]
[preview/preview-container
{:state state
:descriptor descriptor
:blur? (:blur? @state)
:show-blur-background? true}
[rn/view
{:style {:align-self :center
:justify-content :center
:flex 1}}
[quo/network-tags
(assoc @state
:networks
(when (pos? selected-networks-id)
(nth community-networks selected-networks-id)))]]]))))
@@ -22,21 +22,29 @@
[{:key :token-symbol
:type :select
:options [{:key :eth}
{:key :snt}]}
{:key :snt}
{:key :gwei}
{:key :units}]}
{:key :currency
:type :select
:options [{:key "$"}
{:key "€"}]}
{:key :error?
:type :boolean}
{:key :show-token-icon?
:type :boolean}
{:key :swappable?
:type :boolean}])
(defn view
[]
(let [state (reagent/atom {:token-symbol :eth
:currency "$"
:crypto? true
:error? false})]
(let [state (reagent/atom {:token-symbol :eth
:currency "$"
:crypto? true
:error? false
:show-token-icon? true
:swappable? true})]
(fn []
(let [{:keys [currency token-symbol crypto? error?]} @state
[input-state set-input-state] (rn/use-state controlled-input/init-state)
@@ -67,18 +75,20 @@
:component-container-style {:flex 1
:justify-content :space-between}}
[quo/token-input
{:token-symbol token-symbol
:currency-symbol (if crypto? token-symbol currency)
:error? error?
:value input-amount
:converted-value converted-value
:on-swap (fn []
(swap! state assoc :crypto? (not crypto?))
(swap-between-fiat-and-crypto))
:hint-component [quo/network-tags
{:networks networks
:title title
:status (when (:error? @state) :error)}]}]
{:token-symbol token-symbol
:currency-symbol (if crypto? token-symbol currency)
:error? error?
:value input-amount
:converted-value converted-value
:on-swap (fn []
(swap! state assoc :crypto? (not crypto?))
(swap-between-fiat-and-crypto))
:hint-component [quo/network-tags
{:networks networks
:title title
:status (when (:error? @state) :error)}]
:show-token-icon? (:show-token-icon? @state)
:swappable? (:swappable? @state)}]
[quo/numbered-keyboard
{:container-style {:padding-bottom (safe-area/get-top)}
:left-action :dot
+3 -1
View File
@@ -26,7 +26,9 @@
:alchemyOptimismMainnetToken config/ALCHEMY_OPTIMISM_MAINNET_TOKEN
:alchemyOptimismSepoliaToken config/ALCHEMY_OPTIMISM_SEPOLIA_TOKEN
:alchemyArbitrumMainnetToken config/ALCHEMY_ARBITRUM_MAINNET_TOKEN
:alchemyArbitrumSepoliaToken config/ALCHEMY_ARBITRUM_SEPOLIA_TOKEN})
:alchemyArbitrumSepoliaToken config/ALCHEMY_ARBITRUM_SEPOLIA_TOKEN
:alchemyBaseMainnetToken config/ALCHEMY_BASE_MAINNET_TOKEN
:alchemyBaseSepoliaToken config/ALCHEMY_BASE_SEPOLIA_TOKEN})
(defn create
[]
@@ -5,11 +5,9 @@
[utils.re-frame :as rf]))
(rf/reg-event-fx :profile/update-local-picture
(fn [{:keys [db now]} [images]]
(fn [{:keys [db]} [images]]
{:db (if images
(assoc-in db
[:profile/profile :images]
(map #(assoc % :clock now) images))
(assoc-in db [:profile/profile :images] images)
(update db :profile/profile dissoc :images))}))
(rf/reg-event-fx :profile/edit-profile-picture-success
@@ -1,7 +1,9 @@
(ns status-im.contexts.profile.login.events
(:require
[legacy.status-im.data-store.settings :as data-store.settings]
[legacy.status-im.mailserver.core :as mailserver]
[native-module.core :as native-module]
[oops.core :as oops]
[status-im.common.keychain.events :as keychain]
[status-im.config :as config]
[status-im.constants :as constants]
@@ -10,7 +12,8 @@
[taoensso.timbre :as log]
[utils.i18n :as i18n]
[utils.re-frame :as rf]
[utils.security.core :as security]))
[utils.security.core :as security]
[utils.transforms :as transforms]))
(rf/reg-event-fx :profile.login/login
(fn [{:keys [db]}]
@@ -132,9 +135,12 @@
:on-error #(log/error "node-info: failed error" %)}]]]})))
(rf/reg-event-fx :profile.login/messenger-started
(fn [{:keys [db]} [_]]
(let [new-account? (get db :onboarding/new-account?)]
{:db (assoc db :messenger/started? true)
(fn [{:keys [db]} [response-js]]
(let [mailservers (transforms/js->clj (oops/oget response-js :mailservers))
new-account? (get db :onboarding/new-account?)]
{:db (-> db
(assoc :messenger/started? true)
(mailserver/add-mailservers mailservers))
:fx [[:fetch-chats-preview
{:chat-preview-type constants/chat-preview-type-non-community
:on-success (fn [result]
@@ -129,10 +129,8 @@
[:dispatch [:hide-bottom-sheet]]]})))
(rf/reg-event-fx :profile.settings/update-local-picture
(fn [{:keys [db now]} [images]]
{:db (assoc-in db
[:profile/profile :images]
(map #(assoc % :clock now) images))}))
(fn [{:keys [db]} [images]]
{:db (assoc-in db [:profile/profile :images] images)}))
(rf/reg-event-fx :profile.settings/mnemonic-was-shown
(fn [_]
@@ -34,15 +34,28 @@
[]
(let [keycards (rf/sub [:keycard/registered-keycards])]
[:<>
[quo/divider-label
{:counter? false
:tight? true
:blur? true}
(i18n/label :t/registered-keycards)]
[rn/view {:style style/registered-keycards-container}
(for [keycard keycards]
^{:key (:keycard-uid keycard)}
[registered-keycard keycard])]]))
[rn/view {:style {:flex 1}}
[quo/divider-label
{:counter? false
:tight? true
:blur? true}
(i18n/label :t/registered-keycards)]
[rn/view {:style style/registered-keycards-container}
(for [keycard keycards]
^{:key (:keycard-uid keycard)}
[registered-keycard keycard])]]
[quo/text
{:size :heading-2
:weight :semi-bold
:style {:margin-left 20}}
(i18n/label :t/scan-keycard-actions)]
[quo/divider-label (i18n/label :t/tips-scan-keycard)]
[quo/markdown-list {:description (i18n/label :t/remove-phone-case)}]
[quo/markdown-list {:description (i18n/label :t/keep-card-steady)}]
[quo/bottom-actions
{:actions :one-action
:button-one-label (i18n/label :t/ready-to-scan)
:button-one-props {:on-press #(rf/dispatch [:keycard/connect])}}]]))
(defn view
[]
@@ -45,6 +45,9 @@
[{:details (:optimism networks)
:testnet-mode? testnet-mode?
:testnet-label (i18n/label :t/sepolia-active)}
{:details (:base networks)
:testnet-mode? testnet-mode?
:testnet-label (i18n/label :t/sepolia-active)}
{:details (:arbitrum networks)
:testnet-mode? testnet-mode?
:testnet-label (i18n/label :t/sepolia-active)}])
@@ -303,7 +303,7 @@
;; By doing it, we skip a blink while visiting the collectible detail page.
[:dispatch-later
{:ms 17
:dispatch [:navigate-to :screen/wallet.collectible]}]]})))
:dispatch [:open-modal :screen/wallet.collectible]}]]})))
(defn- keep-not-empty-value
[old-value new-value]
@@ -1,5 +1,6 @@
(ns status-im.contexts.wallet.collectible.utils
(:require [status-im.config :as config]
(:require [clojure.string :as string]
[status-im.config :as config]
[status-im.constants :as constants]
[status-im.contexts.wallet.common.utils.networks :as network-utils]
[taoensso.timbre :as log]
@@ -79,3 +80,12 @@
acc)))
{})
vals))
(defn sort-collectibles-by-name
[collectibles]
(sort-by (fn [collectible]
(let [name (-> collectible :collectible-data :name)
normalized-name (some-> name
string/lower-case)]
[(if (seq normalized-name) 0 1) normalized-name]))
collectibles))
@@ -44,3 +44,18 @@
:token-id token-id
:test-networks-enabled? true})
"https://testnets.opensea.io/assets/optimism-sepolia/0xC/0xT"))))
(deftest sort-collectibles-by-name-test
(testing "Sorts collectibles by name, moving nil or empty names to the end"
(let [collectibles [{:collectible-data {:name "Alpha"}}
{:collectible-data {:name nil}}
{:collectible-data {:name "Beta"}}
{:collectible-data {:name ""}}
{:collectible-data {:name "Zeta"}}]
sorted-collectibles (utils/sort-collectibles-by-name collectibles)
expected [{:collectible-data {:name "Alpha"}}
{:collectible-data {:name "Beta"}}
{:collectible-data {:name "Zeta"}}
{:collectible-data {:name nil}}
{:collectible-data {:name ""}}]]
(is (= sorted-collectibles expected)))))
@@ -10,15 +10,11 @@
token-name :name
total-balance :total-balance
disabled? :bridge-disabled?
fiat-value :fiat-value
:as token}
_ _
{:keys [currency currency-symbol on-token-press preselected-token-symbol prices-per-token]}]
(let [fiat-value (utils/calculate-token-fiat-value
{:currency currency
:balance total-balance
:token token
:prices-per-token prices-per-token})
crypto-formatted (utils/get-standard-crypto-format token total-balance prices-per-token)
{:keys [currency-symbol on-token-press preselected-token-symbol prices-per-token]}]
(let [crypto-formatted (utils/get-standard-crypto-format token total-balance prices-per-token)
fiat-formatted (utils/fiat-formatted-for-ui currency-symbol fiat-value)]
[quo/token-network
{:token token-symbol
@@ -38,13 +34,11 @@
(let [filtered-tokens (rf/sub [:wallet/current-viewing-account-tokens-filtered
{:query search-text
:chain-ids chain-ids}])
currency (rf/sub [:profile/currency])
currency-symbol (rf/sub [:profile/currency-symbol])
prices-per-token (rf/sub [:wallet/prices-per-token])]
[gesture/flat-list
{:data filtered-tokens
:render-data {:currency currency
:currency-symbol currency-symbol
:render-data {:currency-symbol currency-symbol
:on-token-press on-token-press
:preselected-token-symbol preselected-token-symbol
:prices-per-token prices-per-token}
@@ -409,13 +409,15 @@
(defn sort-tokens
[tokens]
(let [priority #(get constants/token-sort-priority (:symbol %) ##Inf)]
(sort-by (juxt (comp - :balance) priority) tokens)))
(sort-by (comp - :balance) tokens))
(defn sort-tokens-by-fiat-value
[tokens]
(sort-by (comp - :fiat-value) tokens))
(defn sort-tokens-by-name
[tokens]
(let [priority #(get constants/token-sort-priority (:symbol %) ##Inf)]
(sort-by (juxt :symbol priority) tokens)))
(sort-by :symbol tokens))
(defn token-with-balance
([token networks]
@@ -37,6 +37,9 @@
constants/optimism-mainnet-chain-id
config/optimism-mainnet-tx-details-base-link
constants/base-mainnet-chain-id
config/base-mainnet-tx-details-base-link
constants/ethereum-sepolia-chain-id
config/mainnet-sepolia-tx-details-base-link
@@ -46,6 +49,9 @@
constants/optimism-sepolia-chain-id
config/optimism-sepolia-tx-details-base-link
constants/base-sepolia-chain-id
config/base-sepolia-tx-details-base-link
config/mainnet-tx-details-base-link))
(defn get-link-to-tx-details
@@ -15,7 +15,9 @@
constants/optimism-mainnet-chain-id constants/optimism-network-name
constants/optimism-sepolia-chain-id constants/optimism-network-name
constants/arbitrum-mainnet-chain-id constants/arbitrum-network-name
constants/arbitrum-sepolia-chain-id constants/arbitrum-network-name})
constants/arbitrum-sepolia-chain-id constants/arbitrum-network-name
constants/base-mainnet-chain-id constants/base-network-name
constants/base-sepolia-chain-id constants/base-network-name})
(defn- get-chain-id
[{:keys [mainnet-chain-id sepolia-chain-id testnet-enabled?]}]
@@ -46,6 +48,12 @@
(get-chain-id
{:mainnet-chain-id constants/arbitrum-mainnet-chain-id
:sepolia-chain-id constants/arbitrum-sepolia-chain-id
:testnet-enabled? testnet-enabled?})
#{constants/base-network-name (keyword constants/base-short-name)}
(get-chain-id
{:mainnet-chain-id constants/base-mainnet-chain-id
:sepolia-chain-id constants/base-sepolia-chain-id
:testnet-enabled? testnet-enabled?}))))
(defn network-list
@@ -76,12 +84,14 @@
{constants/mainnet-network-name constants/mainnet-short-name
constants/optimism-network-name constants/optimism-short-name
constants/arbitrum-network-name constants/arbitrum-short-name
constants/ethereum-network-name constants/ethereum-short-name})
constants/ethereum-network-name constants/ethereum-short-name
constants/base-network-name constants/base-short-name})
(def short-name->network
{constants/mainnet-short-name constants/mainnet-network-name
constants/optimism-short-name constants/optimism-network-name
constants/arbitrum-short-name constants/arbitrum-network-name})
constants/arbitrum-short-name constants/arbitrum-network-name
constants/base-short-name constants/base-network-name})
(defn short-names->network-preference-prefix
[short-names]
@@ -152,6 +162,15 @@
:view-on-block-explorer-label :t/view-on-oeth
:link-to-block-explorer-label :t/share-link-to-oeth})
(def base-network-details
{:source (resources/get-network constants/base-network-name)
:short-name constants/base-short-name
:full-name constants/base-full-name
:network-name constants/base-network-name
:abbreviated-name constants/base-abbreviated-name
:view-on-block-explorer-label :t/view-on-base
:link-to-block-explorer-label :t/share-link-to-base})
(defn get-network-details
[chain-id]
(as-> chain-id $
@@ -165,6 +184,9 @@
#{constants/optimism-mainnet-chain-id constants/optimism-sepolia-chain-id}
optimism-network-details
#{constants/base-mainnet-chain-id constants/base-sepolia-chain-id}
base-network-details
nil)
(when $
(assoc $ :chain-id chain-id))))
@@ -345,3 +345,33 @@
expected []]
(is (= (utils/get-accounts-with-token-balance accounts token)
expected)))))
(deftest sort-tokens-test
(testing "Sort tokens by balance in descending order"
(let [tokens [{:symbol "BTC" :balance 2}
{:symbol "ETH" :balance 5}
{:symbol "DAI" :balance 10}]
expected [{:symbol "DAI" :balance 10}
{:symbol "ETH" :balance 5}
{:symbol "BTC" :balance 2}]]
(is (= (utils/sort-tokens tokens) expected)))))
(deftest sort-tokens-by-fiat-value-test
(testing "Sort tokens by fiat value in descending order"
(let [tokens [{:symbol "BTC" :fiat-value 50000}
{:symbol "ETH" :fiat-value 15000}
{:symbol "DAI" :fiat-value 1000}]
expected [{:symbol "BTC" :fiat-value 50000}
{:symbol "ETH" :fiat-value 15000}
{:symbol "DAI" :fiat-value 1000}]]
(is (= (utils/sort-tokens-by-fiat-value tokens) expected)))))
(deftest sort-tokens-by-name-test
(testing "Sort tokens by symbol in ascending order"
(let [tokens [{:symbol "ETH"}
{:symbol "DAI"}
{:symbol "BTC"}]
expected [{:symbol "BTC"}
{:symbol "DAI"}
{:symbol "ETH"}]]
(is (= (utils/sort-tokens-by-name tokens) expected)))))
@@ -279,7 +279,8 @@
:to (:to-chain new-path)
:approval-amount-required (:approval-amount-required new-path)
;; :cost () ;; tbd not used on desktop
:gas-amount (:tx-gas-amount new-path)}))
:gas-amount (:tx-gas-amount new-path)
:router-input-params-uuid (:router-input-params-uuid new-path)}))
(defn tokens-never-loaded?
[db]
@@ -120,6 +120,9 @@
(rf/reg-fx
:effects.wallet/sign-transaction-hashes
(fn [{:keys [hashes address password on-success on-error]}]
(tap> {:in :effects.wallet/sign-transaction-hashes
:hashes hashes
:password password})
(-> (sign-transaction-hashes hashes address password)
(promesa/then on-success)
(promesa/catch on-error))))
+6 -3
View File
@@ -41,18 +41,18 @@
(rf/reg-event-fx :wallet/navigate-to-account
(fn [{:keys [db]} [address]]
{:db (assoc-in db [:wallet :current-viewing-account-address] address)
:fx [[:dispatch [:navigate-to :screen/wallet.accounts address]]]}))
:fx [[:dispatch [:navigate-to :screen/wallet.accounts]]]}))
(rf/reg-event-fx :wallet/navigate-to-account-within-stack
(fn [{:keys [db]} [address]]
{:db (assoc-in db [:wallet :current-viewing-account-address] address)
:fx [[:dispatch [:navigate-to-within-stack [:screen/wallet.accounts :shell-stack] address]]]}))
:fx [[:dispatch [:navigate-to-within-stack [:screen/wallet.accounts :shell-stack]]]]}))
(rf/reg-event-fx :wallet/navigate-to-new-account
(fn [{:keys [db]} [address]]
{:db (assoc-in db [:wallet :current-viewing-account-address] address)
:fx [[:dispatch [:hide-bottom-sheet]]
[:dispatch [:navigate-to :screen/wallet.accounts address]]
[:dispatch [:navigate-to :screen/wallet.accounts]]
[:dispatch [:wallet/show-account-created-toast address]]]}))
(rf/reg-event-fx :wallet/select-account-tab
@@ -762,6 +762,8 @@
(rf/reg-event-fx
:wallet/sign-transactions-signal-received
(fn [{:keys [db]} [{send-details :sendDetails :as data}]]
(tap> {:in :wallet/sign-transactions-signal-received
:data data})
(let [type (if (or (= (:fromToken send-details)
(:toToken send-details))
(string/blank? (:toToken send-details)))
@@ -781,6 +783,7 @@
(fn [{:keys [db]}
[{sent-transactions :sentTransactions
send-details :sendDetails}]]
(tap> {:in :wallet/transactions-sent-signal-received})
(let [swap? (get-in db [:wallet :ui :swap])]
{:fx [[:dispatch
(if-let [error-response (:errorResponse send-details)]
+74 -2
View File
@@ -4,6 +4,7 @@
[status-im.constants :as constants]
[status-im.contexts.wallet.collectible.utils :as collectible.utils]
[status-im.contexts.wallet.common.utils :as utils]
[status-im.contexts.wallet.send.utils :as send-utils]
[status-im.contexts.wallet.common.utils.networks :as network-utils]
[status-im.contexts.wallet.data-store :as data-store]
[status-im.contexts.wallet.send.utils :as send-utils]
@@ -12,7 +13,8 @@
[utils.money :as utils.money]
[utils.number]
[utils.re-frame :as rf]
[utils.security.core :as security]))
[utils.security.core :as security]
[status-im.contexts.wallet.wallet-connect.utils.typed-data :as typed-data]))
(rf/reg-event-fx :wallet/clean-send-data
(fn [{:keys [db]}]
@@ -386,7 +388,7 @@
{:db (-> db
(assoc-in [:wallet :ui :send :amount] amount)
(update-in [:wallet :ui :send] dissoc :transaction-for-signing))
:fx [[:dispatch [:wallet/build-transactions-from-route {:request-uuid last-request-uuid}]]
:fx [#_[:dispatch [:wallet/build-transactions-from-route {:request-uuid last-request-uuid}]]
[:dispatch
[:wallet/wizard-navigate-forward
{:current-screen stack-id
@@ -633,6 +635,7 @@
(rf/reg-event-fx :wallet/clean-up-transaction-flow
(fn [_]
{:fx [[:dispatch [:dismiss-modal :screen/wallet.transaction-confirmation]]
[:dispatch [:dismiss-modal :screen/wallet.collectible]]
[:dispatch [:wallet/clean-scanned-address]]
[:dispatch [:wallet/clean-local-suggestions]]
[:dispatch [:wallet/clean-send-address]]
@@ -650,6 +653,8 @@
(rf/reg-event-fx
:wallet/build-transactions-from-route
(fn [_ [{:keys [request-uuid slippage] :or {slippage constants/default-slippage}}]]
(tap> {:in :wallet/build-transactions-from-route
:request-uuid request-uuid})
{:json-rpc/call [{:method "wallet_buildTransactionsFromRoute"
:params [{:uuid request-uuid
:slippagePercentage slippage}]
@@ -665,6 +670,9 @@
(rf/reg-event-fx
:wallet/prepare-signatures-for-transactions
(fn [{:keys [db]} [type sha3-pwd]]
(tap> {:in :wallet/prepare-signatures-for-transactions
:type type
:sha3-pwd sha3-pwd})
(let [{:keys [hashes address signOnKeycard]} (get-in db
[:wallet :ui type :transaction-for-signing
:signingDetails])
@@ -701,6 +709,9 @@
(rf/reg-event-fx
:wallet/send-router-transactions-with-signatures
(fn [{:keys [db]} [type signatures]]
(tap> {:in :wallet/send-router-transactions-with-signatures
:type type
:signatures signatures})
(let [transaction-for-signing (get-in db [:wallet :ui type :transaction-for-signing])
signatures-map (reduce (fn [acc {:keys [message signature]}]
(assoc acc
@@ -805,3 +816,64 @@
:always (update-in [:wallet :ui :send] dissoc :amount :route)
(not keep-tx-data?) (update-in [:wallet :ui :send] dissoc :tx-type))
:fx [[:dispatch [:navigate-back]]]})))
(rf/reg-event-fx
:wallet/init-tx-settings
(fn [{db :db}]
{:db (assoc-in db
[:wallet :ui :send :tx-settings]
{:max-base-fee {:low 5
:current 8.2
:high 9}
:priority-fee {:low 0.6
:high 5.1
:current 1.1}
:max-gas-amount {:low 30000
:current 31000}
:nonce {:last-transaction 21
:current 22}})}))
(rf/reg-event-fx
:wallet/set-max-base-fee
(fn [{db :db} [value]]
{:db (assoc-in db [:wallet :ui :send :tx-settings :max-base-fee :current] value)}))
(rf/reg-event-fx
:wallet/set-priority-fee
(fn [{db :db} [value]]
{:db (assoc-in db [:wallet :ui :send :tx-settings :priority-fee :current] value)}))
(rf/reg-event-fx
:wallet/set-max-gas-amount
(fn [{db :db} [value]]
{:db (assoc-in db [:wallet :ui :send :tx-settings :max-gas-amount :current] value)}))
(rf/reg-event-fx
:wallet/set-nonce
(fn [{db :db} [value]]
{:db (assoc-in db [:wallet :ui :send :tx-settings :nonce :current] value)}))
(rf/reg-event-fx :wallet/quick-transaction-settings-confirmed
(fn [_cofx [path-tx-identity fee-mode]]
(let [params [path-tx-identity fee-mode]]
{:json-rpc/call [{:method "wallet_setFeeMode"
:params params
:on-error (fn [error]
(log/error "failed to get suggested routes (async)"
{:event :wallet/start-get-suggested-routes
:error (:message error)
:params params}))}]})))
#_(rf/reg-event-fx :wallet/quick-transaction-settings-confirmed
(fn [_cofx [path-tx-identity fee-mode]]
(let [params [path-tx-identity fee-mode]]
{:json-rpc/call [{:method "wallet_setCustomTxDetails"
:params params
:on-error (fn [error]
(tap> {:in :wallet/quick-transaction-settings-confirmed
:error error})
(log/error "failed to get suggested routes (async)"
{:event :wallet/start-get-suggested-routes
:error (:message error)
:params params}))}]})))
@@ -8,6 +8,7 @@
[status-im.common.events-helper :as events-helper]
[status-im.common.floating-button-page.view :as floating-button-page]
[status-im.common.standard-authentication.core :as standard-auth]
[status-im.constants :as constants]
[status-im.contexts.wallet.common.utils :as utils]
[status-im.contexts.wallet.send.transaction-confirmation.style :as style]
[status-im.contexts.wallet.send.transaction-settings.view :as transaction-settings]
@@ -167,11 +168,19 @@
:title title
:subtitle subtitle}])
(defn quick-transaction-settings-confirmed
[path-identity setting]
(let [gas-rate (case setting
:normal constants/gas-rate-low
:fast constants/gas-rate-medium
:urgent constants/gas-rate-high
constants/gas-rate-low)]
(rf/dispatch [:wallet/quick-transaction-settings-confirmed path-identity gas-rate])))
(defn- transaction-details
[{:keys [estimated-time-min max-fees to-network route
transaction-type]}]
(let [route-loaded? (and route (seq route))
loading-suggested-routes? (rf/sub [:wallet/wallet-send-loading-suggested-routes?])
[{:keys [estimated-time-min max-fees to-network
transaction-type path-identity route-loaded?]}]
(let [loading-suggested-routes? (rf/sub [:wallet/wallet-send-loading-suggested-routes?])
amount (rf/sub [:wallet/send-total-amount-formatted])]
[rn/view
{:style (style/details-container
@@ -190,9 +199,14 @@
:inner-style {:opacity 1}
:accessibility-label :advanced-button
:container-style {:margin-right 8}
:on-press #(rf/dispatch
[:show-bottom-sheet
{:content transaction-settings/settings-sheet}])}
:on-press (fn []
(rf/dispatch
[:show-bottom-sheet
{:content (fn []
[transaction-settings/settings-sheet
#(quick-transaction-settings-confirmed
path-identity
%)])}]))}
:i/advanced])
[data-item
{:title (i18n/label :t/est-time)
@@ -217,6 +231,7 @@
{:keys [token-display-name collectible amount
route
to-address bridge-to-chain-id type
last-request-uuid
recipient]} send-transaction-data
collectible? (some? collectible)
image-url (when collectible
@@ -248,9 +263,7 @@
account))}
user-props {:full-name to-address
:address (utils/get-shortened-address
to-address)}
sign-on-keycard? (get-in transaction-for-signing
[:signingDetails :signOnKeycard])]
to-address)}]
(hot-reload/use-safe-unmount #(rf/dispatch [:wallet/clean-route-data-for-collectible-tx]))
;; In token send flow we already have transaction built when
;; we reach confirmation screen. But in send collectible flow
@@ -263,6 +276,10 @@
first-route)
(rf/dispatch [:wallet/build-transaction-for-collectible-route])))
[first-route])
(rn/use-mount
(fn []
(when (ff/enabled? ::ff/wallet.transaction-params)
(rf/dispatch [:wallet/init-tx-settings]))))
[rn/view {:style {:flex 1}}
[floating-button-page/view
{:footer-container-padding 0
@@ -279,7 +296,9 @@
:to-network bridge-to-network
:theme theme
:route route
:transaction-type transaction-type}]
:transaction-type transaction-type
:path-identity (send-utils/path-identity first-route)
:route-loaded? (and route (seq route))}]
(when (and (not loading-suggested-routes?) route (seq route))
[standard-auth/slide-button
{:size :size-48
@@ -287,10 +306,11 @@
(i18n/label :t/slide-to-bridge)
(i18n/label :t/slide-to-send))
:container-style {:z-index 2}
:disabled? (not transaction-for-signing)
;; :disabled? (not transaction-for-signing)
:customization-color account-color
:auth-button-label (i18n/label :t/confirm)
:on-complete (when sign-on-keycard?
:on-complete (when (get-in transaction-for-signing
[:signingDetails :signOnKeycard])
#(rf/dispatch
[:wallet/prepare-signatures-for-transactions
:send
@@ -0,0 +1,30 @@
(ns status-im.contexts.wallet.send.transaction-settings.gas-amount.view
(:require
[quo.theme]
[status-im.contexts.wallet.send.transaction-settings.view :as transaction-settings]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn gas-amount-hint-text
[{:keys [current]} lower-limit-exceeded? _upper-limit-exceeded?]
(cond
lower-limit-exceeded? (i18n/label :t/gas-amount-lower {:current current})
:else (i18n/label :t/current-units {:current current})))
(defn view
[]
(let [suggested-values (rf/sub [:wallet/tx-settings-max-gas-amount])
hint-text (partial gas-amount-hint-text suggested-values)]
[transaction-settings/custom-setting-screen
{:screen-title (i18n/label :t/max-gas-amount)
:token-symbol :units
:hint-text-fn hint-text
:suggested-values suggested-values
:info-title (i18n/label :t/gas-amount)
:info-content (i18n/label :t/about-gas-amount)
:on-save (fn [new-val]
(rf/dispatch [:wallet/set-max-gas-amount new-val])
(rf/dispatch [:navigate-back])
(rf/dispatch [:show-bottom-sheet
{:content transaction-settings/custom-settings-sheet}]))
:with-decimals? false}]))
@@ -0,0 +1,30 @@
(ns status-im.contexts.wallet.send.transaction-settings.max-fee.view
(:require
[quo.theme]
[status-im.contexts.wallet.send.transaction-settings.view :as transaction-settings]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn max-base-fee-hint-text
[current lower-limit-exceeded? upper-limit-exceeded?]
(cond
upper-limit-exceeded? (i18n/label :t/max-base-fee-higher {:current current})
lower-limit-exceeded? (i18n/label :t/max-base-fee-lower {:current current})
:else (i18n/label :t/fee-current-gwei {:current current})))
(defn view
[]
(let [suggested-values (rf/sub [:wallet/tx-settings-max-base-fee])
hint-text (partial max-base-fee-hint-text (:current suggested-values))]
[transaction-settings/custom-setting-screen
{:screen-title (i18n/label :t/max-base-fee)
:token-sybmol :gwei
:hint-text-fn hint-text
:suggested-values suggested-values
:info-title (i18n/label :t/max-base-fee)
:info-content (i18n/label :t/about-max-base-fee)
:on-save (fn [new-val]
(rf/dispatch [:wallet/set-max-base-fee new-val])
(rf/dispatch [:navigate-back])
(rf/dispatch [:show-bottom-sheet
{:content transaction-settings/custom-settings-sheet}]))}]))
@@ -0,0 +1,78 @@
(ns status-im.contexts.wallet.send.transaction-settings.nonce.view
(:require
[quo.core :as quo]
[quo.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[status-im.common.controlled-input.utils :as controlled-input]
[status-im.contexts.wallet.send.transaction-settings.view :as transaction-settings]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn view
[]
(let [{:keys [last-transaction current]} (rf/sub [:wallet/tx-settings-nonce])
suggested-nonce (inc last-transaction)
[input-state set-input-state] (rn/use-state (controlled-input/set-value-numeric
controlled-input/init-state
current))
input-value (controlled-input/input-value input-state)
warning? (> (controlled-input/value-numeric input-state)
suggested-nonce)]
[rn/view
{:style {:flex 1}}
[quo/page-nav
{:type :title
:title (i18n/label :t/nonce)
:text-align :center
:right-side [{:icon-name :i/info
:on-press #(rf/dispatch [:show-bottom-sheet
{:content (fn [] [transaction-settings/info-sheet
(i18n/label :t/nonce)
(i18n/label :t/about-nonce)])}])}]
:icon-name :i/arrow-left
:on-press (fn []
(rf/dispatch [:navigate-back])
(rf/dispatch [:show-bottom-sheet
{:content transaction-settings/custom-settings-sheet}]))}]
[rn/view
{:style {:padding-horizontal 20
:gap 8}}
[quo/input
{:type :text
:label (i18n/label :t/type-nonce)
:label-right (i18n/label :t/last-transaction-is {:number last-transaction})
:editable false
:default-value input-value
:clearable? true
:error? warning?
:on-clear (fn []
(set-input-state controlled-input/delete-all))}]
(when warning?
[quo/text
{:style {:color colors/warning-50}
:weight :regular
:size :paragraph-2}
(i18n/label :t/nonce-higher {:number suggested-nonce})])]
[rn/view {:style {:flex 1}}]
[quo/bottom-actions
{:actions :one-action
:button-one-label (i18n/label :t/save-changes)
:button-one-props {:disabled? (controlled-input/empty-value? input-state)
:on-press (fn []
(rf/dispatch [:wallet/set-nonce
(controlled-input/value-numeric input-state)])
(rf/dispatch [:navigate-back])
(rf/dispatch [:show-bottom-sheet
{:content
transaction-settings/custom-settings-sheet}]))}}]
[quo/numbered-keyboard
{:container-style {:padding-bottom (safe-area/get-bottom)}
:left-action :none
:delete-key? true
:on-press (fn [c]
(set-input-state #(controlled-input/add-character % c)))
:on-delete (fn []
(set-input-state controlled-input/delete-last))
:on-long-press-delete (fn []
(set-input-state controlled-input/delete-all))}]]))
@@ -0,0 +1,30 @@
(ns status-im.contexts.wallet.send.transaction-settings.priority-fee.view
(:require
[quo.theme]
[status-im.contexts.wallet.send.transaction-settings.view :as transaction-settings]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn priority-fee-hint-text
[{:keys [current low high]} lower-limit-exceeded? upper-limit-exceeded?]
(cond
upper-limit-exceeded? (i18n/label :t/priority-fee-higher {:low low :high high})
lower-limit-exceeded? (i18n/label :t/priority-fee-lower {:low low :high high})
:else (i18n/label :t/fee-current-gwei {:current current})))
(defn view
[]
(let [suggested-values (rf/sub [:wallet/tx-settings-priority-fee])
hint-text (partial priority-fee-hint-text suggested-values)]
[transaction-settings/custom-setting-screen
{:screen-title (i18n/label :t/priority-fee)
:token-sybmol :gwei
:hint-text-fn hint-text
:suggested-values suggested-values
:info-title (i18n/label :t/priority-fee)
:info-content (i18n/label :t/about-priority-fee)
:on-save (fn [new-val]
(rf/dispatch [:wallet/set-priority-fee new-val])
(rf/dispatch [:navigate-back])
(rf/dispatch [:show-bottom-sheet
{:content transaction-settings/custom-settings-sheet}]))}]))
@@ -2,63 +2,78 @@
(:require
[quo.core :as quo]
[react-native.core :as rn]
[react-native.platform :as platform]
[react-native.safe-area :as safe-area]
[status-im.common.controlled-input.utils :as controlled-input]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn custom-settings-sheet
[_]
[rn/view
[quo/drawer-top
{:title "Custom"}]
[quo/category
{:list-type :settings
:data [{:title "Max base fee"
:description-props {:text "8.2 GWEI - €1.45"}
:image :none
:description :text
:action :arrow
:on-press #()
:label :text
:preview-size :size-32}
{:title "Priority fee"
:description-props {:text "0.06 GWEI - €0.03"}
:image :none
:description :text
:action :arrow
:on-press #()
:label :text
:preview-size :size-32}
{:title "Gas amount"
:description-props {:text "31,500 UNITS"}
:image :none
:description :text
:action :arrow
:on-press #()
:label :text
:preview-size :size-32}
{:title "Nonce"
:description-props {:text "22"}
:image :none
:description :text
:action :arrow
:on-press #()
:label :text
:preview-size :size-32}]}]
[quo/bottom-actions
{:actions :one-action
:button-one-props {:on-press #(rf/dispatch [:hide-bottom-sheet])}
:button-one-label (i18n/label :t/confirm)}]])
(let [max-base-fee (:current (rf/sub [:wallet/tx-settings-max-base-fee]))
priority-fee (:current (rf/sub [:wallet/tx-settings-priority-fee]))
max-gas-amount (:current (rf/sub [:wallet/tx-settings-max-gas-amount]))
nonce (:current (rf/sub [:wallet/tx-settings-nonce]))]
[rn/view
[quo/drawer-top
{:title (i18n/label :t/custom)}]
[quo/category
{:list-type :settings
:data [{:title (i18n/label :t/max-base-fee)
:description-props {:text (str max-base-fee " GWEI")}
:image :none
:description :text
:action :arrow
:on-press #(rf/dispatch [:navigate-to-within-stack
[:screen/wallet.tx-settings-max-fee
:screen/wallet.transaction-confirmation]])
:label :text
:preview-size :size-32}
{:title (i18n/label :t/priority-fee)
:description-props {:text (str priority-fee " GWEI")}
:image :none
:description :text
:action :arrow
:on-press #(rf/dispatch [:navigate-to-within-stack
[:screen/wallet.tx-settings-priority-fee
:screen/wallet.transaction-confirmation]])
:label :text
:preview-size :size-32}
{:title (i18n/label :t/max-gas-amount)
:description-props {:text (str max-gas-amount " UNITS")}
:image :none
:description :text
:action :arrow
:on-press #(rf/dispatch [:navigate-to-within-stack
[:screen/wallet.tx-settings-gas-amount
:screen/wallet.transaction-confirmation]])
:label :text
:preview-size :size-32}
{:title (i18n/label :t/nonce)
:description-props {:text nonce}
:image :none
:description :text
:action :arrow
:on-press #(rf/dispatch [:navigate-to-within-stack
[:screen/wallet.tx-settings-nonce
:screen/wallet.transaction-confirmation]])
:label :text
:preview-size :size-32}]}]
[quo/bottom-actions
{:actions :one-action
:button-one-props {:on-press #(rf/dispatch [:hide-bottom-sheet])}
:button-one-label (i18n/label :t/confirm)}]]))
(defn settings-sheet
[_]
[on-quick-settings-confirmed]
(let [[selected-id set-selected-id] (rn/use-state :normal)]
[rn/view
[quo/drawer-top
{:title "Transaction settings"}]
{:title (i18n/label :t/transaction-settings)}]
[quo/category
{:list-type :settings
:data [{:title "Normal ~60s"
:data [{:title (str (i18n/label :t/normal) "~60s")
:image-props "🍿"
:description-props {:text "€1.45"}
:image :emoji
@@ -69,7 +84,7 @@
:on-press #(set-selected-id :normal)
:label :text
:preview-size :size-32}
{:title "Fast ~40s"
{:title (str (i18n/label :t/fast) "~40s")
:image-props "🚗"
:description-props {:text "€1.65"}
:image :emoji
@@ -80,7 +95,7 @@
:on-press #(set-selected-id :fast)
:label :text
:preview-size :size-32}
{:title "Urgent ~15s"
{:title (str (i18n/label :t/urgent) "~15s")
:image-props "🚀"
:description-props {:text "€1.85"}
:image :emoji
@@ -91,7 +106,7 @@
:on-press #(set-selected-id :urgent)
:label :text
:preview-size :size-32}
{:title "Custom"
{:title (i18n/label :t/custom)
:image-props :i/edit
:description-props {:text "Set your own fees and nonce"}
:image :icon
@@ -104,5 +119,95 @@
:preview-size :size-32}]}]
[quo/bottom-actions
{:actions :one-action
:button-one-props {:on-press #(rf/dispatch [:hide-bottom-sheet])}
:button-one-props {:on-press (fn []
(rf/dispatch [:hide-bottom-sheet])
(when on-quick-settings-confirmed
(on-quick-settings-confirmed selected-id))
)}
:button-one-label (i18n/label :t/confirm)}]]))
(defn- hint
[{:keys [error? text]}]
[quo/network-tags
{:title text
:status (when error? :error)}])
(defn info-sheet
[info-title info-content]
[quo/documentation-drawers
{:title info-title
:shell? true}
[rn/view
[quo/text {:size :paragraph-2} info-content]
[quo/button
{:type :outline
:size 24
:icon-right :i/info
:container-style {:padding-top 21
:padding-bottom (if platform/ios? 14 24)
:align-self :flex-start
:justify-content :center}
:on-press #()}
(i18n/label :t/read-more)]]])
(defn custom-setting-screen
[{:keys [screen-title token-symbol hint-text-fn suggested-values info-title info-content on-save
with-decimals?]
:or {with-decimals? true}}]
(let [[input-state set-input-state] (rn/use-state (controlled-input/set-value-numeric
controlled-input/init-state
(:current suggested-values)))
input-value (controlled-input/input-value input-state)
out-of-limits? (controlled-input/input-error input-state)
valid-input? (not (or (controlled-input/empty-value? input-state)
out-of-limits?))]
(rn/use-mount
(fn []
(set-input-state (fn [state]
(-> state
(controlled-input/set-upper-limit (:high suggested-values))
(controlled-input/set-lower-limit (:low suggested-values)))))))
[rn/view
{:style {:flex 1}}
[quo/page-nav
{:type :title
:title screen-title
:text-align :center
:right-side [{:icon-name :i/info
:on-press #(rf/dispatch [:show-bottom-sheet
{:content (fn [] [info-sheet info-title
info-content])}])}]
:icon-name :i/arrow-left
:on-press (fn []
(rf/dispatch [:navigate-back])
(rf/dispatch [:show-bottom-sheet
{:content custom-settings-sheet}]))}]
[quo/token-input
{:token-symbol token-symbol
:swappable? false
:show-token-icon? false
:value input-value
:error? out-of-limits?
:currency-symbol token-symbol
:hint-component [hint
{:error? out-of-limits?
:text (hint-text-fn
(controlled-input/lower-limit-exceeded? input-state)
(controlled-input/upper-limit-exceeded? input-state))}]}]
[rn/view {:style {:flex 1}}]
[quo/bottom-actions
{:actions :one-action
:button-one-label (i18n/label :t/save-changes)
:button-one-props {:disabled? (not valid-input?)
:on-press #(on-save (controlled-input/value-numeric input-state))}}]
[quo/numbered-keyboard
{:container-style {:padding-bottom (safe-area/get-bottom)}
:left-action (if with-decimals? :dot :none)
:delete-key? true
:on-press (fn [c]
(set-input-state #(controlled-input/add-character % c)))
:on-delete (fn []
(set-input-state controlled-input/delete-last))
:on-long-press-delete (fn []
(set-input-state controlled-input/delete-all))}]]))
@@ -135,7 +135,8 @@
(def ^:private network-priority-score
{:ethereum 1
:optimism 2
:arbitrum 3})
:arbitrum 3
:base 4})
(defn reset-loading-network-amounts-to-zero
[network-amounts]
@@ -223,3 +224,10 @@
{:r (subs signature 0 64)
:s (subs signature 64 128)
:v (subs signature 128 130)})
(defn path-identity
[path]
{:routerInputParamsUuid (:router-input-params-uuid path)
:pathName (:bridge-name path)
:chainID (get-in path [:to :chain-id])
:isApprovalTx (:approval-required path)})
@@ -279,9 +279,7 @@
(fn [{:keys [db]} [{:keys [sent-transactions swap-data approval-transaction?]}]]
(let [wallet-transactions (get-in db [:wallet :transactions] {})
transactions (utils/transactions->hash-to-transaction-map sent-transactions)
transaction-ids (->> transactions
vals
(map :hash))
transaction-ids (keys transactions)
transaction-id (first transaction-ids)
transaction-details (cond-> transactions
:always (assoc-in [transaction-id :tx-type] :swap)
-2
View File
@@ -26,8 +26,6 @@
:peers-summary []
:transport/message-envelopes {}
:mailserver/mailservers (fleet/default-mailservers {})
:mailserver/topics {}
:mailserver/pending-requests 0
:chat/cooldowns 0
:chat/inputs {}
:chat/cooldown-enabled? false
+2 -1
View File
@@ -31,7 +31,8 @@
{:events [:navigate-to-within-stack]}
[{:keys [db]} comp-id screen-params]
{:db (all-screens-params db (first comp-id) screen-params)
:fx [[:navigate-to-within-stack (conj comp-id (:theme db))]]})
:fx [[:dispatch [:hide-bottom-sheet]]
[:navigate-to-within-stack (conj comp-id (:theme db))]]})
(re-frame/reg-event-fx :open-modal
(fn [{:keys [db]} [component screen-params]]
+107 -38
View File
@@ -33,8 +33,10 @@
[status-im.contexts.keycard.authorise.view :as keycard.authorise]
[status-im.contexts.keycard.check.view :as keycard.check]
[status-im.contexts.keycard.create.view :as keycard.create]
[status-im.contexts.keycard.different-card.view :as keycard.different-card]
[status-im.contexts.keycard.empty.view :as keycard.empty]
[status-im.contexts.keycard.error.view :as keycard.error]
[status-im.contexts.keycard.factory-reset.view :as keycard.factory-reset]
[status-im.contexts.keycard.migrate.fail.view :as keycard.migrate.fail]
[status-im.contexts.keycard.migrate.profile-keys.view :as keycard.migrate.profile-keys]
[status-im.contexts.keycard.migrate.re-encrypting.view :as keycard.re-encrypting]
@@ -137,6 +139,12 @@
[status-im.contexts.wallet.send.send-amount.view :as wallet-send-input-amount]
[status-im.contexts.wallet.send.transaction-confirmation.view :as wallet-transaction-confirmation]
[status-im.contexts.wallet.send.transaction-progress.view :as wallet-transaction-progress]
[status-im.contexts.wallet.send.transaction-settings.gas-amount.view :as
wallet-tx-settings-gas-amount]
[status-im.contexts.wallet.send.transaction-settings.max-fee.view :as wallet-tx-settings-max-fee]
[status-im.contexts.wallet.send.transaction-settings.nonce.view :as wallet-tx-settings-nonce]
[status-im.contexts.wallet.send.transaction-settings.priority-fee.view :as
wallet-tx-settings-priority-fee]
[status-im.contexts.wallet.swap.select-account.view :as wallet-swap-select-account]
[status-im.contexts.wallet.swap.select-asset-to-pay.view :as wallet-swap-select-asset-to-pay]
[status-im.contexts.wallet.swap.set-spending-cap.view :as wallet-swap-set-spending-cap]
@@ -518,6 +526,7 @@
{:name :screen/wallet.collectible
:metrics {:track? true}
:options {:modalPresentationStyle :overCurrentContext}
:component wallet-collectible/view}
{:name :screen/wallet.edit-account
@@ -623,7 +632,31 @@
:metrics {:track? true
:alias-id :wallet-send.select-collectible-amount}
:options {:insets {:top? true}}
:component wallet-select-collectible-amount/view}])
:component wallet-select-collectible-amount/view}
{:name :screen/wallet.tx-settings-max-fee
:metrics {:track? true
:alias-id :wallet-send.tx-settings-max-fee}
:options {:insets {:top? true}}
:component wallet-tx-settings-max-fee/view}
{:name :screen/wallet.tx-settings-priority-fee
:metrics {:track? true
:alias-id :wallet-send.tx-settings-priority-fee}
:options {:insets {:top? true}}
:component wallet-tx-settings-priority-fee/view}
{:name :screen/wallet.tx-settings-gas-amount
:metrics {:track? true
:alias-id :wallet-send.tx-settings-gas-amount}
:options {:insets {:top? true}}
:component wallet-tx-settings-gas-amount/view}
{:name :screen/wallet.tx-settings-nonce
:metrics {:track? true
:alias-id :wallet-send.tx-settings-nonce}
:options {:insets {:top? true}}
:component wallet-tx-settings-nonce/view}])
(def wallet-bridge-screens
[{:name :screen/wallet.bridge-select-asset
@@ -873,99 +906,135 @@
(def keycard-screens
[{:name :screen/keycard.check
:metrics {:track? true}
:options {:theme :dark
:insets {:top? true :bottom? true}}
:options {:theme :dark
:modalPresentationStyle :fullScreen
:insets {:top? true :bottom? true}}
:component keycard.check/view}
{:name :screen/keycard.empty
:metrics {:track? true}
:options {:theme :dark
:insets {:top? true :bottom? true}}
:options {:theme :dark
:modalPresentationStyle :fullScreen
:insets {:top? true :bottom? true}}
:component keycard.empty/view}
{:name :screen/keycard.empty-create
:metrics {:track? true}
:options {:insets {:top? true :bottom? true}}
:options {:insets {:top? true :bottom? true}
:modalPresentationStyle :fullScreen}
:component keycard.empty/create}
{:name :screen/keycard.error
:metrics {:track? true}
:options {:theme :dark
:insets {:top? true :bottom? true}}
:options {:theme :dark
:modalPresentationStyle :fullScreen
:insets {:top? true :bottom? true}}
:component keycard.error/view}
{:name :screen/keycard.different-card
:metrics {:track? true}
:options {:theme :dark
:modalPresentationStyle :fullScreen
:insets {:top? true :bottom? true}}
:component keycard.different-card/view}
{:name :screen/keycard.not-keycard
:metrics {:track? true}
:options {:theme :dark
:insets {:top? true :bottom? true}}
:options {:theme :dark
:modalPresentationStyle :fullScreen
:insets {:top? true :bottom? true}}
:component keycard.not-keycard/view}
{:name :screen/keycard.authorise
:metrics {:track? true}
:options {:theme :dark
:insets {:top? true :bottom? true}}
:options {:theme :dark
:modalPresentationStyle :fullScreen
:insets {:top? true :bottom? true}}
:component keycard.authorise/view}
{:name :screen/keycard.migrate
:metrics {:track? true}
:options {:theme :dark
:insets {:top? true :bottom? true}}
:options {:theme :dark
:modalPresentationStyle :fullScreen
:insets {:top? true :bottom? true}}
:component keycard.migrate/view}
{:name :screen/keycard.re-encrypting
:metrics {:track? true}
:options {:theme :dark
:insets {:top? true :bottom? true}
:popGesture false
:hardwareBackButton {:dismissModalOnPress false
:popStackOnPress false}}
:options {:theme :dark
:insets {:top? true :bottom? true}
:popGesture false
:modalPresentationStyle :fullScreen
:hardwareBackButton {:dismissModalOnPress false
:popStackOnPress false}}
:component keycard.re-encrypting/view}
{:name :screen/keycard.migrate.success
:metrics {:track? true}
:options {:theme :dark
:insets {:top? true :bottom? true}
:popGesture false
:hardwareBackButton {:dismissModalOnPress false
:popStackOnPress false}}
:options {:theme :dark
:insets {:top? true :bottom? true}
:popGesture false
:modalPresentationStyle :fullScreen
:hardwareBackButton {:dismissModalOnPress false
:popStackOnPress false}}
:component keycard.migrate.success/view}
{:name :screen/keycard.migrate.fail
:metrics {:track? true}
:options {:theme :dark
:insets {:top? true :bottom? true}
:popGesture false
:hardwareBackButton {:dismissModalOnPress false
:popStackOnPress false}}
:options {:theme :dark
:insets {:top? true :bottom? true}
:popGesture false
:modalPresentationStyle :fullScreen
:hardwareBackButton {:dismissModalOnPress false
:popStackOnPress false}}
:component keycard.migrate.fail/view}
{:name :screen/keycard.pin.create
:metrics {:track? true}
:options {:theme :dark
:insets {:top? true :bottom? true}}
:options {:theme :dark
:modalPresentationStyle :fullScreen
:insets {:top? true :bottom? true}}
:component keycard.pin.create/view}
{:name :screen/keycard.pin.enter
:metrics {:track? true}
:options {:theme :dark
:insets {:top? true :bottom? true}}
:options {:theme :dark
:modalPresentationStyle :fullScreen
:insets {:top? true :bottom? true}}
:component keycard.pin.enter/view}
{:name :screen/keycard.profile-keys
:metrics {:track? true}
:options {:theme :dark
:insets {:top? true :bottom? true}}
:options {:theme :dark
:modalPresentationStyle :fullScreen
:insets {:top? true :bottom? true}}
:component keycard.migrate.profile-keys/view}
{:name :screen/keycard.create-profile
:metrics {:track? true}
:options {:insets {:top? true :bottom? true}}
:options {:insets {:top? true :bottom? true}
:modalPresentationStyle :fullScreen}
:component keycard.create/view}
{:name :screen/keycard.create.ready-to-add
:metrics {:track? true}
:options {:insets {:top? true :bottom? true}}
:component keycard.create/ready-to-add}])
:options {:insets {:top? true :bottom? true}
:modalPresentationStyle :fullScreen}
:component keycard.create/ready-to-add}
{:name :screen/keycard.factory-reset.success
:metrics {:track? true}
:options {:theme :dark
:modalPresentationStyle :fullScreen
:insets {:top? true :bottom? true}}
:component keycard.factory-reset/success-view}
{:name :screen/keycard.factory-reset.fail
:metrics {:track? true}
:options {:theme :dark
:modalPresentationStyle :fullScreen
:insets {:top? true :bottom? true}}
:component keycard.factory-reset/failed-view}])
(defn screens
[]
+6
View File
@@ -82,3 +82,9 @@
:<- [:keycard]
(fn [keycard]
(get-in keycard [:application-info :initialized?])))
(rf/reg-sub
:keycard/key-uid
:<- [:keycard]
(fn [keycard]
(get-in keycard [:application-info :key-uid])))
+7 -2
View File
@@ -2,6 +2,7 @@
(:require
[clojure.string :as string]
[re-frame.core :as re-frame]
[status-im.contexts.wallet.collectible.utils :as collectible-utils]
[utils.collection]))
(defn- filter-collectibles-in-chains
@@ -46,7 +47,10 @@
:wallet/current-viewing-account-collectibles
:<- [:wallet/current-viewing-account]
(fn [current-account]
(-> current-account :collectibles add-collectibles-preview-url)))
(-> current-account
:collectibles
add-collectibles-preview-url
collectible-utils/sort-collectibles-by-name)))
(re-frame/reg-sub
:wallet/current-viewing-account-collectibles-in-selected-networks
@@ -71,7 +75,8 @@
(apply interleave)
(remove nil?)
(utils.collection/distinct-by :id)
(add-collectibles-preview-url)))))
(add-collectibles-preview-url)
(collectible-utils/sort-collectibles-by-name)))))
(re-frame/reg-sub
:wallet/owned-collectibles-list-in-selected-networks
+25
View File
@@ -204,3 +204,28 @@
fiat-value)]
{:crypto (str crypto-formatted " " (:symbol token))
:fiat fiat-formatted})))
(rf/reg-sub
:wallet/tx-settings
:<- [:wallet/wallet-send]
:-> :tx-settings)
(rf/reg-sub
:wallet/tx-settings-max-base-fee
:<- [:wallet/tx-settings]
:-> :max-base-fee)
(rf/reg-sub
:wallet/tx-settings-priority-fee
:<- [:wallet/tx-settings]
:-> :priority-fee)
(rf/reg-sub
:wallet/tx-settings-max-gas-amount
:<- [:wallet/tx-settings]
:-> :max-gas-amount)
(rf/reg-sub
:wallet/tx-settings-nonce
:<- [:wallet/tx-settings]
:-> :nonce)
+25 -17
View File
@@ -505,30 +505,38 @@
:<- [:wallet/current-viewing-account-or-default]
:<- [:wallet/network-details]
:<- [:wallet/wallet-send]
(fn [[account networks send-data] [_ {:keys [query chain-ids hide-token-fn]}]]
:<- [:profile/currency]
:<- [:wallet/prices-per-token]
(fn [[account networks send-data currency price-per-token] [_ {:keys [query chain-ids hide-token-fn]}]]
(let [tx-type (:tx-type send-data)
tokens (->> (:tokens account)
(map
(fn [token]
(assoc token
:bridge-disabled? (and (= tx-type :tx/bridge)
(send-utils/bridge-disabled? (:symbol
token)))
:networks (cond->>
(network-utils/network-list-with-positive-balance
token
networks)
chain-ids
(filter #(some #{(:chain-id %)} chain-ids)))
:supported-networks (network-utils/network-list token networks)
:available-balance (utils/calculate-total-token-balance token)
:total-balance (utils/calculate-total-token-balance
token
chain-ids))))
(let [total-balance (utils/calculate-total-token-balance
token
chain-ids)]
(assoc token
:bridge-disabled? (and (= tx-type :tx/bridge)
(send-utils/bridge-disabled? (:symbol
token)))
:networks (cond->>
(network-utils/network-list-with-positive-balance
token
networks)
chain-ids
(filter #(some #{(:chain-id %)} chain-ids)))
:supported-networks (network-utils/network-list token networks)
:available-balance (utils/calculate-total-token-balance token)
:total-balance total-balance
:fiat-value (utils/calculate-token-fiat-value
{:currency currency
:balance total-balance
:token token
:prices-per-token price-per-token})))))
(filter (fn [{:keys [networks]}]
(pos? (count networks))))
(remove #(when hide-token-fn (hide-token-fn constants/swap-tokens-my %))))
sorted-tokens (utils/sort-tokens tokens)]
sorted-tokens (utils/sort-tokens-by-fiat-value tokens)]
(if query
(let [query-string (string/lower-case query)]
(filter #(or (string/starts-with? (string/lower-case (:name %)) query-string)
+1 -1
View File
@@ -840,7 +840,7 @@
(swap! rf-db/app-db #(assoc % :wallet db/defaults))
(is
(match? (sort [constants/ethereum-mainnet-chain-id constants/arbitrum-mainnet-chain-id
constants/optimism-mainnet-chain-id])
constants/optimism-mainnet-chain-id constants/base-mainnet-chain-id])
(sort (rf/sub [sub-name])))))
(testing "selected networks -> chain-ids - specific network"
(swap! rf-db/app-db #(assoc-in %
+3 -1
View File
@@ -54,9 +54,11 @@
(is (some #(= constants/ethereum-mainnet-chain-id (get-in % [:Prod :chainId])) response))
(is (some #(= constants/optimism-mainnet-chain-id (get-in % [:Prod :chainId])) response))
(is (some #(= constants/arbitrum-mainnet-chain-id (get-in % [:Prod :chainId])) response))
(is (some #(= constants/base-mainnet-chain-id (get-in % [:Prod :chainId])) response))
(is (some #(= constants/ethereum-sepolia-chain-id (get-in % [:Test :chainId])) response))
(is (some #(= constants/arbitrum-sepolia-chain-id (get-in % [:Test :chainId])) response))
(is (some #(= constants/optimism-sepolia-chain-id (get-in % [:Test :chainId])) response)))
(is (some #(= constants/optimism-sepolia-chain-id (get-in % [:Test :chainId])) response))
(is (some #(= constants/base-sepolia-chain-id (get-in % [:Test :chainId])) response)))
(deftest accounts-get-chains-contract-test
(h/test-async :contract/wallet_get-ethereum-chains
+2 -1
View File
@@ -13,7 +13,8 @@
:bsc-testnet {:id BSC-testnet-chain-id
:name "BSC testnet"}
:arbitrum {:id 42161 :name "Arbitrum"}
:optimism {:id 10 :name "Optimism"}})
:optimism {:id 10 :name "Optimism"}
:base {:id 8453 :name "Base"}})
(defn chain-id->chain-keyword
[i]
+3 -3
View File
@@ -3,7 +3,7 @@
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
"owner": "status-im",
"repo": "status-go",
"version": "v8.1.0",
"commit-sha1": "df1c8788e42784ba3b8ed3e7c5bd3ea530028410",
"src-sha256": "1yxcswrj7p1m96lx795vbqlgjlmpkgzaw7l8f2k4ni3d7vmlklnw"
"version": "v9.1.0",
"commit-sha1": "4ec885a91f2857a30d1838213000f0a5a91fd52a",
"src-sha256": "1fkvhazv7v2vyqpffx3r4p3aii5ai464nx2pdfgn6b6gmb24bxdq"
}
+3 -1
View File
@@ -11,4 +11,6 @@ Pillow~=10.0.0
pytest-xdist==3.2.0
pytz~=2020.4
PyGithub==1.55
typing-extensions==4.12.2
typing-extensions==4.12.2
mnemonic==0.21
bip-utils==2.9.3
+15
View File
@@ -0,0 +1,15 @@
from bip_utils import Bip39SeedGenerator, Bip44, Bip44Coins, Bip44Changes
def generate_wallet_address(passphrase: str, number: int = 1):
# Derive accounts using the standard MetaMask path
seed_bytes = Bip39SeedGenerator(passphrase).Generate()
bip44_mst_ctx = Bip44.FromSeed(seed_bytes, Bip44Coins.ETHEREUM)
# Generate first n addresses
expected_addresses = list()
for i in range(number):
bip44_acc_ctx = bip44_mst_ctx.Purpose().Coin().Account(0).Change(Bip44Changes.CHAIN_EXT).AddressIndex(i)
expected_addresses.append(bip44_acc_ctx.PublicKey().ToAddress().lower())
return expected_addresses
+2 -11
View File
@@ -2,7 +2,6 @@ import base64
import itertools
import json
import logging
import re
from json import JSONDecodeError
from os import environ
from sys import argv
@@ -212,18 +211,10 @@ class TestrailReport(BaseTestReport):
except IndexError:
continue
for res in results:
if last_testrun.first_commands:
try:
pattern = r"%s\?auth=.*#%s" % (device, str(last_testrun.first_commands[device]))
except KeyError:
pattern = device
else:
pattern = device
if re.findall(pattern, res['comment']):
res_id = res['id']
if self.get_lambda_test_job_url(job_id=device) in res['comment']:
try:
for log in test.logs_paths.keys():
self.add_attachment(method='add_attachment_to_result/%s' % str(res_id),
self.add_attachment(method='add_attachment_to_result/%s' % str(res['id']),
path=test.logs_paths[log])
except (AttributeError, FileNotFoundError):
pass
@@ -884,9 +884,10 @@ class TestCommunityMultipleDeviceMergedTwo(MultipleSharedDeviceTestCase):
self.device_1.just_fyi("Admin gets push notification with the mention and tap it")
message_received = False
if self.home_1.get_pn(self.username_1):
pn_element = self.home_1.get_pn(pn_text=self.username_1, wait_time=90)
if pn_element:
pn_element.click()
message_received = True
self.device_1.click_upon_push_notification_by_text(self.username_1)
if not self.channel_1.chat_element_by_text(self.username_1).is_element_displayed():
if self.channel_1.chat_message_input.is_element_displayed():
self.errors.append("Message with the mention is not shown in the chat for the admin")
@@ -904,11 +905,6 @@ class TestCommunityMultipleDeviceMergedTwo(MultipleSharedDeviceTestCase):
if message_received:
self.channel_1.just_fyi("Set reaction for the message with a mention")
self.channel_1.set_reaction(message=self.username_1, emoji="sad", times_to_long_press=2)
try:
self.channel_2.chat_element_by_text(self.username_1).emojis_below_message(
emoji="sad").wait_for_element_text(1)
except (Failed, NoSuchElementException):
self.errors.append("Message reaction is not shown for the sender")
self.device_2.just_fyi("Sender edits the message with a mention")
chat_element = self.channel_2.chat_element_by_text(self.username_1)
@@ -937,6 +933,13 @@ class TestCommunityMultipleDeviceMergedTwo(MultipleSharedDeviceTestCase):
if not element.is_element_displayed(10) or element.text != expected_message:
self.errors.append("Edited message is not shown correctly for the (receiver) admin")
self.device_2.just_fyi("Sender checks the reaction for a message with a mention")
try:
self.channel_2.chat_element_by_text(self.username_1).emojis_below_message(
emoji="sad").wait_for_element_text(1)
except (Failed, NoSuchElementException):
self.errors.append("Message reaction is not shown for the sender")
self.home_2.navigate_back_to_home_view()
if not self.channel_1.chat_message_input.is_element_displayed():
self.channel_1.navigate_back_to_home_view()
@@ -949,7 +952,7 @@ class TestCommunityMultipleDeviceMergedTwo(MultipleSharedDeviceTestCase):
self.channel_1.send_message_button.click()
self.device_2.just_fyi("Invited member gets push notification with the mention and tap it")
self.device_2.open_notification_bar()
push_notification_element = self.home_2.get_pn(self.username_2)
push_notification_element = self.home_2.get_pn(pn_text=self.username_2, wait_time=90)
if push_notification_element:
push_notification_element.click()
if not self.channel_2.chat_element_by_text(self.username_2).is_element_displayed():
+101 -21
View File
@@ -2,6 +2,7 @@ import pytest
from selenium.common import TimeoutException
from base_test_case import MultipleSharedDeviceTestCase, create_shared_drivers
from support.helpers import generate_wallet_address
from tests import marks, run_in_parallel, transl
from users import transaction_senders
from views.sign_in_view import SignInView
@@ -162,34 +163,90 @@ class TestFallbackMultipleDevice(MultipleSharedDeviceTestCase):
@marks.testrail_id(741054)
def test_fallback_add_key_pair(self):
expected_addresses = generate_wallet_address(passphrase=self.recovery_phrase, number=4)
account_to_add = transaction_senders['ETH_1']
self.home_1.navigate_back_to_home_view()
self.home_2.navigate_back_to_home_view()
wallet_1 = self.home_1.wallet_tab.click()
wallet_2 = self.home_2.wallet_tab.click()
regular_account_name = "New regular account"
key_pair_account_name = "Key pair account"
key_pair_name = "New key pair"
key_pair_account_address = '0x' + account_to_add['address'].lower()
wallet_1.just_fyi("Device 1: add a new regular account")
regular_account_name = "New regular account"
regular_derivation_path = wallet_1.add_regular_account(account_name=regular_account_name)
regular_account_wallet_address = wallet_1.get_account_address().split(':')[-1]
regular_account_address = wallet_1.get_account_address().split(':')[-1]
account_element = wallet_1.get_account_element(account_name=regular_account_name)
wallet_1.close_account_button.click_until_presence_of_element(account_element)
wallet_1.just_fyi("Device 1: add a new key pair account")
if regular_account_address != expected_addresses[1]:
self.errors.append("Newly added regular account address %s doesn't match expected %s" % (
regular_account_address, expected_addresses[1]))
if regular_account_address not in expected_addresses:
self.errors.append("Newly added regular account address %s is not in the list of expected addresses %s" % (
regular_account_address, expected_addresses))
wallet_1.just_fyi("Device 1: add a new key pair account by importing recovery phrase")
account_element.swipe_left_on_element()
key_pair_derivation_path = wallet_1.add_key_pair_account(account_name=key_pair_account_name,
passphrase=account_to_add['passphrase'],
key_pair_name=key_pair_name)
imported_key_pair_account_name = "Imported account"
imported_key_pair_name = "Imported key pair"
imported_key_pair_account_address = '0x' + account_to_add['address'].lower()
imported_key_pair_derivation_path = wallet_1.import_key_pair_using_recovery_phrase(
account_name=imported_key_pair_account_name,
passphrase=account_to_add['passphrase'],
key_pair_name=imported_key_pair_name)
wallet_1.close_account_button.click_until_presence_of_element(account_element)
wallet_1.just_fyi("Device 1: verify default and added key pairs details")
account_element.swipe_left_on_element()
wallet_1.get_account_element(account_name=imported_key_pair_account_name).swipe_left_on_element()
if not wallet_1.add_account_button.is_element_displayed():
wallet_1.get_account_element(account_name=imported_key_pair_account_name).swipe_left_on_element()
wallet_1.add_account_button.click()
wallet_1.create_account_button.click()
wallet_1.edit_key_pair_button.click()
expected_texts_regular = [
regular_account_name,
"%s...%s" % (regular_account_address[:5], regular_account_address[-3:])
]
for text in expected_texts_regular:
if not wallet_1.default_key_pair_container.get_child_element_by_text_part(text).is_element_displayed():
self.errors.append("Newly added regular account is not shown in default key pair list")
break
expected_texts_key_pair = [
imported_key_pair_account_name, imported_key_pair_name,
"%s...%s" % (imported_key_pair_account_address[:5], imported_key_pair_account_address[-3:])
]
for text in expected_texts_key_pair:
if not wallet_1.added_key_pair_container.get_child_element_by_text_part(text).is_element_displayed():
self.errors.append("Newly added regular account is not shown in default key pair list")
break
wallet_1.just_fyi("Device 1: add a new key pair account by generating a new key pair")
generated_key_pair_account_name = "Generated account"
generated_key_pair_name = "Generated key pair"
generated_key_pair_derivation_path, generated_passphrase = wallet_1.generate_new_key_pair(
account_name=generated_key_pair_account_name,
key_pair_name=generated_key_pair_name)
generated_key_pair_account_address = wallet_1.get_account_address().split(':')[-1]
wallet_1.close_account_button.click_until_presence_of_element(account_element)
expected_addresses = generate_wallet_address(passphrase=generated_passphrase, number=4)
if generated_key_pair_account_address != expected_addresses[0]:
self.errors.append("Generated key pair account address %s doesn't match expected %s" % (
generated_key_pair_account_address, expected_addresses[0]))
if generated_key_pair_account_address not in expected_addresses:
self.errors.append("Generated key pair account address %s is not in the list of expected addresses %s" % (
generated_key_pair_account_address, expected_addresses))
self.home_2.just_fyi("Device 2: check imported accounts are shown before importing key pair")
self.home_2.profile_button.click()
self.profile_2.profile_wallet_button.click()
self.profile_2.key_pairs_and_accounts_button.click()
if not self.profile_2.get_missing_key_pair_by_name(key_pair_name=key_pair_name).is_element_displayed():
self.errors.append("Key pair is not shown in profile as missing before importing")
if not self.profile_2.get_missing_key_pair_by_name(key_pair_name=imported_key_pair_name).is_element_displayed():
self.errors.append("New imported key pair is not shown in profile as missing before importing")
if not self.profile_2.get_missing_key_pair_by_name(
key_pair_name=generated_key_pair_name).is_element_displayed():
self.errors.append("Generated key pair is not shown in profile as missing before importing")
if not self.profile_2.get_key_pair_account_by_name(account_name=regular_account_name).is_element_displayed():
self.errors.append(
"Newly added regular account is not shown in profile as on device before importing key pair")
@@ -200,7 +257,7 @@ class TestFallbackMultipleDevice(MultipleSharedDeviceTestCase):
wallet_2.just_fyi("Device 2: import key pair")
wallet_2.get_account_element(account_name=regular_account_name).swipe_left_on_element()
wallet_2.get_account_element(account_name=key_pair_account_name).click()
wallet_2.get_account_element(account_name=imported_key_pair_account_name).click()
wallet_2.element_by_translation_id("import-key-pair").click()
self.sign_in_2.passphrase_edit_box.send_keys(account_to_add['passphrase'])
wallet_2.slide_and_confirm_with_password()
@@ -211,19 +268,28 @@ class TestFallbackMultipleDevice(MultipleSharedDeviceTestCase):
self.profile_2.key_pairs_and_accounts_button.click()
if self.profile_2.get_key_pair_account_by_name(account_name=regular_account_name).is_element_displayed():
address_text = self.profile_2.get_key_pair_account_by_name(account_name=regular_account_name).address.text
if address_text != '...'.join((regular_account_wallet_address[:5], regular_account_wallet_address[-3:])):
if address_text != '...'.join((regular_account_address[:5], regular_account_address[-3:])):
self.errors.append(
"Incorrect wallet address if shown for regular account after importing: " + address_text)
else:
self.errors.append("Newly added regular account is not shown in profile after importing key pair")
if self.profile_2.get_key_pair_account_by_name(account_name=key_pair_account_name).is_element_displayed():
address_text = self.profile_2.get_key_pair_account_by_name(account_name=key_pair_account_name).address.text
if address_text != '...'.join((key_pair_account_address[:5], key_pair_account_address[-3:])):
account_element = self.profile_2.get_key_pair_account_by_name(
account_name=imported_key_pair_account_name)
if account_element.is_element_displayed():
address_text = account_element.address.text
if address_text != '...'.join(
(imported_key_pair_account_address[:5], imported_key_pair_account_address[-3:])):
self.errors.append(
"Incorrect wallet address if shown for key pair account after importing: " + address_text)
"Incorrect wallet address if shown for imported key pair account after importing: " + address_text)
else:
self.errors.append("Key pair account is not shown in profile as on device after importing key pair")
self.errors.append(
"Imported key pair account is not shown in profile as on device after importing key pair")
if not self.profile_2.get_missing_key_pair_by_name(
key_pair_name=generated_key_pair_name).is_element_displayed():
self.errors.append(
"Generated key pair account is not shown in profile as missing after importing the first key pair")
self.profile_2.click_system_back_button(times=3)
# ToDo: Arbiscan API is down, looking for analogue
@@ -243,11 +309,25 @@ class TestFallbackMultipleDevice(MultipleSharedDeviceTestCase):
self.errors.append("Incorrect derivation path %s is shown for the regular account" % der_path)
wallet_2.close_account_button.click_until_presence_of_element(account_element)
account_element.swipe_left_on_element()
wallet_2.get_account_element(account_name=key_pair_account_name).click()
wallet_2.get_account_element(account_name=imported_key_pair_account_name).click()
wallet_2.about_tab.click()
der_path = wallet_2.account_about_derivation_path_text.text
if der_path != key_pair_derivation_path:
self.errors.append("Incorrect derivation path %s is shown for the key pair account" % der_path)
if der_path != imported_key_pair_derivation_path:
self.errors.append("Incorrect derivation path %s is shown for the imported key pair account" % der_path)
wallet_2.close_account_button.click_until_presence_of_element(account_element)
account_element.swipe_left_on_element()
wallet_2.get_account_element(account_name=generated_key_pair_account_name).click()
wallet_2.element_by_translation_id("import-key-pair").click()
self.sign_in_2.passphrase_edit_box.send_keys(generated_passphrase)
wallet_2.slide_and_confirm_with_password()
wallet_2.get_account_element(account_name=generated_key_pair_account_name).click()
wallet_2.about_tab.click()
der_path = wallet_2.account_about_derivation_path_text.text
if der_path != generated_key_pair_derivation_path:
self.errors.append("Incorrect derivation path %s is shown for the generated key pair account" % der_path)
if not wallet_2.element_by_text_part(generated_key_pair_account_address).is_element_displayed():
self.errors.append(
"Generated key pair address %s is absent in About tab" % generated_key_pair_account_address)
self.errors.verify_no_errors()
@marks.testrail_id(740222)
+3
View File
@@ -352,6 +352,9 @@ class BaseElement(object):
def get_child_element_by_text(self, text: str):
return BaseElement(self.driver, prefix=self.locator, xpath="//*[@text='%s']" % text)
def get_child_element_by_text_part(self, text: str):
return BaseElement(self.driver, prefix=self.locator, xpath="//*[contains(@text,'%s')]" % text)
class EditBox(BaseElement):
+2 -2
View File
@@ -474,10 +474,10 @@ class HomeView(BaseView):
element.double_click()
self.element_by_translation_id(mute_period).click()
def get_pn(self, pn_text: str):
def get_pn(self, pn_text: str, wait_time: int = 60):
self.driver.info("Getting PN by '%s'" % pn_text)
expected_element = PushNotificationElement(self.driver, pn_text)
return expected_element if expected_element.is_element_displayed(60) else False
return expected_element if expected_element.is_element_displayed(wait_time) else False
def contact_details_row(self, username=None, index=None):
return ContactDetailsRow(self.driver, username=username, index=index)
+36 -13
View File
@@ -107,11 +107,19 @@ class WalletView(BaseView):
# Edit key pair
self.edit_key_pair_button = Button(self.driver, accessibility_id="Edit")
self.key_pairs_plus_button = Button(self.driver, accessibility_id="standard-title-action")
self.default_key_pair_container = BaseElement(self.driver,
xpath="//*[@content-desc='user-avatar, title, details']")
self.added_key_pair_container = BaseElement(self.driver,
xpath="//*[@content-desc='icon, title, details']")
self.generate_new_keypair_button = Button(self.driver, accessibility_id="generate-new-keypair")
self.import_using_recovery_phrase_button = Button(self.driver, accessibility_id="import-using-phrase")
self.key_pair_continue_button = Button(self.driver, accessibility_id="Continue")
self.key_pair_name_input = EditBox(
self.driver, xpath="//*[@text='Key pair name']/..//following-sibling::*/*[@content-desc='input']")
self.passphrase_text_element = Text(
self.driver, xpath="//*[@resource-id='counter-component']/following-sibling::android.widget.TextView")
self.passphrase_word_number_container = Text(
self.driver, xpath="//*[@content-desc='number-container']/android.widget.TextView")
def set_network_in_wallet(self, network_name: str):
self.network_drop_down.click()
@@ -198,25 +206,40 @@ class WalletView(BaseView):
def get_activity_element(self, index=1):
return ActivityElement(self.driver, index=index)
def add_key_pair_account(self, account_name, passphrase=None, key_pair_name=None):
def generate_new_key_pair(self, account_name: str, key_pair_name: str):
self.key_pairs_plus_button.click()
self.generate_new_keypair_button.click()
for checkbox in self.checkbox_button.find_elements():
checkbox.click()
self.element_by_translation_id("reveal-phrase").click()
passphrase = [i.text for i in self.passphrase_text_element.find_elements()]
self.element_by_translation_id("i-have-written").click()
for _ in range(4):
element = self.passphrase_word_number_container.find_element()
number = int(element.text)
Button(self.driver, accessibility_id=passphrase[number - 1]).click()
self.wait_for_staleness_of_element(element)
self.checkbox_button.click()
self.element_by_translation_id("done").click()
self.key_pair_name_input.send_keys(key_pair_name)
self.key_pair_continue_button.click()
derivation_path = self.add_account_derivation_path_text.text
SignInView(self.driver).profile_title_input.send_keys(account_name)
self.slide_and_confirm_with_password()
return derivation_path.replace(' ', ''), ' '.join(passphrase)
def import_key_pair_using_recovery_phrase(self, account_name: str, passphrase: str, key_pair_name: str):
self.add_account_button.click()
self.create_account_button.click()
signin_view = SignInView(self.driver)
signin_view.profile_title_input.send_keys(account_name)
self.edit_key_pair_button.click()
self.key_pairs_plus_button.click()
if passphrase:
self.import_using_recovery_phrase_button.click()
signin_view.passphrase_edit_box.send_keys(passphrase)
self.key_pair_continue_button.click()
self.key_pair_name_input.send_keys(key_pair_name)
self.key_pair_continue_button.click()
else:
self.generate_new_keypair_button.click()
for checkbox in self.checkbox_button.find_elements():
checkbox.click()
self.element_by_translation_id("reveal-phrase").click()
# ToDo: can't be done in current small size emulators, add when moved to LambdaTest
self.import_using_recovery_phrase_button.click()
signin_view.passphrase_edit_box.send_keys(passphrase)
self.key_pair_continue_button.click()
self.key_pair_name_input.send_keys(key_pair_name)
self.key_pair_continue_button.click()
derivation_path = self.add_account_derivation_path_text.text
self.slide_and_confirm_with_password()
return derivation_path.replace(' ', '')
+34
View File
@@ -1,10 +1,14 @@
{
"about": "About",
"about-app": "About",
"about-gas-amount": "AKA gas limit. Refers to the maximum number of computational steps (or units of gas) that a transaction can consume. It represents the complexity or amount of work required to execute a transaction or smart contract.\n\nThe gas limit is a cap on how much work the transaction can do on the blockchain. If the gas limit is set too low, the transaction may fail due to insufficient gas.",
"about-key-storage-content": "Status will never access your private key. Be sure to backup your seed phrase. If you lose your phone it is the only way to access your keys.",
"about-key-storage-title": "About key storage",
"about-max-base-fee": "When your transaction gets included in the block, any difference between your max base fee and the actual base fee will be refunded.",
"about-names-content": "No one can pretend to be you! Youre anonymous by default and never have to reveal your real name. You can register a custom name for a small fee.",
"about-names-title": "Names cant be changed",
"about-nonce": "Transaction counter ensuring transactions from your account are processed in the correct order and cant be replayed. Each new transaction increments the nonce by 1, ensuring uniqueness and preventing double-spending.\n\nIf a transaction with a lower nonce is pending, higher nonce transactions will remain in the queue until the earlier one is confirmed.",
"about-priority-fee": "AKA miner tip. A voluntary fee you can add to incentivise miners or validators to prioritise your transaction.\n\nThe higher the tip, the faster your transaction is likely to be processed, especially curing periods of higher network congestion.",
"about-sharing-data": "About sharing data",
"accent-colour": "Accent colour",
"accent-colour-updated": "Accent colour updated",
@@ -191,6 +195,7 @@
"backup-through-waku": "Backup through waku",
"bad-fees-description": "Your priority fee is below our suggested parameters.",
"balance": "Balance",
"base": "Base",
"be-safe-with-secure-cold-wallet": "Be safe with secure cold wallet",
"begin-set-up": "Begin setup",
"below-base-fee": "max fee below base fee",
@@ -654,6 +659,7 @@
"current-password": "Current password",
"current-pin": "Enter 6-digit passcode",
"current-pin-description": "Enter your 6-digit passcode to proceed",
"current-units": "Current: {{current}} UNITS",
"custom": "Custom",
"custom-node": "You are using custom RPC endpoint. Your local transfers history might be incomplete.",
"custom-seed-phrase": "Invalid seed phrase",
@@ -779,6 +785,7 @@
"device-syncing": "Device syncing",
"devices": "Devices",
"devices-count": "{{number}} devices",
"different-keycard": "Its a different Keycard",
"disable": "disable",
"disable-all": "Disable all",
"disable-later-in-settings": "You can disable this later in Settings",
@@ -1028,6 +1035,9 @@
"export-key": "Export private key",
"external-link": "External link",
"external-storage-denied": "Access to external storage is denied",
"factory-reset": "Factory reset",
"factory-reset-keycard": "Factory reset this Keycard",
"factory-reset-warning": "Please ensure you have a backup of your recovery phrase before proceeding with the factory reset. If you want to switch to password authentication instead of Keycard, remove the profile from the device and log in with your recovery phrase.",
"failed": "Failed",
"failed-on": "Failed on",
"failed-to-fetch-community": "Failed to fetch community",
@@ -1045,6 +1055,7 @@
"featured": "Featured",
"feb": "Feb",
"fee-cap": "Fee cap",
"fee-current-gwei": "Current: {{current}} GWEI",
"fee-explanation": "Maximum overall price for the transaction. If the block base fee exceeds this, it will be included in a following block with a lower base fee.",
"fee-options": "Suggested fee options",
"fees": "Fees",
@@ -1086,7 +1097,9 @@
"from-all-profiles-on-device": "From all profiles on device",
"from-capitalized": "From",
"from-label": "From",
"gas-amount": "Gas amount",
"gas-amount-limit": "Gas amount limit",
"gas-amount-lower": "Too low. Recommended: {{current}} UNITS",
"gas-limit": "Gas limit",
"gas-price": "Gas price",
"gas-used": "Gas used",
@@ -1346,6 +1359,7 @@
"key-name-error-taken": "Key pair name already in use",
"key-name-error-too-short": "Key pair name must be at least {{count}} characters",
"key-on-device": "Private key is saved on this device",
"key-pair-erased": "Key pair will be erased from Keycard",
"key-pair-imported-successfully": "{{name}} key pair imported successfully",
"key-pair-migrated-successfully": "Profile key pair successfully migrated",
"key-pair-name-updated": "Key pair name updated",
@@ -1369,6 +1383,7 @@
"keycard-desc": "Own a Keycard? Store your keys on it; youll need it for transactions",
"keycard-dont-ask-card": "Don't ask for card to sign in",
"keycard-empty": "Keycard is empty",
"keycard-empty-ready": "Keycard is empty and ready to be used",
"keycard-enter-new-passcode": "Enter new passcode {{step}}/2",
"keycard-error-description": "Connect the card again to continue",
"keycard-error-title": "Connection lost",
@@ -1427,7 +1442,9 @@
"keycard-redeem-title": "Redeem to",
"keycard-redeem-tx": "Redeem assets",
"keycard-redeem-tx-desc": "Tap the card to sign and receive assets",
"keycard-reset-failed": "Failed to reset Keycard",
"keycard-reset-passcode": "Reset passcode",
"keycard-reset-success": "Keycard has been reset",
"keycard-success-description": "You may remove the card now",
"keycard-success-title": "Success",
"keycard-unauthorized-operation": "You're unauthorized to perform this operation.\n Please tap valid card and try again.",
@@ -1446,6 +1463,7 @@
"language-and-currency": "Language and currency",
"last-backup-performed": "Last backup performed:",
"last-transaction": "Last transaction",
"last-transaction-is": "Last transaction: {{number}}",
"layer-2": "Layer 2",
"learn-more": "Learn more",
"learn-more-about-keycard": "Learn more about Keycard",
@@ -1552,8 +1570,12 @@
"master-account": "Master account",
"max": "Max: {{number}}",
"max-2-decimals": "Max. 2 decimals",
"max-base-fee": "Max base fee",
"max-base-fee-higher": "Higher than necessary. Current: {{current}} GWEI",
"max-base-fee-lower": "Too low. Current: {{current}} GWEI ",
"max-fee": "Max fee",
"max-fees": "Max fees",
"max-gas-amount": "Max gas amount",
"max-priority-fee": "Max priority fee",
"max-slippage": "Max slippage",
"max-token": "Max: {{number}} {{token-symbol}}",
@@ -1797,6 +1819,7 @@
"non-archival-node": "RPC endpoint doesn't support archival requests. Your local transfers history might be incomplete.",
"non-contacts": "Non contacts",
"nonce": "Nonce",
"nonce-higher": "Higher than suggested nonce of {{number}}",
"none": "None",
"normal": "Normal",
"not-a-chatkey": "This is not a chatkey",
@@ -2023,6 +2046,9 @@
"price-impact-too-high": "Price impact too high. Lower token amount or try again later.",
"principles": "Principles",
"priority": "Priority",
"priority-fee": "Priority fee",
"priority-fee-higher": "More than necessary. Current: {{low}} - {{high}} GWEI",
"priority-fee-lower": "Too low. Current: {{low}} - {{high}} GWEI",
"privacy": "Privacy",
"privacy-and-security": "Privacy and security",
"privacy-photos": "Profile Photo Privacy",
@@ -2140,6 +2166,7 @@
"remove-from-contacts-text": "By removing a user from your contact list you do not hide your wallet address from them",
"remove-group": "Remove group",
"remove-key-pair-and-derived-accounts": "Remove key pair and derived accounts",
"remove-keycard-content": "Remove all content from this Keycard",
"remove-network": "Remove network",
"remove-nickname": "Remove nickname",
"remove-nickname-toast": "You have removed {{secondary-name}}'s nickname",
@@ -2232,9 +2259,11 @@
"scan-an-address-qr-code": "Scan an address QR code",
"scan-key-pairs-qr-code": "Scan key pairs QR code",
"scan-keycard": "Scan Keycard",
"scan-keycard-actions": "Scan Keycard to see available actions",
"scan-or-enter-a-sync-code": "Scan or enter a sync code",
"scan-or-enter-sync-code": "Scan or enter sync code",
"scan-or-enter-sync-code-seen-on-this-device": "Scan or enter sync code seen on this device",
"scan-previous-keycard": "Please scan Keycard you previously scanned",
"scan-qr": "Scan QR",
"scan-qr-code": "Scan QR code",
"scan-sync-code": "Scan Sync Code",
@@ -2362,6 +2391,7 @@
"share-invite-link": "Share an invite link",
"share-link": "Share link",
"share-link-to-arb": "Share link to Arbiscan",
"share-link-to-base": "Share link to Basescan",
"share-link-to-eth": "Share link to Etherscan",
"share-link-to-oeth": "Share link to Optimism Explorer",
"share-logs": "Share logs",
@@ -2617,6 +2647,7 @@
"transaction-history": "Transaction history",
"transaction-request": "Transaction Request",
"transaction-sent": "Transaction sent",
"transaction-settings": "Transaction settings",
"transaction-signed": "The transaction has been successfully signed",
"transactions": "Transactions",
"transactions-filter-select-all": "Select all",
@@ -2677,6 +2708,7 @@
"type": "Type",
"type-a-message": "Message",
"type-nickname": "Type nickname",
"type-nonce": "Type nonce",
"type-pairing-code": "Type or paste pairing code",
"type-slippage": "Type slippage",
"type-some-chat-key": "zQ3...1sgt5N",
@@ -2733,6 +2765,7 @@
"updates-to-tos": "Updates to Terms of Use",
"updates-to-tos-desc": "Before you continue, please review the Terms of Use and confirm you take full responsibility for how you use the app.",
"upvote-it": "upvote it",
"urgent": "Urgent",
"url": "URL",
"usage-data-shared-from-all-profiles": "Usage data will be shared from all profiles added to device. ",
"usd-currency": "USD",
@@ -2787,6 +2820,7 @@
"view-gitcoin": "View in Gitcoin",
"view-members": "View members",
"view-on-arb": "View on Arbiscan",
"view-on-base": "View on Basescan",
"view-on-eth": "View on Etherscan",
"view-on-oeth": "View on Optimism Explorer",
"view-on-opensea": "View on OpenSea",