Compare commits

..
Author SHA1 Message Date
kaichaosun 9f7074ff69 chore_: rebase status-go 2024-06-25 15:42:41 +08:00
yqrashawnandYevheniia Berdnyk ead51b7e7c feat: simplification of onboarding intro view (#20386)
* feat: simplification of onboarding intro view

Signed-off-by: yqrashawn <namy.19@gmail.com>

* feat: new onboarding illustration

* fix: add accessibility label

* fix: wrong navigation stack

Signed-off-by: yqrashawn <namy.19@gmail.com>

* e2e: updated sign in

* fix: onboarding nav stack after flow change

---------

Signed-off-by: yqrashawn <namy.19@gmail.com>
Co-authored-by: Yevheniia Berdnyk <ie.berdnyk@gmail.com>
2024-06-25 11:03:10 +08:00
Icaro Motta 9481890624 fix(profile)_: Truncate profile name in settings screen (#20483)
After migrating from v1 to v2, some user names may be too long to fit in some
devices in the "Settings > Edit Profile > Name" setting. The solution was to
truncate in the UI the name to the max valid length in v2, which is 20
characters.

Other small improvements:

- Don't use entire Clojure maps as the :key in React. This is known to be slow
  because it's expensive for Clojure to generally transform a data structure
  into its string representation.
- Don't find the last item of a list using last and an equality between two
  maps. This will force each iteration to call last, which in turn will iterate
  over the entire list of items (we can think of the Clojure lazy seq as a
  linked list). Instead, we now cache the index outside the loop and do a number
  comparison.
- Don't pass entire props to style functions when not needed because
  destructuring has a cost. I wouldn't personally worry about this 99% of the
  time, but when there's only argument like in this PR where we were passing a
  single blur? argument, it's preferable to not use a map.
2024-06-24 20:08:23 -03:00
Icaro Motta 419e84db08 chore(tests)_: Make bignumber instances test friendly (#20535)
Solves a problem encountered in unit tests, where instances of BigNumber (used
in the utils.money namespace) can't be compared with = or match?

If you try the following code you will always get false because they're
different instances in memory.

  (= (money/bignumber 0) (money/bignumber 0))

We now extend BigNumber (from lib bignumber.js) so that their instances are
comparable (e.g. necessary to sort) and understand equality.

We also extend BigNumber to work with the match? directive. For example, this is
the output of comparing a nested map containing bignumbers (colored in the
terminal):

  (match? {:a {:b {:c (money/bignumber 42)}}}
          {:a {:b {:c (money/bignumber 43)}}})

FAIL in (equivalence-test) (at cljs$test$run_block (status-mobile/target/test/cljs-runtime/cljs.test.js:366:13)
expected: (match? {:a {:b {:c (money/bignumber 42)}}} {:a {:b {:c (money/bignumber 43)}}})
  actual: {:a
 {:b {:c (mismatch (expected "42") (actual "43"))}}}
2024-06-24 15:56:55 -03:00
Icaro Motta 66785d01ec chore(perf)_: Use optimized endpoint to get communities (#20481)
Adapts the client code to use the new optimized endpoint to get communities with
images pointing to the media server. Related status-go PR
https://github.com/status-im/status-go/pull/5336.
2024-06-24 09:45:03 -03:00
Andrea Maria Piana 1cc4807336 chore_: add make targets for tail/pull geth.log 2024-06-24 11:19:23 +01:00
Parvesh Monu 141252e5a0 fix no request for permission for push notifications when you enable them in app settings (#20531) 2024-06-24 15:12:03 +05:30
Yevheniia Berdnyk 9d825ee04e e2e: update for wallet users and community links test 2024-06-21 18:25:49 +03:00
Mohamed Javid fb84f105db chore(wallet): refactor keypairs data in app-db (#20469)
This commit refactors the keypairs data in app-db to save them by indexed by key-uid which will help to fetch, update, and delete easily instead of using filter and some methods every time we need to perform those operations.

Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2024-06-21 20:47:26 +05:30
flexsurfer f509d132f3 Allow non admin to add members to group chats #20396 (#20428) 2024-06-21 15:49:20 +02:00
Parvesh Monu 5ee5d70567 Show correct drawer message for pending community request (#20485) 2024-06-21 17:20:20 +05:30
51 changed files with 753 additions and 521 deletions
+10
View File
@@ -447,6 +447,16 @@ android-devices: export TARGET := android-sdk
android-devices: ##@other Invoke adb devices
adb devices
android-pull-geth: export TARGET := android-sdk
android-pull-geth: export VERSION ?= debug
android-pull-geth:
adb pull "/storage/emulated/0/Android/data/im.status.ethereum$$( [ "$(VERSION)" = "release" ] || echo ".$(VERSION)" )/files/Download/geth.log"
android-tail-geth: export TARGET := android-sdk
android-tail-geth: export VERSION ?= debug
android-tail-geth:
adb shell 'while true; do cat; sleep 1; done < /storage/emulated/0/Android/data/im.status.ethereum$$( [ "$(VERSION)" = "release" ] || echo ".$(VERSION)" )/files/Download/geth.log'
android-logcat: export TARGET := android-sdk
android-logcat: ##@other Read status-mobile logs from Android phone using adb
adb logcat | grep -e RNBootstrap -e ReactNativeJS -e ReactNative -e StatusModule -e StatusNativeLogs -e 'F DEBUG :' -e 'Go :' -e 'GoLog :' -e 'libc :'
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 MiB

After

Width:  |  Height:  |  Size: 2.8 MiB

+2 -1
View File
@@ -131,7 +131,8 @@
:output-dir "target/test"
:optimizations :simple
:target :node-test
:dev {:devtools {:preloads [status-im.setup.schema-preload]}}
:dev {:devtools {:preloads [status-im.setup.schema-preload
status-im.setup.test-preload]}}
;; Uncomment line below to `make test-watch` a specific file
:ns-regexp #shadow/env "SHADOW_NS_REGEXP"
:main legacy.status-im.test-runner/main
@@ -6,6 +6,7 @@
[legacy.status-im.ui.components.react :as react]
[quo.core :as quo]
[react-native.platform :as platform]
[taoensso.timbre :as log]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -57,7 +58,15 @@
:accessibility-label :local-notifications-settings-button
:subtitle (i18n/label :t/local-notifications-subtitle)
:active notifications-enabled?
:on-press #(rf/dispatch [:push-notifications/switch (not notifications-enabled?)])
:on-press (fn []
(when-not notifications-enabled?
(rf/dispatch
[:request-permissions
{:permissions [:post-notifications]
:on-allowed #(log/info "push notification permissions were allowed")
:on-denied #(log/error
"user denied push notification permissions")}]))
(rf/dispatch [:push-notifications/switch (not notifications-enabled?)]))
:accessory :switch}]]))
(defn notifications-settings
@@ -20,8 +20,9 @@
{:background-color (when-not (or scroll? blur?)
(colors/theme-colors colors/white colors/neutral-95 theme))})
(def buttons-container
{:flex-direction :row
(defn buttons-container
[actions]
{:flex-direction (if (= actions :two-vertical-actions) :column :row)
:justify-content :space-around
:padding-vertical 12
:gap 12
@@ -17,9 +17,9 @@
[:catn
[:props
[:map {:closed true}
[:actions [:maybe [:enum :one-action :two-actions]]]
[:actions [:maybe [:enum :one-action :two-actions :two-vertical-actions]]]
[:description {:optional true} [:maybe [:enum :top :bottom :top-error]]]
[:description-text {:optional true} [:maybe :string]]
[:description-text {:optional true} [:maybe [:or :string :schema.common/hiccup]]]
[:description-top-text {:optional true} [:maybe :string]]
[:error-message {:optional true} [:maybe :string]]
[:role {:optional true} [:maybe [:enum :admin :member :token-master :owner]]]
@@ -72,8 +72,9 @@
:context (i18n/label (keyword "t" role))}
context-tag-props)]])
[rn/view {:style style/buttons-container}
(when (= actions :two-actions)
[rn/view {:style (style/buttons-container actions)}
(when (or (= actions :two-actions)
(= actions :two-vertical-actions))
[button/button
(merge
{:size 40
@@ -93,8 +94,10 @@
button-one-props)
button-one-label]]
(when (= description :bottom)
[text/text
{:size :paragraph-2
:style (style/description-bottom scroll? blur? theme)} description-text])]))
(if (string? description-text)
[text/text
{:size :paragraph-2
:style (style/description-bottom scroll? blur? theme)} description-text]
description-text))]))
(def view (schema/instrument #'view-internal ?schema))
@@ -7,20 +7,23 @@
[react-native.core :as rn]))
(defn settings-category
[{:keys [label data container-style] :as props}]
(let [theme (quo.theme/use-theme)
settings-item (filter identity data)]
[{:keys [label data blur? container-style]}]
(let [theme (quo.theme/use-theme)
settings-items (remove nil? data)
last-index (dec (count settings-items))]
[rn/view {:style (merge (style/container label) container-style)}
(when label
[text/text
{:weight :medium
:size :paragraph-2
:style (style/label props theme)}
:style (style/label blur? theme)}
label])
[rn/view {:style (style/settings-items props theme)}
(for [item settings-item]
^{:key item}
[:<>
[settings-item/view item]
(when-not (= item (last settings-item))
[rn/view {:style (style/settings-separator props theme)}])])]]))
[rn/view {:style (style/settings-items blur? theme)}
(map-indexed
(fn [index item]
^{:key (str label (:title item))}
[:<>
[settings-item/view item]
(when-not (= last-index index)
[rn/view {:style (style/settings-separator blur? theme)}])])
settings-items)]]))
@@ -11,7 +11,7 @@
:padding-bottom 8})
(defn settings-items
[{:keys [blur?]} theme]
[blur? theme]
{:border-radius 16
:background-color (if blur?
colors/white-opa-5
@@ -22,7 +22,7 @@
(colors/theme-colors colors/neutral-10 colors/neutral-80 theme))})
(defn label
[{:keys [blur?]} theme]
[blur? theme]
{:margin-bottom 12
:color (if blur?
colors/white-opa-40
@@ -32,7 +32,7 @@
{:margin-top 12})
(defn settings-separator
[{:keys [blur?]} theme]
[blur? theme]
{:height 1
:background-color (if blur?
colors/white-opa-5
@@ -116,7 +116,8 @@
[rn/view {:style (style/left-container (:image props))}
[text/text
{:weight :medium
:style {:color (when blur? colors/white)}} title]
:style {:color (when blur? colors/white)}}
title]
[description-component props]
[tag-component props]]]
[rn/view {:style (style/sub-container (:alignment action-props))}
+1 -1
View File
@@ -151,7 +151,7 @@
(def black-opa-0 (alpha black 0))
(def black-opa-30 (alpha black 0.3))
(def black-opa-60 (alpha black 0.6))
(def onboarding-header-black "#000716")
(def onboarding-header-black neutral-100)
(def border-avatar-light
"Simulates a blurred, transparent border for avatars in light mode"
"#475060")
+5 -1
View File
@@ -33,6 +33,9 @@
[:fn {:error/message "schema.common/exception should be of type ExceptionInfo"}
(fn [v] (instance? ExceptionInfo v))])
(def ^:private ?hiccup
vector?)
(defn register-schemas
[]
(registry/register ::theme ?theme)
@@ -40,4 +43,5 @@
(registry/register ::public-key ?public-key)
(registry/register ::image-source ?image-source)
(registry/register ::rpc-call ?rpc-call)
(registry/register ::exception ?exception))
(registry/register ::exception ?exception)
(registry/register ::hiccup ?hiccup))
+4 -15
View File
@@ -365,20 +365,10 @@
:sub-label nil
:chevron? false}))
(defn add-members-entry
[chat-id]
(defn add-manage-members-entry
[chat-id admin?]
(entry {:icon :i/add-user
:label (i18n/label :t/add-members)
:on-press #(rf/dispatch [:open-modal :group-add-manage-members chat-id])
:danger? false
:accessibility-label :add-members
:sub-label nil
:chevron? false}))
(defn manage-members-entry
[chat-id]
(entry {:icon :i/add-user
:label (i18n/label :t/manage-members)
:label (i18n/label (if admin? :t/manage-members :t/add-members))
:on-press #(rf/dispatch [:open-modal :group-add-manage-members chat-id])
:danger? false
:accessibility-label :manage-members
@@ -433,8 +423,7 @@
admin? (get admins current-pub-key)]
[(group-details-entry chat-id)
(when inside-chat?
(when admin?
(manage-members-entry chat-id)))
(add-manage-members-entry chat-id admin?))
(when (and admin? inside-chat?)
(when config/show-not-implemented-features?
(edit-group-entry)))
@@ -27,29 +27,37 @@
(rf/dispatch [:deselect-member public-key true]))))
(defn add-member-contact-item-render
[{:keys [public-key] :as item} _ _ {:keys [group]}]
(let [current-pk (rf/sub [:multiaccount/public-key])
{:keys [contacts]} group
[{:keys [public-key] :as item} _ _ {:keys [group admin? current-pk]}]
(let [{:keys [contacts]} group
member? (contains? contacts public-key)
checked? (reagent/atom member?)]
(fn []
(let [on-toggle #(group-chat-member-toggle member? (swap! checked? not) public-key)]
(if (or (= current-pk public-key) (and (not admin?) member?))
(fn []
[contact-list-item/contact-list-item
(when (not= current-pk public-key)
{:disabled? true
:accessory {:disabled? true
:type :checkbox
:checked? @checked?}}
item])
(fn []
(let [on-toggle #(group-chat-member-toggle member? (swap! checked? not) public-key)]
[contact-list-item/contact-list-item
{:on-press on-toggle
:allow-multiple-presses? true
:accessory {:type :checkbox
:checked? @checked?
:on-check on-toggle}})
item]))))
:on-check on-toggle}}
item])))))
(defn add-manage-members
[{:keys [scroll-enabled? on-scroll]}]
(let [selected-participants (rf/sub [:group-chat/selected-participants])
deselected-members (rf/sub [:group-chat/deselected-members])
chat-id (rf/sub [:get-screen-params :group-add-manage-members])
group (rf/sub [:chats/chat-by-id chat-id])
theme (quo.theme/use-theme)]
(let [theme (quo.theme/use-theme)
selected-participants (rf/sub [:group-chat/selected-participants])
deselected-members (rf/sub [:group-chat/deselected-members])
chat-id (rf/sub [:get-screen-params :group-add-manage-members])
{:keys [admins] :as group} (rf/sub [:chats/chat-by-id chat-id])
current-pk (rf/sub [:multiaccount/public-key])
admin? (get admins current-pk)]
[rn/view {:flex 1 :margin-top 20}
[rn/touchable-opacity
{:on-press #(rf/dispatch [:navigate-back])
@@ -60,7 +68,7 @@
{:size :heading-1
:weight :semi-bold
:style {:margin-left 20}}
(i18n/label :t/manage-members)]
(i18n/label (if admin? :t/manage-members :t/add-members))]
[gesture/section-list
{:key-fn :title
:scroll-enabled @scroll-enabled?
@@ -70,7 +78,9 @@
:render-section-header-fn contact-list/contacts-section-header
:render-section-footer-fn contact-list/contacts-section-footer
:content-container-style {:padding-bottom 20}
:render-data {:group group}
:render-data {:group group
:admin? admin?
:current-pk current-pk}
:render-fn add-member-contact-item-render}]
[rn/view {:style (style/bottom-container 30 theme)}
[quo/button
@@ -159,17 +169,16 @@
:on-press #(rf/dispatch [:chat.ui/mute chat-id (not muted)
(when-not muted
constants/mute-till-unmuted)])}
(when admin?
{:accessibility-label :manage-members
:customization-color color
:icon :i/add-user
:label (i18n/label :t/manage-members)
:counter-value (count contacts)
:on-press (fn []
(rf/dispatch [:group/clear-added-participants])
(rf/dispatch [:group/clear-removed-members])
(rf/dispatch [:open-modal :group-add-manage-members
chat-id]))})]}]
{:accessibility-label :manage-members
:customization-color color
:icon :i/add-user
:label (i18n/label (if admin? :t/manage-members :t/add-members))
:counter-value (count contacts)
:on-press (fn []
(rf/dispatch [:group/clear-added-participants])
(rf/dispatch [:group/clear-removed-members])
(rf/dispatch [:open-modal :group-add-manage-members
chat-id]))}]}]
[rn/section-list
{:key-fn :title
:sticky-section-headers-enabled false
@@ -16,8 +16,13 @@
contact-id])
{:keys [contact-request-state community-id]} (rf/sub [:chats/current-chat-chat-view])
chat-type (rf/sub [:chats/chat-type])
joined (rf/sub [:communities/community-joined
community-id])
community-chat? (= chat-type :community-chat)
joined (when community-chat?
(rf/sub [:communities/community-joined
community-id]))
pending? (when community-chat?
(rf/sub [:communities/my-pending-request-to-join
community-id]))
contact-request-send? (or (not contact-request-state)
(= contact-request-state
constants/contact-request-state-none))
@@ -28,19 +33,28 @@
[rn/view {:style style/container}
[quo/permission-context
{:blur? true
:on-press (condp = chat-type
:community-chat #(rf/dispatch [:open-modal :community-account-selection-sheet
{:community-id community-id}])
:on-press (cond
(and community-chat? (not pending?) (not joined))
#(rf/dispatch [:open-modal :community-account-selection-sheet
{:community-id community-id}])
(not community-chat?)
#(rf/dispatch [:chat.ui/show-profile contact-id]))
:type :action
:action-icon (cond
(= chat-type :community-chat) :i/communities
contact-request-pending? :i/pending-state
:else :i/add-user)
community-chat? :i/communities
contact-request-pending? :i/pending-state
:else :i/add-user)
:action-label (cond
(= chat-type :community-chat)
(if joined
community-chat?
(cond
pending?
(i18n/label :t/request-to-join-community-pending)
joined
(i18n/label :t/no-permissions-to-post)
:else
(i18n/label :t/join-community-to-post))
(= chat-type :group-chat)
@@ -137,7 +137,7 @@
(rf/reg-event-fx :community/fetch
(fn [_]
{:json-rpc/call [{:method "wakuext_communities"
{:json-rpc/call [{:method "wakuext_serializedCommunities"
:params []
:on-success #(rf/dispatch [:community/fetch-success %])
:on-error #(log/error "failed to fetch communities" %)}
@@ -4,7 +4,7 @@
[react-native.platform :as platform]))
(def background-container
{:background-color colors/neutral-95
{:background-color colors/neutral-100
:flex-direction :row
:position :absolute
:overflow :hidden
@@ -29,8 +29,8 @@
[rn/image
{:resize-mode :stretch
:resize-method :scale
:style {:margin-top 32
:width content-width}
:style {:top 138
:width content-width}
:source (resources/get-image :onboarding-illustration)}])
(defonce progress (atom nil))
@@ -1,4 +1,4 @@
(ns status-im.contexts.onboarding.new-to-status.style
(ns status-im.contexts.onboarding.create-or-sync-profile.style
(:require
[quo.foundations.colors :as colors]))
@@ -24,15 +24,4 @@
(def subtitle-container
{:margin-top 24})
(def doc-main-content
{:color colors/white
:margin-bottom 4})
(def doc-subtitle
{:margin-top 20
:margin-bottom 4})
(def doc-content
{:color colors/white-opa-70})
(def space-between-suboptions {:height 12})
@@ -0,0 +1,141 @@
(ns status-im.contexts.onboarding.create-or-sync-profile.view
(:require
[quo.core :as quo]
re-frame.db
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[status-im.common.not-implemented :as not-implemented]
[status-im.common.resources :as resources]
[status-im.config :as config]
[status-im.contexts.onboarding.create-or-sync-profile.style :as style]
[status-im.contexts.onboarding.getting-started-doc.view :as getting-started-doc]
[utils.debounce :as debounce]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- navigate-to-create-profile
[]
(debounce/throttle-and-dispatch
[:onboarding/navigate-to-create-profile]
1000))
(defn- navigate-to-sign-in-by-syncing
[]
(debounce/throttle-and-dispatch
[:onboarding/navigate-to-sign-in-by-syncing]
1000))
(defn- navigate-to-sign-in-by-seed-phrase
[create-profile?]
(rf/dispatch [:onboarding/navigate-to-sign-in-by-seed-phrase
(if create-profile?
:screen/onboarding.new-to-status
:screen/onboarding.sync-or-recover-profile)]))
(defn- option-card-max-height
[window-height]
(- window-height
(* 2 56) ;; two other list items
(* 2 16) ;; spacing between items
220) ;; extra spacing (top bar)
)
(defn- create-profile-option-card
[window-height]
[quo/small-option-card
{:variant :main
:title (i18n/label :t/generate-keys)
:subtitle (i18n/label :t/generate-keys-subtitle)
:button-label (i18n/label :t/lets-go)
:accessibility-label :generate-key-option-card
:image (resources/get-image :generate-keys)
:max-height (option-card-max-height window-height)
:on-press navigate-to-create-profile}])
(defn- sync-profile-option-card
[window-height]
[quo/small-option-card
{:variant :main
:title (i18n/label :t/sign-in-by-syncing)
:subtitle (i18n/label :t/if-you-have-status-on-another-device)
:button-label (i18n/label :t/scan-sync-code)
:accessibility-label :scan-sync-code-option-card
:image (resources/get-image :generate-keys)
:max-height (option-card-max-height window-height)
:on-press navigate-to-sign-in-by-syncing}])
(defn sign-in-options
[sign-in-type]
(let [window-height (rf/sub [:dimensions/window-height])
create-profile? (= sign-in-type :create-profile)
nav-to-seed-phrase-with-cur-screen (rn/use-callback
#(navigate-to-sign-in-by-seed-phrase
create-profile?)
[create-profile?])
main-option-card (if create-profile?
create-profile-option-card
sync-profile-option-card)]
[rn/view {:style style/options-container}
[quo/text
{:style style/title
:size :heading-1
:weight :semi-bold}
(i18n/label (if create-profile? :t/create-profile :t/sync-or-recover-profile))]
[main-option-card window-height]
[rn/view {:style style/subtitle-container}
[quo/text
{:style style/subtitle
:size :paragraph-2
:weight :medium}
(i18n/label (if create-profile? :t/experienced-web3 :t/dont-have-statatus-on-another-device))]]
[rn/view
[quo/small-option-card
{:variant :icon
:title (i18n/label :t/use-recovery-phrase)
:subtitle (i18n/label :t/use-recovery-phrase-subtitle)
:accessibility-label :use-recovery-phrase-option-card
:image (resources/get-image :ethereum-address)
:on-press nav-to-seed-phrase-with-cur-screen}]
[rn/view {:style style/space-between-suboptions}]
(when config/show-not-implemented-features?
[quo/small-option-card
{:variant :icon
:title (i18n/label :t/use-keycard)
:subtitle (i18n/label :t/use-keycard-subtitle)
:accessibility-label :use-keycard-option-card
:image (resources/get-image :use-keycard)
:on-press status-im.common.not-implemented/alert}])]]))
(defn- navigate-back
[]
(rf/dispatch [:onboarding/overlay-dismiss])
(rf/dispatch [:navigate-back]))
(defn- navigate-to-quo-preview
[]
(rf/dispatch [:navigate-to :quo-preview]))
(defn- internal-view
[sign-in-type]
(let [{:keys [top]} (safe-area/get-insets)]
[rn/view {:style style/content-container}
[quo/page-nav
{:margin-top top
:type :no-title
:background :blur
:icon-name :i/arrow-left
:on-press navigate-back
:right-side [{:icon-name :i/info
:on-press getting-started-doc/show-as-bottom-sheet}
(when config/quo-preview-enabled?
{:icon-name :i/reveal-whitelist
:on-press navigate-to-quo-preview})]}]
[sign-in-options sign-in-type]]))
(defn create-profile
[]
[internal-view :create-profile])
(defn sync-or-recover-profile
[]
[internal-view :sync-or-recover-profile])
@@ -2,7 +2,6 @@
(: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.resources :as resources]
[status-im.contexts.onboarding.enable-notifications.style :as style]
@@ -36,7 +35,7 @@
{:permissions [:post-notifications]
:on-allowed #(log/info "push notification permissions were allowed")
:on-denied #(log/error "user denied push notification permissions")}])
(rf/dispatch [:push-notifications/switch true platform/ios?])
(rf/dispatch [:push-notifications/switch true])
(rf/dispatch [:navigate-to-within-stack
[:screen/onboarding.welcome
:screen/onboarding.enable-notifications]]))
+47 -13
View File
@@ -15,7 +15,10 @@
[{:keys [db]} onboarding-data]
{:db (update db :onboarding/profile merge onboarding-data)
:dispatch [:navigate-to-within-stack
[:screen/onboarding.create-profile-password :screen/onboarding.new-to-status]]})
[:screen/onboarding.create-profile-password
(get db
:onboarding/navigated-to-enter-seed-phrase-from-screen
:screen/onboarding.new-to-status)]]})
(rf/defn enable-biometrics
{:events [:onboarding/enable-biometrics]}
@@ -25,13 +28,24 @@
{:on-success #(rf/dispatch [:onboarding/biometrics-done])
:on-fail #(rf/dispatch [:onboarding/biometrics-fail %])}]]]})
(rf/defn navigate-to-enable-notifications
{:events [:onboarding/navigate-to-enable-notifications]}
[{:keys [db]}]
(let [key-uid (get-in db [:profile/profile :key-uid])]
{:db (dissoc db :onboarding/profile)
:dispatch [:navigate-to-within-stack
[:screen/onboarding.enable-notifications :screen/onboarding.enable-biometrics]]}))
(rf/reg-event-fx :onboarding/navigate-to-sign-in-by-seed-phrase
(fn [{:keys [db]} [from-screen]]
{:db (assoc db :onboarding/navigated-to-enter-seed-phrase-from-screen from-screen)
:fx [[:dispatch [:navigate-to-within-stack [:screen/onboarding.enter-seed-phrase from-screen]]]]}))
(rf/reg-event-fx :onboarding/navigate-to-enable-notifications-from-syncing
(fn [{:keys [db]}]
{:db (dissoc db :onboarding/profile)
:dispatch [:navigate-to-within-stack
[:screen/onboarding.enable-notifications :screen/onboarding.enable-biometrics]]}))
(rf/reg-event-fx :onboarding/navigate-to-enable-notifications
(fn [{:keys [db]}]
{:dispatch [:navigate-to-within-stack
[:screen/onboarding.enable-notifications
(get db
:onboarding/navigated-to-enter-seed-phrase-from-screen
:screen/onboarding.new-to-status)]]}))
(rf/defn biometrics-done
{:events [:onboarding/biometrics-done]}
@@ -54,7 +68,10 @@
(:onboarding/profile db)]
(rf/merge cofx
{:dispatch [:navigate-to-within-stack
[:screen/onboarding.generating-keys :screen/onboarding.new-to-status]]
[:screen/onboarding.generating-keys
(get db
:onboarding/navigated-to-enter-seed-phrase-from-screen
:screen/onboarding.new-to-status)]]
:dispatch-later [{:ms constants/onboarding-generating-keys-animation-duration-ms
:dispatch [:onboarding/navigate-to-identifiers]}]
:db (-> db
@@ -83,7 +100,10 @@
(assoc-in [:onboarding/profile :auth-method] constants/auth-method-password))
:dispatch (if supported-type
[:navigate-to-within-stack
[:screen/onboarding.enable-biometrics :screen/onboarding.new-to-status]]
[:screen/onboarding.enable-biometrics
(get db
:onboarding/navigated-to-enter-seed-phrase-from-screen
:screen/onboarding.new-to-status)]]
[:onboarding/create-account-and-login])}))
(rf/defn navigate-to-enable-biometrics
@@ -118,7 +138,10 @@
:on-cancel #(re-frame/dispatch [:pop-to-root :multiaccounts])}}
{:db (assoc-in db [:onboarding/profile :seed-phrase] seed-phrase)
:dispatch [:navigate-to-within-stack
[:screen/onboarding.create-profile :screen/onboarding.new-to-status]]}))
[:screen/onboarding.create-profile
(get db
:onboarding/navigated-to-enter-seed-phrase-from-screen
:screen/onboarding.new-to-status)]]}))
(rf/defn navigate-to-create-profile
{:events [:onboarding/navigate-to-create-profile]}
@@ -128,6 +151,13 @@
:dispatch [:navigate-to-within-stack
[:screen/onboarding.create-profile :screen/onboarding.new-to-status]]})
(rf/reg-event-fx :onboarding/navigate-to-sign-in-by-syncing
(fn [{:keys [db]}]
;; Restart the flow
{:db (dissoc db :onboarding/profile)
:dispatch [:navigate-to-within-stack
[:screen/onboarding.sign-in-intro :screen/onboarding.sync-or-recover-profile]]}))
(rf/reg-event-fx :onboarding/set-auth-method
(fn [{:keys [db]} [auth-method]]
{:db (assoc db :auth-method auth-method)}))
@@ -151,7 +181,8 @@
:on-success (fn []
(rf/dispatch [:onboarding/set-auth-method auth-method])
(when syncing?
(rf/dispatch [:onboarding/navigate-to-enable-notifications])))
(rf/dispatch
[:onboarding/navigate-to-enable-notifications-from-syncing])))
:on-error #(log/error "failed to save biometrics"
{:key-uid key-uid
:error %})}))))
@@ -161,6 +192,9 @@
[{:keys [db]}]
(if (:onboarding/generated-keys? db)
{:dispatch [:navigate-to-within-stack
[:screen/onboarding.identifiers :screen/onboarding.new-to-status]]}
[:screen/onboarding.identifiers
(get db
:onboarding/navigated-to-enter-seed-phrase-from-screen
:screen/onboarding.new-to-status)]]}
{:dispatch-later [{:ms constants/onboarding-generating-keys-navigation-retry-ms
:dispatch [:onboarding/navigate-to-identifiers]}]}))
@@ -0,0 +1,14 @@
(ns status-im.contexts.onboarding.getting-started-doc.style
(:require
[quo.foundations.colors :as colors]))
(def main-content
{:color colors/white
:margin-bottom 4})
(def subtitle
{:margin-top 20
:margin-bottom 4})
(def content
{:color colors/white-opa-70})
@@ -0,0 +1,50 @@
(ns status-im.contexts.onboarding.getting-started-doc.view
(:require
[quo.core :as quo]
[status-im.contexts.onboarding.getting-started-doc.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn getting-started-doc
[]
[quo/documentation-drawers
{:title (i18n/label :t/getting-started-with-status)
:shell? true}
[:<>
[quo/text
{:size :paragraph-2
:style style/main-content}
(i18n/label :t/getting-started-description)]
[quo/text
{:size :paragraph-1
:style style/subtitle
:weight :semi-bold}
(i18n/label :t/generate-keys)]
[quo/text
{:size :paragraph-2
:style style/content}
(i18n/label :t/getting-started-generate-keys-description)]
[quo/text
{:size :paragraph-1
:style style/subtitle
:weight :semi-bold}
(i18n/label :t/getting-started-generate-keys-from-recovery-phrase)]
[quo/text
{:size :paragraph-2
:style style/content}
(i18n/label :t/getting-started-generate-keys-from-recovery-phrase-description)]
[quo/text
{:size :paragraph-1
:style style/subtitle
:weight :semi-bold}
(i18n/label :t/getting-started-generate-keys-on-keycard)]
[quo/text
{:size :paragraph-2
:style style/content}
(i18n/label :t/getting-started-generate-keys-on-keycard-description)]]])
(defn show-as-bottom-sheet
[]
(rf/dispatch [:show-bottom-sheet
{:content getting-started-doc
:shell? true}]))
@@ -20,6 +20,10 @@
{:text (i18n/label :t/emojihash)
:sub-text (i18n/label :t/emojihash-description)}])
(defn- navigate-to-enable-notifications
[]
(rf/dispatch [:onboarding/navigate-to-enable-notifications]))
(defn f-view
[]
(let [progress (atom nil)
@@ -62,9 +66,7 @@
{:accessibility-label :skip-identifiers
:type :grey
:background :blur
:on-press #(rf/dispatch [:navigate-to-within-stack
[:screen/onboarding.enable-notifications
:screen/onboarding.new-to-status]])
:on-press navigate-to-enable-notifications
:container-style style/button}
(i18n/label :t/continue)]]]]))
@@ -7,9 +7,10 @@
:justify-content :flex-end})
(def text-container
{:flex 1
:max-width 180
:flex-wrap :wrap})
{:flex 1
:text-align :center
:margin-top 16
:flex-wrap :wrap})
(def plain-text
{:color colors/white-opa-70})
@@ -17,3 +18,10 @@
(def highlighted-text
{:flex 1
:color colors/white})
(def bottom-actions-container
{:position :absolute
:background-color colors/onboarding-header-black
:left 0
:right 0
:padding-bottom 40})
@@ -2,12 +2,10 @@
(:require
[quo.core :as quo]
[react-native.core :as rn]
[status-im.constants :as constants]
[status-im.contexts.onboarding.common.background.view :as background]
[status-im.contexts.onboarding.common.overlay.view :as overlay]
[status-im.contexts.onboarding.intro.style :as style]
[status-im.contexts.onboarding.terms.view :as terms]
[status-im.contexts.syncing.scan-sync-code.view :as scan-sync-code]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -15,40 +13,37 @@
[]
[rn/view {:style style/page-container}
[background/view false]
[quo/drawer-buttons
{:on-init (fn [reset-top-animation-fn]
(reset! scan-sync-code/dismiss-animations reset-top-animation-fn))
:animations-duration constants/onboarding-modal-animation-duration
:animations-delay constants/onboarding-modal-animation-delay
:top-card {:on-press #(rf/dispatch [:open-modal
:screen/onboarding.sign-in-intro])
:heading (i18n/label :t/sign-in)
:animated-heading (i18n/label :t/sign-in-by-syncing)
:accessibility-label :already-use-status-button}
:bottom-card {:on-press (fn []
(when-let [blur-show-fn @overlay/blur-show-fn-atom]
(blur-show-fn))
(rf/dispatch
[:open-modal :screen/onboarding.new-to-status]))
:heading (i18n/label :t/new-to-status)
:accessibility-label :new-to-status-button}}
[quo/text
{:size :paragraph-2
:weight :regular
:style style/plain-text}
(i18n/label :t/you-already-use-status)]
[quo/text {:style style/text-container}
[quo/text
{:size :paragraph-2
:weight :regular
:style style/plain-text}
(i18n/label :t/by-continuing-you-accept)]
[quo/text
{:on-press #(rf/dispatch [:show-bottom-sheet
{:content (fn [] [terms/terms-of-use])
:shell? true}])
:size :paragraph-2
:weight :regular
:style style/highlighted-text}
(i18n/label :t/terms-of-service)]]]
[quo/bottom-actions
{:container-style style/bottom-actions-container
:actions :two-vertical-actions
:description :bottom
:description-text [quo/text
{:style style/text-container
:size :paragraph-2
:weight :regular}
[quo/text {:style style/plain-text}
(i18n/label :t/by-continuing-you-accept)]
[quo/text
{:on-press #(rf/dispatch [:show-bottom-sheet
{:content (fn [] [terms/terms-of-use])
:shell? true}])
:style style/highlighted-text}
(i18n/label :t/terms-of-service)]]
:button-one-label (i18n/label :t/sync-or-recover-profile)
:button-one-props {:type :dark-grey
:accessibility-label :already-use-status-button
:on-press (fn []
(when-let [blur-show-fn @overlay/blur-show-fn-atom]
(blur-show-fn))
(rf/dispatch
[:open-modal
:screen/onboarding.sync-or-recover-profile]))}
:button-two-label (i18n/label :t/create-profile)
:button-two-props {:accessibility-label :new-to-status-button
:on-press
(fn []
(when-let [blur-show-fn @overlay/blur-show-fn-atom]
(blur-show-fn))
(rf/dispatch
[:open-modal :screen/onboarding.new-to-status]))}}]
[overlay/view]])
@@ -1,117 +0,0 @@
(ns status-im.contexts.onboarding.new-to-status.view
(:require
[quo.core :as quo]
re-frame.db
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[status-im.common.resources :as resources]
[status-im.config :as config]
[status-im.contexts.onboarding.new-to-status.style :as style]
[utils.debounce :as debounce]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn sign-in-options
[]
(let [window (rf/sub [:dimensions/window])]
[rn/view {:style style/options-container}
[quo/text
{:style style/title
:size :heading-1
:weight :semi-bold}
(i18n/label :t/new-to-status)]
[quo/small-option-card
{:variant :main
:title (i18n/label :t/generate-keys)
:subtitle (i18n/label :t/generate-keys-subtitle)
:button-label (i18n/label :t/lets-go)
:image (resources/get-image :generate-keys)
:max-height (- (:height window)
(* 2 56) ;; two other list items
(* 2 16) ;; spacing between items
220) ;; extra spacing (top bar)
:on-press #(debounce/throttle-and-dispatch
[:onboarding/navigate-to-create-profile]
1000)}]
[rn/view {:style style/subtitle-container}
[quo/text
{:style style/subtitle
:size :paragraph-2
:weight :medium}
(i18n/label :t/experienced-web3)]]
[rn/view
[quo/small-option-card
{:variant :icon
:title (i18n/label :t/use-recovery-phrase)
:subtitle (i18n/label :t/use-recovery-phrase-subtitle)
:image (resources/get-image :ethereum-address)
:on-press #(rf/dispatch [:navigate-to-within-stack
[:screen/onboarding.enter-seed-phrase
:screen/onboarding.new-to-status]])}]
[rn/view {:style style/space-between-suboptions}]
(when config/show-not-implemented-features?
[quo/small-option-card
{:variant :icon
:title (i18n/label :t/use-keycard)
:subtitle (i18n/label :t/use-keycard-subtitle)
:image (resources/get-image :use-keycard)
:on-press #(js/alert "TODO: to be implemented")}])]]))
(defn getting-started-doc
[]
[quo/documentation-drawers
{:title (i18n/label :t/getting-started-with-status)
:shell? true}
[:<>
[quo/text
{:size :paragraph-2
:style style/doc-main-content}
(i18n/label :t/getting-started-description)]
[quo/text
{:size :paragraph-1
:style style/doc-subtitle
:weight :semi-bold}
(i18n/label :t/generate-keys)]
[quo/text
{:size :paragraph-2
:style style/doc-content}
(i18n/label :t/getting-started-generate-keys-description)]
[quo/text
{:size :paragraph-1
:style style/doc-subtitle
:weight :semi-bold}
(i18n/label :t/getting-started-generate-keys-from-recovery-phrase)]
[quo/text
{:size :paragraph-2
:style style/doc-content}
(i18n/label :t/getting-started-generate-keys-from-recovery-phrase-description)]
[quo/text
{:size :paragraph-1
:style style/doc-subtitle
:weight :semi-bold}
(i18n/label :t/getting-started-generate-keys-on-keycard)]
[quo/text
{:size :paragraph-2
:style style/doc-content}
(i18n/label :t/getting-started-generate-keys-on-keycard-description)]]])
(defn new-to-status
[]
(let [{:keys [top]} (safe-area/get-insets)]
[rn/view {:style style/content-container}
[quo/page-nav
{:margin-top top
:type :no-title
:background :blur
:icon-name :i/arrow-left
:on-press #(do
(rf/dispatch [:onboarding/overlay-dismiss])
(rf/dispatch [:navigate-back]))
:right-side [{:icon-name :i/info
:on-press #(rf/dispatch [:show-bottom-sheet
{:content getting-started-doc
:shell? true}])}
(when config/quo-preview-enabled?
{:icon-name :i/reveal-whitelist
:on-press #(rf/dispatch [:navigate-to :quo-preview])})]}]
[sign-in-options]]))
@@ -3,6 +3,7 @@
[quo.foundations.colors :as colors]
[status-im.common.not-implemented :as not-implemented]
[status-im.config :as config]
[status-im.constants :as constants]
[status-im.contexts.profile.edit.style :as style]
[status-im.contexts.profile.utils :as profile.utils]
[utils.i18n :as i18n]
@@ -19,7 +20,7 @@
:on-press #(rf/dispatch [:open-modal :edit-name])
:blur? true
:label :text
:label-props full-name
:label-props (utils/truncate-str full-name constants/profile-name-max-length)
:action :arrow
:container-style style/item-container}
{:title (i18n/label :t/bio)
@@ -1,24 +1,5 @@
(ns status-im.contexts.settings.wallet.data-store)
(defn extract-keypair-name
[db key-uids-set]
(when (= (count key-uids-set) 1)
(let [key-uid (first key-uids-set)
keypairs (get-in db [:wallet :keypairs])]
(->> (filter #(= (:key-uid %) key-uid) keypairs)
first
:name))))
(defn update-keypair
[keypairs key-uid update-fn]
(mapcat (fn [keypair]
(if (= (keypair :key-uid) key-uid)
(if-let [updated (update-fn keypair)]
[updated]
[])
[keypair]))
keypairs))
(defn make-accounts-fully-operable
"Updates accounts to be fully operable based on specified key-uids and an optional operable condition.
@@ -32,10 +13,10 @@
- A new map with accounts updated to be fully operable where the conditions are met."
[{:keys [accounts key-uids-set operable-condition]}]
(reduce-kv
(fn [acc k account]
(if (and (contains? key-uids-set (:key-uid account))
(fn [acc k {:keys [key-uid] :as account}]
(if (and (contains? key-uids-set key-uid)
(or (nil? operable-condition)
(= (keyword (:operable account)) operable-condition)))
(= (:operable account) operable-condition)))
(assoc acc k (assoc account :operable :fully))
(assoc acc k account)))
{}
@@ -44,7 +25,7 @@
(defn- make-keypairs-accounts-fully-operable
[accounts operable-condition]
(map (fn [account]
(if (or (nil? operable-condition) (= (keyword (:operable account)) operable-condition))
(if (or (nil? operable-condition) (= (:operable account) operable-condition))
(assoc account :operable :fully)
account))
accounts))
@@ -53,27 +34,30 @@
"Updates keypairs' accounts to be fully operable based on specified key-uids and an optional operable condition.
Parameters:
- :keypairs (seq): A sequence of keypair maps.
- :keypairs (map): A map of keypair key-uid to keypair details.
- :key-uids-set (set): A set of key-uids that need to be checked and updated.
- :operable-condition (keyword, optional): The condition that the keypair's accounts' operability must meet to be updated.
If nil or not provided, the function will update all keypairs' accounts.
Returns:
- A new sequence with keypairs updated to be fully operable where the conditions are met."
- A new map with keypairs updated to be fully operable where the conditions are met."
[{:keys [keypairs key-uids-set operable-condition]}]
(map (fn [keypair]
(if (contains? key-uids-set (:key-uid keypair))
(-> keypair
(update :accounts #(make-keypairs-accounts-fully-operable % operable-condition))
(assoc :lowest-operability :fully))
keypair))
keypairs))
(reduce-kv (fn [acc k keypair]
(if (contains? key-uids-set k)
(assoc acc
k
(-> keypair
(update :accounts make-keypairs-accounts-fully-operable operable-condition)
(assoc :lowest-operability :fully)))
(assoc acc k keypair)))
{}
keypairs))
(defn map-addresses-to-key-uids
(defn get-keypair-key-uids-set-from-addresses
[db addresses]
(reduce (fn [key-uid-set address]
(if-let [account (get-in db [:wallet :accounts address])]
(conj key-uid-set (:key-uid account))
(if-let [account-key-uid (get-in db [:wallet :accounts address :key-uid])]
(conj key-uid-set account-key-uid)
key-uid-set))
#{}
addresses))
@@ -10,9 +10,7 @@
(rf/reg-event-fx
:wallet/rename-keypair-success
(fn [{:keys [db]} [key-uid name]]
{:db (update-in db
[:wallet :keypairs]
#(data-store/update-keypair % key-uid (fn [keypair] (assoc keypair :name name))))
{:db (update-in db [:wallet :keypairs key-uid] assoc :name name)
:fx [[:dispatch [:navigate-back]]
[:dispatch
[:toasts/upsert
@@ -49,9 +47,7 @@
(rf/reg-event-fx :wallet/remove-keypair-success
(fn [{:keys [db]} [key-uid]]
{:db (update-in db
[:wallet :keypairs]
#(data-store/update-keypair % key-uid (fn [_] nil)))
{:db (update-in db [:wallet :keypairs] dissoc key-uid)
:fx [[:dispatch [:hide-bottom-sheet]]
[:dispatch
[:toasts/upsert
@@ -71,8 +67,11 @@
(defn make-keypairs-accounts-fully-operable
[{:keys [db]} [key-uids-to-update]]
(let [key-uids-set (set key-uids-to-update)
keypair-name (data-store/extract-keypair-name db key-uids-set)]
(let [key-uids-set (set key-uids-to-update)
single-keypair-to-update? (= (count key-uids-to-update) 1)
keypair-name (when single-keypair-to-update?
(let [key-uid (first key-uids-set)]
(get-in db [:wallet :keypairs key-uid :name])))]
{:db (->
db
(update-in [:wallet :accounts]
@@ -85,7 +84,7 @@
[:toasts/upsert
{:type :positive
:theme :dark
:text (if (= (count key-uids-to-update) 1)
:text (if single-keypair-to-update?
(i18n/label :t/key-pair-imported-successfully {:name keypair-name})
(i18n/label :t/key-pairs-successfully-imported
{:count (count key-uids-to-update)}))}]]]}))
@@ -231,7 +230,7 @@
(defn make-partially-operable-accounts-fully-operable-success
[{:keys [db]} [addresses]]
(let [key-uids-to-update (data-store/map-addresses-to-key-uids db addresses)]
(let [key-uids-to-update (data-store/get-keypair-key-uids-set-from-addresses db addresses)]
{:db (-> db
(update-in [:wallet :accounts]
#(data-store/make-accounts-fully-operable {:accounts %
@@ -1,104 +1,100 @@
(ns status-im.contexts.settings.wallet.events-test
(:require
[cljs.test :refer-macros [deftest is testing]]
[cljs.test :refer-macros [deftest is]]
matcher-combinators.test
[native-module.core :as native-module]
[status-im.contexts.settings.wallet.events :as sut]
[utils.security.core :as security]))
(def mock-key-uid "key-1")
(defn mock-db
[keypairs accounts]
{:wallet {:keypairs keypairs
:accounts accounts}
:profile/profile {:key-uid "test-key-uid"}})
(def test-profile {:key-uid "test-key-uid"})
(def test-keypair-key-uid "key-1")
(deftest rename-keypair-test
(let [new-keypair-name "key pair new"
cofx {:db {}}]
(testing "rename-keypair"
(let [expected {:fx [[:json-rpc/call
[{:method "accounts_updateKeypairName"
:params [mock-key-uid new-keypair-name]
:on-success [:wallet/rename-keypair-success mock-key-uid
new-keypair-name]
:on-error fn?}]]]}]
(is (match? expected
(sut/rename-keypair cofx
[{:key-uid mock-key-uid
:keypair-name new-keypair-name}])))))))
cofx {:db {}}
expected {:fx [[:json-rpc/call
[{:method "accounts_updateKeypairName"
:params [test-keypair-key-uid new-keypair-name]
:on-success [:wallet/rename-keypair-success test-keypair-key-uid
new-keypair-name]
:on-error fn?}]]]}]
(is (match? expected
(sut/rename-keypair cofx
[{:key-uid test-keypair-key-uid
:keypair-name new-keypair-name}])))))
(deftest get-keypair-export-connection-test
(let [cofx {:db (mock-db [] {})}
(let [cofx {:db {:profile/profile test-profile}}
sha3-pwd "test-password"
user-key-uid "test-key-uid"
callback (fn [connect-string] (println "callback" connect-string))]
(testing "get-keypair-export-connection"
(let [expected {:fx [[:effects.syncing/export-keypairs-keystores
callback (fn [connect-string] (println "callback" connect-string))
expected {:fx [[:effects.syncing/export-keypairs-keystores
{:key-uid user-key-uid
:sha3-pwd sha3-pwd
:keypair-key-uid mock-key-uid
:keypair-key-uid test-keypair-key-uid
:on-success fn?
:on-fail fn?}]]}]
(is (match? expected
(sut/get-keypair-export-connection
cofx
[{:sha3-pwd sha3-pwd :keypair-key-uid mock-key-uid :callback callback}])))))))
(is (match?
expected
(sut/get-keypair-export-connection
cofx
[{:sha3-pwd sha3-pwd :keypair-key-uid test-keypair-key-uid :callback callback}])))))
(deftest remove-keypair-test
(let [cofx {:db {}}]
(testing "remove-keypair"
(let [expected {:fx [[:json-rpc/call
[{:method "accounts_deleteKeypair"
:params [mock-key-uid]
:on-success [:wallet/remove-keypair-success mock-key-uid]
:on-error fn?}]]]}]
(is (match? expected
(sut/remove-keypair cofx [mock-key-uid])))))))
(let [cofx {:db {}}
expected {:fx [[:json-rpc/call
[{:method "accounts_deleteKeypair"
:params [test-keypair-key-uid]
:on-success [:wallet/remove-keypair-success test-keypair-key-uid]
:on-error fn?}]]]}]
(is (match? expected
(sut/remove-keypair cofx [test-keypair-key-uid])))))
(deftest make-keypairs-accounts-fully-operable-test
(let [db (mock-db [{:key-uid mock-key-uid
:lowest-operability :no
:accounts [{:key-uid mock-key-uid :operable "no"}]}]
{"0x1" {:key-uid mock-key-uid :operable "no"}})
key-uids-to-update [mock-key-uid]]
(testing "make-keypairs-accounts-fully-operable"
(let [effects (sut/make-keypairs-accounts-fully-operable {:db db} [key-uids-to-update])
result-db (:db effects)
updated-keypair (some #(when (= (:key-uid %) mock-key-uid) %)
(get-in result-db [:wallet :keypairs]))
updated-account (get-in result-db [:wallet :accounts "0x1"])]
(is (= (keyword (-> updated-keypair :accounts first :operable)) :fully))
(is (= (keyword (:operable updated-account)) :fully))
(is (= (:lowest-operability updated-keypair) :fully))))))
(let [db {:wallet {:keypairs {test-keypair-key-uid {:key-uid
test-keypair-key-uid
:lowest-operability :no
:accounts
[{:key-uid
test-keypair-key-uid
:operable :no}]}}
:accounts {"0x1" {:key-uid test-keypair-key-uid
:operable :no}}}
:profile/profile test-profile}
key-uids-to-update [test-keypair-key-uid]
effects (sut/make-keypairs-accounts-fully-operable {:db db} [key-uids-to-update])
result-db (:db effects)
updated-keypair (get-in result-db [:wallet :keypairs test-keypair-key-uid])
updated-account (get-in result-db [:wallet :accounts "0x1"])]
(is (= (-> updated-keypair :accounts first :operable) :fully))
(is (= (:operable updated-account) :fully))
(is (= (:lowest-operability updated-keypair) :fully))))
(deftest connection-string-for-import-keypair-test
(let [cofx {:db (mock-db [] {})}
(let [cofx {:db {:profile/profile test-profile}}
sha3-pwd "test-password"
user-key-uid "test-key-uid"
connection-string "test-connection-string"]
(testing "connection-string-for-import-keypair"
(let [expected {:fx [[:effects.syncing/import-keypairs-keystores
{:key-uid user-key-uid
:sha3-pwd sha3-pwd
:keypairs-key-uids [mock-key-uid]
:connection-string connection-string
:on-success fn?
:on-fail fn?}]]}]
(is (match? expected
(sut/connection-string-for-import-keypair cofx
[{:sha3-pwd sha3-pwd
:keypairs-key-uids [mock-key-uid]
:connection-string
connection-string}])))))))
connection-string "test-connection-string"
expected {:fx [[:effects.syncing/import-keypairs-keystores
{:key-uid user-key-uid
:sha3-pwd sha3-pwd
:keypairs-key-uids [test-keypair-key-uid]
:connection-string connection-string
:on-success fn?
:on-fail fn?}]]}]
(is (match? expected
(sut/connection-string-for-import-keypair cofx
[{:sha3-pwd sha3-pwd
:keypairs-key-uids [test-keypair-key-uid]
:connection-string
connection-string}])))))
(deftest success-keypair-qr-scan-test
(let [connection-string "valid-connection-string"
keypairs-key-uids ["keypair-uid"]]
(testing "success-keypair-qr-scan"
(let [effects (sut/success-keypair-qr-scan nil [connection-string keypairs-key-uids])
fx (:fx effects)]
(is (some? fx))))))
keypairs-key-uids [test-keypair-key-uid]
effects (sut/success-keypair-qr-scan nil [connection-string keypairs-key-uids])
fx (:fx effects)]
(is (some? fx))))
(deftest wallet-validate-seed-phrase-test
(let [cofx {:db {}}
@@ -70,7 +70,15 @@
{:keys [address path watch-only?]} (rf/sub [:wallet/current-viewing-account])
{keypair-name :name
keypair-type :type} (rf/sub [:wallet/current-viewing-account-keypair])
networks (rf/sub [:wallet/network-preference-details])]
networks (rf/sub [:wallet/network-preference-details])
origin-type (case keypair-type
:seed
:recovery-phrase
:key
:private-key
:default-keypair)]
[rn/scroll-view
{:style style/about-tab
:content-container-style {:padding-bottom (+ constants/floating-shell-button-height 8)}}
@@ -89,7 +97,7 @@
:on-press #(rf/dispatch [:show-bottom-sheet {:content about-options}])}]
(when (not watch-only?)
[quo/account-origin
{:type (if (= keypair-type "seed") :recovery-phrase :default-keypair)
{:type origin-type
:stored :on-device
:profile-picture (profile.utils/photo profile)
:customization-color customization-color
@@ -5,6 +5,7 @@
[status-im.contexts.wallet.add-account.create-account.utils :as create-account.utils]
[status-im.contexts.wallet.data-store :as data-store]
[taoensso.timbre :as log]
[utils.collection]
[utils.re-frame :as rf]
[utils.security.core :as security]
[utils.transforms :as transforms]))
@@ -12,9 +13,11 @@
(defn get-keypairs-success
[{:keys [db]} [keypairs]]
(let [parsed-keypairs (data-store/rpc->keypairs keypairs)
default-key-uid (:key-uid (some #(when (= (:type %) :profile) %) parsed-keypairs))]
default-key-uid (->> parsed-keypairs
(some #(when (= (:type %) :profile) %))
:key-uid)]
{:db (-> db
(assoc-in [:wallet :keypairs] parsed-keypairs)
(assoc-in [:wallet :keypairs] (utils.collection/index-by :key-uid parsed-keypairs))
(assoc-in [:wallet :ui :create-account :selected-keypair-uid] default-key-uid))}))
(rf/reg-event-fx :wallet/get-keypairs-success get-keypairs-success)
@@ -41,10 +44,10 @@
(defn seed-phrase-validated
[{:keys [db]} [seed-phrase key-uid on-error]]
(let [keypair-already-added? (->> db
:wallet
:keypairs
(some #(= key-uid (:key-uid %))))]
(let [keypair-already-added? (-> db
:wallet
:keypairs
(contains? key-uid))]
(if keypair-already-added?
(do
(on-error)
@@ -73,7 +73,7 @@
[]
(let [compressed-key (rf/sub [:profile/compressed-key])
customization-color (rf/sub [:profile/customization-color])
keypairs (rf/sub [:wallet/keypairs])
keypairs (rf/sub [:wallet/keypairs-list])
selected-keypair (rf/sub [:wallet/selected-keypair-uid])
profile-picture (rf/sub [:profile/image])
[selected-key-uid set-selected-key-uid] (rn/use-state selected-keypair)]
+3 -4
View File
@@ -529,10 +529,9 @@
:wallet/process-keypair-from-backup
(fn [{:keys [db]} [{:keys [backedUpKeypair]}]]
(let [{:keys [key-uid accounts]} backedUpKeypair
keypairs-db (get-in db [:wallet :keypairs])
updated-keypairs (-> (filter #(not= (:key-uid %) key-uid) keypairs-db)
(conj backedUpKeypair)
data-store/rpc->keypairs)
updated-keypairs (assoc-in db
[:wallet :keypairs key-uid]
(data-store/rpc->keypair backedUpKeypair))
accounts-fx (mapv (fn [{:keys [chat] :as account}]
;; We exclude the chat account from the profile keypair
;; for fetching the assets
+11 -2
View File
@@ -26,6 +26,7 @@
[status-im.contexts.communities.actions.share-community.view :as share-community]
[status-im.contexts.communities.discover.view :as communities.discover]
[status-im.contexts.communities.overview.view :as communities.overview]
[status-im.contexts.onboarding.create-or-sync-profile.view :as create-or-sync-profile]
[status-im.contexts.onboarding.create-password.view :as create-password]
[status-im.contexts.onboarding.create-profile.view :as create-profile]
[status-im.contexts.onboarding.enable-biometrics.view :as enable-biometrics]
@@ -33,7 +34,6 @@
[status-im.contexts.onboarding.generating-keys.view :as generating-keys]
[status-im.contexts.onboarding.identifiers.view :as identifiers]
[status-im.contexts.onboarding.intro.view :as intro]
[status-im.contexts.onboarding.new-to-status.view :as new-to-status]
[status-im.contexts.onboarding.sign-in.view :as sign-in]
[status-im.contexts.onboarding.syncing.progress.view :as syncing-devices]
[status-im.contexts.onboarding.syncing.results.view :as syncing-results]
@@ -284,7 +284,16 @@
transitions/push-animations-for-transparent-background)
:popGesture false
:modalPresentationStyle :overCurrentContext}
:component new-to-status/new-to-status}
:component create-or-sync-profile/create-profile}
{:name :screen/onboarding.sync-or-recover-profile
:options {:theme :dark
:layout options/onboarding-transparent-layout
:animations (merge
transitions/new-to-status-modal-animations
transitions/push-animations-for-transparent-background)
:popGesture false
:modalPresentationStyle :overCurrentContext}
:component create-or-sync-profile/sync-or-recover-profile}
{:name :screen/onboarding.create-profile
:options {:theme :dark
+4 -4
View File
@@ -44,15 +44,15 @@
(def stack-slide-transition
{:push {:content {:translationX {:from (:width (rn/get-window))
:to 0
:duration 200}}}
:duration 250}}}
:pop {:content {:translationX {:from 0
:to (:width (rn/get-window))
:duration 200}}}})
:duration 250}}}})
(def stack-transition-from-bottom
{:push {:content {:translationY {:from (:height (rn/get-window))
:to 0
:duration 200}}}
:duration 250}}}
:pop {:content {:translationY {:from 0
:to (:height (rn/get-window))
:duration 200}}}})
:duration 250}}}})
+18
View File
@@ -0,0 +1,18 @@
(ns status-im.setup.test-preload
(:require
["bignumber.js" :as BigNumber]
[matcher-combinators.core :as matcher-combinators]
[matcher-combinators.model :as matcher.model]))
;; We must implement Matcher in order for tests to work with the `match?`
;; directive.
(extend-type BigNumber
matcher-combinators/Matcher
(-matcher-for [this] this)
(-base-name [_] 'bignumber)
(-match [this actual]
(if (-equiv this actual)
{:matcher-combinators.result/type :match
:matcher-combinators.result/value actual}
{:matcher-combinators.result/type :mismatch
:matcher-combinators.result/value (matcher.model/->Mismatch this actual)})))
+33 -31
View File
@@ -199,6 +199,12 @@
:<- [:wallet]
:-> :keypairs)
(rf/reg-sub
:wallet/keypairs-list
:<- [:wallet]
(fn [{:keys [keypairs]}]
(vals keypairs)))
(rf/reg-sub
:wallet/selected-keypair-uid
:<- [:wallet/create-account]
@@ -209,19 +215,15 @@
:<- [:wallet/keypairs]
:<- [:wallet/selected-keypair-uid]
(fn [[keypairs selected-keypair-uid]]
(some #(when (= (:key-uid %) selected-keypair-uid)
%)
keypairs)))
(get keypairs selected-keypair-uid)))
(rf/reg-sub
:wallet/selected-primary-keypair?
:<- [:wallet/keypairs]
:<- [:wallet/selected-keypair-uid]
(fn [[keypairs selected-keypair-uid]]
(let [primary-keypair-uid (->> keypairs
(some #(when (= (:type %) "profile") %))
(:key-uid))]
(= selected-keypair-uid primary-keypair-uid))))
(= (get-in keypairs [selected-keypair-uid :type])
:profile)))
(rf/reg-sub
:wallet/selected-networks->chain-ids
@@ -264,29 +266,29 @@
(rf/reg-sub
:wallet/settings-keypairs-accounts
:<- [:wallet/keypairs]
:<- [:wallet/keypairs-list]
(fn [keypairs [_ format-options]]
(let [grouped-keypairs (group-by :lowest-operability keypairs)
operable-keypair-ids (->> (concat (:fully grouped-keypairs)
(:partially grouped-keypairs))
(map :key-uid)
(into #{}))
missing-keypair-ids (->> (map :key-uid (:no grouped-keypairs))
(into #{}))]
{:operable (->> keypairs
(filter #(contains? operable-keypair-ids (:key-uid %)))
(map (fn [{:keys [accounts name type key-uid]}]
{:type (keyword type)
:name name
:key-uid key-uid
:accounts (format-settings-keypair-accounts accounts format-options)})))
:missing (->> keypairs
(filter #(contains? missing-keypair-ids (:key-uid %)))
(map (fn [{:keys [accounts name type key-uid]}]
{:type (keyword type)
:name name
:key-uid key-uid
:accounts (format-settings-missing-keypair-accounts accounts)})))})))
(reduce
(fn [acc {:keys [accounts name type key-uid lowest-operability]}]
(if (= lowest-operability :no)
(update acc
:missing
conj
{:type type
:name name
:key-uid key-uid
:accounts (format-settings-missing-keypair-accounts accounts)})
(update acc
:operable
conj
{:type type
:name name
:key-uid key-uid
:accounts (format-settings-keypair-accounts accounts format-options)})))
{:missing []
:operable []}
keypairs)))
(rf/reg-sub
:wallet/derivation-path-state
:<- [:wallet/create-account]
@@ -343,7 +345,7 @@
(= operable :no) :missing-keypair
watch-only? :watch-only
:else :empty)
keypair (first (filter #(= key-uid (:key-uid %)) keypairs))]
keypair (get keypairs key-uid)]
(assoc account
:customization-color color
:type (cond
@@ -387,7 +389,7 @@
:<- [:wallet/current-viewing-account]
:<- [:wallet/keypairs]
(fn [[{:keys [key-uid]} keypairs]]
(first (filter #(= key-uid (:key-uid %)) keypairs))))
(get keypairs key-uid)))
(rf/reg-sub
:wallet/current-viewing-account-tokens-in-selected-networks
+55 -43
View File
@@ -600,18 +600,6 @@
(assoc :network-preferences-names #{}))]
(rf/sub [sub-name])))))
(def keypairs
[{:key-uid "abc"}])
(h/deftest-sub :wallet/keypairs
[sub-name]
(testing "returns all keypairs"
(swap! rf-db/app-db
#(assoc-in % [:wallet :keypairs] keypairs))
(is
(= keypairs
(rf/sub [sub-name])))))
(def chat-account
{:path "m/43'/60'/1581'/0'/0"
:emoji ""
@@ -654,20 +642,40 @@
:operable :no
:removed false})
(def default-keypair-accounts
{:key-uid "abc"
(def profile-key-pair-key-uid "abc")
(def seed-phrase-key-pair-key-uid "def")
(def profile-keypair
{:key-uid profile-key-pair-key-uid
:name "My Profile"
:type "profile"
:type :profile
:lowest-operability :fully
:accounts []})
(def seed-phrase-keypair-accounts
{:key-uid "def"
(def seed-phrase-keypair
{:key-uid seed-phrase-key-pair-key-uid
:name "My Key Pair"
:type "seed"
:type :seed
:lowest-operability :no
:accounts []})
(h/deftest-sub :wallet/keypairs
[sub-name]
(testing "returns keypairs map"
(swap! rf-db/app-db assoc-in [:wallet :keypairs] {profile-key-pair-key-uid profile-keypair})
(is (match? {profile-key-pair-key-uid profile-keypair} (rf/sub [sub-name])))))
(h/deftest-sub :wallet/keypairs-list
[sub-name]
(swap! rf-db/app-db assoc-in
[:wallet :keypairs]
{profile-key-pair-key-uid profile-keypair
seed-phrase-key-pair-key-uid seed-phrase-keypair})
(let [result (rf/sub [sub-name])
expected (list profile-keypair seed-phrase-keypair)]
(is (= 2 (count result)))
(is (match? expected result))))
(h/deftest-sub :wallet/settings-keypairs-accounts
[sub-name]
(testing "returns formatted key-pairs and accounts"
@@ -676,12 +684,14 @@
(-> db
(assoc-in
[:wallet :keypairs]
[(assoc default-keypair-accounts
:accounts
[operable-wallet-account])
(assoc seed-phrase-keypair-accounts
:accounts
[inoperable-wallet-account])])
{profile-key-pair-key-uid (update profile-keypair
:accounts
conj
operable-wallet-account)
seed-phrase-key-pair-key-uid (update seed-phrase-keypair
:accounts
conj
inoperable-wallet-account)})
(assoc-in
[:wallet :accounts]
{(:address operable-wallet-account) operable-wallet-account
@@ -689,15 +699,15 @@
(is
(match?
{:missing [{:name (:name seed-phrase-keypair-accounts)
:key-uid (:key-uid seed-phrase-keypair-accounts)
:type (keyword (:type seed-phrase-keypair-accounts))
{:missing [{:name (:name seed-phrase-keypair)
:key-uid (:key-uid seed-phrase-keypair)
:type (:type seed-phrase-keypair)
:accounts [{:customization-color (:color inoperable-wallet-account)
:emoji (:emoji inoperable-wallet-account)
:type :default}]}]
:operable [{:name (:name default-keypair-accounts)
:key-uid (:key-uid default-keypair-accounts)
:type (keyword (:type default-keypair-accounts))
:operable [{:name (:name profile-keypair)
:key-uid (:key-uid profile-keypair)
:type (:type profile-keypair)
:accounts [{:account-props {:customization-color (:color operable-wallet-account)
:size 32
:emoji (:emoji operable-wallet-account)
@@ -715,9 +725,10 @@
(-> db
(assoc-in
[:wallet :keypairs]
[(assoc default-keypair-accounts
:accounts
[operable-wallet-account])])
{profile-key-pair-key-uid (update profile-keypair
:accounts
conj
operable-wallet-account)})
(assoc-in
[:wallet :accounts]
{(:address operable-wallet-account) operable-wallet-account}))))
@@ -732,9 +743,9 @@
size-option 20]
(is
(match? {:missing []
:operable [{:name (:name default-keypair-accounts)
:key-uid (:key-uid default-keypair-accounts)
:type (keyword (:type default-keypair-accounts))
:operable [{:name (:name profile-keypair)
:key-uid (:key-uid profile-keypair)
:type (:type profile-keypair)
:accounts [{:account-props {:customization-color color
:size size-option
:emoji emoji
@@ -754,10 +765,11 @@
(-> db
(assoc-in
[:wallet :keypairs]
[(assoc default-keypair-accounts
:accounts
[operable-wallet-account
chat-account])])
{profile-key-pair-key-uid (update profile-keypair
:accounts
conj
operable-wallet-account
chat-account)})
(assoc-in
[:wallet :accounts]
{(:address operable-wallet-account) operable-wallet-account
@@ -765,9 +777,9 @@
(is
(match?
{:missing []
:operable [{:name (:name default-keypair-accounts)
:key-uid (:key-uid default-keypair-accounts)
:type (keyword (:type default-keypair-accounts))
:operable [{:name (:name profile-keypair)
:key-uid (:key-uid profile-keypair)
:type (:type profile-keypair)
:accounts [{:account-props {:customization-color (:color operable-wallet-account)
:size 32
:emoji (:emoji operable-wallet-account)
-1
View File
@@ -4,7 +4,6 @@
[react-native.fs :as utils.fs]
[react-native.platform :as platform]
[schema.core :as schema]
[schema.quo]
[utils.datetime :as datetime]))
(def ^:const image-server-uri-prefix "https://localhost:")
+16 -1
View File
@@ -50,10 +50,26 @@
[bn1 bn2]
(.greaterThan ^js bn1 bn2))
(defn less-than
[bn1 bn2]
(.lessThan ^js bn1 bn2))
(defn equal-to
[bn1 bn2]
(.eq ^js bn1 bn2))
(extend-type BigNumber
IEquiv
(-equiv [this other]
(equal-to this other))
IComparable
(-compare [this other]
(cond
(less-than this other) -1
(greater-than this other) 1
:else 0)))
(defn sub
[bn1 bn2]
(.sub ^js bn1 bn2))
@@ -260,4 +276,3 @@
(schema/=> format-amount
[:=> [:cat [:maybe :int]]
[:maybe :string]])
+22
View File
@@ -3,6 +3,28 @@
[cljs.test :refer-macros [deftest testing is are]]
[utils.money :as money]))
(deftest comparable-test
(is (= [(money/bignumber -4)
(money/bignumber 0)
(money/bignumber 1)
(money/bignumber 1.1)
(money/bignumber 2.1)]
(sort [(money/bignumber 0)
(money/bignumber 2.1)
(money/bignumber -4)
(money/bignumber 1.1)
(money/bignumber 1)]))))
(deftest equivalence-test
(is (= (money/bignumber 0)
(money/bignumber 0)))
(is (= (money/bignumber -1)
(money/bignumber -1)))
(is (not (= (money/bignumber 10)
(money/bignumber -10))))
(is (match? {:a {:b {:c (money/bignumber 42)}}}
{:a {:b {:c (money/bignumber 42)}}})))
(deftest wei->ether-test
(testing "Numeric input, 15 significant digits"
(is (= (str (money/wei->ether 111122223333444000))
+3 -3
View File
@@ -3,7 +3,7 @@
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
"owner": "status-im",
"repo": "status-go",
"version": "chore/keycard-login-endpoints",
"commit-sha1": "cd4f51d738da8a5294798a38e6661c76b14b7615",
"src-sha256": "1kdscjq4f3qpbw49w8v8iq21m6c6hys8b14gnslq269zkjb39dnj"
"version": "94b127d17e49f2de59d4f0c7b375690866e0928c",
"commit-sha1": "94b127d17e49f2de59d4f0c7b375690866e0928c",
"src-sha256": "0qs3rvnbmmxyf3q4irdwyq3r5ppb4j58qikvwmg21d4br3wlqf0c"
}
+6 -5
View File
@@ -14,7 +14,7 @@ import tests
class NetworkApi:
def __init__(self):
self.network_url = 'http://api-sepolia.etherscan.io/api'
self.network_url = 'http://api-sepolia.arbiscan.io/api'
self.api_key = environ.get('ETHERSCAN_API_KEY')
def log(self, text: str):
@@ -50,7 +50,7 @@ class NetworkApi:
balance = self.send_etherscan_request(params)
if balance:
self.log('Balance is %s Gwei' % balance)
return int(balance)
return int(balance) / 1000000000000000000
else:
self.log('Cannot extract balance!')
@@ -138,11 +138,12 @@ class NetworkApi:
def wait_for_balance_to_be(self, address: str, expected_balance: int, less: bool = True):
for _ in range(5):
balance = self.get_balance(address) / 1000000000000000000
if (less and balance < expected_balance) or (not less and balance > expected_balance):
balance = self.get_balance(address)
if balance == expected_balance:
return
time.sleep(10)
raise TimeoutException('Balance is not updated on Etherscan')
raise TimeoutException(
'balance is not updated on Etherscan, it is %s but expected to be %s' % (balance, expected_balance))
# Do not use until web3 update
# def faucet(self, address):
@@ -47,15 +47,15 @@ class TestDeepLinksOneDevice(MultipleSharedDeviceTestCase):
self.errors.append("Profile was not opened by the profile url %s" % url)
self.profile_view.close_button.click()
closed_community_urls = {
"https://status.app/c/G0IAAGRy3S0pLm1NeQ91pwKgFaFGoIlkxXmDxITXXi3KdZ7vpb9-ERczhqwoFwMK6sCPnKwA#zQ3shtJ8A3rxUZWcfWDL3vKYQBt3jMPTuf44dJUGfjZjsek66":
"e2e community token-gated",
community_urls = {
"https://status.app/c/G0IAAGS9TbI9SrSPbDPplfBUeBBOIWhFRhGIKVlxntAg5CSvsJw4jurb636UKo7Lm2gTUS_M#zQ3shm7cS2MX6K1iinjNhiw88g1WH6fbE8rvnMHBq4RhznkWc":
"token-gated community e2e",
"https://status.app/c/GzwAAGS9TbI9CiYaoZj0TRNelWAPwk8gSHIEmqgqb0ADPw5rnFvk6bp_n3BlZxVMshmxFyI=#zQ3shkrmSmwb66sw2EuUvC5iqiNqEeevTfjtks3p8ZaaCYoNj":
"Open community for e2e",
"https://status.app/c/GzAAAORtwyW4xNWM4td0F7hOnYZ1apSqCCRUUR0qxD19n3Ec97fX_aIVIGFWbdUM#zQ3shk6dgK8dYWWSC4m8Jj5c91zyfhfj1fFkgypS8D9gsXkrK":
"Closed community"
}
for url, text in closed_community_urls.items():
for url, text in community_urls.items():
self.channel.just_fyi("Opening community '%s' by the url %s" % (text, url))
self.channel.chat_message_input.clear()
self.channel.send_message(url)
@@ -95,8 +95,8 @@ class TestDeepLinksOneDevice(MultipleSharedDeviceTestCase):
self.browser_view.click_system_back_button()
community_links = {
"status.app://c/G0IAAGRy3S0pLm1NeQ91pwKgFaFGoIlkxXmDxITXXi3KdZ7vpb9-ERczhqwoFwMK6sCPnKwA#zQ3shtJ8A3rxUZWcfWDL3vKYQBt3jMPTuf44dJUGfjZjsek66":
"e2e community token-gated",
"status.app://c/G0IAAGS9TbI9SrSPbDPplfBUeBBOIWhFRhGIKVlxntAg5CSvsJw4jurb636UKo7Lm2gTUS_M#zQ3shm7cS2MX6K1iinjNhiw88g1WH6fbE8rvnMHBq4RhznkWc":
"token-gated community e2e",
"status.app://c/GzwAAGS9TbI9CiYaoZj0TRNelWAPwk8gSHIEmqgqb0ADPw5rnFvk6bp_n3BlZxVMshmxFyI=#zQ3shkrmSmwb66sw2EuUvC5iqiNqEeevTfjtks3p8ZaaCYoNj":
"Open community for e2e",
"status.app://c/GzAAAORtwyW4xNWM4td0F7hOnYZ1apSqCCRUUR0qxD19n3Ec97fX_aIVIGFWbdUM#zQ3shk6dgK8dYWWSC4m8Jj5c91zyfhfj1fFkgypS8D9gsXkrK":
+17 -16
View File
@@ -8,7 +8,7 @@ from selenium.common import TimeoutException, NoSuchElementException
from base_test_case import MultipleSharedDeviceTestCase, create_shared_drivers
from support.api.network_api import NetworkApi
from tests import marks, run_in_parallel
from users import recovery_users
from users import transaction_senders
from views.sign_in_view import SignInView
@@ -21,9 +21,9 @@ class TestWalletMultipleDevice(MultipleSharedDeviceTestCase):
self.network_api = NetworkApi()
self.drivers, self.loop = create_shared_drivers(2)
self.sign_in_1, self.sign_in_2 = SignInView(self.drivers[0]), SignInView(self.drivers[1])
passphrases, addresses = list(recovery_users), list(recovery_users.values())
self.sender = {'passphrase': passphrases[0], 'address': addresses[0]}
self.receiver = {'passphrase': passphrases[1], 'address': addresses[1]}
self.sender, self.receiver = transaction_senders['ETH_1'], transaction_senders['ETH_2']
self.sender['wallet_address'] = '0x' + self.sender['address']
self.receiver['wallet_address'] = '0x' + self.receiver['address']
self.sender_username, self.receiver_username = 'sender', 'receiver'
self.loop.run_until_complete(
run_in_parallel(((self.sign_in_1.recover_access, {'passphrase': self.sender['passphrase'],
@@ -34,8 +34,8 @@ class TestWalletMultipleDevice(MultipleSharedDeviceTestCase):
self.wallet_1, self.wallet_2 = self.sign_in_1.get_wallet_view(), self.sign_in_2.get_wallet_view()
def _get_balances_before_tx(self):
sender_balance = self.network_api.get_balance(self.sender['address'])
receiver_balance = self.network_api.get_balance(self.receiver['address'])
sender_balance = self.network_api.get_balance(self.sender['wallet_address'])
receiver_balance = self.network_api.get_balance(self.receiver['wallet_address'])
self.wallet_1.just_fyi("Getting ETH amount in the wallet of the sender before transaction")
self.wallet_1.wallet_tab.click()
self.wallet_1.get_account_element().click()
@@ -49,15 +49,15 @@ class TestWalletMultipleDevice(MultipleSharedDeviceTestCase):
def _check_balances_after_tx(self, amount_to_send, sender_balance, receiver_balance, eth_amount_sender,
eth_amount_receiver):
try:
self.network_api.wait_for_balance_to_be(address=self.sender['address'],
self.network_api.wait_for_balance_to_be(address=self.sender['wallet_address'],
expected_balance=sender_balance - amount_to_send)
except TimeoutException:
self.errors.append("Sender balance was not updated")
except TimeoutException as e:
self.errors.append("Sender " + e.msg)
try:
self.network_api.wait_for_balance_to_be(address=self.receiver['address'],
self.network_api.wait_for_balance_to_be(address=self.receiver['wallet_address'],
expected_balance=receiver_balance + amount_to_send)
except TimeoutException:
self.errors.append("Receiver balance was not updated")
except TimeoutException as e:
self.errors.append("Receiver " + e.msg)
def wait_for_wallet_balance_to_update(wallet_view, user_name, initial_eth_amount):
wallet_view.just_fyi("Getting ETH amount in the wallet of the %s after transaction" % user_name)
@@ -102,8 +102,9 @@ class TestWalletMultipleDevice(MultipleSharedDeviceTestCase):
expected_time = "Today %s" % current_time.strftime('%-I:%M %p')
possible_times = [expected_time,
"Today %s" % (current_time + datetime.timedelta(minutes=1)).strftime('%-I:%M %p')]
sender_address_short = self.sender['address'].replace(self.sender['address'][5:-3], '...').lower()
receiver_address_short = self.receiver['address'].replace(self.receiver['address'][5:-3], '...').lower()
sender_address_short = self.sender['wallet_address'].replace(self.sender['wallet_address'][5:-3], '...').lower()
receiver_address_short = self.receiver['wallet_address'].replace(self.receiver['wallet_address'][5:-3],
'...').lower()
activity_element = wallet_view.get_activity_element()
try:
if not all((activity_element.header == 'Send' if sender else 'Receive',
@@ -128,7 +129,7 @@ class TestWalletMultipleDevice(MultipleSharedDeviceTestCase):
self.wallet_1.just_fyi("Sending funds from wallet")
amount_to_send = 0.0001
self.wallet_1.send_asset(address=self.receiver['address'], asset_name='Ether', amount=amount_to_send)
self.wallet_1.send_asset(address=self.receiver['wallet_address'], asset_name='Ether', amount=amount_to_send)
device_time = self.wallet_1.driver.device_time
@@ -154,7 +155,7 @@ class TestWalletMultipleDevice(MultipleSharedDeviceTestCase):
self.wallet_1.just_fyi("Sending asset from drawer")
amount_to_send = 0.0001
self.wallet_1.send_asset_from_drawer(address=self.receiver['address'], asset_name='Ether',
self.wallet_1.send_asset_from_drawer(address=self.receiver['wallet_address'], asset_name='Ether',
amount=amount_to_send)
device_time = self.wallet_1.driver.device_time
+7 -7
View File
@@ -147,9 +147,11 @@ class SignInView(BaseView):
self.driver = driver
# intro screen
self.sign_in_intro_button = Button(self.driver, accessibility_id="already-use-status-button")
self.i_m_new_in_status_button = Button(self.driver, accessibility_id="new-to-status-button")
self.create_profile_button = Button(self.driver, accessibility_id='new-to-status-button')
self.sync_or_recover_profile_button = Button(self.driver, accessibility_id='already-use-status-button')
self.migration_password_input = EditBox(self.driver, accessibility_id="enter-password-input")
self.access_key_button = AccessKeyButton(self.driver)
self.generate_key_button = Button(self.driver, accessibility_id="generate-old-key")
@@ -195,7 +197,7 @@ class SignInView(BaseView):
self.cancel_custom_seed_phrase_button = Button(self.driver, accessibility_id="cancel-custom-seed-phrase")
# New onboarding
self.generate_keys_button = Button(self.driver, translation_id="lets-go")
self.generate_keys_button = Button(self.driver, accessibility_id="generate-key-option-card")
self.profile_title_input = EditBox(self.driver, accessibility_id="profile-title-input")
self.profile_continue_button = Button(self.driver, accessibility_id="submit-create-profile-button")
self.profile_password_edit_box = EditBox(self.driver, translation_id="password-creation-placeholder-1")
@@ -206,7 +208,7 @@ class SignInView(BaseView):
self.enable_notifications_button = Button(self.driver, accessibility_id="enable-notifications-button")
self.maybe_later_button = Button(self.driver, accessibility_id="enable-notifications-later-button")
self.start_button = Button(self.driver, accessibility_id="welcome-button")
self.use_recovery_phrase_button = Button(self.driver, translation_id="use-recovery-phrase")
self.use_recovery_phrase_button = Button(self.driver, accessibility_id="use-recovery-phrase-option-card")
self.passphrase_edit_box = EditBox(self.driver, accessibility_id="passphrase-input")
self.show_profiles_button = Button(self.driver, accessibility_id="show-profiles")
self.plus_profiles_button = Button(self.driver, accessibility_id="show-new-account-options")
@@ -232,10 +234,8 @@ class SignInView(BaseView):
username="test user", first_user=True):
self.driver.info("## Creating new multiaccount (password:'%s', keycard:'%s', enable_notification: '%s')" %
(password, str(keycard), str(enable_notifications)), device=False)
if self.element_by_text('CONTINUE').is_element_displayed(5):
self.element_by_text('CONTINUE').click()
if first_user:
self.i_m_new_in_status_button.click_until_presence_of_element(self.generate_keys_button)
self.create_profile_button.click_until_presence_of_element(self.generate_keys_button)
else:
if self.show_profiles_button.is_element_displayed(20):
self.show_profiles_button.click()
@@ -273,7 +273,7 @@ class SignInView(BaseView):
self.driver.info("## Recover access(password:%s, keycard:%s)" % (password, str(keycard)), device=False)
if not second_user:
self.i_m_new_in_status_button.click_until_presence_of_element(self.generate_keys_button)
self.sync_or_recover_profile_button.click_until_presence_of_element(self.generate_keys_button)
else:
self.show_profiles_button.wait_and_click(20)
self.plus_profiles_button.click()
+4
View File
@@ -719,6 +719,7 @@
"identicon-ring": "Identicon ring",
"identicon-ring-explanation": "This multicoloured ring around your profile picture represents your chat key.",
"if-you-cancel": "If you cancel, you can request to join this community at any point.",
"if-you-have-status-on-another-device": "If you have Status on another device",
"image-remove-current": "Remove current photo",
"image-source-gallery": "Select from gallery",
"image-source-make-photo": "Capture",
@@ -1276,6 +1277,7 @@
"request-to-join-disclaimer": "Joining the community will reveal your public addresses to the owner",
"request-to-join": "Request to join",
"request-to-join-community": "Request to join community",
"request-to-join-community-pending": "Request to join community pending",
"requested-to-join-community": "You requested to join “{{community}}”",
"request-transaction": "Request transaction",
"required-field": "Required field",
@@ -1395,6 +1397,7 @@
"symbol": "Symbol",
"sync-all-devices": "Sync all devices",
"sync-in-progress": "Syncing...",
"sync-or-recover-profile": "Sync or recover profile",
"sync-settings": "Sync settings",
"sync-synced": "In sync",
"syncing-devices": "Syncing...",
@@ -2360,6 +2363,7 @@
"read-more": "Read more",
"token-gated-communities-info": "Here will be something relevant about this topic. This will help the user get more context and therefore have a better understanding of it.",
"dont-yell-at-me": "Dont yell at me",
"dont-have-statatus-on-another-device": "Don't have Status on another device?",
"unmute-channel": "Unmute channel",
"all-messages": "All messages",
"muted-until": "Muted until {{duration}}",