Compare commits

..
33 changed files with 412 additions and 596 deletions
+11 -20
View File
@@ -1,7 +1,8 @@
(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]
@@ -58,20 +59,18 @@
(defn- transfer-mention-result
[result]
(let [{:keys [input-segments mentionable-users state chat-id new-text call-id]}
(let [{:keys [input-segments mentionable-users state chat-id new-text]}
(set/rename-keys result
{:InputSegments :input-segments
:MentionSuggestions :mentionable-users
:MentionState :state
:ChatID :chat-id
:NewText :new-text
:CallID :call-id})]
:NewText :new-text})]
{: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
:call-id call-id}))
:new-text new-text}))
(rf/defn on-error
{:events [:mention/on-error]}
@@ -105,12 +104,10 @@
{:events [:mention/on-change-text]}
[{:keys [db]} text]
(let [chat-id (:current-chat-id db)
call-id (inc (get-in db [:chat/inputs chat-id :current-mentions-call-id] 0))
params [chat-id text call-id]
params [chat-id text]
method "wakuext_chatMentionOnChangeText"]
(log/debug "[mentions] on-change-text" {:params params})
{:db (assoc-in db [:chat/inputs chat-id :current-mentions-call-id] call-id)
:json-rpc/call [{:method method
{:json-rpc/call [{:method method
:params params
:on-success #(rf/dispatch [:mention/on-change-text-success %])
:on-error #(rf/dispatch [:mention/on-error
@@ -121,14 +118,8 @@
{:events [:mention/on-change-text-success]}
[{:keys [db]} result]
(log/debug "[mentions] on-change-text-success" {:result result})
(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))})))
(let [{:keys [chat-id mentionable-users]} (transfer-mention-result result)]
{:db (assoc-in db [:chats/mention-suggestions chat-id] mentionable-users)}))
(rf/defn on-select-mention-success
{:events [:mention/on-select-mention-success]}
-11
View File
@@ -57,11 +57,6 @@
(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]
@@ -169,12 +164,6 @@
[_ 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]
+2 -22
View File
@@ -1,10 +1,7 @@
(ns react-native.permissions
(:require
["react-native-permissions" :refer
[check openSettings PERMISSIONS requestMultiple requestNotifications
RESULTS]]
[react-native.platform :as platform]
[taoensso.timbre :as log]))
["react-native-permissions" :refer (check openSettings requestMultiple PERMISSIONS RESULTS)]
[react-native.platform :as platform]))
(def permissions-map
{:read-external-storage (cond
@@ -48,20 +45,3 @@
(.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))))))))
@@ -8,8 +8,7 @@
(h/test "joined options - Non token Gated"
(h/setup-subs {:communities/my-pending-request-to-join nil
:communities/community {:joined true}
:profile/test-networks-enabled? false})
:communities/community {:joined true}})
(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))
@@ -24,8 +23,7 @@
(h/test "joined options - Token Gated"
(h/setup-subs {:communities/my-pending-request-to-join nil
:communities/community {:joined true
:role-permissions? true}
:profile/test-networks-enabled? false})
:role-permissions? true}})
(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))
@@ -40,8 +38,7 @@
(h/test "admin options - Non token Gated"
(h/setup-subs {:communities/my-pending-request-to-join nil
:communities/community {:admin true}
:profile/test-networks-enabled? false})
:communities/community {:admin true}})
(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))
@@ -55,8 +52,7 @@
(h/test "admin options - Token Gated"
(h/setup-subs {:communities/my-pending-request-to-join nil
:communities/community {:admin true
:role-permissions? true}
:profile/test-networks-enabled? false})
:role-permissions? true}})
(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))
@@ -69,8 +65,7 @@
(h/test "request sent options - Non token Gated"
(h/setup-subs {:communities/my-pending-request-to-join "mock-id"
:communities/community {}
:profile/test-networks-enabled? false})
:communities/community {}})
(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))
@@ -81,8 +76,7 @@
(h/test "request sent options - Token Gated"
(h/setup-subs {:communities/my-pending-request-to-join "mock-id"
:communities/community {:role-permissions? true}
:profile/test-networks-enabled? false})
:communities/community {:role-permissions? true}})
(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))
@@ -92,8 +86,7 @@
(h/test "banned options - Non token Gated"
(h/setup-subs {:communities/my-pending-request-to-join nil
:communities/community {:banList true}
:profile/test-networks-enabled? false})
:communities/community {:banList true}})
(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))
@@ -104,8 +97,7 @@
(h/test "banned options - Token Gated"
(h/setup-subs {:communities/my-pending-request-to-join nil
:communities/community {:banList 100
:role-permissions? true}
:profile/test-networks-enabled? false})
:role-permissions? true}})
(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))
@@ -115,8 +107,7 @@
(h/test "banned options - Token Gated"
(h/setup-subs {:communities/my-pending-request-to-join nil
:communities/community {:banList 100
:role-permissions? true}
:profile/test-networks-enabled? false})
:role-permissions? true}})
(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))
@@ -127,7 +118,6 @@
(h/setup-subs {:communities/my-pending-request-to-join nil
:communities/community {:joined true
:muted true
:role-permissions? true}
:profile/test-networks-enabled? false})
:role-permissions? true}})
(h/render [options/community-options-bottom-sheet {:id "test"}])
(h/is-truthy (h/get-by-translation-text :t/unmute-community))))
@@ -36,13 +36,14 @@
(defn view-token-gating
[id]
{: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)})
(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)}))
(defn edit-shared-addresses
[id]
@@ -55,7 +56,7 @@
(defn mark-as-read
[id]
{:icon :i/mark-as-read
{:icon :i/up-to-date
: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])})
@@ -135,27 +136,23 @@
request-id])}])})
(defn not-joined-options
[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)]))
[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)]])
(defn join-request-sent-options
[id token-gated? request-id intro-message test-networks-enabled?]
[(conj (first (not-joined-options id token-gated? intro-message test-networks-enabled?))
[id token-gated? request-id intro-message]
[(conj (first (not-joined-options id token-gated? intro-message))
(assoc (cancel-request-to-join id request-id) :add-divider? true))])
(defn banned-options
[id token-gated? intro-message test-networks-enabled?]
(not-joined-options id token-gated? intro-message test-networks-enabled?))
[id token-gated? intro-message]
(not-joined-options id token-gated? intro-message))
(defn joined-options
[id token-gated? muted? muted-till color intro-message]
@@ -189,19 +186,13 @@
(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])
test-networks? (rf/sub [:profile/test-networks-enabled?])]
request-id (rf/sub [:communities/my-pending-request-to-join id])]
(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 test-networks?)
banList
(banned-options id role-permissions? intro-message test-networks?)
:else
(not-joined-options id role-permissions? intro-message test-networks?))))
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))))
(defn community-options-bottom-sheet
[id]
@@ -74,7 +74,6 @@
featured (:contract-featured-communities cc)
unknown (:unknown-communities cc)
other (remove (set featured) (:contract-communities cc))]
(print "-------------- parvesh handle contract communities" contract-communities)
{:db (assoc db
:contract-communities
{:featured (select-keys (:communities cc) featured)
+29 -36
View File
@@ -2,7 +2,6 @@
(: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]
@@ -26,7 +25,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 (and id (>= clock (get-in db [:communities id :clock])))
(when (>= 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)))
@@ -224,14 +223,14 @@
:fx [[:dispatch [:communities/check-permissions-to-join-community community-id]]]})))
(defn community-fetched
[{:keys [db]} [community-id community-js]]
(when community-js
[{:keys [db]} [community-id community]]
(when community
{:db (update db :communities/fetching-communities dissoc community-id)
:fx [[:dispatch [:communities/handle-community community-js]]
:fx [[:dispatch [:communities/handle-community community]]
[:dispatch [:chat.ui/spectate-community community-id]]
[:dispatch
[:chat.ui/cache-link-preview-data (link-preview.events/community-link community-id)
(data-store.communities/<-rpc community-js)]]]}))
community]]]}))
(rf/reg-event-fx :chat.ui/community-fetched community-fetched)
@@ -254,19 +253,18 @@
(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}]
: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)}]}))
: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)}]}))
(schema/=> fetch-community
[:=>
@@ -285,15 +283,11 @@
(rf/reg-event-fx :communities/fetch-community fetch-community)
(defn spectate-community-success
[{: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]]]}))))
[{:keys [db]} [{:keys [communities]}]]
(when-let [community (first communities)]
{:db (-> db
(assoc-in [:communities (:id community) :spectated] true))
:fx [[:dispatch [:communities/handle-community community]]]}))
(rf/reg-event-fx :chat.ui/spectate-community-success spectate-community-success)
@@ -301,14 +295,13 @@
[{: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]
:js-response true
: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]
:on-success [:chat.ui/spectate-community-success]
:on-error (fn [err]
(log/error {:message
"Failed to spectate community"
:error err}))}]})))
(schema/=> spectate-community
[:=>
@@ -1,6 +1,5 @@
(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]))
@@ -52,7 +51,7 @@
[:dispatch [:chat.ui/spectate-community community-id]]
[:dispatch
[:chat.ui/cache-link-preview-data "community-link+community-id"
(data-store.communities/<-rpc #js {"id" community-id})]]]}
{:id community-id}]]]}
(events/community-fetched cofx arg))))))
(testing "given a joined community"
(let [cofx {:db {:communities/fetching-communities {community-id true}}}
@@ -63,7 +62,7 @@
[:dispatch [:chat.ui/spectate-community community-id]]
[:dispatch
[:chat.ui/cache-link-preview-data "community-link+community-id"
(data-store.communities/<-rpc #js {"id" community-id})]]]}
{:id community-id}]]]}
(events/community-fetched cofx arg))))))
(testing "given a token-gated community"
(let [cofx {:db {:communities/fetching-communities {community-id true}}}
@@ -74,7 +73,7 @@
[:dispatch [:chat.ui/spectate-community community-id]]
[:dispatch
[:chat.ui/cache-link-preview-data "community-link+community-id"
(data-store.communities/<-rpc #js {"id" community-id})]]]}
{:id community-id}]]]}
(events/community-fetched cofx arg))))))
(testing "given nil community"
(testing "do nothing"
@@ -104,38 +103,26 @@
(events/spectate-community {:db {:communities {community-id {}}}} [community-id]))))))
(deftest spectate-community-success-test
(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 []))))))))
(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 {} []))))))
(deftest get-revealed-accounts-test
(let [community {:id community-id}]
@@ -209,10 +209,9 @@
(when same-passwords?
[rn/view {:style style/disclaimer-container}
[quo/disclaimer
{:blur? true
:on-change (partial set-accepts-disclaimer? not)
:checked? accepts-disclaimer?
:customization-color user-color}
{:blur? true
:on-change (partial set-accepts-disclaimer? not)
:checked? accepts-disclaimer?}
(i18n/label :t/password-creation-disclaimer)]])
(when (and (= focused-input :password) (not same-passwords?))
[help
@@ -7,6 +7,7 @@
[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]))
@@ -19,36 +20,39 @@
: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])
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)]
(let [profile-color (rf/sub [:onboarding/customization-color])]
[rn/view {:style (style/buttons insets)}
[quo/button
{:on-press ask-permission
{: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]]))
: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 skip-permission
{: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]]))
:accessibility-label :enable-notifications-later-button
:type :grey
:background :blur
@@ -0,0 +1,36 @@
(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})
@@ -0,0 +1,54 @@
(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)]]]))
+16 -19
View File
@@ -34,25 +34,22 @@
(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
;; 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?)))
(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?)))
(defn strip-file-prefix
[path]
@@ -84,7 +84,7 @@
(load-and-show-profile scanned-text)
(utils-address/supported-address? scanned-text)
(when-let [address (utils-address/supported-address->eth-address scanned-text)]
(when-let [address (utils-address/supported-address->status-address scanned-text)]
(debounce/debounce-and-dispatch [:generic-scanner/scan-success address] 300)
(debounce/debounce-and-dispatch [:navigate-change-tab :wallet-stack] 300))
@@ -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->eth-address result)]
(let [address (utils-address/supported-address->status-address result)]
(when on-result (on-result address))
(debounce/debounce-and-dispatch
[:wallet/scan-address-success address]
+27 -70
View File
@@ -8,8 +8,9 @@
[taoensso.timbre :as log]
[utils.address :as address]
[utils.debounce :as debounce]
[utils.hex :as hex]
[utils.i18n :as i18n]
[utils.money :as money]
[utils.number]
[utils.number :as number]))
(rf/reg-event-fx :wallet.swap/start
@@ -46,14 +47,14 @@
(rf/reg-event-fx :wallet.swap/set-max-slippage
(fn [{:keys [db]} [max-slippage]]
{:db (assoc-in db [:wallet :ui :swap :max-slippage] (number/parse-float max-slippage))}))
{:db (assoc-in db [:wallet :ui :swap :max-slippage] (utils.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 clean-approval-transaction?]}]]
(fn [{:keys [db]} [{:keys [amount-in amount-out]}]]
(let [wallet-address (get-in db [:wallet :current-viewing-account-address])
{:keys [asset-to-pay asset-to-receive
network]} (get-in db [:wallet :ui :swap])
@@ -96,17 +97,12 @@
(when-let [amount (or amount-in amount-out)]
{:db (update-in db
[:wallet :ui :swap]
#(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)))
#(-> %
(assoc
:last-request-uuid request-uuid
:amount amount
:loading-swap-proposal? true)
(dissoc :error-response)))
:json-rpc/call [{:method "wallet_getSuggestedRoutesAsync"
:params params
:on-error (fn [error]
@@ -119,30 +115,17 @@
(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 (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))))
(when (= request-uuid last-request-uuid)
(cond-> {:db (update-in db
[:wallet :ui :swap]
assoc
:swap-proposal (when-not (empty? best-routes)
(assoc (first best-routes) :uuid request-uuid))
:swap-proposal (first best-routes)
: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
@@ -173,18 +156,16 @@
{:event :wallet/stop-get-swap-proposal
:error error}))}]}))
(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-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
(fn [{:keys [db]}]
@@ -264,8 +245,10 @@
constants/min-token-decimals-to-display)
receive-amount (when amount-out
(number/remove-trailing-zeroes
(.toFixed (number/hex->whole
amount-out
(.toFixed (number/convert-to-whole-number
(native-module/hex-to-number
(hex/normalize-hex
amount-out))
receive-token-decimals)
decimals-to-display)))]
(rf/dispatch [:wallet.swap/add-authorized-transaction
@@ -285,7 +268,7 @@
:screen/wallet.swap-confirmation)])
(when-not approval-required?
(rf/dispatch [:wallet/select-account-tab :activity])
(rf/dispatch [:wallet/clean-swap])
(debounce/debounce-and-dispatch [:wallet/clean-swap] 1000)
(debounce/debounce-and-dispatch
[:toasts/upsert
{:id :swap-transaction-pending
@@ -359,8 +342,6 @@
: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)))))))
@@ -387,27 +368,3 @@
: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-without-fees])
swap-proposal (rf/sub [:wallet/swap-proposal])
account (rf/sub [:wallet/current-viewing-account])
on-auth-success (rn/use-callback #(rf/dispatch
[:wallet/swap-transaction
@@ -1,5 +1,6 @@
(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]
@@ -10,7 +11,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.debounce :as debounce]
[utils.hex :as hex]
[utils.i18n :as i18n]
[utils.money :as money]
[utils.number :as number]
@@ -21,18 +22,14 @@
(defn- on-close
[]
(rf/dispatch [:wallet/clean-swap-proposal {:clean-approval-transaction? true}])
(rf/dispatch [:wallet/clean-swap-proposal])
(events-helper/navigate-back))
(defn- fetch-swap-proposal
[{:keys [amount valid-input? clean-approval-transaction?]}]
[{:keys [amount valid-input?]}]
(if valid-input?
(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?}])))
(rf/dispatch [:wallet/start-get-swap-proposal {:amount-in amount}])
(rf/dispatch [:wallet/clean-swap-proposal])))
(defn- data-item
[{:keys [title subtitle size subtitle-icon loading?]}]
@@ -72,13 +69,11 @@
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-without-fees])
swap-proposal (rf/sub [:wallet/swap-proposal])
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)
@@ -98,16 +93,16 @@
(min pay-token-decimals
constants/min-token-decimals-to-display)))
approval-amount-required-num (when approval-amount-required
(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)))
(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)))
valid-pay-input? (and
(not (string/blank?
pay-input-amount))
@@ -116,9 +111,8 @@
request-fetch-swap-proposal (rn/use-callback
(fn []
(fetch-swap-proposal
{:amount pay-input-amount
:valid-input? valid-pay-input?
:clean-approval-transaction? true}))
{:amount pay-input-amount
:valid-input? valid-pay-input?}))
[pay-input-amount])]
(rn/use-effect
(fn []
@@ -129,8 +123,7 @@
:error? pay-input-error?
:token pay-token-symbol
:customization-color :blue
:show-approval-label? (or (and swap-proposal approval-required)
approval-transaction-id)
:show-approval-label? (and swap-proposal approval-required)
:auto-focus? true
:show-keyboard? false
:status (cond
@@ -152,7 +145,7 @@
:confirmed :approved
:finalised :approved
:approve)
:token-value (or approval-amount-required-num approved-amount)
:token-value approval-amount-required-num
:button-props {:on-press on-approve-press}
:customization-color account-color
:token-symbol pay-token-symbol}}]))
@@ -176,9 +169,14 @@
receive-token-symbol (:symbol asset-to-receive)
receive-token-decimals (:decimals asset-to-receive)
amount-out-whole-number (when amount-out
(number/hex->whole amount-out receive-token-decimals))
(number/convert-to-whole-number
(native-module/hex-to-number
(utils.hex/normalize-hex
amount-out))
receive-token-decimals))
amount-out-num (if amount-out-whole-number
(number/to-fixed amount-out-whole-number receive-token-decimals)
(number/remove-trailing-zeroes
(.toFixed amount-out-whole-number receive-token-decimals))
default-text-for-unfocused-input)
receive-token-fiat-value (str (utils/calculate-token-fiat-value
{:currency currency
@@ -207,7 +205,7 @@
(defn- action-button
[{:keys [on-press]}]
(let [account-color (rf/sub [:wallet/current-viewing-account-color])
swap-proposal (rf/sub [:wallet/swap-proposal-without-fees])
swap-proposal (rf/sub [:wallet/swap-proposal])
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])]
@@ -225,10 +223,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 (rn/use-ref-atom nil)
[refetch-interval set-refetch-interval] (rn/use-state 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-without-fees])
swap-proposal (rf/sub [:wallet/swap-proposal])
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)
@@ -272,9 +270,7 @@
(fn []
(set-pay-input-state
controlled-input/delete-last)
(rf/dispatch [:wallet/clean-swap-proposal
{:clean-approval-transaction?
true}])))
(rf/dispatch [:wallet/clean-swap-proposal])))
on-max-press (rn/use-callback
(fn [max-value]
(set-pay-input-state
@@ -284,66 +280,32 @@
max-value)))))
on-refresh-swap-proposal (rn/use-callback
(fn []
(let
[bottom-sheets (rf/sub
[:bottom-sheet-sheets])
approval-transaction-status
(rf/sub
[:wallet/swap-approval-transaction-status])]
(let [bottom-sheets (rf/sub
[:bottom-sheet-sheets])]
(when-not valid-pay-input?
(when @refetch-interval
(js/clearTimeout @refetch-interval))
(reset! refetch-interval nil))
(when @refetch-interval
(js/clearTimeout @refetch-interval))
(reset! refetch-interval nil)
(js/clearInterval refetch-interval)
(set-refetch-interval nil))
(when (and valid-pay-input?
(not loading-swap-proposal?)
(not bottom-sheets)
(not= approval-transaction-status
:pending))
(not bottom-sheets))
(fetch-swap-proposal
{:amount pay-input-amount
:valid-input? valid-pay-input?
:clean-approval-transaction? false}))))
{:amount pay-input-amount
:valid-input? valid-pay-input?}))))
[valid-pay-input? loading-swap-proposal?
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})))]
pay-input-amount])]
(rn/use-effect (fn []
(when @refetch-interval
(js/clearInterval @refetch-interval)
(reset! refetch-interval nil))
(when refetch-interval
(js/clearInterval refetch-interval)
(set-refetch-interval nil))
(when (or swap-proposal error-response)
(reset! refetch-interval
(js/setInterval
on-refresh-swap-proposal
constants/swap-proposal-refresh-interval-ms))))
(set-refetch-interval (js/setInterval
on-refresh-swap-proposal
constants/swap-proposal-refresh-interval-ms))))
[swap-proposal error-response])
(rn/use-unmount (fn []
(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])
(when refetch-interval
(js/clearInterval refetch-interval)
(set-refetch-interval nil))))
[rn/view {:style style/container}
[account-switcher/view
{:on-press on-close
@@ -360,12 +322,7 @@
:on-input-focus (fn []
(when platform/android? (rf/dispatch [:dismiss-keyboard]))
(set-pay-input-focused? true))}]
[swap-order-button
{:on-press (fn []
(when @refetch-interval
(js/clearTimeout @refetch-interval)
(reset! refetch-interval nil))
(rf/dispatch [:wallet.swap/flip-assets]))}]
[swap-order-button {:on-press #(js/alert "Swap Order Pressed")}]
[receive-token-input
{:input-focused? (not pay-input-focused?)
:on-token-press #(js/alert "Token Pressed")
@@ -157,13 +157,12 @@
(defn- slide-button
[]
(let [loading-swap-proposal? (rf/sub [:wallet/swap-loading-swap-proposal?])
swap-proposal (rf/sub [:wallet/swap-proposal-without-fees])
swap-proposal (rf/sub [:wallet/swap-proposal])
account (rf/sub [:wallet/current-viewing-account])
account-color (:color account)
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)])))]
on-auth-success (rn/use-callback #(rf/dispatch
[:wallet/swap-transaction
(security/safe-unmask-data %)]))]
[standard-auth/slide-button
{:size :size-48
:track-text (i18n/label :t/slide-to-swap)
+10 -1
View File
@@ -37,6 +37,7 @@
[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]
@@ -355,7 +356,9 @@
{:name :screen/onboarding.enable-notifications
:options {:theme :dark
:layout options/onboarding-transparent-layout
:animations transitions/push-animations-for-transparent-background
:animations (merge
transitions/new-to-status-modal-animations
transitions/push-animations-for-transparent-background)
:popGesture false
:modalPresentationStyle :overCurrentContext
:hardwareBackButton {:dismissModalOnPress false
@@ -406,6 +409,12 @@
: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}
+12 -21
View File
@@ -1,9 +1,11 @@
(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]))
@@ -93,25 +95,6 @@
:<- [: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]
@@ -134,7 +117,11 @@
(fn [[amount-out asset-to-receive]]
(let [receive-token-decimals (:decimals asset-to-receive)
receive-amount (when amount-out
(number/hex->whole amount-out receive-token-decimals))
(number/convert-to-whole-number
(native-module/hex-to-number
(hex/normalize-hex
amount-out))
receive-token-decimals))
receive-amount (when amount-out
(number/remove-trailing-zeroes
(.toFixed receive-amount
@@ -149,7 +136,11 @@
(fn [[amount-in asset-to-pay]]
(let [pay-token-decimals (:decimals asset-to-pay)
pay-amount (when amount-in
(number/hex->whole amount-in pay-token-decimals))
(number/convert-to-whole-number
(native-module/hex-to-number
(hex/normalize-hex
amount-in))
pay-token-decimals))
pay-amount (when amount-in
(number/remove-trailing-zeroes
(.toFixed pay-amount
+9 -18
View File
@@ -101,39 +101,30 @@
(defn eip-3770-address?
"Checks if address follows EIP-3770 format which is default for Status"
[address]
(re-find regx-eip-3770-address address))
[s]
(re-find regx-eip-3770-address s))
(defn supported-address?
[s]
(boolean (or (eip-3770-address? s)
(metamask-address? s))))
(defn metamask-address->eip-3770-address
(defn metamask-address->status-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 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
(defn supported-address->status-address
[address]
(cond
(eip-3770-address? address)
(eip-3770-address->eth-address address)
address
(metamask-address? address)
(metamask-address->eth-address address)))
(metamask-address->status-address address)))
(defn extract-address-without-chains-info
[address]
(re-find regx-address-contains address))
+5 -78
View File
@@ -46,19 +46,6 @@
"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"
@@ -67,29 +54,13 @@
"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 "0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"}
:status "eth:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"}
{:metamask "ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2@0xa4b1"
:status "0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"}
:status "arb1:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"}
{:metamask "ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2@0xa"
:status "0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"}
:status "oeth:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"}
{:metamask "ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"
:status "0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"}
{:metamask "ethe:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2@0x1" :status nil}
@@ -99,26 +70,6 @@
{: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
@@ -129,33 +80,9 @@
(for [address invalid-metamask-addresses]
(is (not (utils.address/metamask-address? address)))))))
(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
(deftest metamask-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/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)))))))
(is (= status-address (utils.address/metamask-address->status-address metamask-address)))))))
+3 -6
View File
@@ -44,18 +44,15 @@
(defn greater-than-or-equals
[^js bn1 ^js bn2]
(when (bignumber? bn1)
(.greaterThanOrEqualTo bn1 bn2)))
(.greaterThanOrEqualTo bn1 bn2))
(defn greater-than
[bn1 bn2]
(when (bignumber? bn1)
(.greaterThan ^js bn1 bn2)))
(.greaterThan ^js bn1 bn2))
(defn less-than
[bn1 bn2]
(when (bignumber? bn1)
(.lessThan ^js bn1 bn2)))
(.lessThan ^js bn1 bn2))
(defn equal-to
[n1 n2]
+1 -17
View File
@@ -1,8 +1,5 @@
(ns utils.number
(:require [clojure.string :as string]
[native-module.core :as native-module]
[utils.hex :as utils.hex]
[utils.money :as utils.money]))
(:require [clojure.string :as string]))
(defn naive-round
"Quickly and naively round number `n` up to `decimal-places`.
@@ -64,16 +61,3 @@
(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))
+3 -5
View File
@@ -18,7 +18,7 @@
(defn <-js-map
"Shallowly transforms JS Object keys/values with `key-fn`/`val-fn`.
Returns m if `m` is not an instance of `js/Object`.
Returns nil 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,8 +33,7 @@
([^js m]
(<-js-map m nil))
([^js m {:keys [key-fn val-fn]}]
(assert (or (nil? m) (identical? (type m) js/Object) (map? m)))
(if (identical? (type m) js/Object)
(when (identical? (type m) js/Object)
(persistent!
(reduce (fn [r k]
(let [v (oops/oget+ m k)
@@ -42,8 +41,7 @@
new-val (if val-fn (val-fn k v) v)]
(assoc! r new-key new-val)))
(transient {})
(js-keys m)))
m)))
(js-keys 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
{:a 1} {:a 1}
nil #js []
#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": "fix/discover-communities-issue",
"commit-sha1": "079bb25861ca30cfa61aa34aeab597e802ade3e5",
"src-sha256": "1xnkkxzznnnlk5ilzfw2npwxy4bh9wn68gvg79y62yjgrvry59bb"
"version": "f859b58c3896523b2fb9a09b3e5c1cedb04f959b",
"commit-sha1": "f859b58c3896523b2fb9a09b3e5c1cedb04f959b",
"src-sha256": "009nd47aajng5k7wrcqv5zvvzniaswqi706fpkbbjhqziympi1s1"
}
+17 -19
View File
@@ -28,31 +28,29 @@ class BaseTestReport:
file_name = "%s.json" % test_name
return os.path.join(self.TEST_REPORT_DIR, file_name)
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])
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])
result.close()
logs_paths[log] = log_path
return logs_paths
geth_paths[log] = geth_path
return 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)
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
else:
if hasattr(test, 'logs_paths'):
logs_paths = test.logs_paths
else:
logs_paths = ''
geth_paths = ''
file_path = self.get_test_report_file_path(test.name)
test_dict = {
'testrail_case_id': test.testrail_case_id,
'name': test.name,
'logs_paths': logs_paths,
'geth_paths': geth_paths,
'testruns': list(),
'group_name': test.group_name,
'secured': test.secured
@@ -76,7 +74,7 @@ class BaseTestReport:
first_commands=testrun_data['first_commands'],
xfail=testrun_data['xfail']))
tests.append(SingleTestData(name=test_data['name'],
logs_paths=test_data['logs_paths'],
geth_paths=test_data['geth_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, logs_paths, grop_name, secured):
def __init__(self, name, testruns, testrail_case_id, geth_paths, grop_name, secured):
self.testrail_case_id = testrail_case_id
self.name = name
self.testruns = testruns
self.logs_paths = logs_paths
self.geth_paths = geth_paths
self.group_name = grop_name
self.secured = secured
+3 -2
View File
@@ -8,6 +8,7 @@ from os import environ
from sys import argv
import emoji
import pytest
import requests
from support.base_test_report import BaseTestReport
@@ -213,9 +214,9 @@ class TestrailReport(BaseTestReport):
if re.findall(pattern, res['comment']):
res_id = res['id']
try:
for log in test.logs_paths.keys():
for geth in test.geth_paths.keys():
self.add_attachment(method='add_attachment_to_result/%s' % str(res_id),
path=test.logs_paths[log])
path=test.geth_paths[geth])
except (AttributeError, FileNotFoundError):
pass
break
+18 -23
View File
@@ -111,13 +111,12 @@ 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_app_path() + 'geth.log')
return base64.b64decode(result)
def pull_requests_log(driver):
result = driver.pull_file(get_app_path() + 'requests.log')
result = driver.pull_file(get_geth_path())
return base64.b64decode(result)
@@ -378,23 +377,21 @@ class SauceSharedMultipleDeviceTestCase(AbstractTestCase):
test_suite_data.current_test.group_name = self.__class__.__name__
def teardown_method(self, method):
log_names, log_contents = [], []
geth_names, geth_contents = [], []
for driver in self.drivers:
try:
self.print_sauce_lab_info(self.drivers[driver])
self.add_alert_text_to_report(self.drivers[driver])
log_names.append(
geth_names.append(
'%s_geth%s.log' % (test_suite_data.current_test.name, str(self.drivers[driver].number)))
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]))
geth_contents.append(pull_geth(self.drivers[driver]))
except (WebDriverException, AttributeError, RemoteDisconnected, ProtocolError):
pass
finally:
try:
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)
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)
except IndexError:
pass
@@ -416,14 +413,11 @@ class SauceSharedMultipleDeviceTestCase(AbstractTestCase):
group_setup_failed = True
else:
group_setup_failed = False
log_contents, log_names = list(), list()
geth_contents = list()
try:
for i, driver in cls.drivers.items():
for _, driver in cls.drivers.items():
if group_setup_failed:
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))
geth_contents.append(pull_geth(driver=driver))
session_id = driver.session_id
try:
sauce.jobs.update_job(username=sauce_username, job_id=session_id, name=cls.__name__)
@@ -455,12 +449,13 @@ class SauceSharedMultipleDeviceTestCase(AbstractTestCase):
except AttributeError:
pass
logs = dict(zip(log_names, log_contents))
logs_paths = github_report.save_logs(logs)
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)
for test in test_suite_data.tests:
if group_setup_failed:
test.logs_paths = logs_paths
test.geth_paths = geth_paths
github_report.save_test(test)
+6 -4
View File
@@ -267,11 +267,12 @@ class SignInView(BaseView):
for _ in range(3):
self.allow_button.click_if_shown(sec=10)
self.enable_notifications_button.click_if_shown()
if self.chats_tab.is_element_displayed():
if self.start_button.is_element_displayed():
break
else:
self.maybe_later_button.wait_and_click()
self.maybe_later_button.click_until_presence_of_element(self.start_button)
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()
@@ -297,10 +298,11 @@ 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()
self.enable_notifications_button.click_until_presence_of_element(self.start_button)
else:
self.maybe_later_button.wait_and_click()
self.maybe_later_button.click_until_presence_of_element(self.start_button)
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()