Compare commits

...
Author SHA1 Message Date
jo-mut 74c38186a4 fixed reloading contacts when scrolling after selecting/unselected to add to a group chat 2024-07-29 12:11:50 +05:30
yqrashawn 55c620e59d fix: create password for small screen (#20645)
* fix: create password for small screen

* feat: use floating button page

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

* fix: use keyboard will show for ios

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

* fix: safe area bottom on devices without physical home button

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

* feat(create-password): tips and checkbox stick with confirm button

* fix: floating button blur after rebase

* fix(floating-button): absolute content avoid keyboard view

---------

Signed-off-by: yqrashawn <namy.19@gmail.com>
2024-07-29 13:41:15 +08:00
mmilad75 525609f0af Wallet Activity: transactions are not sorted by time #20808 (#20862) 2024-07-27 17:22:01 +02:00
Icaro Motta 90653955a6 chore(settings): Disable telemetry option (#20881) 2024-07-26 16:51:49 -03:00
John Ngei d27ab756d0 fix_:display group message using the new ui (#20787) 2024-07-26 21:14:04 +02:00
Siddarth Kumar c6a1db6334 ci: enable split apks & build only for arm64-v8a (#20683)
In this commit:
- we set `ANDROID_ABI_SPLIT` to `true`
- we set `ANDROID_ABI_INCLUDE` to `arm64-v8a` for debug & PR android builds
- release builds would still contain `armeabi-v7a;arm64-v8a` and there is no change for E2E android builds
- we point to relevant changes in `status-jenkins-lib` which also introduces a size check for this `apk`.
The agreed threshold is 100 MB.
2024-07-27 00:02:44 +05:30
flexsurfer 73777e052e Ensure keycard account can send transaction after upgrading from v1 to v2 #20552 (#20845) 2024-07-26 17:45:45 +02:00
Mohsen a6d3fc3742 [#20524] fix: the missed keypairs are shown in the key pair list screen (#20888) 2024-07-26 19:11:01 +03:30
Parvesh Monu a671c70838 fix broken screen and navigation when syncing fails (#20887) 2024-07-26 19:31:42 +05:30
Shivek Khurana a45991b6dc 🥅 Filter connected dapps based on testnet mode, reject proposals and requests gracefully (#20799)
* 🥅 Filter connected dapps based on testnet mode

- Fixes #20794

* 🥅 Remove map, just filter

* 💿 Rebase

*  Remove greedy fetch

* 🙅‍♀️ Properly reject proposals and requests

* 🎗️ Remove newline and move `set`

- `set` was applied at the wrong place here

* ✏️ Address review comments

* 👀 Read proposal to reject from state

* ◀️ Bring back network filtering

* 🧹 Cleanup

* ✏️ Move comment around

* 🎣 Use filter operable accounts helper

*  Add back events deleted during rebase

* 🧰 Fix Issue 2, Testnet sessions not visible

* 🖊️ Fix lint

* 🔗 Make testnet filtering more explicit

* 🥢 Use union instead of two subsets call

* ✏️ Fix lint

* 🔇 Undo changes that creeped in an unrelated ns
2024-07-26 18:24:53 +05:30
BalogunofAfrica 2e9fa22e4f feat: wallet router v2 (#20631)
* add v2 method

* rename v2 to get-suggested-route

* remove timestamp check on success

* handle async signal for suggestion

* fix stop get suggested routes

* address feedback

* rename get-suggest-route

* prefer lazy seq

* fix formatting

* update suggested routes success

* refactor get-in calls in start-get-suggested-routes

* move transformations to data store

* clean suggested routes immediately

* fix lint

* pass precision as ar

* change test name

* fix big number division error (issues 1,2)

* only trigger router fetch when there address (to/from)

* check response data for error response when routes received via signal

* update status-go

* fix: test failure

* update status go

* handle error message for generic errors
2024-07-26 12:23:09 +01:00
71 changed files with 958 additions and 548 deletions
+1 -3
View File
@@ -215,15 +215,13 @@ build-fdroid: ##@build Build release for F-Droid
build-android: export BUILD_ENV ?= prod
build-android: export BUILD_TYPE ?= nightly
build-android: export ORG_GRADLE_PROJECT_versionCode ?= $(TMP_BUILD_NUMBER)
build-android: export ANDROID_ABI_SPLIT ?= false
build-android: export ANDROID_ABI_INCLUDE ?= armeabi-v7a;arm64-v8a;x86
build-android: ##@build Build unsigned Android APK
@scripts/build-android.sh
release-android: export TARGET := keytool
release-android: export KEYSTORE_PATH ?= $(HOME)/.gradle/status-im.keystore
release-android: keystore build-android ##@build Build signed Android APK
@scripts/sign-android.sh result/app-release-unsigned.apk
@scripts/sign-android.sh result/app-arm64-v8a-release-unsigned.apk
release-ios: export TARGET := ios
release-ios: export IOS_STATUS_GO_TARGETS := ios/arm64
+1 -1
View File
@@ -211,7 +211,7 @@ android {
reset()
enable getEnvOrConfig('ANDROID_ABI_SPLIT').toBoolean()
include getEnvOrConfig('ANDROID_ABI_INCLUDE').split(";")
universalApk true
universalApk false
}
}
signingConfigs {
+4 -4
View File
@@ -38,10 +38,10 @@ KEYSTORE_PASSWORD=password
KEYSTORE_ALIAS=status
KEYSTORE_KEY_PASSWORD=password
# By default we build a mostly universal APK
ANDROID_ABI_SPLIT=false
# Some platforms are excluded though
ANDROID_ABI_INCLUDE=armeabi-v7a;arm64-v8a;x86;x86_64
# Splitting by CPU Architecture produces smaller APKs.
ANDROID_ABI_SPLIT=true
# By default its better to only build apk for most recent devices.
ANDROID_ABI_INCLUDE=arm64-v8a
org.gradle.jvmargs=-Xmx8704M -XX:+UseParallelGC
+2 -6
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.9.3'
/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()
@@ -72,11 +72,7 @@ pipeline {
stage('Upload') {
steps { script {
def urls = apks.collect { s5cmd.upload(it) }
if (urls.size() > 1) { /* Return only the universal APK. */
env.PKG_URL = urls.find { it.contains('universal') }
} else { /* If no universal is available pick first. */
env.PKG_URL = urls.first()
}
env.PKG_URL = urls.first()
jenkins.setBuildDesc(APK: env.PKG_URL)
} }
}
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.9.3'
import groovy.json.JsonBuilder
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.9.3'
pipeline {
agent { label 'linux' }
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.9.3'
/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.9.3'
/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.9.3'
pipeline {
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.9.3'
pipeline {
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.9.3'
pipeline {
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.9.3'
pipeline {
agent { label 'macos' }
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.9.3'
pipeline {
agent { label params.AGENT_LABEL }
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.9.3'
pipeline {
agent { label 'linux' }
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.9.3'
pipeline {
agent {
+2 -2
View File
@@ -18,10 +18,10 @@
buildUrl ? lib.getEnvWithDefault "ORG_GRADLE_PROJECT_buildUrl" null,
statusGoSrcOverride ? lib.getEnvWithDefault "STATUS_GO_SRC_OVERRIDE" null,
# If APKs should be split based on architectures
androidAbiSplit ? lib.getEnvWithDefault "ANDROID_ABI_SPLIT" "false",
androidAbiSplit ? lib.getEnvWithDefault "ANDROID_ABI_SPLIT" "true",
# Android architectures to build for
# Used to detect end-to-end builds
androidAbiInclude ? lib.getEnvWithDefault "ANDROID_ABI_INCLUDE" "armeabi-v7a;arm64-v8a;x86",
androidAbiInclude ? lib.getEnvWithDefault "ANDROID_ABI_INCLUDE" "arm64-v8a",
}:
let
Binary file not shown.

After

Width:  |  Height:  |  Size: 424 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 752 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 547 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

+1 -1
View File
@@ -13,7 +13,7 @@ export BUILD_TYPE=debug
# Install the APK on running emulator or android device.
installAndLaunchApp() {
adb install -r ./result/app-debug.apk > "${ADB_INSTALL_LOG_FILE}" 2>&1
adb install -r ./result/app-arm64-v8a-debug.apk > "${ADB_INSTALL_LOG_FILE}" 2>&1
"${GIT_ROOT}/scripts/wait-for-metro-port.sh" 2>&1
# connected android devices need this port to be exposed for metro
adb reverse "tcp:${RCT_METRO_PORT}" "tcp:${RCT_METRO_PORT}"
@@ -5,6 +5,7 @@
[legacy.status-im.ui.components.list.views :as list]
[quo.core :as quo]
[re-frame.core :as re-frame]
[status-im.feature-flags :as ff]
[utils.i18n :as i18n]
[utils.re-frame :as rf])
(:require-macros [legacy.status-im.utils.views :as views]))
@@ -59,14 +60,14 @@
:on-press
#(re-frame/dispatch [:open-modal :peers-stats])
:chevron true}
{:size :small
:title "Telemetry"
:accessibility-label :telemetry-enabled
:container-margin-bottom 8
:on-press
#(re-frame/dispatch [:profile.settings/toggle-telemetry])
:accessory :switch
:active telemetry-enabled?}
(when (ff/enabled? ::ff/settings.telemetry)
{:size :small
:title "Telemetry"
:accessibility-label :telemetry-enabled
:container-margin-bottom 8
:on-press #(re-frame/dispatch [:profile.settings/toggle-telemetry])
:accessory :switch
:active telemetry-enabled?})
{:size :small
:title (i18n/label :t/light-client-enabled)
:accessibility-label :light-client-enabled
@@ -32,8 +32,7 @@
(def system-message-base-wrapper
{:flex-direction :row
:flex 1
:align-items :center})
:flex 1})
(def system-message-base-content-wrapper
{:align-self :center
@@ -127,6 +127,14 @@
(when incoming? [split-text "sent you a contact request" theme true])
[sm-timestamp timestamp theme]]]))
(defn system-message-group
[{:keys [customization-color child]}]
[system-message-base
{:icon {:icon :i/add-user
:color (or customization-color :primary)
:opacity 5}}
[rn/view child]])
(defn system-message-pinned
[{:keys [pinned-by child customization-color timestamp]}]
(let [theme (quo.theme/use-theme)]
@@ -183,6 +191,7 @@
:contact-request [system-message-contact-request data]
:added [system-message-added data]
:removed [system-message-removed data]
:group [system-message-group data]
nil)]))
(defn system-message
+29 -3
View File
@@ -4,11 +4,37 @@
[oops.core :as oops]
[react-native.core :as rn]))
(defn- add-keyboard-listener
[listener callback]
(oops/ocall rn/keyboard "addListener" listener callback))
(defn use-keyboard
[]
(let [kb (.useKeyboard hooks)]
{:keyboard-shown (.-keyboardShown ^js kb)
:keyboard-height (.-keyboardHeight ^js kb)}))
(let [[keyboard-height set-keyboard-height] (rn/use-state 0)
[did-show? set-did-show] (rn/use-state false)
[will-show? set-will-show] (rn/use-state false)]
(rn/use-mount
(fn []
(let [will-show-listener (add-keyboard-listener "keyboardWillShow" #(set-will-show true))
did-show-listener (add-keyboard-listener "keyboardDidShow"
(fn [e]
(set-did-show true)
(set-keyboard-height
(oops/oget e "endCoordinates.height"))))
will-hide-listener (add-keyboard-listener "keyboardWillHide" #(set-will-show false))
did-hide-listener (add-keyboard-listener "keyboardDidHide"
(fn [e]
(set-did-show false)
(when e
(oops/oget e "endCoordinates.height"))))]
(fn []
(oops/ocall will-show-listener "remove")
(oops/ocall did-show-listener "remove")
(oops/ocall will-hide-listener "remove")
(oops/ocall did-hide-listener "remove")))))
{:keyboard-shown did-show?
:keyboard-will-show? will-show?
:keyboard-height keyboard-height}))
(defn use-back-handler
[handler]
@@ -3,21 +3,23 @@
[react-native.safe-area :as safe-area]))
(defn content-container
[blur? keyboard-shown?]
[blur? keyboard-shown? {:keys [padding-vertical padding-horizontal]}]
(let [margin-bottom (if keyboard-shown? 0 (safe-area/get-bottom))]
(cond-> {:margin-top :auto
:overflow :hidden
:margin-bottom margin-bottom
:padding-vertical 12
:padding-horizontal 20}
:padding-vertical (or padding-vertical 12)
:padding-horizontal (or padding-horizontal 20)}
blur? (dissoc :padding-vertical :padding-horizontal))))
(defn blur-inner-container
[theme shell-overlay?]
{:background-color (colors/theme-colors colors/white-70-blur
(if shell-overlay?
colors/neutral-80-opa-80-blur
colors/neutral-95-opa-70-blur)
theme)
:padding-vertical 12
:padding-horizontal 20})
[{:keys [theme shell-overlay? padding-vertical padding-horizontal background-color]}]
{:background-color (or background-color
(colors/theme-colors
colors/white-70-blur
(if shell-overlay?
colors/neutral-80-opa-80-blur
colors/neutral-95-opa-70-blur)
theme))
:padding-vertical (or padding-vertical 12)
:padding-horizontal (or padding-horizontal 20)})
@@ -6,20 +6,25 @@
[status-im.common.floating-button-page.floating-container.style :as style]))
(defn- blur-container
[child shell-overlay?]
[shell-overlay? blur-options child]
(let [theme (quo.theme/use-theme)]
[quo/blur
{:blur-amount 20
:blur-type :transparent
:overlay-color :transparent}
[rn/view {:style (style/blur-inner-container theme shell-overlay?)}
(or blur-options
{:blur-amount 20
:blur-type :transparent
:overlay-color :transparent})
[rn/view
{:style (style/blur-inner-container (assoc
blur-options
:theme theme
:shell-overlay? shell-overlay?))}
child]]))
(defn view
[{:keys [on-layout keyboard-shown? blur? shell-overlay?]} child]
[{:keys [on-layout keyboard-shown? blur? shell-overlay? blur-options]} child]
[rn/view
{:style (style/content-container blur? keyboard-shown?)
{:style (style/content-container blur? keyboard-shown? blur-options)
:on-layout on-layout}
(if blur?
[blur-container child shell-overlay?]
[blur-container shell-overlay? blur-options child]
child)])
@@ -13,3 +13,13 @@
:bottom 0
:left 0
:right 0})
(defn content-keyboard-avoiding-view
[{:keys [top bottom]}]
{:position :absolute
:top top
:left 0
:right 0
:bottom bottom})
(def scroll-view-container {:flex 1})
@@ -30,13 +30,15 @@
(reset! ratom height))))
(defn- init-keyboard-listeners
[{:keys [on-did-show scroll-view-ref]}]
[{:keys [on-did-show on-will-show scroll-view-ref]}]
(let [keyboard-will-show? (reagent/atom false)
keyboard-did-show? (reagent/atom false)
add-listener (fn [listener callback]
(oops/ocall rn/keyboard "addListener" listener callback))
will-show-listener (add-listener "keyboardWillShow"
#(reset! keyboard-will-show? true))
(fn [e]
(reset! keyboard-will-show? true)
(when on-will-show (on-will-show e))))
did-show-listener (add-listener "keyboardDidShow"
(fn [e]
(reset! keyboard-did-show? true)
@@ -58,7 +60,8 @@
(defn view
[{:keys [header footer customization-color footer-container-padding header-container-style
content-container-style gradient-cover? keyboard-should-persist-taps shell-overlay?]
content-container-style gradient-cover? keyboard-should-persist-taps shell-overlay?
blur-options content-avoid-keyboard?]
:or {footer-container-padding (safe-area/get-top)}}
& children]
(reagent/with-let [scroll-view-ref (atom nil)
@@ -69,29 +72,34 @@
content-container-height (reagent/atom 0)
content-scroll-y (reagent/atom 0)
keyboard-height (reagent/atom 0)
reset-keyboard-height #(reset! keyboard-height (oops/oget
%
"endCoordinates.height"))
{:keys [keyboard-will-show?
keyboard-did-show?
remove-listeners]} (init-keyboard-listeners
{:scroll-view-ref scroll-view-ref
:on-did-show
(fn [e]
(reset! keyboard-height
(oops/oget e "endCoordinates.height")))})
(cond-> {:scroll-view-ref scroll-view-ref}
platform/ios?
(assoc :on-will-show reset-keyboard-height)
(not platform/ios?)
(assoc :on-did-show reset-keyboard-height)))
set-header-height (set-height-on-layout header-height)
set-content-container-height (set-height-on-layout content-container-height)
set-footer-container-height (set-height-on-layout footer-container-height)
set-content-y-scroll (fn [event]
(reset! content-scroll-y
(oops/oget event "nativeEvent.contentOffset.y")))]
(oops/oget event "nativeEvent.contentOffset.y")))
bottom-safe-area (safe-area/get-bottom)]
(let [keyboard-shown? (if platform/ios? @keyboard-will-show? @keyboard-did-show?)
footer-container-padding (+ footer-container-padding (rf/sub [:alert-banners/top-margin]))
show-background? (show-background {:window-height window-height
:footer-container-height @footer-container-height
:keyboard-height @keyboard-height
:content-scroll-y @content-scroll-y
:content-container-height @content-container-height
:header-height @header-height
:keyboard-shown? keyboard-shown?})]
show-background? (show-background
{:window-height window-height
:footer-container-height @footer-container-height
:keyboard-height @keyboard-height
:content-scroll-y @content-scroll-y
:content-container-height @content-container-height
:header-height @header-height
:keyboard-shown? keyboard-shown?})]
[:<>
(when gradient-cover?
[quo/gradient-cover {:customization-color customization-color}])
@@ -100,20 +108,28 @@
{:on-layout set-header-height
:style header-container-style}
header]
[gesture/scroll-view
{:ref set-scroll-ref
:on-scroll set-content-y-scroll
:scroll-event-throttle 64
:content-container-style {:flex-grow 1
:padding-bottom (when @keyboard-did-show?
@footer-container-height)}
:always-bounce-vertical @keyboard-did-show?
:shows-vertical-scroll-indicator false
:keyboard-should-persist-taps keyboard-should-persist-taps}
(into [rn/view
{:style content-container-style
:on-layout set-content-container-height}]
children)]
[(if content-avoid-keyboard? rn/keyboard-avoiding-view rn/view)
{:style
(if content-avoid-keyboard?
(style/content-keyboard-avoiding-view
{:top @header-height
:bottom (if keyboard-shown?
@footer-container-height
(+ bottom-safe-area @footer-container-height))})
style/scroll-view-container)}
[gesture/scroll-view
{:ref set-scroll-ref
:on-scroll set-content-y-scroll
:scroll-event-throttle 64
:content-container-style {:flex-grow 1}
:always-bounce-vertical @keyboard-did-show?
:automatically-adjust-keyboard-insets true
:shows-vertical-scroll-indicator false
:keyboard-should-persist-taps keyboard-should-persist-taps}
(into [rn/view
{:style content-container-style
:on-layout set-content-container-height}]
children)]]
[rn/keyboard-avoiding-view
{:style style/keyboard-avoiding-view
:keyboard-vertical-offset (if platform/ios? footer-container-padding 0)
@@ -121,8 +137,9 @@
[floating-container/view
{:on-layout set-footer-container-height
:keyboard-shown? keyboard-shown?
:blur? show-background?
:shell-overlay? shell-overlay?}
:blur-options blur-options
:shell-overlay? shell-overlay?
:blur? show-background?}
footer]]]])
(finally
(remove-listeners))))
+1 -1
View File
@@ -55,7 +55,7 @@
{:dispatch (if user-in-sign-in-intro-screen?
[:navigate-to-within-stack
[:screen/onboarding.syncing-progress-intro :screen/onboarding.sign-in-intro]]
[:navigate-to :screen/onboarding.syncing-progress])}
[:open-modal :screen/onboarding.syncing-progress])}
(and completed-pairing? sender?)
{:dispatch [:syncing/clear-states]}
+3 -1
View File
@@ -27,7 +27,9 @@
:welcome-illustration (js/require "../resources/images/ui2/welcome_illustration.png")
: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")})
:nfc-success (js/require "../resources/images/ui2/nfc-success.png")
:syncing-devices (js/require "../resources/images/ui2/syncing_devices.png")
:syncing-wrong (js/require "../resources/images/ui2/syncing_wrong.png")})
(def ui-themed
{:angry-man
+9
View File
@@ -38,6 +38,15 @@
"wallet"
{:fx [[:dispatch [:wallet/signal-received event-js]]]}
"wallet.sign.transactions"
{:fx [[:dispatch
[:standard-auth/authorize-with-keycard
{:on-complete #(rf/dispatch [:keycard/sign-hash %
(first (transforms/js->clj event-js))])}]]]}
"wallet.suggested.routes"
{:fx [[:dispatch [:wallet/handle-suggested-routes (transforms/js->clj event-js)]]]}
"envelope.sent"
(messages.transport/update-envelopes-status
cofx
@@ -3,21 +3,35 @@
[schema.core :as schema]
[status-im.common.standard-authentication.enter-password.view :as enter-password]
[status-im.common.standard-authentication.events-schema :as events-schema]
[status-im.contexts.keycard.pin.view :as keycard.pin]
[taoensso.timbre :as log]
[utils.address]
[utils.i18n :as i18n]
[utils.re-frame :as rf]
[utils.security.core :as security]))
(rf/reg-fx :effects.keycard/call-on-auth-success
(fn [on-auth-success]
(when on-auth-success (on-auth-success ""))))
(defn authorize
[{:keys [db]} [args]]
[{:keys [db]} [{:keys [on-auth-success keycard-supported?] :as args}]]
(let [key-uid (get-in db [:profile/profile :key-uid])
keycard? (get-in db [:profile/profile :keycard-pairing])]
{:fx [[:effects.biometric/check-if-available
{:key-uid key-uid
:on-success #(rf/dispatch [:standard-auth/authorize-with-biometric args])
:on-fail (if keycard?
#(rf/dispatch [:standard-auth/authorize-with-keycard args])
#(rf/dispatch [:standard-auth/authorize-with-password args]))}]]}))
{:fx
[(if keycard?
(if keycard-supported?
[:effects.keycard/call-on-auth-success on-auth-success]
[:effects.utils/show-popup
{:title "This feature is not supported yet "
:content
"Keycard support is limited to logging in
and signing the sending transaction.
Use Status Desktop to access all functions."}])
[:effects.biometric/check-if-available
{:key-uid key-uid
:on-success #(rf/dispatch [:standard-auth/authorize-with-biometric args])
:on-fail #(rf/dispatch [:standard-auth/authorize-with-password args])}])]}))
(schema/=> authorize events-schema/?authorize)
(rf/reg-event-fx :standard-auth/authorize authorize)
@@ -94,6 +108,16 @@
:button-icon-left auth-button-icon-left
:button-label auth-button-label}])))
(defn authorize-with-keycard
[_ [{:keys [on-complete]}]]
{:fx [[:dispatch
[:show-bottom-sheet
{:hide-on-background-press? false
:on-close #(rf/dispatch [:standard-auth/reset-login-password])
:content (fn []
[keycard.pin/auth {:on-complete on-complete}])}]]]})
(rf/reg-event-fx :standard-auth/authorize-with-keycard authorize-with-keycard)
(defn authorize-with-password
[_ [{:keys [on-close theme blur?] :as args}]]
{:fx [[:dispatch [:standard-auth/reset-login-password]]
@@ -110,7 +134,9 @@
(rf/reg-event-fx
:standard-auth/reset-login-password
(fn [{:keys [db]}]
{:db (update db :profile/login dissoc :password :error)}))
{:db (-> db
(update :profile/login dissoc :password :error)
(update :keycard dissoc :pin))}))
(rf/reg-fx
:standard-auth/on-close
@@ -8,7 +8,7 @@
(defn view
[{:keys [track-text customization-color auth-button-label on-auth-success on-auth-fail
auth-button-icon-left size blur? container-style disabled? dependencies]
auth-button-icon-left size blur? container-style disabled? dependencies keycard-supported?]
:or {container-style {:flex 1}}}]
(let [theme (quo.theme/use-theme)
auth-method (rf/sub [:auth-method])
@@ -21,6 +21,7 @@
:auth-button-icon-left auth-button-icon-left
:theme theme
:blur? blur?
:keycard-supported? keycard-supported?
:biometric-auth? biometric-auth?
:on-auth-success on-auth-success
:on-auth-fail on-auth-fail
+1
View File
@@ -291,6 +291,7 @@
(def ^:const wallet-connect-session-delete-event "session_delete")
(def ^:const wallet-connect-user-rejected-error-key "USER_REJECTED")
(def ^:const wallet-connect-user-disconnected-reason-key "USER_DISCONNECTED")
(def ^:const wallet-connect-user-rejected-chains-error-key "USER_REJECTED_CHAINS")
(def ^:const transaction-pending-type-wallet-connect-transfer "WalletConnectTransfer")
@@ -50,7 +50,7 @@
item])))))
(defn add-manage-members
[{:keys [scroll-enabled? on-scroll]}]
[{:keys [on-scroll]}]
(let [theme (quo.theme/use-theme)
selected-participants (rf/sub [:group-chat/selected-participants])
deselected-members (rf/sub [:group-chat/deselected-members])
@@ -71,7 +71,6 @@
(i18n/label (if admin? :t/manage-members :t/add-members))]
[gesture/section-list
{:key-fn :title
:scroll-enabled @scroll-enabled?
:on-scroll on-scroll
:sticky-section-headers-enabled false
:sections (rf/sub [:contacts/grouped-by-first-letter])
@@ -33,3 +33,7 @@
(def drawer-message-container
{:padding-top 4
:padding-bottom 4})
(def group-member-mention
{:flex-direction :row
:align-items :center})
@@ -126,14 +126,60 @@
:photo-path photo-path
:incoming? (not= public-key from)}]))
(defn group-member
[literal]
(let [[primary-name _] (rf/sub [:contacts/contact-two-names-by-identity literal])
photo-path (rf/sub [:chats/photo-path literal])]
[rn/view {:style style/group-member-mention}
[quo/user-avatar
{:full-name primary-name
:profile-picture photo-path
:status-indicator? false
:size :xxxs
:ring? false}]
[quo/text
{:weight :semi-bold
:style {:margin-left 4}}
primary-name]]))
(defn resolve-group-system-message
[{:keys [children]}]
(reduce (fn [acc {:keys [type literal]}]
(if (= type "mention")
(conj acc [group-member literal])
(conj acc
[rn/view
[quo/text literal]])))
[:<>]
children))
(defn render-parsed-text
[content]
(reduce (fn [acc e]
(conj acc (resolve-group-system-message e)))
[quo/text]
(:parsed-text content)))
(defn group-system-message
[{:keys [chat-id timestamp-str content]} type]
(let [{:keys [customization-color]} (rf/sub [:contacts/contact-by-address chat-id])]
[quo/system-message
{:type type
:timestamp timestamp-str
:customization-color customization-color
:child (render-parsed-text content)}]))
(defn system-message-content
[{:keys [content-type quoted-message] :as message-data}]
(if quoted-message
[pin/pinned-message message-data]
(condp = content-type
constants/content-type-system-text
[system.text/text-content message-data]
[group-system-message message-data :group]
constants/content-type-system-pinned-message
[system.text/text-content message-data]
@@ -109,3 +109,22 @@
[pairings]
(keycard/set-pairings pairings))
(rf/reg-fx :effects.keycard/set-pairing-to-keycard set-pairing-to-keycard)
(defn sign
[{:keys [on-success on-failure] :as args}]
(log/debug "[keycard] sign")
(keycard/sign
(assoc
args
:on-success
(fn [response]
(log/debug "[keycard response succ] sign")
(when on-success
(on-success (transforms/js->clj response))))
:on-failure
(fn [response]
(log/warn "[keycard response fail] sign"
(error-object->map response))
(when on-failure
(on-failure (error-object->map response)))))))
(rf/reg-fx :effects.keycard/sign sign)
@@ -3,6 +3,8 @@
status-im.contexts.keycard.login.events
status-im.contexts.keycard.pin.events
status-im.contexts.keycard.sheet.events
status-im.contexts.keycard.sign.events
[status-im.contexts.keycard.utils :as keycard.utils]
[taoensso.timbre :as log]))
(rf/reg-event-fx :keycard/on-check-nfc-enabled-success
@@ -55,3 +57,19 @@
(fn [{:keys [db]} [{:keys [on-cancel-event-vector]}]]
(log/debug "[keycard] nfc started success")
{:db (assoc-in db [:keycard :on-nfc-cancelled-event-vector] on-cancel-event-vector)}))
(rf/reg-event-fx :keycard/on-action-with-pin-error
(fn [{:keys [db]} [error]]
(log/debug "[keycard] get keys error: " error)
(let [tag-was-lost? (keycard.utils/tag-lost? (:error error))
pin-retries-count (keycard.utils/pin-retries (:error error))]
(if tag-was-lost?
{:db (assoc-in db [:keycard :pin :status] nil)}
(if (nil? pin-retries-count)
{:effects.utils/show-popup {:title "wrong-keycard"}}
{:db (-> db
(assoc-in [:keycard :application-info :pin-retry-counter] pin-retries-count)
(update-in [:keycard :pin] assoc :status :error))
:fx [[:dispatch [:keycard/hide-connection-sheet]]
(when (zero? pin-retries-count)
[:effects.utils/show-popup {:title "frozen-keycard"}])]})))))
@@ -3,22 +3,6 @@
[taoensso.timbre :as log]
[utils.re-frame :as rf]))
(rf/reg-event-fx :keycard.login/on-get-keys-error
(fn [{:keys [db]} [error]]
(log/debug "[keycard] get keys error: " error)
(let [tag-was-lost? (keycard.utils/tag-lost? (:error error))
pin-retries-count (keycard.utils/pin-retries (:error error))]
(if tag-was-lost?
{:db (assoc-in db [:keycard :pin :status] nil)}
(if (nil? pin-retries-count)
{:effects.utils/show-popup {:title "wrong-keycard"}}
{:db (-> db
(assoc-in [:keycard :application-info :pin-retry-counter] pin-retries-count)
(update-in [:keycard :pin] assoc :status :error))
:fx [[:dispatch [:keycard/hide-connection-sheet]]
(when (zero? pin-retries-count)
[:effects.utils/show-popup {:title "frozen-keycard"}])]})))))
(rf/reg-event-fx :keycard.login/on-get-keys-success
(fn [{:keys [db]} [data]]
(let [{:keys [key-uid encryption-public-key
@@ -56,28 +40,25 @@
:key-uid key-uid}]]}))))
(rf/reg-event-fx :keycard.login/on-get-application-info-success
(fn [{:keys [db]} [application-info]]
(let [profile (get-in db [:profile/profiles-overview (get-in db [:profile/login :key-uid])])
pin (get-in db [:keycard :pin :text])
error (keycard.utils/validate-application-info profile application-info)]
(fn [{:keys [db]} [application-info {:keys [key-uid on-read-fx]}]]
(let [error (keycard.utils/validate-application-info key-uid application-info)]
(if error
{:effects.utils/show-popup {:title (str error)}}
{:db (-> db
(assoc-in [:keycard :application-info] application-info)
(assoc-in [:keycard :pin :status] :verifying))
:effects.keycard/get-keys {:pin pin
:on-success #(rf/dispatch [:keycard.login/on-get-keys-success %])
:on-failure #(rf/dispatch [:keycard.login/on-get-keys-error %])}}))))
{:db (-> db
(assoc-in [:keycard :application-info] application-info)
(assoc-in [:keycard :pin :status] :verifying))
:fx on-read-fx}))))
(rf/reg-event-fx :keycard.login/cancel-reading-card
(fn [{:keys [db]}]
{:db (assoc-in db [:keycard :on-card-connected-event-vector] nil)}))
(rf/reg-event-fx :keycard/read-card-and-login
(fn [{:keys [db]}]
(rf/reg-event-fx :keycard/read-card
(fn [{:keys [db]} [args]]
(let [connected? (get-in db [:keycard :card-connected?])
event-vector [:keycard/get-application-info
{:on-success #(rf/dispatch [:keycard.login/on-get-application-info-success %])}]]
{:on-success #(rf/dispatch [:keycard.login/on-get-application-info-success %
args])}]]
(log/debug "[keycard] proceed-to-login")
{:db (assoc-in db [:keycard :on-card-connected-event-vector] event-vector)
:fx [[:dispatch
@@ -9,13 +9,17 @@
(assoc-in [:keycard :pin :text] (.slice pin 0 -1))
(assoc-in [:keycard :pin :status] nil))}))))
(rf/reg-fx :effects.keycard.pin/dispatch-on-complete
(fn [[on-complete new-pin]]
(on-complete new-pin)))
(rf/reg-event-fx :keycard.pin/number-pressed
(fn [{:keys [db]} [number max-numbers on-complete-event]]
(fn [{:keys [db]} [number max-numbers on-complete]]
(let [pin (get-in db [:keycard :pin :text])
new-pin (str pin number)]
(when (<= (count new-pin) max-numbers)
{:db (-> db
(assoc-in [:keycard :pin :text] new-pin)
(assoc-in [:keycard :pin :status] nil))
:fx [(when (= (dec max-numbers) (count pin))
[:dispatch [on-complete-event]])]}))))
:fx [(when (and on-complete (= (dec max-numbers) (count pin)))
[:effects.keycard.pin/dispatch-on-complete [on-complete new-pin]])]}))))
+2 -2
View File
@@ -6,7 +6,7 @@
[utils.re-frame :as rf]))
(defn auth
[callback-event-key]
[{:keys [on-complete]}]
(let [{:keys [text status]} (rf/sub [:keycard/pin])
pin-retry-counter (rf/sub [:keycard/pin-retry-counter])
error? (= status :error)]
@@ -23,4 +23,4 @@
{:delete-key? true
:on-delete #(rf/dispatch [:keycard.pin/delete-pressed])
:on-press #(rf/dispatch [:keycard.pin/number-pressed % constants/pincode-length
callback-event-key])}]]))
on-complete])}]]))
@@ -0,0 +1,29 @@
(ns status-im.contexts.keycard.sign.events
(:require [utils.address]
[utils.re-frame :as rf]))
(defn get-signature-map
[tx-hash signature]
{tx-hash {:r (subs signature 0 64)
:s (subs signature 64 128)
:v (str (js/parseInt (subs signature 128 130) 16))}})
(rf/reg-event-fx :keycard/sign-hash
(fn [{:keys [db]} [pin-text tx-hash]]
(let [current-address (get-in db [:wallet :current-viewing-account-address])
path (get-in db [:wallet :accounts current-address :path])
key-uid (get-in db [:profile/profile :key-uid])]
{:fx [[:dispatch
[:keycard/read-card
{:key-uid key-uid
:on-read-fx [[:effects.keycard/sign
{:pin pin-text
:path path
:hash (utils.address/naked-address tx-hash)
:on-success
#(do
(rf/dispatch [:keycard/hide-connection-sheet])
(rf/dispatch
[:wallet/proceed-with-transactions-signatures
(get-signature-map tx-hash %)]))
:on-failure #(rf/dispatch [:keycard/on-action-with-pin-error %])}]]}]]]})))
+2 -2
View File
@@ -16,8 +16,8 @@
(re-matches #".*NFCError:100.*" error)))
(defn validate-application-info
[profile {:keys [key-uid paired? pin-retry-counter puk-retry-counter] :as application-info}]
(let [profile-mismatch? (or (nil? profile) (not= (:key-uid profile) key-uid))]
[profile-key-uid {:keys [key-uid paired? pin-retry-counter puk-retry-counter] :as application-info}]
(let [profile-mismatch? (or (nil? profile-key-uid) (not= profile-key-uid key-uid))]
(log/debug "[keycard] login-with-keycard"
"empty application info" (empty? application-info)
"no key-uid" (empty? key-uid)
@@ -2,8 +2,6 @@
(:require
[quo.foundations.colors :as colors]))
(def flex-fill {:flex 1})
(def heading {:margin-bottom 20})
(def heading-subtitle {:color colors/white})
(def heading-title (assoc heading-subtitle :margin-bottom 8))
@@ -14,23 +12,15 @@
(def space-between-inputs {:height 16})
(def password-tips
{:flex-direction :row
:justify-content :space-between
:margin-horizontal 20})
{:flex-direction :row
:justify-content :space-between
:padding-horizontal 20})
(def top-part
{:margin-horizontal 20
:margin-top 12})
(def form-container
{:justify-content :space-between
:padding-top 12
:padding-horizontal 20})
(def bottom-part
{:flex 1
:margin-top 12
:justify-content :flex-end})
(def disclaimer-container
{:margin-horizontal 20
:margin-vertical 4})
(def button-container
{:margin-horizontal 20
:margin-vertical 12})
(def disclaimer-container {:padding-horizontal 20})
(def footer-container {:padding-bottom 12})
(def footer-button-container {:margin-top 20 :padding-horizontal 20})
@@ -1,11 +1,11 @@
(ns status-im.contexts.onboarding.create-password.view
(:require
[oops.core :refer [ocall]]
[quo.core :as quo]
[quo.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.platform :as platform]
[react-native.safe-area :as safe-area]
[reagent.core :as reagent]
[status-im.common.floating-button-page.view :as floating-button]
[status-im.constants :as constants]
[status-im.contexts.onboarding.create-password.style :as style]
[utils.i18n :as i18n]
@@ -94,7 +94,7 @@
[quo/tips {:completed? symbols?}
(i18n/label :t/password-creation-tips-4)]]])
(defn password-validations
(defn validate-password
[password]
(let [validations (juxt utils.string/has-lower-case?
utils.string/has-upper-case?
@@ -111,68 +111,25 @@
(filter true?)
count))
(defn password-form
[]
(let [password (reagent/atom "")
repeat-password (reagent/atom "")
accepts-disclaimer? (reagent/atom false)
focused-input (reagent/atom nil)
show-password-validation? (reagent/atom false)
same-password-length? #(and (seq @password)
(= (count @password) (count @repeat-password)))]
(fn []
(let [{user-color :color} (rf/sub [:onboarding/profile])
{:keys [long-enough?]
:as validations} (password-validations @password)
password-strength (calc-password-strength validations)
empty-password? (empty? @password)
same-passwords? (and (not empty-password?) (= @password @repeat-password))
meet-requirements? (and (not empty-password?)
(utils.string/at-least-n-chars? @password 10)
same-passwords?
@accepts-disclaimer?)]
[:<>
[rn/view {:style style/top-part}
[header]
[password-inputs
{:password-long-enough? long-enough?
:passwords-match? same-passwords?
:empty-password? empty-password?
:show-password-validation? @show-password-validation?
:on-input-focus #(reset! focused-input :password)
:on-change-password (fn [new-value]
(reset! password new-value)
(when (same-password-length?)
(reset! show-password-validation? true)))
:on-change-repeat-password (fn [new-value]
(reset! repeat-password new-value)
(when (same-password-length?)
(reset! show-password-validation? true)))
:on-blur-repeat-password #(if empty-password?
(reset! show-password-validation? false)
(reset! show-password-validation? true))}]]
(defn- use-password-checks
[password]
(rn/use-memo
(fn []
(let [{:keys [long-enough?]
:as validations} (validate-password password)]
{:password-long-enough? long-enough?
:password-validations validations
:password-strength (calc-password-strength validations)
:empty-password? (empty? password)}))
[password]))
[rn/view {:style style/bottom-part}
(when same-passwords?
[rn/view {:style style/disclaimer-container}
[quo/disclaimer
{:blur? true
:on-change #(swap! accepts-disclaimer? not)
:checked? @accepts-disclaimer?}
(i18n/label :t/password-creation-disclaimer)]])
(when (and (= @focused-input :password) (not same-passwords?))
[help
{:validations validations
:password-strength password-strength}])
[rn/view {:style style/button-container}
[quo/button
{:disabled? (not meet-requirements?)
:customization-color user-color
:on-press #(rf/dispatch
[:onboarding/password-set
(security/mask-data @password)])}
(i18n/label :t/password-creation-confirm)]]]]))))
(defn- use-repeat-password-checks
[password repeat-password]
(rn/use-memo
(fn []
{:same-password-length? (and (seq password) (= (count password) (count repeat-password)))
:same-passwords? (and (seq password) (= password repeat-password))})
[password repeat-password]))
(defn create-password-doc
[]
@@ -183,38 +140,108 @@
[quo/text {:size :paragraph-2}
(i18n/label :t/create-profile-password-info-box-description)]]])
(defn- on-press-info
[]
(rn/dismiss-keyboard!)
(rf/dispatch [:show-bottom-sheet
{:content create-password-doc
:shell? true}]))
(defn- navigate-back
[]
(rf/dispatch [:navigate-back]))
(defn- page-nav
[]
(let [{:keys [top]} (safe-area/get-insets)]
[quo/page-nav
{:margin-top top
:background :blur
:icon-name :i/arrow-left
:on-press navigate-back
:right-side [{:icon-name :i/info
:on-press on-press-info}]}]))
(defn create-password
[]
(reagent/with-let [keyboard-shown? (reagent/atom false)
{:keys [top bottom]} (safe-area/get-insets)
will-show-listener (ocall rn/keyboard
"addListener"
"keyboardWillShow"
#(reset! keyboard-shown? true))
will-hide-listener (ocall rn/keyboard
"addListener"
"keyboardWillHide"
#(reset! keyboard-shown? false))
on-press-info (fn []
(rn/dismiss-keyboard!)
(rf/dispatch [:show-bottom-sheet
{:content create-password-doc
:shell? true}]))]
[:<>
[rn/touchable-without-feedback
{:on-press rn/dismiss-keyboard!
:accessible false}
[rn/view {:style style/flex-fill}
[rn/keyboard-avoiding-view {:style style/flex-fill}
[quo/page-nav
{:margin-top top
:background :blur
:icon-name :i/arrow-left
:on-press #(rf/dispatch [:navigate-back])
:right-side [{:icon-name :i/info
:on-press on-press-info}]}]
[password-form]
[rn/view {:style {:height (if-not @keyboard-shown? bottom 0)}}]]]]]
(finally
(ocall will-show-listener "remove")
(ocall will-hide-listener "remove"))))
(let [[password set-password] (rn/use-state "")
[repeat-password set-repeat-password] (rn/use-state "")
[accepts-disclaimer? set-accepts-disclaimer?] (rn/use-state false)
[focused-input set-focused-input] (rn/use-state nil)
[show-password-validation?
set-show-password-validation?] (rn/use-state false)
{user-color :color} (rf/sub [:onboarding/profile])
{:keys [password-long-enough?
password-validations password-strength
empty-password?]} (use-password-checks password)
{:keys [same-password-length? same-passwords?]} (use-repeat-password-checks password
repeat-password)
meet-requirements? (rn/use-memo
#(and (not empty-password?)
(utils.string/at-least-n-chars? password
10)
same-passwords?
accepts-disclaimer?)
[password repeat-password
accepts-disclaimer?])]
[floating-button/view
{:header [page-nav]
:keyboard-should-persist-taps :handled
:content-avoid-keyboard? true
:blur-options
{:blur-amount 34
:blur-radius 20
:blur-type :transparent
:overlay-color :transparent
:background-color (if platform/android? colors/neutral-100 colors/neutral-80-opa-1-blur)
:padding-vertical 0
:padding-horizontal 0}
:footer-container-padding 0
:footer
[rn/view
{:style style/footer-container}
(when same-passwords?
[rn/view {:style style/disclaimer-container}
[quo/disclaimer
{:blur? true
:on-change (partial set-accepts-disclaimer? not)
:checked? accepts-disclaimer?}
(i18n/label :t/password-creation-disclaimer)]])
(when (and (= focused-input :password) (not same-passwords?))
[help
{:validations password-validations
:password-strength password-strength}])
[quo/button
{:container-style style/footer-button-container
:disabled? (not meet-requirements?)
:customization-color user-color
:on-press #(rf/dispatch
[:onboarding/password-set
(security/mask-data password)])}
(i18n/label :t/password-creation-confirm)]]}
[rn/view {:style style/form-container}
[header]
[password-inputs
{:password-long-enough? password-long-enough?
:passwords-match? same-passwords?
:empty-password? empty-password?
:show-password-validation? show-password-validation?
:on-input-focus #(set-focused-input :password)
:on-change-password (fn [new-value]
(set-password new-value)
(when same-password-length?
(set-show-password-validation? true)))
:on-change-repeat-password (fn [new-value]
(set-repeat-password new-value)
(when same-password-length?
(set-show-password-validation? true)))
:on-blur-repeat-password #(if empty-password?
(set-show-password-validation? false)
(set-show-password-validation? true))}]]]))
@@ -20,14 +20,13 @@
:padding-bottom 20
:background-color (when-not in-onboarding? colors/neutral-80-opa-80-blur)})
(def page-illustration
{:flex 1
:background-color colors/danger-50
:align-items :center
:margin-horizontal 20
:border-radius 20
:margin-top 20
:justify-content :center})
(defn page-illustration
[width]
{:flex 1
:width width
:align-items :center
:align-self :center
:justify-content :center})
(def try-again-button
{:margin-top 20
@@ -2,10 +2,9 @@
(:require
[quo.core :as quo]
[react-native.core :as rn]
[status-im.config :as config]
[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]))
@@ -27,45 +26,39 @@
:description-accessibility-label :progress-screen-sub-title}])
(defn try-again-button
[profile-color in-onboarding? logged-in?]
[profile-color]
[quo/button
{:on-press (fn []
(rf/dispatch [:syncing/clear-states])
(cond
logged-in? (rf/dispatch [:navigate-back])
in-onboarding? (rf/dispatch [:navigate-back-to
:screen/onboarding.sign-in-intro])
:else (do
(rf/dispatch [:navigate-back])
(debounce/throttle-and-dispatch
[:open-modal
:screen/onboarding.sign-in]
1000))))
(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)])
(defn- illustration
[pairing-progress?]
[rn/image
{:resize-mode :contain
:style (style/page-illustration (:width (rn/get-window)))
:source (resources/get-image (if pairing-progress? :syncing-devices :syncing-wrong))}])
(defn view
[in-onboarding?]
(let [pairing-status (rf/sub [:pairing/pairing-status])
profile-color (:color (rf/sub [:onboarding/profile]))
logged-in? (rf/sub [:multiaccount/logged-in?])]
(let [pairing-status (rf/sub [:pairing/pairing-status])
pairing-progress? (pairing-progress pairing-status)
profile-color (or (:color (rf/sub [:onboarding/profile]))
(rf/sub [:profile/customization-color]))]
[rn/view {:style (style/page-container in-onboarding?)}
(when-not in-onboarding?
[rn/view {:style style/absolute-fill}
[background/view true]])
[quo/page-nav {:type :no-title :background :blur}]
[page-title (pairing-progress pairing-status)]
(if config/show-not-implemented-features?
(if (pairing-progress pairing-status)
[rn/view {:style style/page-illustration}
[quo/text "[Success here]"]]
[rn/view {:style style/page-illustration}
[quo/text "[Error here]"]])
[rn/view {:flex 1}])
[page-title pairing-progress?]
[illustration pairing-progress?]
(when-not (pairing-progress pairing-status)
[try-again-button profile-color in-onboarding? logged-in?])]))
[try-again-button profile-color])]))
(defn view-onboarding
[]
@@ -239,7 +239,16 @@
:profile-picture profile-picture
:card-style style/login-profile-card}]
(if keycard-pairing
[keycard.pin/auth :keycard/read-card-and-login]
[keycard.pin/auth
{:on-complete
(fn [pin-text]
(rf/dispatch
[:keycard/read-card
{:key-uid key-uid
:on-read-fx [[:effects.keycard/get-keys
{:pin pin-text
:on-success #(rf/dispatch [:keycard.login/on-get-keys-success %])
:on-failure #(rf/dispatch [:keycard/on-action-with-pin-error %])}]]}]))}]
[password-input])]
(when-not keycard-pairing
[quo/button
@@ -73,7 +73,7 @@
[]
(let [compressed-key (rf/sub [:profile/compressed-key])
customization-color (rf/sub [:profile/customization-color])
keypairs (rf/sub [:wallet/keypairs-list])
keypairs (rf/sub [:wallet/fully-operable-keypairs-list])
selected-keypair (rf/sub [:wallet/selected-keypair-uid])
profile-picture (rf/sub [:profile/image])
[selected-key-uid set-selected-key-uid] (rn/use-state selected-keypair)]
@@ -9,7 +9,7 @@
(defn view
[]
(hot-reload/use-safe-unmount #(rf/dispatch [:wallet/clean-routes-calculation]))
(hot-reload/use-safe-unmount #(rf/dispatch [:wallet/stop-get-suggested-routes]))
[rn/view {:style style/bridge-send-wrapper}
[input-amount/view
{:current-screen-id :screen/wallet.bridge-input-amount
@@ -41,7 +41,6 @@
(not watch-only?))
{:icon-name :i/dapps
:on-press #(rf/dispatch [:navigate-to :screen/wallet.connected-dapps])})
{:content-type :account-switcher
:customization-color color
:on-press #(on-dapps-press switcher-type)
@@ -84,10 +84,10 @@
[]
(let [{:keys [bottom]} (safe-area/get-insets)
{:keys [color] :as wallet-account} (rf/sub [:wallet/current-viewing-account])
customization-color (rf/sub [:profile/customization-color])
sessions (rf/sub
[:wallet-connect/sessions-for-current-account])
theme (quo.theme/use-theme)
customization-color (rf/sub [:profile/customization-color])]
[:wallet-connect/sessions-for-current-account-and-networks])
theme (quo.theme/use-theme)]
[rn/view {:flex 1}
[header
{:title (i18n/label :t/connected-dapps)
@@ -5,6 +5,7 @@
[clojure.string :as string]
[status-im.constants :as constants]
[status-im.contexts.wallet.common.utils.networks :as network-utils]
[status-im.contexts.wallet.send.utils :as send-utils]
[utils.collection :as utils.collection]
[utils.money :as money]
[utils.number :as utils.number]
@@ -188,3 +189,77 @@
:removed-account-addresses removed-account-addresses
:updated-keypairs-by-id updated-keypairs-by-id
:updated-accounts-by-address updated-accounts-by-address}))
(defn- rename-keys-to-kebab-case
[m]
(set/rename-keys m (zipmap (keys m) (map transforms/->kebab-case-keyword (keys m)))))
(defn rpc->suggested-routes
[suggested-routes]
(cond
(map? suggested-routes)
(into {}
(for [[k v] (rename-keys-to-kebab-case suggested-routes)]
[k (rpc->suggested-routes v)]))
(vector? suggested-routes)
(map rpc->suggested-routes suggested-routes)
:else suggested-routes))
(def ^:private precision 6)
(defn new->old-route-path
[new-path]
(let [bonder-fees (:tx-bonder-fees new-path)
token-fees (+ (money/wei->ether bonder-fees)
(money/wei->ether
(:tx-token-fees new-path)))]
{:from (:from-chain new-path)
:amount-in-locked (:amount-in-locked new-path)
:amount-in (:amount-in new-path)
:max-amount-in "0x0"
:gas-fees {:gas-price "0"
:base-fee (send-utils/convert-to-gwei (:tx-base-fee
new-path)
precision)
:max-priority-fee-per-gas (send-utils/convert-to-gwei (:tx-priority-fee
new-path)
precision)
:max-fee-per-gas-low (send-utils/convert-to-gwei
(get-in
new-path
[:suggested-levels-for-max-fees-per-gas
:low])
precision)
:max-fee-per-gas-medium (send-utils/convert-to-gwei
(get-in
new-path
[:suggested-levels-for-max-fees-per-gas
:medium])
precision)
:max-fee-per-gas-high (send-utils/convert-to-gwei
(get-in
new-path
[:suggested-levels-for-max-fees-per-gas
:high])
precision)
:l-1-gas-fee (send-utils/convert-to-gwei (:tx-l-1-fee
new-path)
precision)
:eip-1559-enabled true}
:bridge-name (:processor-name new-path)
:amount-out (:amount-out new-path)
:approval-contract-address (:approval-contract-address new-path)
:approval-required (:approval-required new-path)
:estimated-time (:estimated-time new-path)
:approval-gas-fees (* (money/wei->ether (get-in new-path
[:suggested-levels-for-max-fees-per-gas
:medium]))
(:approval-gas-amount new-path))
:to (:to-chain new-path)
:bonder-fees bonder-fees
:approval-amount-required (:approval-amount-required new-path)
;; :cost () ;; tbd not used on desktop
:token-fees token-fees
:gas-amount (:tx-gas-amount new-path)}))
+190 -154
View File
@@ -1,19 +1,18 @@
(ns status-im.contexts.wallet.send.events
(:require
[camel-snake-kebab.extras :as cske]
[clojure.string :as string]
[native-module.core :as native-module]
[status-im.constants :as constants]
[status-im.contexts.wallet.collectible.utils :as collectible.utils]
[status-im.contexts.wallet.common.utils :as utils]
[status-im.contexts.wallet.common.utils.networks :as network-utils]
[status-im.contexts.wallet.data-store :as data-store]
[status-im.contexts.wallet.send.utils :as send-utils]
[taoensso.timbre :as log]
[utils.address :as address]
[utils.money :as money]
[utils.number]
[utils.re-frame :as rf]
[utils.transforms :as transforms]))
[utils.re-frame :as rf]))
(rf/reg-event-fx :wallet/clean-send-data
(fn [{:keys [db]}]
@@ -24,86 +23,82 @@
{:db (assoc-in db [:wallet :ui :send :select-address-tab] tab)}))
(rf/reg-event-fx :wallet/suggested-routes-success
(fn [{:keys [db]} [suggested-routes timestamp]]
(when (= (get-in db [:wallet :ui :send :suggested-routes-call-timestamp]) timestamp)
(let [suggested-routes-data (cske/transform-keys transforms/->kebab-case-keyword
suggested-routes)
chosen-route (:best suggested-routes-data)
token (get-in db [:wallet :ui :send :token])
collectible (get-in db [:wallet :ui :send :collectible])
token-display-name (get-in db [:wallet :ui :send :token-display-name])
receiver-networks (get-in db [:wallet :ui :send :receiver-networks])
receiver-network-values (get-in db [:wallet :ui :send :receiver-network-values])
sender-network-values (get-in db [:wallet :ui :send :sender-network-values])
tx-type (get-in db [:wallet :ui :send :tx-type])
disabled-from-chain-ids (get-in db [:wallet :ui :send :disabled-from-chain-ids] [])
from-locked-amounts (get-in db [:wallet :ui :send :from-locked-amounts] {})
token-decimals (if collectible 0 (:decimals token))
native-token? (and token (= token-display-name "ETH"))
routes-available? (pos? (count chosen-route))
token-networks (:networks token)
token-networks-ids (when token-networks (mapv #(:chain-id %) token-networks))
from-network-amounts-by-chain (send-utils/network-amounts-by-chain {:route chosen-route
:token-decimals
token-decimals
:native-token?
native-token?
:receiver? false})
from-network-values-for-ui (send-utils/network-values-for-ui from-network-amounts-by-chain)
to-network-amounts-by-chain (send-utils/network-amounts-by-chain {:route chosen-route
:token-decimals
token-decimals
:native-token?
native-token?
:receiver? true})
to-network-values-for-ui (send-utils/network-values-for-ui to-network-amounts-by-chain)
sender-possible-chain-ids (mapv :chain-id sender-network-values)
sender-network-values (if routes-available?
(send-utils/network-amounts
{:network-values
(if (= tx-type :tx/bridge)
from-network-values-for-ui
(send-utils/add-zero-values-to-network-values
from-network-values-for-ui
sender-possible-chain-ids))
:disabled-chain-ids disabled-from-chain-ids
:receiver-networks receiver-networks
:token-networks-ids token-networks-ids
:from-locked-amounts from-locked-amounts
:tx-type tx-type
:receiver? false})
(fn [{:keys [db]} [suggested-routes-data]]
(let [chosen-route (:best suggested-routes-data)
{:keys [token collectible token-display-name
receiver-networks
receiver-network-values
sender-network-values tx-type
disabled-from-chain-ids
from-locked-amounts]} (get-in db [:wallet :ui :send])
token-decimals (if collectible 0 (:decimals token))
native-token? (and token (= token-display-name "ETH"))
routes-available? (pos? (count chosen-route))
token-networks (:networks token)
token-networks-ids (when token-networks
(map #(:chain-id %) token-networks))
from-network-amounts-by-chain (send-utils/network-amounts-by-chain
{:route chosen-route
:token-decimals token-decimals
:native-token? native-token?
:receiver? false})
from-network-values-for-ui (send-utils/network-values-for-ui
from-network-amounts-by-chain)
to-network-amounts-by-chain (send-utils/network-amounts-by-chain
{:route chosen-route
:token-decimals token-decimals
:native-token? native-token?
:receiver? true})
to-network-values-for-ui (send-utils/network-values-for-ui
to-network-amounts-by-chain)
sender-possible-chain-ids (map :chain-id sender-network-values)
sender-network-values (if routes-available?
(send-utils/network-amounts
{:network-values
(if (= tx-type :tx/bridge)
from-network-values-for-ui
(send-utils/add-zero-values-to-network-values
from-network-values-for-ui
sender-possible-chain-ids))
:disabled-chain-ids disabled-from-chain-ids
:receiver-networks receiver-networks
:token-networks-ids token-networks-ids
:from-locked-amounts from-locked-amounts
:tx-type tx-type
:receiver? false})
(send-utils/reset-loading-network-amounts-to-zero
sender-network-values))
receiver-network-values (if routes-available?
(send-utils/network-amounts
{:network-values to-network-values-for-ui
:disabled-chain-ids disabled-from-chain-ids
:receiver-networks receiver-networks
:token-networks-ids token-networks-ids
:tx-type tx-type
:receiver? true})
(->
(send-utils/reset-loading-network-amounts-to-zero
sender-network-values))
receiver-network-values (if routes-available?
(send-utils/network-amounts
{:network-values to-network-values-for-ui
:disabled-chain-ids disabled-from-chain-ids
:receiver-networks receiver-networks
:token-networks-ids token-networks-ids
:tx-type tx-type
:receiver? true})
(->
(send-utils/reset-loading-network-amounts-to-zero
receiver-network-values)
vec
(conj {:type :edit})))
network-links (when routes-available?
(send-utils/network-links chosen-route
sender-network-values
receiver-network-values))]
{:db (-> db
(assoc-in [:wallet :ui :send :suggested-routes] suggested-routes-data)
(assoc-in [:wallet :ui :send :route] chosen-route)
(assoc-in [:wallet :ui :send :from-values-by-chain] from-network-values-for-ui)
(assoc-in [:wallet :ui :send :to-values-by-chain] to-network-values-for-ui)
(assoc-in [:wallet :ui :send :sender-network-values] sender-network-values)
(assoc-in [:wallet :ui :send :receiver-network-values] receiver-network-values)
(assoc-in [:wallet :ui :send :network-links] network-links)
(assoc-in [:wallet :ui :send :loading-suggested-routes?] false))}))))
receiver-network-values)
vec
(conj {:type :edit})))
network-links (when routes-available?
(send-utils/network-links chosen-route
sender-network-values
receiver-network-values))]
{:db (update-in db
[:wallet :ui :send]
assoc
:suggested-routes suggested-routes-data
:route chosen-route
:from-values-by-chain from-network-values-for-ui
:to-values-by-chain to-network-values-for-ui
:sender-network-values sender-network-values
:receiver-network-values receiver-network-values
:network-links network-links
:loading-suggested-routes? false)})))
(rf/reg-event-fx :wallet/suggested-routes-error
(fn [{:keys [db]} [error]]
(fn [{:keys [db]} [error-message]]
(let [cleaned-sender-network-values (-> (get-in db [:wallet :ui :send :sender-network-values])
(send-utils/reset-loading-network-amounts-to-zero))
cleaned-receiver-network-values (-> (get-in db [:wallet :ui :send :receiver-network-values])
@@ -120,7 +115,7 @@
[:toasts/upsert
{:id :send-transaction-error
:type :negative
:text (:message error)}]]]})))
:text error-message}]]]})))
(rf/reg-event-fx :wallet/clean-suggested-routes
(fn [{:keys [db]}]
@@ -135,8 +130,7 @@
:sender-network-values
:receiver-network-values
:network-links
:loading-suggested-routes?
:suggested-routes-call-timestamp)}))
:loading-suggested-routes?)}))
(rf/reg-event-fx :wallet/clean-send-address
(fn [{:keys [db]}]
@@ -177,7 +171,7 @@
(assoc-in [:wallet :ui :send :receiver-preferred-networks] receiver-networks)
(assoc-in [:wallet :ui :send :receiver-networks] receiver-networks))
:fx [(when (and collectible-tx? one-collectible?)
[:dispatch [:wallet/get-suggested-routes {:amount 1}]])
[:dispatch [:wallet/start-get-suggested-routes {:amount 1}]])
[:dispatch
[:wallet/wizard-navigate-forward
{:current-screen stack-id
@@ -189,7 +183,7 @@
(fn [{:keys [db]} [selected-networks]]
(let [amount (get-in db [:wallet :ui :send :amount])]
{:db (assoc-in db [:wallet :ui :send :receiver-networks] selected-networks)
:fx [[:dispatch [:wallet/get-suggested-routes {:amount amount}]]]})))
:fx [[:dispatch [:wallet/start-get-suggested-routes {:amount amount}]]]})))
(rf/reg-event-fx
:wallet/set-token-to-send
@@ -300,7 +294,7 @@
one-collectible?
(assoc-in [:wallet :ui :send :amount] 1))
:fx [(when (and one-collectible? recipient-set?)
[:dispatch [:wallet/get-suggested-routes {:amount 1}]])
[:dispatch [:wallet/start-get-suggested-routes {:amount 1}]])
[:dispatch
[:wallet/wizard-navigate-forward
{:current-screen current-screen
@@ -311,7 +305,7 @@
:wallet/set-collectible-amount-to-send
(fn [{db :db} [{:keys [stack-id amount]}]]
{:db (assoc-in db [:wallet :ui :send :amount] amount)
:fx [[:dispatch [:wallet/get-suggested-routes {:amount amount}]]
:fx [[:dispatch [:wallet/start-get-suggested-routes {:amount amount}]]
[:dispatch
[:wallet/wizard-navigate-forward
{:current-screen stack-id
@@ -347,7 +341,7 @@
(fn [{:keys [db]}]
(let [keys-to-remove [:to-values-by-chain :network-links :sender-network-values :route
:receiver-network-values :suggested-routes :from-values-by-chain
:loading-suggested-routes? :suggested-routes-call-timestamp]]
:loading-suggested-routes?]]
{:db (update-in db [:wallet :ui :send] #(apply dissoc % keys-to-remove))})))
(rf/reg-event-fx :wallet/disable-from-networks
@@ -382,74 +376,67 @@
(when (empty? sender-network-values) :sender-network-values)
(when (empty? receiver-network-values) :receiver-network-values)))})))
(rf/reg-event-fx :wallet/get-suggested-routes
(fn [{:keys [db now]} [{:keys [amount updated-token]}]]
(rf/reg-event-fx :wallet/start-get-suggested-routes
(fn [{:keys [db]} [{:keys [amount amount-out updated-token] :as args :or {amount-out "0"}}]]
(let [wallet-address (get-in db [:wallet :current-viewing-account-address])
token (or updated-token (get-in db [:wallet :ui :send :token]))
transaction-type (get-in db [:wallet :ui :send :tx-type])
collectible (get-in db [:wallet :ui :send :collectible])
to-address (get-in db [:wallet :ui :send :to-address])
receiver-networks (get-in db [:wallet :ui :send :receiver-networks])
disabled-from-chain-ids (or (get-in db [:wallet :ui :send :disabled-from-chain-ids]) [])
from-locked-amounts (or (get-in db [:wallet :ui :send :from-locked-amounts]) {})
{:keys [token tx-type collectible to-address
receiver-networks disabled-from-chain-ids
from-locked-amounts bridge-to-chain-id]
:or {token updated-token}} (get-in db [:wallet :ui :send])
test-networks-enabled? (get-in db [:profile/profile :test-networks-enabled?])
networks ((if test-networks-enabled? :test :prod)
(get-in db [:wallet :networks]))
network-chain-ids (map :chain-id networks)
bridge-to-chain-id (get-in db [:wallet :ui :send :bridge-to-chain-id])
token-decimal (when token (:decimals token))
token-id (utils/format-token-id token collectible)
to-token-id ""
network-preferences (if token [] [(get-in collectible [:id :contract-id :chain-id])])
gas-rates constants/gas-rate-medium
to-hex (fn [v] (send-utils/amount-in-hex v (if token token-decimal 0)))
amount-in (to-hex amount)
amount-out (to-hex amount-out)
from-address wallet-address
disabled-from-chain-ids disabled-from-chain-ids
disabled-to-chain-ids (if (= transaction-type :tx/bridge)
disabled-to-chain-ids (if (= tx-type :tx/bridge)
(filter #(not= % bridge-to-chain-id) network-chain-ids)
(filter (fn [chain-id]
(not (some #(= chain-id %)
receiver-networks)))
network-chain-ids))
from-locked-amount (update-vals from-locked-amounts to-hex)
transaction-type-param (case transaction-type
:tx/collectible-erc-721 constants/send-type-erc-721-transfer
:tx/collectible-erc-1155 constants/send-type-erc-1155-transfer
:tx/bridge constants/send-type-bridge
constants/send-type-transfer)
transaction-type (case tx-type
:tx/collectible-erc-721 constants/send-type-erc-721-transfer
:tx/collectible-erc-1155 constants/send-type-erc-1155-transfer
:tx/bridge constants/send-type-bridge
constants/send-type-transfer)
balances-per-chain (when token (:balances-per-chain token))
sender-token-available-networks-for-suggested-routes
(when token
(send-utils/token-available-networks-for-suggested-routes {:balances-per-chain
balances-per-chain
:disabled-chain-ids
disabled-from-chain-ids
:only-with-balance? true}))
(send-utils/token-available-networks-for-suggested-routes
{:balances-per-chain balances-per-chain
:disabled-chain-ids disabled-from-chain-ids
:only-with-balance? true}))
receiver-token-available-networks-for-suggested-routes
(when token
(send-utils/token-available-networks-for-suggested-routes {:balances-per-chain
balances-per-chain
:disabled-chain-ids
disabled-from-chain-ids
:only-with-balance? false}))
token-networks-ids (when token (mapv #(:chain-id %) (:networks token)))
(send-utils/token-available-networks-for-suggested-routes
{:balances-per-chain balances-per-chain
:disabled-chain-ids disabled-from-chain-ids
:only-with-balance? false}))
token-networks-ids (when token (map #(:chain-id %) (:networks token)))
sender-network-values (when sender-token-available-networks-for-suggested-routes
(send-utils/loading-network-amounts
{:valid-networks
(if (= transaction-type :tx/bridge)
(if (= tx-type :tx/bridge)
(remove #(= bridge-to-chain-id %)
sender-token-available-networks-for-suggested-routes)
sender-token-available-networks-for-suggested-routes)
:disabled-chain-ids disabled-from-chain-ids
:receiver-networks receiver-networks
:token-networks-ids token-networks-ids
:tx-type transaction-type
:tx-type tx-type
:receiver? false}))
receiver-network-values (when receiver-token-available-networks-for-suggested-routes
(send-utils/loading-network-amounts
{:valid-networks
(if (= transaction-type :tx/bridge)
(if (= tx-type :tx/bridge)
(filter
#(= bridge-to-chain-id %)
receiver-token-available-networks-for-suggested-routes)
@@ -457,40 +444,70 @@
:disabled-chain-ids disabled-from-chain-ids
:receiver-networks receiver-networks
:token-networks-ids token-networks-ids
:tx-type transaction-type
:tx-type tx-type
:receiver? true}))
request-params [transaction-type-param
from-address
to-address
amount-in
token-id
to-token-id
disabled-from-chain-ids
disabled-to-chain-ids
network-preferences
gas-rates
from-locked-amount]]
{:db (cond-> db
:always (assoc-in [:wallet :ui :send :amount] amount)
:always (assoc-in [:wallet :ui :send :loading-suggested-routes?] true)
:always (assoc-in [:wallet :ui :send :sender-network-values]
sender-network-values)
:always (assoc-in [:wallet :ui :send :receiver-network-values]
receiver-network-values)
:always (assoc-in [:wallet :ui :send :suggested-routes-call-timestamp] now)
:always (update-in [:wallet :ui :send] dissoc :network-links)
token (assoc-in [:wallet :ui :send :token] token))
:json-rpc/call [{:method "wallet_getSuggestedRoutes"
:params request-params
:on-success (fn [suggested-routes]
(rf/dispatch [:wallet/suggested-routes-success suggested-routes
now]))
:on-error (fn [error]
params [{:uuid (str (random-uuid))
:sendType transaction-type
:addrFrom from-address
:addrTo to-address
:amountIn amount-in
:amountOut amount-out
:tokenID token-id
:toTokenID to-token-id
:disabledFromChainIDs disabled-from-chain-ids
:disabledToChainIDs disabled-to-chain-ids
:gasFeeMode gas-rates
:fromLockedAmount from-locked-amount
:username (:username args)
:publicKey (:publicKey args)
:packID (:packID args)}]]
(when (and to-address from-address amount-in token-id)
{:db (update-in db
[:wallet :ui :send]
#(-> %
(assoc :amount amount
:loading-suggested-routes? true
:sender-network-values sender-network-values
:receiver-network-values receiver-network-values)
(dissoc :network-links)
(cond-> token (assoc :token token))))
:json-rpc/call [{:method "wallet_getSuggestedRoutesV2Async"
:params params
:on-error (fn [error]
(rf/dispatch [:wallet/suggested-routes-error error])
(log/error "failed to get suggested routes"
{:event :wallet/get-suggested-routes
:error error
:params request-params}))}]})))
(log/error "failed to get suggested routes (async)"
{:event :wallet/start-get-suggested-routes
:error (:message error)
:params params}))}]}))))
(rf/reg-event-fx :wallet/stop-get-suggested-routes
(fn []
{:fx [[:dispatch [:wallet/clean-routes-calculation]]]
:json-rpc/call [{:method "wallet_stopSuggestedRoutesV2AsyncCalcualtion"
:params []
:on-error (fn [error]
(log/error "failed to stop suggested routes calculation"
{:event :wallet/stop-get-suggested-routes
:error error}))}]}))
(rf/reg-event-fx :wallet/handle-suggested-routes
(fn [_ data]
(if-let [error (some-> data
first
:ErrorResponse
(#(if (= (:code %) "0") "An error occurred" (:details %))))]
(do
(log/error "failed to get suggested routes (async)"
{:event :wallet/handle-suggested-routes
:error error})
{:fx [[:dispatch [:wallet/suggested-routes-error error]]]})
(let [suggested-routes-new-data (data-store/rpc->suggested-routes data)
suggested-routes (-> suggested-routes-new-data
first
(update :best #(map data-store/new->old-route-path %))
(update :candidates #(map data-store/new->old-route-path %)))]
{:fx [[:dispatch
[:wallet/suggested-routes-success suggested-routes]]]}))))
(rf/reg-event-fx :wallet/add-authorized-transaction
(fn [{:keys [db]} [transaction]]
@@ -677,11 +694,13 @@
:transfer-type transaction-type-param})
transaction-paths
sha3-pwd]]
(log/info "multi transaction called")
{:json-rpc/call [{:method "wallet_createMultiTransaction"
:params request-params
:on-success (fn [result]
(rf/dispatch [:wallet/add-authorized-transaction result])
(rf/dispatch [:hide-bottom-sheet]))
(when result
(rf/dispatch [:wallet/add-authorized-transaction result])
(rf/dispatch [:hide-bottom-sheet])))
:on-error (fn [error]
(log/error "failed to send transaction"
{:event :wallet/send-transaction
@@ -692,6 +711,23 @@
:type :negative
:text (:message error)}]))}]})))
(rf/reg-event-fx :wallet/proceed-with-transactions-signatures
(fn [_ [signatures]]
{:json-rpc/call [{:method "wallet_proceedWithTransactionsSignatures"
:params [signatures]
:on-success (fn [result]
(when result
(rf/dispatch [:wallet/add-authorized-transaction result])
(rf/dispatch [:hide-bottom-sheet])))
:on-error (fn [error]
(log/error "failed to proceed-with-transactions-signatures"
{:event :wallet/proceed-with-transactions-signatures
:error error})
(rf/dispatch [:toasts/upsert
{:id :send-transaction-error
:type :negative
:text (:message error)}]))}]}))
(rf/reg-event-fx
:wallet/select-from-account
(fn [{db :db} [{:keys [address stack-id network-details start-flow?]}]]
@@ -141,7 +141,7 @@
(h/deftest-event :wallet/set-collectible-amount-to-send
[event-id dispatch]
(let [initial-db {:wallet {:ui {:send nil}}}
expected-fx [[:dispatch [:wallet/get-suggested-routes {:amount 10}]]
expected-fx [[:dispatch [:wallet/start-get-suggested-routes {:amount 10}]]
[:dispatch
[:wallet/wizard-navigate-forward
{:current-screen nil :flow-id :wallet-send-flow}]]]
@@ -273,19 +273,18 @@
[event-id dispatch]
(reset! rf-db/app-db
{:wallet {:ui {:send
{:other-props :value
:suggested-routes ["1" "2"]
:route "1"
:amount 10
:from-values-by-chain [{:chain-id 1} {:chain-id 10} {:chain-id 42161}]
:to-values-by-chain [{:chain-id 1} {:chain-id 10} {:chain-id 42161}]
:sender-network-values [:eth :arb1]
:receiver-network-values [:eth :arb1]
:network-links [{:from-chain-id 1
:to-chain-id 10
:position-diff 1}]
:loading-suggested-routes? false
:suggested-routes-call-timestamp ["1" "2"]}}}})
{:other-props :value
:suggested-routes ["1" "2"]
:route "1"
:amount 10
:from-values-by-chain [{:chain-id 1} {:chain-id 10} {:chain-id 42161}]
:to-values-by-chain [{:chain-id 1} {:chain-id 10} {:chain-id 42161}]
:sender-network-values [:eth :arb1]
:receiver-network-values [:eth :arb1]
:network-links [{:from-chain-id 1
:to-chain-id 10
:position-diff 1}]
:loading-suggested-routes? false}}}})
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :suggested-routes)))
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :route)))
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :amount)))
@@ -296,8 +295,6 @@
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :network-links)))
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send])
:loading-suggested-routes?)))
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send])
:suggested-routes-call-timestamp)))
(is (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :other-props)))
(h/deftest-event :wallet/suggested-routes-error
@@ -324,7 +321,7 @@
:receiver-network-values receiver-network-amounts
:route :values
:loading-suggested-routes? true}}}})
(is (match? expected-result (dispatch [event-id {:message "error"}])))))
(is (match? expected-result (dispatch [event-id "error"])))))
(h/deftest-event :wallet/reset-network-amounts-to-zero
[event-id dispatch]
@@ -438,7 +435,7 @@
:collectible collectible}}}
:profile/profile {:test-networks-enabled? false
:is-goerli-enabled? false}}
:fx [[:dispatch [:wallet/get-suggested-routes {:amount 1}]]
:fx [[:dispatch [:wallet/start-get-suggested-routes {:amount 1}]]
[:dispatch
[:wallet/wizard-navigate-forward
{:current-screen stack-id
@@ -129,7 +129,7 @@
[{:keys [amount bounce-duration-ms token valid-input?]}]
(if valid-input?
(debounce/debounce-and-dispatch
[:wallet/get-suggested-routes
[:wallet/start-get-suggested-routes
{:amount amount
:updated-token token}]
bounce-duration-ms)
@@ -396,7 +396,7 @@
(and (not should-try-again?) confirm-disabled?))
:on-press (cond
should-try-again?
#(rf/dispatch [:wallet/get-suggested-routes
#(rf/dispatch [:wallet/start-get-suggested-routes
{:amount amount-in-crypto
:updated-token token-by-symbol}])
sending-to-unpreferred-networks?
@@ -257,7 +257,8 @@
:transaction-type transaction-type}]
(when (and (not loading-suggested-routes?) route (seq route))
[standard-auth/slide-button
{:size :size-48
{:keycard-supported? true
:size :size-48
:track-text (if (= transaction-type :tx/bridge)
(i18n/label :t/slide-to-bridge)
(i18n/label :t/slide-to-send))
@@ -265,8 +266,7 @@
:customization-color account-color
:on-auth-success #(rf/dispatch
[:wallet/send-transaction
(security/safe-unmask-data
%)])
(security/safe-unmask-data %)])
:auth-button-label (i18n/label :t/confirm)}])]
:gradient-cover? true
:customization-color (:color account)}
@@ -242,3 +242,10 @@
(defn tx-type-collectible?
[tx-type]
(contains? collectible-tx-set tx-type))
(defn convert-to-gwei
[n precision]
(-> n
money/wei->gwei
(money/with-precision precision)
(str)))
@@ -134,6 +134,7 @@
:iconUrl (get-in session [:peer :metadata :icons 0])
:url (get-in session [:peer :metadata :url])
:accounts (get-in session [:namespaces :eip155 :accounts])
:chains (get-in session [:namespaces :eip155 :chains])
:disconnected false})
(defn filter-operable-accounts
@@ -79,7 +79,6 @@
(if (and (not-empty session-networks) required-networks-supported?)
{:db (update db
:wallet-connect/current-proposal assoc
:response-sent? false
:request proposal
:session-networks session-networks
:address (or current-viewing-address
@@ -89,23 +88,30 @@
:fx [[:dispatch
[:open-modal :screen/wallet.wallet-connect-session-proposal]]]}
{:fx [[:dispatch
[:wallet-connect/session-networks-unsupported proposal]]]}))))
[:wallet-connect/show-session-networks-unsupported-toast proposal]]
[:dispatch
[:wallet-connect/reject-session-proposal proposal]]]}))))
(rf/reg-event-fx
:wallet-connect/session-networks-unsupported
:wallet-connect/show-session-networks-unsupported-toast
(fn [{:keys [db]} [proposal]]
(let [{:keys [name]} (wallet-connect-core/get-session-dapp-metadata proposal)]
(let [{:keys [name url]} (wallet-connect-core/get-session-dapp-metadata proposal)]
{:fx [[:dispatch
[:toasts/upsert
{:type :negative
:theme (:theme db)
:text (i18n/label :t/wallet-connect-networks-not-supported {:dapp name})}]]]})))
:text (i18n/label :t/wallet-connect-networks-not-supported
{:dapp (wallet-connect-core/compute-dapp-name name url)})}]]]})))
(rf/reg-event-fx
:wallet-connect/on-session-request
(fn [{:keys [db]} [event]]
(when (wallet-connect-core/event-should-be-handled? db event)
{:fx [[:dispatch [:wallet-connect/process-session-request event]]]})))
(if (wallet-connect-core/event-should-be-handled? db event)
{:fx [[:dispatch [:wallet-connect/process-session-request event]]]}
{:fx [[:dispatch
[:wallet-connect/send-response
{:error (wallet-connect/get-sdk-error
constants/wallet-connect-user-rejected-chains-error-key)}]]]})))
(rf/reg-event-fx
:wallet-connect/on-session-delete
@@ -146,10 +146,25 @@
[:dispatch [:wallet-connect/dismiss-request-modal]]]}))
(rf/reg-event-fx
:wallet-connect/reject-session-proposal
:wallet-connect/dismiss-request-modal
(fn [{:keys [db]} _]
(let [screen (-> db
(get-in [:wallet-connect/current-request :event])
wallet-connect-core/get-request-method
wallet-connect-core/method-to-screen)]
{:fx [[:dispatch [:dismiss-modal screen]]]})))
(rf/reg-event-fx
:wallet-connect/finish-session-request
(fn [_ [result]]
{:fx [[:dispatch [:wallet-connect/send-response {:result result}]]
[:dispatch [:wallet-connect/dismiss-request-modal]]]}))
(rf/reg-event-fx
:wallet-connect/reject-session-proposal
(fn [{:keys [db]} [proposal]]
(let [web3-wallet (get db :wallet-connect/web3-wallet)
{:keys [request response-sent?]} (:wallet-connect/current-proposal db)]
{:keys [request response-sent?]} (or proposal (:wallet-connect/current-proposal db))]
{:fx [(when-not response-sent?
[:effects.wallet-connect/reject-session-proposal
{:web3-wallet web3-wallet
+2
View File
@@ -17,9 +17,11 @@
;; works and we may re-enable it by default.
::profile-pictures-visibility (enabled-in-env? :FLAG_PROFILE_PICTURES_VISIBILITY_ENABLED)
::settings.telemetry (enabled-in-env? :FLAG_TELEMETRY_ENABLED)
::settings.import-all-keypairs (enabled-in-env?
:FLAG_WALLET_SETTINGS_IMPORT_ALL_KEYPAIRS)
::shell.jump-to (enabled-in-env? :ENABLE_JUMP_TO)
::wallet.advanced-sending (enabled-in-env? :FLAG_ADVANCED_SENDING)
::wallet.assets-modal-hide (enabled-in-env? :FLAG_ASSETS_MODAL_HIDE)
::wallet.assets-modal-manage-tokens (enabled-in-env? :FLAG_ASSETS_MODAL_MANAGE_TOKENS)
+5 -4
View File
@@ -82,10 +82,11 @@
{})})
(def dark-screen
{:theme :dark
:layout {:componentBackgroundColor colors/neutral-95
:orientation ["portrait"]
:backgroundColor colors/neutral-95}})
{:theme :dark
:modalPresentationStyle :overCurrentContext
:layout {:componentBackgroundColor colors/neutral-95
:orientation ["portrait"]
:backgroundColor colors/neutral-95}})
(def lightbox
{:topBar {:visible false}
+8 -14
View File
@@ -147,7 +147,7 @@
:component shell/shell-stack}
{:name :shell-qr-reader
:options (assoc options/dark-screen :modalPresentationStyle :overCurrentContext)
:options options/dark-screen
:component shell-qr-reader/view}
{:name :chat
@@ -369,7 +369,7 @@
:popStackOnPress false}}}
{:name :scan-sync-code-page
:options options/dark-screen
:options options/transparent-modal-screen-options
:component scan-sync-code-page/view}
{:name :screen/onboarding.sign-in-intro
@@ -387,9 +387,9 @@
:component sign-in/view}
{:name :screen/onboarding.syncing-progress
:options {:theme :dark
:layout options/onboarding-layout
:popGesture false}
:options (assoc options/dark-screen
:popGesture
false)
:component syncing-devices/view}
{:name :screen/onboarding.syncing-progress-intro
@@ -513,9 +513,7 @@
:component wallet-transaction-progress/view}
{:name :screen/wallet.scan-address
:options (merge
options/dark-screen
{:modalPresentationStyle :overCurrentContext})
:options options/dark-screen
:component wallet-scan-address/view}
{:name :screen/wallet.swap-select-asset-to-pay
@@ -536,9 +534,7 @@
:component wallet-swap-set-spending-cap/view}
{:name :scan-profile-qr-code
:options (merge
options/dark-screen
{:modalPresentationStyle :overCurrentContext})
:options options/dark-screen
:component scan-profile-qr-page/view}
{:name :invite-people-community
@@ -564,9 +560,7 @@
:component wallet-connected-dapps/view}
{:name :screen/wallet.scan-dapp
:options (merge
options/dark-screen
{:modalPresentationStyle :overCurrentContext})
:options options/dark-screen
:component wallet-scan-dapp/view}
;; Settings
+2 -2
View File
@@ -115,13 +115,13 @@
(comp :network-name first))
address-activities (->> (get activities current-viewing-account-address)
(vals)
(sort :timestamp))]
(sort-by :timestamp))]
(->> address-activities
(keep #(process-activity-by-type chain-id->network-name %))
(group-by (fn [{:keys [timestamp]}]
(datetime/timestamp->relative-short-date (* timestamp 1000))))
(map (fn [[date activities]]
{:title date
:data activities
:data (reverse activities)
:timestamp (:timestamp (first activities))}))
(sort-by (fn [{:keys [timestamp]}] (- timestamp)))))))
+70 -39
View File
@@ -38,48 +38,79 @@
:amount-out "0x1"
:sender "acc1"
:recipient "acc4"
:timestamp 1588464000}}
"acc3" {4 {:activity-type constants/wallet-activity-type-receive
:timestamp 1588464000}
4 {:activity-type constants/wallet-activity-type-send
:amount-out "0x1"
:sender "acc1"
:recipient "acc4"
:timestamp 1588464100}
5 {:activity-type constants/wallet-activity-type-send
:amount-out "0x1"
:sender "acc1"
:recipient "acc4"
:timestamp 1588464050}}
"acc3" {6 {:activity-type constants/wallet-activity-type-receive
:amount-in "0x1"
:sender "acc4"
:recipient "acc3"
:timestamp 1588464000}}})
(assoc-in [:wallet :current-viewing-account-address] "acc1"))))
(is
(match? [{:title "May 3, 2020"
:timestamp 1588464000
:data [{:relative-date "May 3, 2020"
:amount "0"
:network-logo nil
:recipient "acc4"
:transaction :send
:token nil
:network-name nil
:status nil
:sender "acc1"
:timestamp 1588464000}]}
{:title "May 2, 2020"
:timestamp 1588377600
:data [{:relative-date "May 2, 2020"
:amount "0"
:network-logo nil
:recipient "acc1"
:transaction :receive
:token nil
:network-name nil
:status nil
:sender "acc2"
:timestamp 1588377600}]}
{:title "May 1, 2020"
:timestamp 1588291200
:data [{:relative-date "May 1, 2020"
:amount "0"
:network-logo nil
:recipient "acc2"
:transaction :send
:token nil
:network-name nil
:status nil
:sender "acc1"
:timestamp 1588291200}]}]
(rf/sub [sub-name])))))
(match?
[{:title "May 3, 2020"
:timestamp 1588464000
:data [{:relative-date "May 3, 2020"
:amount "0"
:network-logo nil
:recipient "acc4"
:transaction :send
:token nil
:network-name nil
:status nil
:sender "acc1"
:timestamp 1588464100}
{:relative-date "May 3, 2020"
:amount "0"
:network-logo nil
:recipient "acc4"
:transaction :send
:token nil
:network-name nil
:status nil
:sender "acc1"
:timestamp 1588464050}
{:relative-date "May 3, 2020"
:amount "0"
:network-logo nil
:recipient "acc4"
:transaction :send
:token nil
:network-name nil
:status nil
:sender "acc1"
:timestamp 1588464000}]}
{:title "May 2, 2020"
:timestamp 1588377600
:data [{:relative-date "May 2, 2020"
:amount "0"
:network-logo nil
:recipient "acc1"
:transaction :receive
:token nil
:network-name nil
:status nil
:sender "acc2"
:timestamp 1588377600}]}
{:title "May 1, 2020"
:timestamp 1588291200
:data [{:relative-date "May 1, 2020"
:amount "0"
:network-logo nil
:recipient "acc2"
:transaction :send
:token nil
:network-name nil
:status nil
:sender "acc1"
:timestamp 1588291200}]}]
(rf/sub [sub-name])))))
+6
View File
@@ -207,6 +207,12 @@
(fn [{:keys [keypairs]}]
(vals keypairs)))
(rf/reg-sub
:wallet/fully-operable-keypairs-list
:<- [:wallet/keypairs-list]
(fn [keypairs]
(filter #(= :fully (:lowest-operability %)) keypairs)))
(rf/reg-sub
:wallet/keypair-names
:<- [:wallet/keypairs-list]
+21 -1
View File
@@ -1,6 +1,8 @@
(ns status-im.subs.wallet.wallet-connect
(:require [clojure.string :as string]
(:require [clojure.set :as set]
[clojure.string :as string]
[re-frame.core :as rf]
[status-im.constants :as constants]
[status-im.contexts.wallet.common.utils :as wallet-utils]
[status-im.contexts.wallet.wallet-connect.core :as wallet-connect-core]
[status-im.contexts.wallet.wallet-connect.transactions :as transactions]
@@ -58,6 +60,24 @@
(some #(string/includes? % address) accounts))
sessions)))
(rf/reg-sub
:wallet-connect/sessions-for-current-account-and-networks
:<- [:wallet-connect/sessions-for-current-account]
:<- [:profile/test-networks-enabled?]
(fn [[sessions testnet-mode?]]
(filter
(fn [{:keys [chains]}]
(let [chain-ids (set (map (fn [chain]
(-> chain
(string/split ":")
second
js/parseInt))
chains))]
(if testnet-mode?
(set/subset? chain-ids (set/union constants/sepolia-chain-ids constants/goerli-chain-ids))
(set/subset? chain-ids constants/mainnet-chain-ids))))
sessions)))
(rf/reg-sub
:wallet-connect/chain-id
:<- [:wallet-connect/current-request]
+3 -3
View File
@@ -3,7 +3,7 @@
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
"owner": "status-im",
"repo": "status-go",
"version": "v0.182.37",
"commit-sha1": "4a43b2b2bebe45df2100d1a5c5034105d93e50b8",
"src-sha256": "0f5mm7lx6s2qcy9xpa9v7piqb60yazi6p677fy105yz7hg731cw6"
"version": "v0.182.38",
"commit-sha1": "2bbdb35f6cabd1a4f7775e180e0647b70ce8d1aa",
"src-sha256": "03bksi5gn44ky76kblikpr6j3x69baid81ghfk27a4qx9hnc0qgc"
}