Compare commits
14
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a1a33f459 | ||
|
|
1190fc8069 | ||
|
|
92456612b1 | ||
|
|
9912136ac9 | ||
|
|
0eb065bbb7 | ||
|
|
2e61f94d84 | ||
|
|
f606dc065b | ||
|
|
6464ef96b6 | ||
|
|
9068801e4f | ||
|
|
2f3d3fc7f9 | ||
|
|
69664322b8 | ||
|
|
a1662752bc | ||
|
|
3363152160 | ||
|
|
7cad13c3c7 |
Binary file not shown.
|
After Width: | Height: | Size: 722 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.3 MiB |
@@ -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
|
||||
|
||||
@@ -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}))))
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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}}]])
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)]]]))
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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)))
|
||||
|
||||
|
||||
@@ -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)))))))
|
||||
|
||||
|
||||
@@ -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
@@ -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))
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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,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"
|
||||
}
|
||||
|
||||
@@ -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,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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user