Compare commits

...
Author SHA1 Message Date
Prem Chaitanya Prathi 7a1a33f459 chore: take status-go fixes for push notifications that is already in 2.30 2024-09-20 13:34:29 +05:30
Volodymyr Kozieiev 1190fc8069 Fixed amounts for multiple collectibles (#21237) 2024-09-19 12:35:14 +01:00
Siddarth Kumar 92456612b1 chore: fix status-go versioning script (#21276) 2024-09-19 16:49:35 +05:30
Mohamed Javid 9912136ac9 fix(wallet)_: crash on viewing dynamic file type collectibles (#21245)
This commit removes the support for GIF file types for the collectibles.

Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2024-09-19 15:45:52 +05:30
Parvesh MonuandAndrea Maria Piana 0eb065bbb7 Implement seed phrase fallback flow (#21090)
Co-authored-by: Parvesh Monu <parvesh.dhullmonu@gmail.com>
Co-authored-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
2024-09-19 15:23:23 +05:30
frank 2e61f94d84 fix(mention)_: async call for mention suggestion (#21171)
* fix(mention)_: ensure async call work as expected

https://github.com/status-im/status-go/compare/81cfce70...b2c2e407

* chore_: remove call-time and rename

* chore_: update status go version
2024-09-19 13:24:48 +08:00
Ulises Manuel f606dc065b [#21212] - Fix not joined options for token gated communities (#21247)
* Fix not joined drawer options for token gated communities

* Remove `show-not-implemented-features?` flag for token gated options

* Fix component tests
2024-09-18 17:52:01 -06:00
Icaro Motta 6464ef96b6 chore(waku): Enable message missing verification flag (#21005)
As recommended in
https://github.com/status-im/status-go/pull/5570#discussion_r1692345230 [1] and
https://github.com/status-im/status-go/pull/5570#discussion_r1690794119 [2], we set
the Waku config flag WakuV2EnableMissingMessageVerification to true. The flag
can't be toggled in the UI because there's no supporting endpoint for that in
status-go at the moment.

[1] I doubt the hash based store-query going to be as expensive as legacy-store.
Because we only query hashes and if we miss any messages we fetch them which
would improve message reliability.
https://github.com/status-im/status-go/pull/5511 is expensive as it doesn't
query hashes rather full messages. I think we can keep this new flag enabled by
default and provide a switch in the app in case it becomes expensive to disable
it.

[2] we can keep this enabled for mobile by default. The reason
WakuV2EnableStoreConfirmationForMessagesSent was disabled is as it was giving
bad UX to users where messages were sent but still showing as not sent due to
storeNode performance issues. But this flag doesn't give any bad UX, so we can
keep it enabled by default.

Fixes https://github.com/status-im/status-mobile/issues/20879
2024-09-18 17:52:48 -03:00
Brian Sztamfater 9068801e4f feat(swap): switch pay/receive assets (#21179)
Signed-off-by: Brian Sztamfater <brian@status.im>
2024-09-18 13:07:13 -03:00
Parvesh Monu 2f3d3fc7f9 fix hidden community appears on "Opened" Tab (#21238) 2024-09-18 20:17:44 +05:30
Yevheniia Berdnyk 69664322b8 e2e: requests.log for failed tests 2024-09-18 12:07:50 +03:00
a1662752bc chore(onboarding): Remove welcome screen from onboarding (#20912)
* Fix customization color in disclaimer on onboarding

* Remove welcome page from onboarding

* Fix notification permission request on onboarding

* e2e: updated create user flow

---------

Co-authored-by: Ulises M <ulises.ssb@hotmail.com>
Co-authored-by: Yevheniia Berdnyk <ie.berdnyk@gmail.com>
2024-09-17 16:20:34 -06:00
Alexander 3363152160 WC: Last account that established connection is not selected when connecting through global scanner #20801 (#20913)
* WC: Last account that established connection is not selected when connecting through global scanner

* WC: Last account that established connection is not selected when connecting through global scanner

* Fixes
2024-09-17 15:29:05 +02:00
Volodymyr Kozieiev 7cad13c3c7 Strip out eip-3770 prefixes when scan qr (#21256) 2024-09-17 12:57:06 +01:00
68 changed files with 1114 additions and 542 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 722 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

+1 -1
View File
@@ -29,7 +29,7 @@ identify_git_sha() {
STATUS_GO_MATCHING_REFS=$(git ls-remote ${REPO_URL} ${1})
# It's possible that there's both a branch and a tag matching the given version
STATUS_GO_TAG_SHA1=$(echo "${STATUS_GO_MATCHING_REFS}" | grep 'refs/tags' | cut -f1)
STATUS_GO_TAG_SHA1=$(echo "${STATUS_GO_MATCHING_REFS}" | grep "refs/tags/${1}" | cut -f1)
STATUS_GO_BRANCH_SHA1=$(echo "${STATUS_GO_MATCHING_REFS}" | grep 'refs/heads' | cut -f1)
# Prefer tag over branch if both are found
+20 -11
View File
@@ -1,8 +1,7 @@
(ns legacy.status-im.chat.models.mentions
(:require
[clojure.set :as set]
[taoensso.timbre :as log]
[utils.re-frame :as rf]))
(:require [clojure.set :as set]
[taoensso.timbre :as log]
[utils.re-frame :as rf]))
(defn- transfer-input-segments
[segments]
@@ -59,18 +58,20 @@
(defn- transfer-mention-result
[result]
(let [{:keys [input-segments mentionable-users state chat-id new-text]}
(let [{:keys [input-segments mentionable-users state chat-id new-text call-id]}
(set/rename-keys result
{:InputSegments :input-segments
:MentionSuggestions :mentionable-users
:MentionState :state
:ChatID :chat-id
:NewText :new-text})]
:NewText :new-text
:CallID :call-id})]
{:chat-id chat-id
:input-segments (transfer-input-segments input-segments)
:mentionable-users (rename-mentionable-users mentionable-users)
:state (rename-state state)
:new-text new-text}))
:new-text new-text
:call-id call-id}))
(rf/defn on-error
{:events [:mention/on-error]}
@@ -104,10 +105,12 @@
{:events [:mention/on-change-text]}
[{:keys [db]} text]
(let [chat-id (:current-chat-id db)
params [chat-id text]
call-id (inc (get-in db [:chat/inputs chat-id :current-mentions-call-id] 0))
params [chat-id text call-id]
method "wakuext_chatMentionOnChangeText"]
(log/debug "[mentions] on-change-text" {:params params})
{:json-rpc/call [{:method method
{:db (assoc-in db [:chat/inputs chat-id :current-mentions-call-id] call-id)
:json-rpc/call [{:method method
:params params
:on-success #(rf/dispatch [:mention/on-change-text-success %])
:on-error #(rf/dispatch [:mention/on-error
@@ -118,8 +121,14 @@
{:events [:mention/on-change-text-success]}
[{:keys [db]} result]
(log/debug "[mentions] on-change-text-success" {:result result})
(let [{:keys [chat-id mentionable-users]} (transfer-mention-result result)]
{:db (assoc-in db [:chats/mention-suggestions chat-id] mentionable-users)}))
(let [{:keys [state chat-id mentionable-users
input-segments call-id]} (transfer-mention-result result)
current-mentions-call-id (get-in db [:chat/inputs chat-id :current-mentions-call-id])]
(when (= call-id current-mentions-call-id)
{:db (-> db
(assoc-in [:chat/inputs-with-mentions chat-id] input-segments)
(assoc-in [:chats/mention-suggestions chat-id] mentionable-users)
(assoc-in [:chats/mentions chat-id :mentions] state))})))
(rf/defn on-select-mention-success
{:events [:mention/on-select-mention-success]}
@@ -62,6 +62,7 @@
:chatId :chat-id
:contactVerificationStatus :contact-verification-status
:communityId :community-id
:installationId :installation-id
:membershipStatus :membership-status
:albumMessages :album-messages})
(update :last-message #(when % (messages/<-rpc %)))
@@ -117,20 +117,24 @@
(deftest parse-notification-counts-response-test
(is
(= {notification-types/one-to-one-chat 15
notification-types/private-group-chat 16
notification-types/mention 17
notification-types/reply 18
notification-types/contact-request 19
notification-types/admin 20
notification-types/contact-verification 21}
(= {notification-types/one-to-one-chat 15
notification-types/private-group-chat 16
notification-types/mention 17
notification-types/reply 18
notification-types/contact-request 19
notification-types/admin 20
notification-types/contact-verification 21
notification-types/new-installation-received 22
notification-types/new-installation-created 23}
(store/parse-notification-counts-response
{(keyword (str notification-types/one-to-one-chat)) 15
(keyword (str notification-types/private-group-chat)) 16
(keyword (str notification-types/mention)) 17
(keyword (str notification-types/reply)) 18
(keyword (str notification-types/contact-request)) 19
(keyword (str notification-types/admin)) 20
(keyword (str notification-types/contact-verification)) 21
{(keyword (str notification-types/one-to-one-chat)) 15
(keyword (str notification-types/private-group-chat)) 16
(keyword (str notification-types/mention)) 17
(keyword (str notification-types/reply)) 18
(keyword (str notification-types/contact-request)) 19
(keyword (str notification-types/admin)) 20
(keyword (str notification-types/contact-verification)) 21
(keyword (str notification-types/new-installation-received)) 22
(keyword (str notification-types/new-installation-created)) 23
;; Unsupported type in the response is ignored
:999 100}))))
:999 100}))))
+11
View File
@@ -57,6 +57,11 @@
(fn [options]
(permissions/request-permissions options)))
(re-frame/reg-fx
:request-notifications-fx
(fn [options]
(permissions/request-notifications options)))
(re-frame/reg-fx
:ui/show-error
(fn [content]
@@ -164,6 +169,12 @@
[_ options]
{:request-permissions-fx options})
(rf/reg-event-fx
:request-notifications
(fn [_ [options]]
(prn options)
{:request-notifications-fx options}))
(rf/defn update-window-dimensions
{:events [:update-window-dimensions]}
[{:keys [db]} dimensions]
+17
View File
@@ -243,6 +243,23 @@
{}
installations))})
(rf/defn finish-seed-phrase-fallback-syncing
{:events [:pairing/finish-seed-phrase-fallback-syncing]}
[{:keys [db]}]
{:fx [[:json-rpc/call
[{:method "wakuext_enableInstallationAndPair"
:params [{:installationId (:syncing/installation-id db)}]
:js-response true
:on-success [:sanitize-messages-and-process-response]}]]]})
(rf/defn pair-and-sync
{:events [:pairing/pair-and-sync]}
[cofx installation-id]
{:fx [[:json-rpc/call
[{:method "wakuext_enableInstallationAndSync"
:params [{:installationId installation-id}]
:on-success #(log/debug "successfully synced devices")}]]]})
(rf/defn enable-installation-success
{:events [:pairing.callback/enable-installation-success]}
[cofx installation-id]
+22 -2
View File
@@ -1,7 +1,10 @@
(ns react-native.permissions
(:require
["react-native-permissions" :refer (check openSettings requestMultiple PERMISSIONS RESULTS)]
[react-native.platform :as platform]))
["react-native-permissions" :refer
[check openSettings PERMISSIONS requestMultiple requestNotifications
RESULTS]]
[react-native.platform :as platform]
[taoensso.timbre :as log]))
(def permissions-map
{:read-external-storage (cond
@@ -45,3 +48,20 @@
(.catch #(on-error %))))
(def open-settings openSettings)
(defn request-notifications
"`notification-options` is only used on iOS.
A map with `:status` and `settings` (only for iOS) is passed to the callbacks.
See https://github.com/zoontek/react-native-permissions?tab=readme-ov-file#requestnotifications."
[{:keys [notification-options on-allowed on-denied]
:or {notification-options #js ["alert"]}}]
(-> (requestNotifications notification-options)
(.then (fn [js-response]
(let [response (js->clj js-response :keywordize-keys true)]
(if (= (:status response) "granted")
(do
(on-allowed response)
(log/debug "Notification permission were allowed" response))
(do
(on-denied response)
(log/debug "Notification permission were denied" response))))))))
@@ -0,0 +1,23 @@
(ns status-im.common.new-device-sheet.style
(:require [quo.foundations.colors :as colors]))
(def heading
{:padding-left 20
:padding-bottom 8})
(def message
{:padding-horizontal 20
:padding-top 4})
(def warning
{:margin-horizontal 20
:margin-top 10})
(def drawer-container
{:padding-horizontal 13
:padding-top 16})
(def settings-subtext
{:color colors/white-opa-70
:align-self :center
:margin-bottom 12})
@@ -0,0 +1,75 @@
(ns status-im.common.new-device-sheet.view
(:require
[quo.core :as quo]
[react-native.core :as rn]
[status-im.common.events-helper :as events-helper]
[status-im.common.new-device-sheet.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- pair-and-sync
[installation-id]
(rf/dispatch [:pairing/pair-and-sync installation-id])
(events-helper/hide-bottom-sheet))
(defn installation-request-receiver-view
[installation-id]
(rn/use-mount events-helper/dismiss-keyboard)
[:<>
[quo/text
{:weight :semi-bold
:size :heading-2
:accessibility-label :new-device-sheet-heading
:style style/heading}
(i18n/label :t/pair-new-device-and-sync)]
[quo/text
{:weight :regular
:size :paragraph-1
:accessibility-label :new-device-sheet-message
:style style/message}
(i18n/label :t/new-device-detected-recovered-device-message)]
[quo/text
{:weight :semi-bold
:size :heading-2
:accessibility-label :new-device-installation-id
:style style/heading}
installation-id]
[quo/bottom-actions
{:actions :two-actions
:blur? true
:container-style {:margin-top 12}
:button-two-label (i18n/label :t/cancel)
:button-two-props {:type :grey
:on-press events-helper/hide-bottom-sheet}
:button-one-label (i18n/label :t/pair-and-sync)
:button-one-props {:on-press #(pair-and-sync installation-id)}}]])
(defn installation-request-creator-view
[installation-id]
(rn/use-mount events-helper/dismiss-keyboard)
[:<>
[quo/text
{:weight :semi-bold
:size :heading-2
:accessibility-label :new-device-sheet-heading
:style style/heading}
(i18n/label :t/pair-this-device-and-sync)]
[quo/text
{:weight :regular
:size :paragraph-1
:accessibility-label :new-device-sheet-message
:style style/message}
(i18n/label :t/new-device-detected-other-device-message)]
[quo/text
{:weight :semi-bold
:size :heading-2
:accessibility-label :new-device-installation-id
:style style/heading}
installation-id]
[quo/bottom-actions
{:actions :one-action
:blur? true
:container-style {:margin-top 12}
:button-one-label (i18n/label :t/close)
:button-one-props {:type :grey
:on-press events-helper/hide-bottom-sheet}}]])
+1
View File
@@ -28,6 +28,7 @@
:notifications (js/require "../resources/images/ui2/notifications.png")
:nfc-prompt (js/require "../resources/images/ui2/nfc-prompt.png")
:nfc-success (js/require "../resources/images/ui2/nfc-success.png")
:preparing-status (js/require "../resources/images/ui2/preparing-status.png")
:syncing-devices (js/require "../resources/images/ui2/syncing_devices.png")
:syncing-wrong (js/require "../resources/images/ui2/syncing_wrong.png")})
@@ -37,6 +37,7 @@
:screen/onboarding.enable-biometrics
:screen/onboarding.generating-keys
:screen/onboarding.enable-notifications
:screen/onboarding.preparing-status
:screen/onboarding.sign-in-intro
:screen/onboarding.sign-in
:screen/onboarding.syncing-progress
@@ -8,7 +8,8 @@
(h/test "joined options - Non token Gated"
(h/setup-subs {:communities/my-pending-request-to-join nil
:communities/community {:joined true}})
:communities/community {:joined true}
:profile/test-networks-enabled? false})
(h/render [options/community-options-bottom-sheet {:id "test"}])
(h/is-truthy (h/get-by-translation-text :t/view-members))
(h/is-truthy (h/get-by-translation-text :t/view-community-rules))
@@ -23,7 +24,8 @@
(h/test "joined options - Token Gated"
(h/setup-subs {:communities/my-pending-request-to-join nil
:communities/community {:joined true
:role-permissions? true}})
:role-permissions? true}
:profile/test-networks-enabled? false})
(h/render [options/community-options-bottom-sheet {:id "test"}])
(h/is-truthy (h/get-by-translation-text :t/view-members))
(h/is-truthy (h/get-by-translation-text :t/view-community-rules))
@@ -38,7 +40,8 @@
(h/test "admin options - Non token Gated"
(h/setup-subs {:communities/my-pending-request-to-join nil
:communities/community {:admin true}})
:communities/community {:admin true}
:profile/test-networks-enabled? false})
(h/render [options/community-options-bottom-sheet {:id "test"}])
(h/is-truthy (h/get-by-translation-text :t/view-members))
(h/is-truthy (h/get-by-translation-text :t/view-community-rules))
@@ -52,7 +55,8 @@
(h/test "admin options - Token Gated"
(h/setup-subs {:communities/my-pending-request-to-join nil
:communities/community {:admin true
:role-permissions? true}})
:role-permissions? true}
:profile/test-networks-enabled? false})
(h/render [options/community-options-bottom-sheet {:id "test"}])
(h/is-truthy (h/get-by-translation-text :t/view-members))
(h/is-truthy (h/get-by-translation-text :t/view-community-rules))
@@ -65,7 +69,8 @@
(h/test "request sent options - Non token Gated"
(h/setup-subs {:communities/my-pending-request-to-join "mock-id"
:communities/community {}})
:communities/community {}
:profile/test-networks-enabled? false})
(h/render [options/community-options-bottom-sheet {:id "test"}])
(h/is-truthy (h/get-by-translation-text :t/view-members))
(h/is-truthy (h/get-by-translation-text :t/view-community-rules))
@@ -76,7 +81,8 @@
(h/test "request sent options - Token Gated"
(h/setup-subs {:communities/my-pending-request-to-join "mock-id"
:communities/community {:role-permissions? true}})
:communities/community {:role-permissions? true}
:profile/test-networks-enabled? false})
(h/render [options/community-options-bottom-sheet {:id "test"}])
(h/is-truthy (h/get-by-translation-text :t/invite-people-from-contacts))
;(h/is-truthy (h/get-by-translation-text :t/view-token-gating))
@@ -86,7 +92,8 @@
(h/test "banned options - Non token Gated"
(h/setup-subs {:communities/my-pending-request-to-join nil
:communities/community {:banList true}})
:communities/community {:banList true}
:profile/test-networks-enabled? false})
(h/render [options/community-options-bottom-sheet {:id "test"}])
(h/is-truthy (h/get-by-translation-text :t/view-members))
(h/is-truthy (h/get-by-translation-text :t/view-community-rules))
@@ -97,7 +104,8 @@
(h/test "banned options - Token Gated"
(h/setup-subs {:communities/my-pending-request-to-join nil
:communities/community {:banList 100
:role-permissions? true}})
:role-permissions? true}
:profile/test-networks-enabled? false})
(h/render [options/community-options-bottom-sheet {:id "test"}])
(h/is-truthy (h/get-by-translation-text :t/invite-people-from-contacts))
;(h/is-truthy (h/get-by-translation-text :t/view-token-gating))
@@ -107,7 +115,8 @@
(h/test "banned options - Token Gated"
(h/setup-subs {:communities/my-pending-request-to-join nil
:communities/community {:banList 100
:role-permissions? true}})
:role-permissions? true}
:profile/test-networks-enabled? false})
(h/render [options/community-options-bottom-sheet {:id "test"}])
(h/is-truthy (h/get-by-translation-text :t/invite-people-from-contacts))
;(h/is-truthy (h/get-by-translation-text :t/view-token-gating))
@@ -118,6 +127,7 @@
(h/setup-subs {:communities/my-pending-request-to-join nil
:communities/community {:joined true
:muted true
:role-permissions? true}})
:role-permissions? true}
:profile/test-networks-enabled? false})
(h/render [options/community-options-bottom-sheet {:id "test"}])
(h/is-truthy (h/get-by-translation-text :t/unmute-community))))
@@ -36,14 +36,13 @@
(defn view-token-gating
[id]
(when config/show-not-implemented-features?
{:icon :i/token
:right-icon :i/chevron-right
:accessibility-label :view-token-gating
:on-press #(rf/dispatch [:show-bottom-sheet
{:content (fn [] [permissions-sheet/view id])
:padding-bottom-override 16}])
:label (i18n/label :t/view-token-gating)}))
{:icon :i/token
:right-icon :i/chevron-right
:accessibility-label :view-token-gating
:on-press #(rf/dispatch [:show-bottom-sheet
{:content (fn [] [permissions-sheet/view id])
:padding-bottom-override 16}])
:label (i18n/label :t/view-token-gating)})
(defn edit-shared-addresses
[id]
@@ -56,7 +55,7 @@
(defn mark-as-read
[id]
{:icon :i/up-to-date
{:icon :i/mark-as-read
:accessibility-label :mark-as-read
:label (i18n/label :t/mark-as-read)
:on-press #(hide-sheet-and-dispatch [:chat.ui/mark-all-read-in-community-pressed id])})
@@ -136,23 +135,27 @@
request-id])}])})
(defn not-joined-options
[id token-gated? intro-message]
[[(when-not token-gated? (view-members id))
(when-not token-gated? (view-rules id intro-message))
(mark-as-read id)
(invite-contacts id)
(when token-gated? (view-token-gating id))
(show-qr id)
(share-community id)]])
[id token-gated? intro-message test-networks-enabled?]
(let [common [(show-qr id) (share-community id)]
specific (cond
(and token-gated? (not test-networks-enabled?))
[(invite-contacts id) (view-token-gating id)]
token-gated?
[(invite-contacts id)]
(not token-gated?)
[(view-members id) (view-rules id intro-message) (invite-contacts id)])]
[(concat specific common)]))
(defn join-request-sent-options
[id token-gated? request-id intro-message]
[(conj (first (not-joined-options id token-gated? intro-message))
[id token-gated? request-id intro-message test-networks-enabled?]
[(conj (first (not-joined-options id token-gated? intro-message test-networks-enabled?))
(assoc (cancel-request-to-join id request-id) :add-divider? true))])
(defn banned-options
[id token-gated? intro-message]
(not-joined-options id token-gated? intro-message))
[id token-gated? intro-message test-networks-enabled?]
(not-joined-options id token-gated? intro-message test-networks-enabled?))
(defn joined-options
[id token-gated? muted? muted-till color intro-message]
@@ -186,13 +189,19 @@
(let [{:keys [role-permissions? admin joined
muted banList muted-till color
intro-message]} (rf/sub [:communities/community id])
request-id (rf/sub [:communities/my-pending-request-to-join id])]
request-id (rf/sub [:communities/my-pending-request-to-join id])
test-networks? (rf/sub [:profile/test-networks-enabled?])]
(cond
admin (owner-options id role-permissions? muted muted-till intro-message)
joined (joined-options id role-permissions? muted muted-till color intro-message)
request-id (join-request-sent-options id role-permissions? request-id intro-message)
banList (banned-options id role-permissions? intro-message)
:else (not-joined-options id role-permissions? intro-message))))
admin
(owner-options id role-permissions? muted muted-till intro-message)
joined
(joined-options id role-permissions? muted muted-till color intro-message)
request-id
(join-request-sent-options id role-permissions? request-id intro-message test-networks?)
banList
(banned-options id role-permissions? intro-message test-networks?)
:else
(not-joined-options id role-permissions? intro-message test-networks?))))
(defn community-options-bottom-sheet
[id]
+36 -29
View File
@@ -2,6 +2,7 @@
(:require
[clojure.string :as string]
[legacy.status-im.data-store.communities :as data-store.communities]
[oops.core :as oops]
[schema.core :as schema]
[status-im.constants :as constants]
[status-im.contexts.chat.messenger.messages.link-preview.events :as link-preview.events]
@@ -25,7 +26,7 @@
token-permissions-check id last-opened-at]
:as community} (data-store.communities/<-rpc community-js)
previous-last-opened-at (get-in db [:communities id :last-opened-at])]
(when (>= clock (get-in db [:communities id :clock]))
(when (and id (>= clock (get-in db [:communities id :clock])))
{:db (assoc-in db
[:communities id]
(assoc community :last-opened-at (max last-opened-at previous-last-opened-at)))
@@ -223,14 +224,14 @@
:fx [[:dispatch [:communities/check-permissions-to-join-community community-id]]]})))
(defn community-fetched
[{:keys [db]} [community-id community]]
(when community
[{:keys [db]} [community-id community-js]]
(when community-js
{:db (update db :communities/fetching-communities dissoc community-id)
:fx [[:dispatch [:communities/handle-community community]]
:fx [[:dispatch [:communities/handle-community community-js]]
[:dispatch [:chat.ui/spectate-community community-id]]
[:dispatch
[:chat.ui/cache-link-preview-data (link-preview.events/community-link community-id)
community]]]}))
(data-store.communities/<-rpc community-js)]]]}))
(rf/reg-event-fx :chat.ui/community-fetched community-fetched)
@@ -253,18 +254,19 @@
(not (get-in db [:communities community-id]))
(not (get-in db [:communities/fetching-communities community-id])))
{:db (assoc-in db [:communities/fetching-communities community-id] true)
:json-rpc/call [{:method "wakuext_fetchCommunity"
:params [{:CommunityKey community-id
:TryDatabase true
:WaitForResponse true}]
:on-success (fn [community]
(if community
(rf/dispatch [:chat.ui/community-fetched community-id
community])
(failed-to-fetch-community
community-id
"community wasn't found at the store node")))
:on-error (partial failed-to-fetch-community community-id)}]}))
:json-rpc/call [{:method "wakuext_fetchCommunity"
:params [{:CommunityKey community-id
:TryDatabase true
:WaitForResponse true}]
:js-response true
:on-success (fn [community]
(if community
(rf/dispatch [:chat.ui/community-fetched community-id
community])
(failed-to-fetch-community
community-id
"community wasn't found at the store node")))
:on-error (partial failed-to-fetch-community community-id)}]}))
(schema/=> fetch-community
[:=>
@@ -283,11 +285,15 @@
(rf/reg-event-fx :communities/fetch-community fetch-community)
(defn spectate-community-success
[{:keys [db]} [{:keys [communities]}]]
(when-let [community (first communities)]
{:db (-> db
(assoc-in [:communities (:id community) :spectated] true))
:fx [[:dispatch [:communities/handle-community community]]]}))
[{:keys [db]} [response-js]]
(when response-js
(let [communities (oops/oget response-js "communities")
community (first communities)
community-id (when community (oops/oget community "id"))]
(when community
{:db (-> db
(assoc-in [:communities community-id :spectated] true))
:fx [[:dispatch [:communities/handle-community community]]]}))))
(rf/reg-event-fx :chat.ui/spectate-community-success spectate-community-success)
@@ -295,13 +301,14 @@
[{:keys [db]} [community-id]]
(let [{:keys [spectated joined]} (get-in db [:communities community-id])]
(when (and (not joined) (not spectated))
{:json-rpc/call [{:method "wakuext_spectateCommunity"
:params [community-id]
:on-success [:chat.ui/spectate-community-success]
:on-error (fn [err]
(log/error {:message
"Failed to spectate community"
:error err}))}]})))
{:json-rpc/call [{:method "wakuext_spectateCommunity"
:params [community-id]
:js-response true
:on-success [:chat.ui/spectate-community-success]
:on-error (fn [err]
(log/error {:message
"Failed to spectate community"
:error err}))}]})))
(schema/=> spectate-community
[:=>
@@ -1,5 +1,6 @@
(ns status-im.contexts.communities.events-test
(:require [cljs.test :refer [deftest is testing]]
[legacy.status-im.data-store.communities :as data-store.communities]
matcher-combinators.test
[status-im.contexts.chat.messenger.messages.link-preview.events :as link-preview.events]
[status-im.contexts.communities.events :as events]))
@@ -51,7 +52,7 @@
[:dispatch [:chat.ui/spectate-community community-id]]
[:dispatch
[:chat.ui/cache-link-preview-data "community-link+community-id"
{:id community-id}]]]}
(data-store.communities/<-rpc #js {"id" community-id})]]]}
(events/community-fetched cofx arg))))))
(testing "given a joined community"
(let [cofx {:db {:communities/fetching-communities {community-id true}}}
@@ -62,7 +63,7 @@
[:dispatch [:chat.ui/spectate-community community-id]]
[:dispatch
[:chat.ui/cache-link-preview-data "community-link+community-id"
{:id community-id}]]]}
(data-store.communities/<-rpc #js {"id" community-id})]]]}
(events/community-fetched cofx arg))))))
(testing "given a token-gated community"
(let [cofx {:db {:communities/fetching-communities {community-id true}}}
@@ -73,7 +74,7 @@
[:dispatch [:chat.ui/spectate-community community-id]]
[:dispatch
[:chat.ui/cache-link-preview-data "community-link+community-id"
{:id community-id}]]]}
(data-store.communities/<-rpc #js {"id" community-id})]]]}
(events/community-fetched cofx arg))))))
(testing "given nil community"
(testing "do nothing"
@@ -103,26 +104,38 @@
(events/spectate-community {:db {:communities {community-id {}}}} [community-id]))))))
(deftest spectate-community-success-test
(testing "given communities"
(testing "mark first community spectated true"
(is (match?
{:db {:communities {community-id {:spectated true}}}}
(events/spectate-community-success {} [{:communities [{:id community-id}]}]))))
(testing "dispatch fxs for first community"
(is (match?
{:fx [[:dispatch [:communities/handle-community {:id community-id}]]
]}
(events/spectate-community-success {} [{:communities [{:id community-id}]}])))))
(testing "given empty community"
(testing "do nothing"
(is (match?
nil
(events/spectate-community-success {} [{:communities []}])))))
(testing "given nil community"
(testing "do nothing"
(is (match?
nil
(events/spectate-community-success {} []))))))
(let [community-id-1 1
community-id-2 2]
(testing "given communities"
(testing "mark first community spectated true"
(is (match?
{:db {:communities {community-id-1 {:spectated true}}}}
(events/spectate-community-success {}
(clj->js [{:communities [{:id community-id-1}
{:id community-id-2}]}])))))
(testing "dispatch fxs for first community"
;; Convert the JavaScript object back to a Clojure map because `match?` does not work well
;; with JavaScript objects.
(is (match?
{:fx [[:dispatch [:communities/handle-community {:id community-id-1}]]]}
(let [result (events/spectate-community-success {}
(clj->js [{:communities
[{:id community-id-1}
{:id community-id-2}]}]))]
(update-in result [:fx 0 1] #(js->clj % :keywordize-keys true)))))))
(testing "given empty community"
(testing "do nothing"
(is (match?
nil
(events/spectate-community-success {}
(clj->js [{:communities []}]))))))
(testing "given nil community"
(testing "do nothing"
(is (match?
nil
(events/spectate-community-success {}
(clj->js []))))))))
(deftest get-revealed-accounts-test
(let [community {:id community-id}]
@@ -209,9 +209,10 @@
(when same-passwords?
[rn/view {:style style/disclaimer-container}
[quo/disclaimer
{:blur? true
:on-change (partial set-accepts-disclaimer? not)
:checked? accepts-disclaimer?}
{:blur? true
:on-change (partial set-accepts-disclaimer? not)
:checked? accepts-disclaimer?
:customization-color user-color}
(i18n/label :t/password-creation-disclaimer)]])
(when (and (= focused-input :password) (not same-passwords?))
[help
@@ -7,7 +7,6 @@
[status-im.contexts.onboarding.enable-notifications.style :as style]
[status-im.contexts.shell.jump-to.constants :as shell.constants]
[status-im.contexts.shell.jump-to.utils :as shell.utils]
[taoensso.timbre :as log]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -20,39 +19,36 @@
:description (i18n/label :t/enable-notifications-sub-title)
:description-accessibility-label :notifications-sub-title}])
(defn- finish-onboarding
[notifications-enabled?]
(rf/dispatch [:push-notifications/switch notifications-enabled?])
(shell.utils/change-selected-stack-id shell.constants/default-selected-stack true nil)
(rf/dispatch [:update-theme-and-init-root :shell-stack])
(rf/dispatch [:profile/show-testnet-mode-banner-if-enabled])
(rf/dispatch [:universal-links/process-stored-event]))
(defn enable-notification-buttons
[{:keys [insets]}]
(let [profile-color (rf/sub [:onboarding/customization-color])]
(let [profile-color (rf/sub [:onboarding/customization-color])
ask-permission (fn []
(rf/dispatch [:request-notifications
{:on-allowed (fn []
(js/setTimeout #(finish-onboarding true)
300))
:on-denied (fn []
(js/setTimeout #(finish-onboarding false)
300))}]))
skip-permission #(finish-onboarding false)]
[rn/view {:style (style/buttons insets)}
[quo/button
{:on-press (fn []
(shell.utils/change-selected-stack-id
shell.constants/default-selected-stack
true
nil)
(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 true])
(rf/dispatch [:navigate-to-within-stack
[:screen/onboarding.welcome
:screen/onboarding.enable-notifications]]))
{:on-press ask-permission
:type :primary
:icon-left :i/notifications
:accessibility-label :enable-notifications-button
:customization-color profile-color}
(i18n/label :t/intro-wizard-title6)]
[quo/button
{:on-press (fn []
(shell.utils/change-selected-stack-id
shell.constants/default-selected-stack
true
nil)
(rf/dispatch [:navigate-to-within-stack
[:screen/onboarding.welcome
:screen/onboarding.enable-notifications]]))
{:on-press skip-permission
:accessibility-label :enable-notifications-later-button
:type :grey
:background :blur
+32 -19
View File
@@ -71,17 +71,20 @@
{:events [:onboarding/create-account-and-login]}
[{:keys [db] :as cofx}]
(let [{:keys [display-name seed-phrase password image-path color] :as profile}
(:onboarding/profile db)]
(:onboarding/profile db)
loading-screen (if (seq (:syncing/key-uid db))
:screen/onboarding.preparing-status
:screen/onboarding.generating-keys)]
(rf/merge cofx
{:dispatch [:navigate-to-within-stack
[:screen/onboarding.generating-keys
[loading-screen
(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 [:navigate-to-within-stack
[:screen/onboarding.enable-notifications
:screen/onboarding.generating-keys]]}]
loading-screen]]}]
:db (-> db
(dissoc :profile/login)
(dissoc :auth-method)
@@ -134,22 +137,32 @@
(rf/defn seed-phrase-validated
{:events [:onboarding/seed-phrase-validated]}
[{:keys [db]} seed-phrase key-uid]
(if (contains? (:profile/profiles-overview db) key-uid)
{:effects.utils/show-confirmation
{:title (i18n/label :t/multiaccount-exists-title)
:content (i18n/label :t/multiaccount-exists-content)
:confirm-button-text (i18n/label :t/unlock)
:on-accept (fn []
(re-frame/dispatch [:pop-to-root :screen/profile.profiles])
(re-frame/dispatch
[:profile/profile-selected key-uid]))
: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
(get db
:onboarding/navigated-to-enter-seed-phrase-from-screen
:screen/onboarding.new-to-status)]]}))
(let [syncing-account-recovered? (and (seq (:syncing/key-uid db))
(= (:syncing/key-uid db) key-uid))
next-screen (if syncing-account-recovered?
:screen/onboarding.create-profile-password
:screen/onboarding.create-profile)]
(if (contains? (:profile/profiles-overview db) key-uid)
{:effects.utils/show-confirmation
{:title (i18n/label :t/multiaccount-exists-title)
:content (i18n/label :t/multiaccount-exists-content)
:confirm-button-text (i18n/label :t/unlock)
:on-accept (fn []
(re-frame/dispatch [:pop-to-root :screen/profile.profiles])
(re-frame/dispatch
[:profile/profile-selected key-uid]))
:on-cancel #(re-frame/dispatch [:pop-to-root :multiaccounts])}}
{:db (-> db
(assoc-in [:onboarding/profile :seed-phrase] seed-phrase)
(assoc-in [:onboarding/profile :color] constants/profile-default-color))
:fx [[:dispatch
[:navigate-to-within-stack
[next-screen
(get db
:onboarding/navigated-to-enter-seed-phrase-from-screen
:screen/onboarding.new-to-status)]]]
(when-not syncing-account-recovered?
[:dispatch [:syncing/clear-syncing-data]])]})))
(rf/defn navigate-to-create-profile
{:events [:onboarding/navigate-to-create-profile]}
@@ -0,0 +1,11 @@
(ns status-im.contexts.onboarding.preparing-status.style)
(defn page-container
[insets]
{:flex 1
:padding-top (:top insets)})
(defn page-illustration
[width]
{:flex 1
:width width})
@@ -0,0 +1,36 @@
(ns status-im.contexts.onboarding.preparing-status.view
(:require
[quo.core :as quo]
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[status-im.common.resources :as resources]
[status-im.contexts.onboarding.generating-keys.style :as style]
[utils.i18n :as i18n]))
(defn title
[]
[rn/view
{:style {:margin-top 56
:height 56
:margin-bottom 10}}
[quo/text-combinations
{:container-style {:margin-horizontal 20
:margin-vertical 12}
:title (i18n/label :t/preparing-app-for-you)
:description (i18n/label :t/hang-in-there)}]])
(defn content
[]
(let [width (:width (rn/get-window))]
[rn/image
{:resize-mode :stretch
:style (style/page-illustration width)
:source (resources/get-image :preparing-status)}]))
(defn view
[]
(let [insets (safe-area/get-insets)]
[rn/view {:style (style/page-container insets)}
[:<>
[title]
[content]]]))
@@ -27,7 +27,3 @@
:align-items :center
:align-self :center
:justify-content :center})
(def try-again-button
{:margin-top 20
:padding-horizontal 20})
@@ -5,6 +5,7 @@
[status-im.common.resources :as resources]
[status-im.contexts.onboarding.common.background.view :as background]
[status-im.contexts.onboarding.syncing.progress.style :as style]
[utils.debounce :as debounce]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -25,17 +26,40 @@
:title-accessibility-label :progress-screen-title
:description-accessibility-label :progress-screen-sub-title}])
(defn- navigate-to-enter-seed-phrase
[]
(debounce/debounce-and-dispatch
[:onboarding/navigate-to-sign-in-by-seed-phrase :screen/onboarding.sync-or-recover-profile]
500))
(defn- try-again
[logged-in?]
(rf/dispatch [:syncing/clear-states])
(if logged-in?
(rf/dispatch [:navigate-back])
(rf/dispatch [:navigate-back-to :screen/onboarding.sync-or-recover-profile])))
(defn try-again-button
[profile-color]
[quo/button
{:on-press (fn []
(rf/dispatch [:syncing/clear-states])
(rf/dispatch [:navigate-back]))
:accessibility-label :try-again-later-button
:customization-color profile-color
:size 40
:container-style style/try-again-button}
(i18n/label :t/try-again)])
[profile-color logged-in?]
[quo/bottom-actions
{:actions (if logged-in? :one-action :two-actions)
:blur? true
:button-one-label (i18n/label :t/recovery-phrase)
:button-one-props {:type :primary
:accessibility-label :try-seed-phrase-button
:customization-color profile-color
:container-style {:flex 1}
:size 40
:on-press navigate-to-enter-seed-phrase}
(if logged-in? :button-one-label :button-two-label)
(i18n/label :t/try-again)
(if logged-in? :button-one-props :button-two-props)
{:type (if logged-in? :primary :grey)
:accessibility-label :try-again-later-button
:customization-color profile-color
:container-style {:flex 1}
:size 40
:on-press #(try-again logged-in?)}}])
(defn- illustration
[pairing-progress?]
@@ -47,6 +71,7 @@
(defn view
[in-onboarding?]
(let [pairing-status (rf/sub [:pairing/pairing-status])
logged-in? (rf/sub [:multiaccount/logged-in?])
pairing-progress? (pairing-progress pairing-status)
profile-color (or (:color (rf/sub [:onboarding/profile]))
(rf/sub [:profile/customization-color]))]
@@ -58,7 +83,7 @@
[page-title pairing-progress?]
[illustration pairing-progress?]
(when-not (pairing-progress pairing-status)
[try-again-button profile-color])]))
[try-again-button profile-color logged-in?])]))
(defn view-onboarding
[]
@@ -1,36 +0,0 @@
(ns status-im.contexts.onboarding.welcome.style)
(def default-margin 20)
(defn page-container
[insets]
{:flex 1
:padding-top (:top insets)})
(defn page-illustration
[width]
{:width width
:aspect-ratio 0.7
:height :auto})
(def page-title
{:margin-top 12
:margin-horizontal 20
:margin-bottom 8})
(defn buttons
[insets]
{:position :absolute
:left 0
:right 0
:padding-left default-margin
:padding-right default-margin
:bottom (+ 12 (:bottom insets))})
(def bottom-shadow
{:position :absolute
:height 64
:top 0
:bottom 0
:left 0
:right 0})
@@ -1,54 +0,0 @@
(ns status-im.contexts.onboarding.welcome.view
(:require
[quo.core :as quo]
[quo.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.linear-gradient :as linear-gradient]
[react-native.safe-area :as safe-area]
[status-im.common.resources :as resources]
[status-im.contexts.onboarding.welcome.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn page-title
[]
(let [new-account? (rf/sub [:onboarding/new-account?])]
[quo/text-combinations
{:container-style style/page-title
:title (i18n/label (if new-account?
:t/welcome-to-web3
:t/welcome-back))
:title-accessibility-label :welcome-title
:description (i18n/label :t/welcome-to-web3-sub-title)
:description-accessibility-label :welcome-sub-title}]))
(defn view
[]
(let [profile-color (rf/sub [:onboarding/customization-color])
window (rf/sub [:dimensions/window])
insets (safe-area/get-insets)]
[rn/view {:style (style/page-container insets)}
[quo/page-nav
{:type :no-title
:background :blur
:icon-name :i/arrow-left
:on-press #(rf/dispatch [:navigate-back])}]
[page-title]
[rn/image
{:style (style/page-illustration (:width window))
:resize-mode :contain
:source (resources/get-image :welcome-illustration)}]
[rn/view {:style (style/buttons insets)}
(when rn/small-screen?
[linear-gradient/linear-gradient
{:style style/bottom-shadow
:colors [colors/neutral-100-opa-0 colors/neutral-100-opa-80]}])
[quo/button
{:on-press (fn []
(rf/dispatch [:update-theme-and-init-root :shell-stack])
(rf/dispatch [:profile/show-testnet-mode-banner-if-enabled])
(rf/dispatch [:universal-links/process-stored-event]))
:type :primary
:accessibility-label :welcome-button
:customization-color profile-color}
(i18n/label :t/start-using-status)]]]))
+19 -16
View File
@@ -34,22 +34,25 @@
(defn create
[]
(let [log-enabled? (boolean (not-empty config/log-level))]
(assoc (login)
:deviceName (native-module/get-installation-name)
:rootDataDir (native-module/backup-disabled-data-dir)
:rootKeystoreDir (native-module/keystore-dir)
:logLevel (when log-enabled? config/log-level)
:logEnabled log-enabled?
:logFilePath (native-module/log-file-directory)
:verifyTransactionURL config/verify-transaction-url
:verifyENSURL config/verify-ens-url
:verifyENSContractAddress config/verify-ens-contract-address
:verifyTransactionChainID config/verify-transaction-chain-id
:wakuV2LightClient true
:wakuV2Fleet config/fleet
:wakuV2EnableStoreConfirmationForMessagesSent false
:previewPrivacy config/blank-preview?
:testNetworksEnabled config/test-networks-enabled?)))
(assoc
(login)
:deviceName (native-module/get-installation-name)
:rootDataDir (native-module/backup-disabled-data-dir)
:rootKeystoreDir (native-module/keystore-dir)
:logLevel (when log-enabled? config/log-level)
:logEnabled log-enabled?
:logFilePath (native-module/log-file-directory)
:verifyTransactionURL config/verify-transaction-url
:verifyENSURL config/verify-ens-url
:verifyENSContractAddress config/verify-ens-contract-address
:verifyTransactionChainID config/verify-transaction-chain-id
:wakuV2LightClient true
:wakuV2Fleet config/fleet
;; NOTE: https://github.com/status-im/status-go/pull/5570#discussion_r1690794119
:wakuV2EnableMissingMessageVerification true
:wakuV2EnableStoreConfirmationForMessagesSent false
:previewPrivacy config/blank-preview?
:testNetworksEnabled config/test-networks-enabled?)))
(defn strip-file-prefix
[path]
@@ -142,6 +142,8 @@
(rf/dispatch [:chats-list/load-success result])
(rf/dispatch [:communities/get-user-requests-to-join])
(rf/dispatch [:profile.login/get-chats-callback]))}]
(when (:syncing/installation-id db)
[:dispatch [:pairing/finish-seed-phrase-fallback-syncing]])
(when-not new-account?
[:dispatch [:universal-links/process-stored-event]])]})))
@@ -1,6 +1,7 @@
(ns status-im.contexts.profile.recover.events
(:require
[native-module.core :as native-module]
[status-im.constants :as constants]
[status-im.contexts.profile.config :as profile.config]
status-im.contexts.profile.recover.effects
[utils.re-frame :as rf]
@@ -16,10 +17,10 @@
(assoc-in [:syncing :login-sha3-password] login-sha3-password))
:effects.profile/restore-and-login
(merge (profile.config/create)
{:displayName display-name
:mnemonic (security/safe-unmask-data seed-phrase)
:password login-sha3-password
:imagePath (profile.config/strip-file-prefix image-path)
:customizationColor color
:fetchBackup true})}))
(assoc (profile.config/create)
:displayName display-name
:mnemonic (security/safe-unmask-data seed-phrase)
:password login-sha3-password
:imagePath (profile.config/strip-file-prefix image-path)
:customizationColor (or color constants/profile-default-color)
:fetchBackup true)}))
@@ -0,0 +1,78 @@
(ns status-im.contexts.shell.activity-center.notification.syncing.view
(:require
[quo.core :as quo]
quo.theme
[react-native.core :as rn]
[status-im.common.new-device-sheet.view :as new-device-sheet]
[status-im.contexts.shell.activity-center.notification.common.view :as common]
[utils.datetime :as datetime]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- swipeable
[{:keys [extra-fn]} child]
[common/swipeable
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:extra-fn extra-fn}
child])
(defn installation-created-view
[{:keys [notification extra-fn]}]
(let [{:keys [installation-id read timestamp]} notification
customization-color (rf/sub [:profile/customization-color])
theme (quo.theme/use-theme)
more-details (rn/use-callback
(fn []
(rf/dispatch [:show-bottom-sheet
{:content
(fn []
[new-device-sheet/installation-request-creator-view
installation-id])}]))
[installation-id])]
[swipeable {:extra-fn extra-fn}
[quo/activity-log
{:title (i18n/label :t/sync-your-profile)
:customization-color customization-color
:icon :i/mobile
:timestamp (datetime/timestamp->relative timestamp)
:unread? (not read)
:context [(i18n/label :t/check-other-device-for-pairing)]
:items [{:type :button
:subtype :positive
:key :review-pairing-request
:blur? true
:label (i18n/label :t/more-details)
:theme theme
:on-press more-details}]}]]))
(defn installation-received-view
[{:keys [notification extra-fn]}]
(let [{:keys [installation-id read timestamp]} notification
customization-color (rf/sub [:profile/customization-color])
theme (quo.theme/use-theme)
review-pairing-request (rn/use-callback
(fn []
(rf/dispatch [:show-bottom-sheet
{:content
(fn []
[new-device-sheet/installation-request-receiver-view
installation-id])}]))
[installation-id])]
[swipeable {:extra-fn extra-fn}
[quo/activity-log
{:title (i18n/label :t/new-device-detected)
:customization-color customization-color
:icon :i/mobile
:timestamp (datetime/timestamp->relative timestamp)
:unread? (not read)
:context [(i18n/label :t/new-device-detected)]
:items [{:type :button
:subtype :positive
:key :review-pairing-request
:blur? true
:label (i18n/label :t/review-pairing-request)
:theme theme
:on-press review-pairing-request}]}]]))
@@ -10,6 +10,8 @@
(def ^:const admin 8)
(def ^:const community-kicked 9)
(def ^:const contact-verification 10)
(def ^:const new-installation-received 23)
(def ^:const new-installation-created 24)
(def ^:const all-supported
#{one-to-one-chat
@@ -20,7 +22,9 @@
community-request
admin
community-kicked
contact-verification})
contact-verification
new-installation-received
new-installation-created})
;; TODO: Replace with correct enum values once status-go implements them.
(def ^:const tx 66612)
@@ -19,6 +19,7 @@
[status-im.contexts.shell.activity-center.notification.membership.view :as membership]
[status-im.contexts.shell.activity-center.notification.mentions.view :as mentions]
[status-im.contexts.shell.activity-center.notification.reply.view :as reply]
[status-im.contexts.shell.activity-center.notification.syncing.view :as syncing]
[status-im.contexts.shell.activity-center.style :as style]
[status-im.contexts.shell.activity-center.tabs.empty-tab.view :as empty-tab]
[utils.re-frame :as rf]))
@@ -48,6 +49,12 @@
(= notification-type types/admin)
[admin/view props]
(= notification-type types/new-installation-received)
[syncing/installation-received-view props]
(= notification-type types/new-installation-created)
[syncing/installation-created-view props]
(types/membership notification-type)
(condp = notification-type
types/private-group-chat [membership/view props]
@@ -84,7 +84,7 @@
(load-and-show-profile scanned-text)
(utils-address/supported-address? scanned-text)
(when-let [address (utils-address/supported-address->status-address scanned-text)]
(when-let [address (utils-address/supported-address->eth-address scanned-text)]
(debounce/debounce-and-dispatch [:generic-scanner/scan-success address] 300)
(debounce/debounce-and-dispatch [:navigate-change-tab :wallet-stack] 300))
+32 -3
View File
@@ -2,6 +2,7 @@
(:require
[clojure.string :as string]
[native-module.core :as native-module]
[re-frame.core :as re-frame]
[react-native.platform :as platform]
[status-im.constants :as constants]
[status-im.contexts.profile.config :as profile.config]
@@ -21,18 +22,45 @@
{:events [:syncing/clear-states]}
[{:keys [db]} role]
{:db (dissoc db :syncing)})
(defn- input-connection-string-callback
[res]
(log/info "[local-pairing] input-connection-string-for-bootstrapping callback"
{:response res
:event :syncing/input-connection-string-for-bootstrapping})
(let [error (when (sync-utils/extract-error res)
(str "generic-error: " res))]
(when (some? error)
(let [response (transforms/json->clj res)
installation-id (:installationId response)
key-uid (:keyUID response)
error (:error response)]
(when (seq installation-id)
(rf/dispatch [:syncing/set-syncing-installation-id installation-id key-uid]))
(when (seq error)
(rf/dispatch [:toasts/upsert
{:type :negative
:text error}]))))
(rf/defn initiate-pairing-process
{:events [:syncing/initiate-pairing-process]}
[{:keys [db]}]
{:db (assoc db :syncing/pairing-process-initiated? true)})
(rf/defn set-syncing-installation-id
{:events [:syncing/set-syncing-installation-id]}
[{:keys [db]} installation-id key-uid]
{:db (assoc db
:syncing/key-uid key-uid
:syncing/installation-id installation-id)})
(defn clear-syncing-data
[{:keys [db]}]
{:db (dissoc
db
:syncing/key-uid
:syncing/installation-id
:syncing/pairing-process-initiated?)})
(re-frame/reg-event-fx :syncing/clear-syncing-data clear-syncing-data)
(rf/defn preflight-outbound-check-for-local-pairing
{:events [:syncing/preflight-outbound-check]}
[_ set-checks-passed]
@@ -67,6 +95,7 @@
(when (sync-utils/valid-connection-string? response)
(on-valid-connection-string response)
(rf/dispatch [:syncing/update-role constants/local-pairing-role-sender])
(rf/dispatch [:syncing/initiate-pairing-process])
(rf/dispatch [:hide-bottom-sheet])))]
(when-not (and error (string/blank? error))
(let [key-uid (get-in db [:profile/profile :key-uid])
@@ -244,7 +244,10 @@
first
key)
ownership-status (get ownership-status-by-address owner-address)
collectibles (data-store/rpc->collectibles collectibles)
collectibles (->> collectibles
data-store/rpc->collectibles
(map #(update % :ownership distinct))
vec)
pending-requests (dec (get-in db [:wallet :ui :collectibles :pending-requests]))
;; check if collectibles are updating (never fetched and cached before) for this address
updating-chains (-> (select-keys
@@ -301,16 +304,20 @@
old-value
new-value))
(def merge-skipping-empty-values (partial merge-with keep-not-empty-value))
(rf/reg-event-fx
:wallet/get-collectible-details-done
(fn [{db :db} [{:keys [message]}]]
(let [response (cske/transform-keys transforms/->kebab-case-keyword
(transforms/json->clj message))
{[collectible] :collectibles} response]
{[collectible] :collectibles} response
known-collectible-info (get-in db [:wallet :ui :collectible :details])
merged-collectible (as-> known-collectible-info c
(merge-with keep-not-empty-value
c
collectible)
(update c :ownership distinct))]
(if collectible
{:db (update-in db [:wallet :ui :collectible :details] merge-skipping-empty-values collectible)}
{:db (assoc-in db [:wallet :ui :collectible :details] merged-collectible)}
(log/error "failed to get collectible details"
{:event :wallet/get-collectible-details-done
:response response})))))
@@ -63,7 +63,9 @@
(defn view
[collectible]
(let [owner-account (rf/sub [:wallet/collectible-details-owner collectible])
(let [owner-address (or (rf/sub [:wallet/current-viewing-account-address])
(-> collectible :ownership first :address))
owner-account (rf/sub [:wallet-connect/account-details-by-address owner-address])
traits (-> collectible :collectible-data :traits)]
[:<>
[info
@@ -15,7 +15,6 @@
(def supported-collectible-types
#{"image/jpeg"
"image/gif"
"image/bmp"
"image/png"
"image/webp"
@@ -157,12 +157,10 @@
set-title-ref (rn/use-callback #(reset! title-ref %))
animation-shared-element-id (rf/sub [:animation-shared-element-id])
collectible (rf/sub [:wallet/collectible-details])
collectible-owner (rf/sub [:wallet/collectible-details-owner collectible])
collectible-owner (rf/sub [:wallet/current-viewing-account])
aspect-ratio (rf/sub [:wallet/collectible-aspect-ratio])
gradient-color (rf/sub [:wallet/collectible-gradient-color])
total-owned (rf/sub [:wallet/total-owned-collectible
(:ownership collectible)
(:address collectible-owner)])
total-owned (:total-owned collectible)
{:keys [id
preview-url
collection-data
@@ -40,7 +40,8 @@
[quo/collectible-list-item
{:type :card
:image-src (:uri preview-url)
:avatar-image-src (:image-url collection-data)
:avatar-image-src (when (utils/supported-file? (:image-url collection-data))
(:image-url collection-data))
:collectible-name (:name collectible-data)
:supported-file? (utils/supported-file? (:animation-media-type collectible-data))
:gradient-color-index gradient-color
@@ -15,7 +15,7 @@
:error-message (i18n/label :t/oops-this-qr-does-not-contain-an-address)
:validate-fn #(utils-address/supported-address? %)
:on-success-scan (fn [result]
(let [address (utils-address/supported-address->status-address result)]
(let [address (utils-address/supported-address->eth-address result)]
(when on-result (on-result address))
(debounce/debounce-and-dispatch
[:wallet/scan-address-success address]
@@ -284,7 +284,7 @@
collectible
(str (:name collection-data) " #" collectible-id))
owner-address (-> collectible :ownership first :address)
owner-address (-> db :wallet :current-viewing-account-address)
collectible-tx (-> db
(update-in [:wallet :ui :send] dissoc :token)
(assoc-in [:wallet :ui :send :collectible] collectible)
@@ -30,14 +30,15 @@
(let [collectibles (rf/sub [:wallet/current-viewing-account-collectibles-filtered search-text])
search-performed? (not (string/blank? search-text))]
[collectibles-tab/view
{:collectibles collectibles
:filtered? search-performed?
:on-end-reached #(rf/dispatch [:wallet/request-collectibles-for-current-viewing-account])
:on-collectible-press (fn [{:keys [collectible]}]
(rf/dispatch [:wallet/set-collectible-to-send
{:collectible collectible
:current-screen :screen/wallet.select-asset
:entry-point :account-send-button}]))}]))
{:collectibles collectibles
:current-account-address (rf/sub [:wallet/current-viewing-account-address])
:filtered? search-performed?
:on-end-reached #(rf/dispatch [:wallet/request-collectibles-for-current-viewing-account])
:on-collectible-press (fn [{:keys [collectible]}]
(rf/dispatch [:wallet/set-collectible-to-send
{:collectible collectible
:current-screen :screen/wallet.select-asset
:entry-point :account-send-button}]))}]))
(defn- tab-view
[search-text selected-tab on-change-text]
@@ -15,7 +15,9 @@
#(rf/dispatch [:wallet/collectible-amount-navigate-back]))
send-transaction-data (rf/sub [:wallet/wallet-send])
collectible (:collectible send-transaction-data)
balance (utils/collectible-balance collectible)
sender-address (rf/sub [:wallet/current-viewing-account-address])
balance (rf/sub [:wallet/total-owned-collectible (:ownership collectible)
sender-address])
[input-state set-input-state] (rn/use-state (-> controlled-input/init-state
(controlled-input/set-value-numeric 1)
(controlled-input/set-lower-limit 1)))
+70 -27
View File
@@ -8,9 +8,8 @@
[taoensso.timbre :as log]
[utils.address :as address]
[utils.debounce :as debounce]
[utils.hex :as hex]
[utils.i18n :as i18n]
[utils.number]
[utils.money :as money]
[utils.number :as number]))
(rf/reg-event-fx :wallet.swap/start
@@ -47,14 +46,14 @@
(rf/reg-event-fx :wallet.swap/set-max-slippage
(fn [{:keys [db]} [max-slippage]]
{:db (assoc-in db [:wallet :ui :swap :max-slippage] (utils.number/parse-float max-slippage))}))
{:db (assoc-in db [:wallet :ui :swap :max-slippage] (number/parse-float max-slippage))}))
(rf/reg-event-fx :wallet.swap/select-asset-to-receive
(fn [{:keys [db]} [{:keys [token]}]]
{:db (assoc-in db [:wallet :ui :swap :asset-to-receive] token)}))
(rf/reg-event-fx :wallet/start-get-swap-proposal
(fn [{:keys [db]} [{:keys [amount-in amount-out]}]]
(fn [{:keys [db]} [{:keys [amount-in amount-out clean-approval-transaction?]}]]
(let [wallet-address (get-in db [:wallet :current-viewing-account-address])
{:keys [asset-to-pay asset-to-receive
network]} (get-in db [:wallet :ui :swap])
@@ -97,12 +96,17 @@
(when-let [amount (or amount-in amount-out)]
{:db (update-in db
[:wallet :ui :swap]
#(-> %
(assoc
:last-request-uuid request-uuid
:amount amount
:loading-swap-proposal? true)
(dissoc :error-response)))
#(cond-> %
:always
(assoc
:last-request-uuid request-uuid
:amount amount
:amount-hex amount-in-hex
:loading-swap-proposal? true)
:always
(dissoc :error-response)
clean-approval-transaction?
(dissoc :approval-transaction-id :approved-amount :swap-proposal)))
:json-rpc/call [{:method "wallet_getSuggestedRoutesAsync"
:params params
:on-error (fn [error]
@@ -115,17 +119,30 @@
(rf/reg-event-fx :wallet/swap-proposal-success
(fn [{:keys [db]} [swap-proposal]]
(let [last-request-uuid (get-in db [:wallet :ui :swap :last-request-uuid])
amount-hex (get-in db [:wallet :ui :swap :amount-hex])
view-id (:view-id db)
request-uuid (:uuid swap-proposal)
best-routes (:best swap-proposal)
error-response (:error-response swap-proposal)]
(when (= request-uuid last-request-uuid)
(when (and (= request-uuid last-request-uuid)
(or (and (empty? best-routes) error-response)
(and
(pos? (count best-routes))
(= (:amount-in (first best-routes)) amount-hex))))
(cond-> {:db (update-in db
[:wallet :ui :swap]
assoc
:swap-proposal (first best-routes)
:swap-proposal (when-not (empty? best-routes)
(assoc (first best-routes) :uuid request-uuid))
:error-response (when (empty? best-routes) error-response)
:loading-swap-proposal? false)}
(empty? best-routes)
(assoc :fx
[[:dispatch
[:toasts/upsert
{:id :swap-proposal-error
:type :negative
:text error-response}]]])
;; Router is unstable and it can return a swap proposal and after auto-refetching it can
;; return an error. Ideally this shouldn't happen, but adding this behavior so if the
;; user is in swap confirmation screen or in token approval confirmation screen, we
@@ -156,16 +173,18 @@
{:event :wallet/stop-get-swap-proposal
:error error}))}]}))
(rf/reg-event-fx :wallet/clean-swap-proposal
(fn [{:keys [db]}]
{:db (update-in db
[:wallet :ui :swap]
dissoc
:last-request-uuid
:swap-proposal
:error-response
:loading-swap-proposal?
:approval-transaction-id)}))
(rf/reg-event-fx
:wallet/clean-swap-proposal
(fn [{:keys [db]} [{:keys [clean-approval-transaction?]}]]
(let [keys-to-dissoc (cond-> [:amount
:amount-hex
:last-request-uuid
:swap-proposal
:error-response
:loading-swap-proposal?]
clean-approval-transaction? (conj :approval-transaction-id :approved-amount))]
{:db (apply update-in db [:wallet :ui :swap] dissoc keys-to-dissoc)
:fx [[:dispatch [:wallet/stop-get-swap-proposal]]]})))
(rf/reg-event-fx :wallet/clean-swap
(fn [{:keys [db]}]
@@ -245,10 +264,8 @@
constants/min-token-decimals-to-display)
receive-amount (when amount-out
(number/remove-trailing-zeroes
(.toFixed (number/convert-to-whole-number
(native-module/hex-to-number
(hex/normalize-hex
amount-out))
(.toFixed (number/hex->whole
amount-out
receive-token-decimals)
decimals-to-display)))]
(rf/dispatch [:wallet.swap/add-authorized-transaction
@@ -268,7 +285,7 @@
:screen/wallet.swap-confirmation)])
(when-not approval-required?
(rf/dispatch [:wallet/select-account-tab :activity])
(debounce/debounce-and-dispatch [:wallet/clean-swap] 1000)
(rf/dispatch [:wallet/clean-swap])
(debounce/debounce-and-dispatch
[:toasts/upsert
{:id :swap-transaction-pending
@@ -342,6 +359,8 @@
:token-symbol token-symbol
:provider-name provider-name
:account-name account-name}))}]]]}
transaction-confirmed?
(assoc :db (assoc-in db [:wallet :ui :swap :approved-amount] amount))
(not transaction-confirmed?)
(assoc :db (update-in db [:wallet :ui :swap] dissoc :approval-transaction-id)))))))
@@ -368,3 +387,27 @@
:receive-token-symbol receive-token-symbol
:receive-amount receive-amount})
(i18n/label :t/swap-failed))}]]]}))))
(rf/reg-event-fx :wallet.swap/flip-assets
(fn [{:keys [db]}]
(let [{:keys [asset-to-pay asset-to-receive
swap-proposal amount]} (get-in db [:wallet :ui :swap])
receive-token-decimals (:decimals asset-to-receive)
amount-out (when swap-proposal (:amount-out swap-proposal))
receive-amount (when amount-out
(-> amount-out
(number/hex->whole receive-token-decimals)
(money/to-fixed receive-token-decimals)))]
{:db (update-in db
[:wallet :ui :swap]
#(-> %
(assoc
:asset-to-pay asset-to-receive
:asset-to-receive asset-to-pay
:amount (or receive-amount amount))
(dissoc :swap-proposal
:error-response
:loading-swap-proposal?
:last-request-uuid
:approved-amount
:approval-transaction-id)))})))
@@ -212,7 +212,7 @@
(defn- slide-button
[]
(let [loading-swap-proposal? (rf/sub [:wallet/swap-loading-swap-proposal?])
swap-proposal (rf/sub [:wallet/swap-proposal])
swap-proposal (rf/sub [:wallet/swap-proposal-without-fees])
account (rf/sub [:wallet/current-viewing-account])
on-auth-success (rn/use-callback #(rf/dispatch
[:wallet/swap-transaction
@@ -1,6 +1,5 @@
(ns status-im.contexts.wallet.swap.setup-swap.view
(:require [clojure.string :as string]
[native-module.core :as native-module]
[quo.core :as quo]
[react-native.core :as rn]
[react-native.platform :as platform]
@@ -11,7 +10,7 @@
[status-im.contexts.wallet.common.account-switcher.view :as account-switcher]
[status-im.contexts.wallet.common.utils :as utils]
[status-im.contexts.wallet.swap.setup-swap.style :as style]
[utils.hex :as hex]
[utils.debounce :as debounce]
[utils.i18n :as i18n]
[utils.money :as money]
[utils.number :as number]
@@ -22,14 +21,18 @@
(defn- on-close
[]
(rf/dispatch [:wallet/clean-swap-proposal])
(rf/dispatch [:wallet/clean-swap-proposal {:clean-approval-transaction? true}])
(events-helper/navigate-back))
(defn- fetch-swap-proposal
[{:keys [amount valid-input?]}]
[{:keys [amount valid-input? clean-approval-transaction?]}]
(if valid-input?
(rf/dispatch [:wallet/start-get-swap-proposal {:amount-in amount}])
(rf/dispatch [:wallet/clean-swap-proposal])))
(debounce/debounce-and-dispatch [:wallet/start-get-swap-proposal
{:amount-in amount
:clean-approval-transaction? clean-approval-transaction?}]
100)
(rf/dispatch [:wallet/clean-swap-proposal
{:clean-approval-transaction? clean-approval-transaction?}])))
(defn- data-item
[{:keys [title subtitle size subtitle-icon loading?]}]
@@ -69,11 +72,13 @@
asset-to-pay (rf/sub [:wallet/swap-asset-to-pay])
currency (rf/sub [:profile/currency])
loading-swap-proposal? (rf/sub [:wallet/swap-loading-swap-proposal?])
swap-proposal (rf/sub [:wallet/swap-proposal])
swap-proposal (rf/sub [:wallet/swap-proposal-without-fees])
approval-required (rf/sub [:wallet/swap-proposal-approval-required])
approval-amount-required (rf/sub [:wallet/swap-proposal-approval-amount-required])
currency-symbol (rf/sub [:profile/currency-symbol])
approval-transaction-status (rf/sub [:wallet/swap-approval-transaction-status])
approval-transaction-id (rf/sub [:wallet/swap-approval-transaction-id])
approved-amount (rf/sub [:wallet/swap-approved-amount])
pay-input-num-value (controlled-input/value-numeric input-state)
pay-input-amount (controlled-input/input-value input-state)
pay-token-symbol (:symbol asset-to-pay)
@@ -93,16 +98,16 @@
(min pay-token-decimals
constants/min-token-decimals-to-display)))
approval-amount-required-num (when approval-amount-required
(str (number/convert-to-whole-number
(native-module/hex-to-number
(hex/normalize-hex
approval-amount-required))
pay-token-decimals)))
pay-input-error? (and (not (string/blank? pay-input-amount))
(money/greater-than
(money/bignumber pay-input-num-value)
(money/bignumber
pay-token-balance-selected-chain)))
(str (number/hex->whole approval-amount-required
pay-token-decimals)))
pay-input-error? (or (and (not (string/blank? pay-input-amount))
(money/greater-than
(money/bignumber pay-input-num-value)
(money/bignumber
pay-token-balance-selected-chain)))
(money/equal-to (money/bignumber
available-crypto-limit)
(money/bignumber 0)))
valid-pay-input? (and
(not (string/blank?
pay-input-amount))
@@ -111,8 +116,9 @@
request-fetch-swap-proposal (rn/use-callback
(fn []
(fetch-swap-proposal
{:amount pay-input-amount
:valid-input? valid-pay-input?}))
{:amount pay-input-amount
:valid-input? valid-pay-input?
:clean-approval-transaction? true}))
[pay-input-amount])]
(rn/use-effect
(fn []
@@ -123,7 +129,8 @@
:error? pay-input-error?
:token pay-token-symbol
:customization-color :blue
:show-approval-label? (and swap-proposal approval-required)
:show-approval-label? (or (and swap-proposal approval-required)
approval-transaction-id)
:auto-focus? true
:show-keyboard? false
:status (cond
@@ -145,7 +152,7 @@
:confirmed :approved
:finalised :approved
:approve)
:token-value approval-amount-required-num
:token-value (or approval-amount-required-num approved-amount)
:button-props {:on-press on-approve-press}
:customization-color account-color
:token-symbol pay-token-symbol}}]))
@@ -169,14 +176,9 @@
receive-token-symbol (:symbol asset-to-receive)
receive-token-decimals (:decimals asset-to-receive)
amount-out-whole-number (when amount-out
(number/convert-to-whole-number
(native-module/hex-to-number
(utils.hex/normalize-hex
amount-out))
receive-token-decimals))
(number/hex->whole amount-out receive-token-decimals))
amount-out-num (if amount-out-whole-number
(number/remove-trailing-zeroes
(.toFixed amount-out-whole-number receive-token-decimals))
(number/to-fixed amount-out-whole-number receive-token-decimals)
default-text-for-unfocused-input)
receive-token-fiat-value (str (utils/calculate-token-fiat-value
{:currency currency
@@ -205,7 +207,7 @@
(defn- action-button
[{:keys [on-press]}]
(let [account-color (rf/sub [:wallet/current-viewing-account-color])
swap-proposal (rf/sub [:wallet/swap-proposal])
swap-proposal (rf/sub [:wallet/swap-proposal-without-fees])
loading-swap-proposal? (rf/sub [:wallet/swap-loading-swap-proposal?])
approval-required? (rf/sub [:wallet/swap-proposal-approval-required])
approval-transaction-status (rf/sub [:wallet/swap-approval-transaction-status])]
@@ -223,10 +225,10 @@
[]
(let [[pay-input-state set-pay-input-state] (rn/use-state controlled-input/init-state)
[pay-input-focused? set-pay-input-focused?] (rn/use-state true)
[refetch-interval set-refetch-interval] (rn/use-state nil)
refetch-interval (rn/use-ref-atom nil)
error-response (rf/sub [:wallet/swap-error-response])
loading-swap-proposal? (rf/sub [:wallet/swap-loading-swap-proposal?])
swap-proposal (rf/sub [:wallet/swap-proposal])
swap-proposal (rf/sub [:wallet/swap-proposal-without-fees])
asset-to-pay (rf/sub [:wallet/swap-asset-to-pay])
network (rf/sub [:wallet/swap-network])
pay-input-amount (controlled-input/input-value pay-input-state)
@@ -270,7 +272,9 @@
(fn []
(set-pay-input-state
controlled-input/delete-last)
(rf/dispatch [:wallet/clean-swap-proposal])))
(rf/dispatch [:wallet/clean-swap-proposal
{:clean-approval-transaction?
true}])))
on-max-press (rn/use-callback
(fn [max-value]
(set-pay-input-state
@@ -280,32 +284,66 @@
max-value)))))
on-refresh-swap-proposal (rn/use-callback
(fn []
(let [bottom-sheets (rf/sub
[:bottom-sheet-sheets])]
(let
[bottom-sheets (rf/sub
[:bottom-sheet-sheets])
approval-transaction-status
(rf/sub
[:wallet/swap-approval-transaction-status])]
(when-not valid-pay-input?
(js/clearInterval refetch-interval)
(set-refetch-interval nil))
(when @refetch-interval
(js/clearTimeout @refetch-interval))
(reset! refetch-interval nil))
(when @refetch-interval
(js/clearTimeout @refetch-interval))
(reset! refetch-interval nil)
(when (and valid-pay-input?
(not loading-swap-proposal?)
(not bottom-sheets))
(not bottom-sheets)
(not= approval-transaction-status
:pending))
(fetch-swap-proposal
{:amount pay-input-amount
:valid-input? valid-pay-input?}))))
{:amount pay-input-amount
:valid-input? valid-pay-input?
:clean-approval-transaction? false}))))
[valid-pay-input? loading-swap-proposal?
pay-input-amount])]
pay-input-amount])
on-asset-to-pay-change (fn []
(when valid-pay-input?
(fetch-swap-proposal
{:amount pay-input-amount
:valid-input? valid-pay-input?
:clean-approval-transaction? true})))]
(rn/use-effect (fn []
(when refetch-interval
(js/clearInterval refetch-interval)
(set-refetch-interval nil))
(when @refetch-interval
(js/clearInterval @refetch-interval)
(reset! refetch-interval nil))
(when (or swap-proposal error-response)
(set-refetch-interval (js/setInterval
on-refresh-swap-proposal
constants/swap-proposal-refresh-interval-ms))))
(reset! refetch-interval
(js/setInterval
on-refresh-swap-proposal
constants/swap-proposal-refresh-interval-ms))))
[swap-proposal error-response])
(rn/use-unmount (fn []
(when refetch-interval
(js/clearInterval refetch-interval)
(set-refetch-interval nil))))
(rf/dispatch [:wallet/clean-swap-proposal {:clean-approval-transaction? true}])
(when @refetch-interval
(js/clearInterval @refetch-interval)
(reset! refetch-interval nil))))
(rn/use-effect
(fn []
(when asset-to-pay
(let [swap-amount (rf/sub [:wallet/swap-amount])]
(when (and swap-amount refetch-interval)
(js/clearTimeout @refetch-interval)
(reset! refetch-interval nil))
(if (and swap-amount (not= swap-amount pay-input-amount))
(set-pay-input-state
(fn [input-state]
(controlled-input/set-input-value
input-state
swap-amount)))
(on-asset-to-pay-change)))))
[asset-to-pay])
[rn/view {:style style/container}
[account-switcher/view
{:on-press on-close
@@ -322,7 +360,12 @@
:on-input-focus (fn []
(when platform/android? (rf/dispatch [:dismiss-keyboard]))
(set-pay-input-focused? true))}]
[swap-order-button {:on-press #(js/alert "Swap Order Pressed")}]
[swap-order-button
{:on-press (fn []
(when @refetch-interval
(js/clearTimeout @refetch-interval)
(reset! refetch-interval nil))
(rf/dispatch [:wallet.swap/flip-assets]))}]
[receive-token-input
{:input-focused? (not pay-input-focused?)
:on-token-press #(js/alert "Token Pressed")
@@ -157,12 +157,13 @@
(defn- slide-button
[]
(let [loading-swap-proposal? (rf/sub [:wallet/swap-loading-swap-proposal?])
swap-proposal (rf/sub [:wallet/swap-proposal])
swap-proposal (rf/sub [:wallet/swap-proposal-without-fees])
account (rf/sub [:wallet/current-viewing-account])
account-color (:color account)
on-auth-success (rn/use-callback #(rf/dispatch
[:wallet/swap-transaction
(security/safe-unmask-data %)]))]
on-auth-success (rn/use-callback (fn [data]
(rf/dispatch [:wallet/stop-get-swap-proposal])
(rf/dispatch [:wallet/swap-transaction
(security/safe-unmask-data data)])))]
[standard-auth/slide-button
{:size :size-48
:track-text (i18n/label :t/slide-to-swap)
@@ -1,5 +1,6 @@
(ns status-im.contexts.wallet.wallet-connect.events.session-proposals
(:require [re-frame.core :as rf]
(:require [clojure.string :as string]
[re-frame.core :as rf]
[react-native.wallet-connect :as wallet-connect]
[status-im.contexts.wallet.wallet-connect.utils.data-store :as
data-store]
@@ -59,21 +60,30 @@
:wallet-connect/on-session-proposal
(fn [{:keys [db]} [proposal]]
(log/info "Received Wallet Connect session proposal: " proposal)
(let [accounts (get-in db [:wallet :accounts])
current-viewing-address (get-in db [:wallet :current-viewing-account-address])
available-accounts (sessions/filter-operable-accounts (vals accounts))
networks (networks/get-networks-by-mode db)
session-networks (networks/proposal-networks-intersection proposal networks)
required-networks-supported? (networks/required-networks-supported? proposal networks)]
(let [accounts (get-in db [:wallet :accounts])
current-viewing-address (get-in db [:wallet :current-viewing-account-address])
sessions (get db :wallet-connect/sessions)
available-accounts (sessions/filter-operable-accounts (vals accounts))
latest-connected-account-address (sessions/latest-connected-account-address sessions)
networks (networks/get-networks-by-mode db)
session-networks (networks/proposal-networks-intersection proposal networks)
required-networks-supported? (networks/required-networks-supported? proposal networks)]
(if (and (not-empty session-networks) required-networks-supported?)
{:db (update db
:wallet-connect/current-proposal assoc
:request proposal
:session-networks session-networks
:address (or current-viewing-address
(-> available-accounts
first
:address)))
:address (cond
(not (string/blank? current-viewing-address))
current-viewing-address
(not (string/blank?
latest-connected-account-address))
latest-connected-account-address
:else (-> available-accounts
first
:address)))
:fx [[:dispatch [:open-modal :screen/wallet.wallet-connect-session-proposal]]]}
{:fx [[:dispatch [:wallet-connect/show-session-networks-unsupported-toast proposal]]
[:dispatch [:wallet-connect/reject-session-proposal proposal]]]}))))
@@ -31,3 +31,14 @@
account-addresses))
accounts))
sessions))
(defn latest-connected-account-address
[sessions]
(let [all-accounts (->> sessions
(sort-by :expiry >)
first
:accounts)]
(-> all-accounts
first
(string/split #":")
last)))
+11 -10
View File
@@ -34,10 +34,10 @@
[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.preparing-status.view :as preparing-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]
[status-im.contexts.onboarding.welcome.view :as welcome]
[status-im.contexts.preview.feature-flags.view :as feature-flags]
[status-im.contexts.preview.quo.component-preview.view :as component-preview]
[status-im.contexts.preview.quo.main :as quo.preview]
@@ -346,6 +346,15 @@
:popStackOnPress false}}
:component generating-keys/view}
{:name :screen/onboarding.preparing-status
:options {:theme :dark
:layout options/onboarding-transparent-layout
:animations transitions/push-animations-for-transparent-background
:popGesture false
:hardwareBackButton {:dismissModalOnPress false
:popStackOnPress false}}
:component preparing-status/view}
{:name :screen/onboarding.enter-seed-phrase
:options {:theme :dark
:layout options/onboarding-transparent-layout
@@ -356,9 +365,7 @@
{:name :screen/onboarding.enable-notifications
:options {:theme :dark
:layout options/onboarding-transparent-layout
:animations (merge
transitions/new-to-status-modal-animations
transitions/push-animations-for-transparent-background)
:animations transitions/push-animations-for-transparent-background
:popGesture false
:modalPresentationStyle :overCurrentContext
:hardwareBackButton {:dismissModalOnPress false
@@ -409,12 +416,6 @@
:options {:theme :dark}
:component syncing-results/view}
{:name :screen/onboarding.welcome
:options {:theme :dark
:layout options/onboarding-transparent-layout
:animations transitions/push-animations-for-transparent-background}
:component welcome/view}
{:name :emoji-picker
:options {:sheet? true}
:component emoji-picker/view}
+30 -23
View File
@@ -22,32 +22,37 @@
(testing "returns an empty set when no types have unread notifications"
(swap! rf-db/app-db assoc-in
[:activity-center :unread-counts-by-type]
{types/one-to-one-chat 0
types/private-group-chat 0
types/contact-verification 0
types/contact-request 0
types/mention 0
types/reply 0
types/admin 0})
{types/one-to-one-chat 0
types/private-group-chat 0
types/contact-verification 0
types/contact-request 0
types/mention 0
types/reply 0
types/admin 0
types/new-installation-received 0
types/new-installation-created 0})
(is (= #{} (rf/sub [sub-name]))))
(testing "returns a set with all types containing positive unread counts"
(swap! rf-db/app-db assoc-in
[:activity-center :unread-counts-by-type]
{types/one-to-one-chat 1
types/private-group-chat 0
types/contact-verification 1
types/contact-request 0
types/mention 3
types/reply 0
types/admin 2})
{types/one-to-one-chat 1
types/private-group-chat 0
types/contact-verification 1
types/contact-request 0
types/mention 3
types/reply 0
types/admin 2
types/new-installation-received 1
types/new-installation-created 0})
(let [actual (rf/sub [sub-name])]
(is (= #{types/one-to-one-chat
types/contact-verification
types/mention
types/admin}
types/admin
types/new-installation-received}
actual))
(is (set? actual)))))
@@ -55,15 +60,17 @@
[sub-name]
(swap! rf-db/app-db assoc-in
[:activity-center :unread-counts-by-type]
{types/one-to-one-chat 1
types/private-group-chat 2
types/contact-verification 3
types/contact-request 4
types/mention 5
types/reply 6
types/admin 7})
{types/one-to-one-chat 1
types/private-group-chat 2
types/contact-verification 3
types/contact-request 4
types/mention 5
types/reply 6
types/admin 7
types/new-installation-received 8
types/new-installation-created 9})
(is (= 28 (rf/sub [sub-name]))))
(is (= 45 (rf/sub [sub-name]))))
(h/deftest-sub :activity-center/unread-indicator
[sub-name]
+5
View File
@@ -266,6 +266,11 @@
(fn [{:keys [preview-privacy?]}]
(boolean preview-privacy?)))
(re-frame/reg-sub :profile/installation-id
:<- [:profile/profile]
(fn [{:keys [installation-id]}]
installation-id))
(defn- replace-multiaccount-image-uri
[profile ens-names port font-file avatar-opts theme]
(let [{:keys [key-uid ens-name? images
+9 -8
View File
@@ -1,7 +1,8 @@
(ns status-im.subs.wallet.collectibles
(:require
[clojure.string :as string]
[re-frame.core :as re-frame]))
[re-frame.core :as re-frame]
[utils.collection]))
(defn- filter-collectibles-in-chains
[collectibles chain-ids]
@@ -69,6 +70,7 @@
(->> all-collectibles
(apply interleave)
(remove nil?)
(utils.collection/distinct-by :id)
(add-collectibles-preview-url)))))
(re-frame/reg-sub
@@ -118,8 +120,8 @@
:wallet/collectible-details-owner
:<- [:wallet/accounts]
(fn [accounts [_ collectible]]
(let [collectible-address (-> collectible :ownership first :address)]
(some #(when (= (:address %) collectible-address)
(let [owner-address (-> collectible :ownership first :address)]
(some #(when (= (:address %) owner-address)
%)
accounts))))
@@ -127,12 +129,11 @@
:wallet/total-owned-collectible
:<- [:wallet/accounts-without-watched-accounts]
(fn [accounts [_ ownership address]]
(let [addresses (map :address accounts)]
(let [addresses (if address
#{address}
(set (map :address accounts)))]
(reduce (fn [acc item]
(if (or
(and (not address)
(contains? (set addresses) (:address item)))
(= (:address item) address))
(if (contains? addresses (:address item))
(+ acc (js/parseInt (:balance item)))
acc))
0
+21 -12
View File
@@ -1,11 +1,9 @@
(ns status-im.subs.wallet.swap
(:require [clojure.string :as string]
[native-module.core :as native-module]
[re-frame.core :as rf]
[status-im.constants :as constants]
[status-im.contexts.wallet.common.utils :as utils]
[status-im.contexts.wallet.send.utils :as send-utils]
[utils.hex :as hex]
[utils.money :as money]
[utils.number :as number]))
@@ -95,6 +93,25 @@
:<- [:wallet/swap]
:-> :swap-proposal)
(rf/reg-sub
:wallet/swap-proposal-without-fees
:<- [:wallet/swap]
(fn [swap]
(let [swap-proposal (:swap-proposal swap)]
(reduce dissoc
swap-proposal
[:gas-fees :gas-amount :token-fees :bonder-fees :approval-gas-fees]))))
(rf/reg-sub
:wallet/swap-amount
:<- [:wallet/swap]
:-> :amount)
(rf/reg-sub
:wallet/swap-approved-amount
:<- [:wallet/swap]
:-> :approved-amount)
(rf/reg-sub
:wallet/swap-loading-swap-proposal?
:<- [:wallet/swap]
@@ -117,11 +134,7 @@
(fn [[amount-out asset-to-receive]]
(let [receive-token-decimals (:decimals asset-to-receive)
receive-amount (when amount-out
(number/convert-to-whole-number
(native-module/hex-to-number
(hex/normalize-hex
amount-out))
receive-token-decimals))
(number/hex->whole amount-out receive-token-decimals))
receive-amount (when amount-out
(number/remove-trailing-zeroes
(.toFixed receive-amount
@@ -136,11 +149,7 @@
(fn [[amount-in asset-to-pay]]
(let [pay-token-decimals (:decimals asset-to-pay)
pay-amount (when amount-in
(number/convert-to-whole-number
(native-module/hex-to-number
(hex/normalize-hex
amount-in))
pay-token-decimals))
(number/hex->whole amount-in pay-token-decimals))
pay-amount (when amount-in
(number/remove-trailing-zeroes
(.toFixed pay-amount
+21 -12
View File
@@ -101,30 +101,39 @@
(defn eip-3770-address?
"Checks if address follows EIP-3770 format which is default for Status"
[s]
(re-find regx-eip-3770-address s))
[address]
(re-find regx-eip-3770-address address))
(defn supported-address?
[s]
(boolean (or (eip-3770-address? s)
(metamask-address? s))))
(defn metamask-address->status-address
(defn metamask-address->eip-3770-address
[metamask-address]
(when-let [[_ address metamask-network-suffix] (split-metamask-address metamask-address)]
(if-let [status-network-prefix (eip-155-suffix->eip-3770-prefix metamask-network-suffix)]
(str status-network-prefix address)
address)))
(defn supported-address->status-address
[address]
(cond
(eip-3770-address? address)
address
(metamask-address? address)
(metamask-address->status-address address)))
(defn extract-address-without-chains-info
[address]
(re-find regx-address-contains address))
(defn metamask-address->eth-address
[eip-3770-address]
(extract-address-without-chains-info eip-3770-address))
(defn eip-3770-address->eth-address
[eip-3770-address]
(extract-address-without-chains-info eip-3770-address))
(defn supported-address->eth-address
[address]
(cond
(eip-3770-address? address)
(eip-3770-address->eth-address address)
(metamask-address? address)
(metamask-address->eth-address address)))
+78 -5
View File
@@ -46,6 +46,19 @@
"ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2@0xa"
"ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"])
(def valid-eip-3770-addresses
["0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"
"eth:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"
"eth:arb1:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"
"eth:arb1:oeth:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"])
(def invalid-eip-3770-addresses
["0x+38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"
"eth3:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"
":eth:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"
"0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2:eth"
"eth:arb10x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"])
(def invalid-metamask-addresses
["ethe:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2@0x1"
":0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2@0xa4b1"
@@ -54,13 +67,29 @@
"ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd20xa4b1"
"ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2:0xa"])
(def metamask-to-eip-3770
[{:metamask "ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2@0x1"
:eip-3770 "eth:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"}
{:metamask "ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2@0xa4b1"
:eip-3770 "arb1:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"}
{:metamask "ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2@0xa"
:eip-3770 "oeth:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"}
{:metamask "ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"
:eip-3770 "0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"}
{:metamask "ethe:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2@0x1" :eip-3770 nil}
{:metamask ":0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2@0xa4b1" :eip-3770 nil}
{:metamask "0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2@0xa" :eip-3770 nil}
{:metamask "ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2@0x1d" :eip-3770 nil}
{:metamask "ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd20xa4b1" :eip-3770 nil}
{:metamask "ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2:0xa" :eip-3770 nil}])
(def metamask-to-status
[{:metamask "ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2@0x1"
:status "eth:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"}
:status "0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"}
{:metamask "ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2@0xa4b1"
:status "arb1:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"}
:status "0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"}
{:metamask "ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2@0xa"
:status "oeth:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"}
:status "0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"}
{:metamask "ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"
:status "0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"}
{:metamask "ethe:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2@0x1" :status nil}
@@ -70,6 +99,26 @@
{:metamask "ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd20xa4b1" :status nil}
{:metamask "ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2:0xa" :status nil}])
(def eip-3770-to-status
[{:eip-3770 "0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"
:status "0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"}
{:eip-3770 "eth:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"
:status "0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"}
{:eip-3770 "eth:arb1:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"
:status "0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"}
{:eip-3770 "eth:arb1:oeth:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"
:status "0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"}
{:status nil
:eip-3770 "0x+38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"}
{:status nil
:eip-3770 "eth3:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"}
{:status nil
:eip-3770 ":eth:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"}
{:status nil
:eip-3770 "0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2:eth"}
{:status nil
:eip-3770 "eth:arb10x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"}])
(deftest metamask-address?-test
(testing "Check valid metamask addresses"
(dorun
@@ -80,9 +129,33 @@
(for [address invalid-metamask-addresses]
(is (not (utils.address/metamask-address? address)))))))
(deftest metamask-address->status-address-test
(deftest eip-3770-address?-test
(testing "Check valid eip-3770 addresses"
(dorun
(for [address valid-eip-3770-addresses]
(is (utils.address/eip-3770-address? address)))))
(testing "Check invalid eip-3770 addresses"
(dorun
(for [address invalid-eip-3770-addresses]
(is (not (utils.address/metamask-address? address)))))))
(deftest metamask-address->eip-3770-address-test
(testing "Check metamask to status address conversion is valid"
(dorun
(for [{metamask-address :metamask
eip-3770-address :eip-3770} metamask-to-eip-3770]
(is (= eip-3770-address (utils.address/metamask-address->eip-3770-address metamask-address)))))))
(deftest supported-address->status-address-test
(testing "Check metamask to status address conversion is valid"
(dorun
(for [{metamask-address :metamask
status-address :status} metamask-to-status]
(is (= status-address (utils.address/metamask-address->status-address metamask-address)))))))
(is (= status-address (utils.address/supported-address->eth-address metamask-address))))))
(testing "Check eip-3770 to status address conversion is valid"
(dorun
(for [{eip-3770-address :eip-3770
status-address :status} eip-3770-to-status]
(is (= status-address (utils.address/supported-address->eth-address eip-3770-address)))))))
+6 -3
View File
@@ -44,15 +44,18 @@
(defn greater-than-or-equals
[^js bn1 ^js bn2]
(.greaterThanOrEqualTo bn1 bn2))
(when (bignumber? bn1)
(.greaterThanOrEqualTo bn1 bn2)))
(defn greater-than
[bn1 bn2]
(.greaterThan ^js bn1 bn2))
(when (bignumber? bn1)
(.greaterThan ^js bn1 bn2)))
(defn less-than
[bn1 bn2]
(.lessThan ^js bn1 bn2))
(when (bignumber? bn1)
(.lessThan ^js bn1 bn2)))
(defn equal-to
[n1 n2]
+17 -1
View File
@@ -1,5 +1,8 @@
(ns utils.number
(:require [clojure.string :as string]))
(:require [clojure.string :as string]
[native-module.core :as native-module]
[utils.hex :as utils.hex]
[utils.money :as utils.money]))
(defn naive-round
"Quickly and naively round number `n` up to `decimal-places`.
@@ -61,3 +64,16 @@
(str "." (string/replace decimals #"0+$" ""))
"")
""))))
(defn hex->whole
[num decimals]
(-> num
utils.hex/normalize-hex
native-module/hex-to-number
(convert-to-whole-number decimals)))
(defn to-fixed
[num decimals]
(-> num
(utils.money/to-fixed decimals)
remove-trailing-zeroes))
+5 -3
View File
@@ -18,7 +18,7 @@
(defn <-js-map
"Shallowly transforms JS Object keys/values with `key-fn`/`val-fn`.
Returns nil if `m` is not an instance of `js/Object`.
Returns m if `m` is not an instance of `js/Object`.
Implementation taken from `js->clj`, but with the ability to customize how
keys and/or values are transformed in one loop.
@@ -33,7 +33,8 @@
([^js m]
(<-js-map m nil))
([^js m {:keys [key-fn val-fn]}]
(when (identical? (type m) js/Object)
(assert (or (nil? m) (identical? (type m) js/Object) (map? m)))
(if (identical? (type m) js/Object)
(persistent!
(reduce (fn [r k]
(let [v (oops/oget+ m k)
@@ -41,7 +42,8 @@
new-val (if val-fn (val-fn k v) v)]
(assoc! r new-key new-val)))
(transient {})
(js-keys m))))))
(js-keys m)))
m)))
(defn js-stringify
[js-object spaces]
+1 -1
View File
@@ -13,7 +13,7 @@
(are [expected m]
(is (equals-as-json expected (sut/<-js-map m)))
nil nil
nil #js []
{:a 1} {:a 1}
#js {} #js {}
#js {"a" 1 "b" 2} #js {"a" 1 "b" 2}))
+3 -3
View File
@@ -3,7 +3,7 @@
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
"owner": "status-im",
"repo": "status-go",
"version": "f859b58c3896523b2fb9a09b3e5c1cedb04f959b",
"commit-sha1": "f859b58c3896523b2fb9a09b3e5c1cedb04f959b",
"src-sha256": "009nd47aajng5k7wrcqv5zvvzniaswqi706fpkbbjhqziympi1s1"
"version": "1cdfcd6bd7b0b7c68a008fee406f81067a21b910",
"commit-sha1": "1cdfcd6bd7b0b7c68a008fee406f81067a21b910",
"src-sha256": "19hdli07skhcmjrd7xm2q1d7qylsln6w9id2y5x64bnf0saz3g95"
}
+19 -17
View File
@@ -28,29 +28,31 @@ class BaseTestReport:
file_name = "%s.json" % test_name
return os.path.join(self.TEST_REPORT_DIR, file_name)
def save_geth(self, geth: dict):
geth_paths = {}
for log in geth.keys():
geth_path = os.path.join(self.TEST_REPORT_DIR, log)
result = open(geth_path, 'wb')
result.write(geth[log])
def save_logs(self, logs: dict):
logs_paths = {}
for log in logs.keys():
log_path = os.path.join(self.TEST_REPORT_DIR, log)
result = open(log_path, 'wb')
result.write(logs[log])
result.close()
geth_paths[log] = geth_path
return geth_paths
logs_paths[log] = log_path
return logs_paths
def save_test(self, test, geth: dict = None):
if geth:
geth_paths = self.save_geth(geth)
else:
if hasattr(test, 'geth_paths'):
geth_paths = test.geth_paths
def save_test(self, test, geth: dict = None, requests_log: dict = None):
for log in geth, requests_log:
if log:
logs_paths = self.save_logs(log)
else:
geth_paths = ''
if hasattr(test, 'logs_paths'):
logs_paths = test.logs_paths
else:
logs_paths = ''
file_path = self.get_test_report_file_path(test.name)
test_dict = {
'testrail_case_id': test.testrail_case_id,
'name': test.name,
'geth_paths': geth_paths,
'logs_paths': logs_paths,
'testruns': list(),
'group_name': test.group_name,
'secured': test.secured
@@ -74,7 +76,7 @@ class BaseTestReport:
first_commands=testrun_data['first_commands'],
xfail=testrun_data['xfail']))
tests.append(SingleTestData(name=test_data['name'],
geth_paths=test_data['geth_paths'],
logs_paths=test_data['logs_paths'],
testruns=testruns,
testrail_case_id=test_data['testrail_case_id'],
grop_name=test_data['group_name'],
+2 -2
View File
@@ -2,11 +2,11 @@ from typing import Dict
class SingleTestData(object):
def __init__(self, name, testruns, testrail_case_id, geth_paths, grop_name, secured):
def __init__(self, name, testruns, testrail_case_id, logs_paths, grop_name, secured):
self.testrail_case_id = testrail_case_id
self.name = name
self.testruns = testruns
self.geth_paths = geth_paths
self.logs_paths = logs_paths
self.group_name = grop_name
self.secured = secured
+2 -3
View File
@@ -8,7 +8,6 @@ from os import environ
from sys import argv
import emoji
import pytest
import requests
from support.base_test_report import BaseTestReport
@@ -214,9 +213,9 @@ class TestrailReport(BaseTestReport):
if re.findall(pattern, res['comment']):
res_id = res['id']
try:
for geth in test.geth_paths.keys():
for log in test.logs_paths.keys():
self.add_attachment(method='add_attachment_to_result/%s' % str(res_id),
path=test.geth_paths[geth])
path=test.logs_paths[log])
except (AttributeError, FileNotFoundError):
pass
break
+23 -18
View File
@@ -111,12 +111,13 @@ def get_app_path():
return app_path
def get_geth_path():
return get_app_path() + 'geth.log'
def pull_geth(driver):
result = driver.pull_file(get_geth_path())
result = driver.pull_file(get_app_path() + 'geth.log')
return base64.b64decode(result)
def pull_requests_log(driver):
result = driver.pull_file(get_app_path() + 'requests.log')
return base64.b64decode(result)
@@ -377,21 +378,23 @@ class SauceSharedMultipleDeviceTestCase(AbstractTestCase):
test_suite_data.current_test.group_name = self.__class__.__name__
def teardown_method(self, method):
geth_names, geth_contents = [], []
log_names, log_contents = [], []
for driver in self.drivers:
try:
self.print_sauce_lab_info(self.drivers[driver])
self.add_alert_text_to_report(self.drivers[driver])
geth_names.append(
log_names.append(
'%s_geth%s.log' % (test_suite_data.current_test.name, str(self.drivers[driver].number)))
geth_contents.append(pull_geth(self.drivers[driver]))
log_contents.append(pull_geth(self.drivers[driver]))
log_names.append(
'%s_requests%s.log' % (test_suite_data.current_test.name, str(self.drivers[driver].number)))
log_contents.append(pull_requests_log(self.drivers[driver]))
except (WebDriverException, AttributeError, RemoteDisconnected, ProtocolError):
pass
finally:
try:
geth = {geth_names[i]: geth_contents[i] for i in range(len(geth_names))}
test_suite_data.current_test.geth_paths = github_report.save_geth(geth)
logs = {log_names[i]: log_contents[i] for i in range(len(log_names))}
test_suite_data.current_test.logs_paths = github_report.save_logs(logs)
except IndexError:
pass
@@ -413,11 +416,14 @@ class SauceSharedMultipleDeviceTestCase(AbstractTestCase):
group_setup_failed = True
else:
group_setup_failed = False
geth_contents = list()
log_contents, log_names = list(), list()
try:
for _, driver in cls.drivers.items():
for i, driver in cls.drivers.items():
if group_setup_failed:
geth_contents.append(pull_geth(driver=driver))
log_contents.append(pull_geth(driver=driver))
log_names.append('%s_geth%s.log' % (cls.__name__, i))
log_contents.append(pull_requests_log(driver=driver))
log_names.append('%s_requests%s.log' % (cls.__name__, i))
session_id = driver.session_id
try:
sauce.jobs.update_job(username=sauce_username, job_id=session_id, name=cls.__name__)
@@ -449,13 +455,12 @@ class SauceSharedMultipleDeviceTestCase(AbstractTestCase):
except AttributeError:
pass
geth_names = ['%s_geth%s.log' % (cls.__name__, i) for i in range(len(geth_contents))]
geth = dict(zip(geth_names, geth_contents))
geth_paths = github_report.save_geth(geth)
logs = dict(zip(log_names, log_contents))
logs_paths = github_report.save_logs(logs)
for test in test_suite_data.tests:
if group_setup_failed:
test.geth_paths = geth_paths
test.logs_paths = logs_paths
github_report.save_test(test)
+4 -6
View File
@@ -267,12 +267,11 @@ class SignInView(BaseView):
for _ in range(3):
self.allow_button.click_if_shown(sec=10)
self.enable_notifications_button.click_if_shown()
if self.start_button.is_element_displayed():
if self.chats_tab.is_element_displayed():
break
else:
self.maybe_later_button.click_until_presence_of_element(self.start_button)
self.maybe_later_button.wait_and_click()
self.cancel_button.click_if_shown() # TODO: remove when issue 20806 is fixed
self.start_button.click()
self.chats_tab.wait_for_visibility_of_element(30)
self.driver.info("## New multiaccount is created successfully!", device=False)
return self.get_home_view()
@@ -298,11 +297,10 @@ class SignInView(BaseView):
# self.enable_biometric_maybe_later_button.click()
# self.identifiers_button.wait_and_click(30)
if enable_notifications:
self.enable_notifications_button.click_until_presence_of_element(self.start_button)
self.enable_notifications_button.click()
else:
self.maybe_later_button.click_until_presence_of_element(self.start_button)
self.maybe_later_button.wait_and_click()
self.cancel_button.click_if_shown() # TODO: remove when issue 20806 is fixed
self.start_button.click()
self.chats_tab.wait_for_visibility_of_element(30)
self.driver.info("## Multiaccount is recovered successfully!", device=False)
return self.get_home_view()
+13 -2
View File
@@ -363,6 +363,7 @@
"check-before-syncing-doc-description": "To sync your devices successfully, make sure to check and complete these steps:",
"check-on-block-explorer": "Check on block explorer",
"check-on-opensea": "Check on opensea",
"check-other-device-for-pairing": "Check your other device for a pairing request.",
"check-your-account-balance-and-activity": "Check your account balance and activity",
"check-your-recovery-phrase": "Check your seed phrase",
"choose-actions": "Choose actions",
@@ -964,7 +965,6 @@
"enter-puk-code-description": "6-digit passcode has been blocked.\n Please enter PUK code to unblock passcode.",
"enter-recipient-address-or-username": "Enter address or username of the recipient",
"enter-recovery-phrase": "Enter recovery phrase",
"enter-seed-phrase": "Enter seed phrase",
"enter-sync-code": "Enter sync code",
"enter-url": "Enter URL",
"enter-user-pk": "Enter user public key",
@@ -1111,6 +1111,7 @@
"group-membership-request": "Group membership request",
"groups": "Groups",
"gwei": "Gwei",
"hang-in-there": "Hang in there! Just a few more seconds!",
"has-permissions": "has permission to access",
"hash": "Hash",
"have-a-sync-code?": "Have a sync code?",
@@ -1582,6 +1583,7 @@
"mobile-syncing-sheet-title": "Sync using mobile data?",
"mon": "Mon",
"more": "more",
"more-details": "More details",
"more-details-in-privacy-policy-1": "For more details refer to our ",
"more-details-in-privacy-policy-2": "Privacy Policy",
"more-details-in-privacy-policy-settings-1": "For details on this and other potential limited data processing by Status, see our ",
@@ -1650,6 +1652,9 @@
"new-community-title": "New community",
"new-contact": "New contact",
"new-contract": "New Contract",
"new-device-detected": "New device detected",
"new-device-detected-other-device-message": "Check your other device for a pairing request. Ensure that the this device ID displayed on your other device. Only proceed with pairing and syncing if the IDs are identical.",
"new-device-detected-recovered-device-message": "A new device has been detected. You can see device ID below and on your other device. Only confirm the request if device ID matches.",
"new-favourite": "New favourite",
"new-group": "New group",
"new-group-chat": "New group chat",
@@ -1817,14 +1822,17 @@
"page-camera-request-blocked": "camera requests blocked. To enable camera requests go to Settings",
"page-would-like-to-use-camera": "would like to use your camera",
"pair": "Pair",
"pair-and-sync": "Pair and Sync",
"pair-card": "Pair to this device",
"pair-code": "Pair code",
"pair-code-explanation": "Pairs card to a different device (up to 5) to unlock keys and sign transactions with the same Keycard",
"pair-code-placeholder": "Pair code...",
"pair-device-toast": "Device successfully paired",
"pair-devices": "Pair devices",
"pair-new-device-and-sync": "Pair new device and sync profile",
"pair-this-card": "Pair this card",
"pair-this-device": "Advertise device",
"pair-this-device-and-sync": "Pair this device and sync profile",
"pair-this-device-description": "Pair your devices to sync contacts and chats between them",
"paired-devices": "Paired devices",
"paired-with-this-device": "Paired with this device",
@@ -1920,6 +1928,7 @@
"powered-by-paraswap": "Powered by Paraswap",
"preference": "Preference",
"preferred-by-receiver": "Preferred by receiver",
"preparing-app-for-you": "Preparing app for you...",
"press": "Press",
"preview-privacy": "Preview privacy mode",
"previewing-may-share-metadata": "Previewing links from these websites may share your metadata with their owners",
@@ -2006,7 +2015,7 @@
"recover-with-seed-phrase": "Recover with seed phrase",
"recovering-key": "Accessing keys...",
"recovery-confirm-phrase": "Confirm seed phrase",
"recovery-phrase": "Seed phrase",
"recovery-phrase": "Recovery phrase",
"recovery-success-text": "You will have to create a new code or password to re-encrypt your keys",
"recovery-typo-dialog-description": "Please note, your seed phrase must use the exact same words and order as you received it",
"recovery-typo-dialog-title": "Is the seed phrase correct?",
@@ -2089,6 +2098,7 @@
"reveal-qr-code": "Reveal QR code",
"reveal-sync-code": "Reveal sync code",
"review-bridge": "Review bridge",
"review-pairing-request": "Review pairing request",
"review-send": "Review send",
"review-swap": "Review swap",
"revoke-access": "Revoke access",
@@ -2400,6 +2410,7 @@
"sync-or-recover-profile": "Sync or recover profile",
"sync-settings": "Sync settings",
"sync-synced": "In sync",
"sync-your-profile": "Sync your profile",
"synced-devices": "Synced Devices",
"synced-with": "Synced with",
"synchronise-your-data-across-your-devices": "Synchronise your data across your devices",