Compare commits
24
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8408b4fff | ||
|
|
55a99da2f5 | ||
|
|
6093d56c90 | ||
|
|
9cf4556b9d | ||
|
|
536ebf56cb | ||
|
|
3ad345519b | ||
|
|
dc587e493f | ||
|
|
f692ae2222 | ||
|
|
aa89ebdb93 | ||
|
|
198a4d74a5 | ||
|
|
3b5fe36717 | ||
|
|
03444ae4ff | ||
|
|
390bbdb6ec | ||
|
|
2bc7b62324 | ||
|
|
4376ee8908 | ||
|
|
195f0cfa40 | ||
|
|
ab61d8d5c0 | ||
|
|
aaf0b8e423 | ||
|
|
7e14846f0b | ||
|
|
5ebd133c63 | ||
|
|
563f1c588d | ||
|
|
6b612588c4 | ||
|
|
6ef113e821 | ||
|
|
c25f44c2a0 |
@@ -0,0 +1,4 @@
|
||||
{:linters
|
||||
{:unresolved-symbol
|
||||
{:exclude [(cljs.test/is [match? thrown-match?])
|
||||
(clojure.test/is [match? thrown-match?])]}}}
|
||||
@@ -641,6 +641,26 @@ keywords and concatenating them into a single string.
|
||||
```
|
||||
|
||||
### Tests
|
||||
#### Prefer `match?` over `=` when comparing data structures
|
||||
|
||||
Prefer the `match?` directive over `=` when comparing data structures, otherwise
|
||||
when the check fails the output can be too difficult to read. `match?` is
|
||||
defined by library https://github.com/nubank/matcher-combinators.
|
||||
|
||||
```clojure
|
||||
;; bad
|
||||
(deftest some-test
|
||||
(let [expected {...}
|
||||
actual {...}]
|
||||
(is (= expected actual))))
|
||||
|
||||
;; good
|
||||
(deftest some-test
|
||||
(let [expected {...}
|
||||
actual {...}]
|
||||
(is (match? expected actual))))
|
||||
```
|
||||
|
||||
#### Subscription tests
|
||||
|
||||
Test [layer-3 subscriptions](https://day8.github.io/re-frame/subscriptions/) by
|
||||
|
||||
@@ -602,6 +602,15 @@
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "nubank/matcher-combinators/3.8.8/matcher-combinators-3.8.8",
|
||||
"host": "https://repo.clojars.org",
|
||||
"jar": {
|
||||
"sha1": "4c94bd510f0c18a20191e46dd6becedebc640bbd",
|
||||
"sha256": "0wpla2hx0s4mda58ndyd8938zmnz1gyhgfr6pzfphy27xfbvsssl"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/apache/ant/ant/1.10.11/ant-1.10.11",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
@@ -746,6 +755,15 @@
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/clojure/math.combinatorics/0.2.0/math.combinatorics-0.2.0",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
"jar": {
|
||||
"sha1": "aa95d25ea98bfe1152ea540f6e58a303c8cacc86",
|
||||
"sha256": "0qvdsr5ryjmrpz622ivpyq5aayn42y4bk531vbasyj2yj7gcg35h"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/clojure/spec.alpha/0.3.218/spec.alpha-0.3.218",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
|
||||
@@ -65,6 +65,7 @@ net/cgrand/macrovich/0.2.1/macrovich-0.2.1.jar
|
||||
net/java/dev/jna/jna/5.12.1/jna-5.12.1.jar
|
||||
nrepl/bencode/1.1.0/bencode-1.1.0.jar
|
||||
nrepl/nrepl/1.0.0/nrepl-1.0.0.jar
|
||||
nubank/matcher-combinators/3.8.8/matcher-combinators-3.8.8.jar
|
||||
org/apache/ant/ant/1.10.11/ant-1.10.11.jar
|
||||
org/apache/ant/ant-launcher/1.10.11/ant-launcher-1.10.11.jar
|
||||
org/babashka/sci/0.7.38/sci-0.7.38.jar
|
||||
@@ -81,6 +82,7 @@ org/clojure/data.json/2.4.0/data.json-2.4.0.jar
|
||||
org/clojure/data.priority-map/1.1.0/data.priority-map-1.1.0.jar
|
||||
org/clojure/google-closure-library/0.0-20230227-c7c0a541/google-closure-library-0.0-20230227-c7c0a541.jar
|
||||
org/clojure/google-closure-library-third-party/0.0-20230227-c7c0a541/google-closure-library-third-party-0.0-20230227-c7c0a541.jar
|
||||
org/clojure/math.combinatorics/0.2.0/math.combinatorics-0.2.0.jar
|
||||
org/clojure/spec.alpha/0.3.218/spec.alpha-0.3.218.jar
|
||||
org/clojure/test.check/1.1.1/test.check-1.1.1.jar
|
||||
org/clojure/tools.analyzer/1.1.0/tools.analyzer-1.1.0.jar
|
||||
|
||||
@@ -14,6 +14,7 @@ stdenv.mkDerivation {
|
||||
"patchJavaPhase"
|
||||
"patchReactNativePhase"
|
||||
"patchPodPhase"
|
||||
"patchGlogPhase"
|
||||
"installPhase"
|
||||
];
|
||||
|
||||
@@ -98,6 +99,14 @@ stdenv.mkDerivation {
|
||||
'[RCTConvert UIColor:options.tintColor() ? @(*options.tintColor()) : nil];'
|
||||
'';
|
||||
|
||||
# Fix pod issue after upgrading to MacOS Sonoma and Xcode 15
|
||||
# https://github.com/status-im/status-mobile/issues/17682
|
||||
patchGlogPhase = ''
|
||||
substituteInPlace ./node_modules/react-native/scripts/ios-configure-glog.sh \
|
||||
--replace 'export CC="' '#export CC="' \
|
||||
--replace 'export CXX="' '#export CXX="'
|
||||
'';
|
||||
|
||||
# The ELF types are incompatible with the host platform, so let's not even try
|
||||
# TODO: Use Android NDK to strip binaries manually
|
||||
dontPatchELF = true;
|
||||
|
||||
@@ -73,6 +73,7 @@ in {
|
||||
allowHigher = true;
|
||||
};
|
||||
go = super.go_1_19;
|
||||
clang = super.clang_15;
|
||||
buildGoPackage = super.buildGo119Package;
|
||||
buildGoModule = super.buildGo119Module;
|
||||
gomobile = (super.gomobile.overrideAttrs (old: {
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 851 B |
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
@@ -17,6 +17,7 @@
|
||||
[cider/piggieback "0.4.1"]
|
||||
[org.slf4j/slf4j-nop "2.0.9"]
|
||||
[re-frisk-remote "1.6.0"]
|
||||
[nubank/matcher-combinators "3.8.8"]
|
||||
|
||||
;; Use the same version specified in the Nix dependency.
|
||||
[clj-kondo/clj-kondo "2023.09.07"]
|
||||
|
||||
@@ -40,23 +40,6 @@
|
||||
config
|
||||
#(callback (types/json->clj %))))
|
||||
|
||||
(defn save-account-and-login
|
||||
"NOTE: beware, the password has to be sha3 hashed"
|
||||
[key-uid multiaccount-data hashed-password settings config accounts-data]
|
||||
(log/debug "[native-module] save-account-and-login"
|
||||
"multiaccount-data"
|
||||
multiaccount-data)
|
||||
(clear-web-data)
|
||||
(init-keystore
|
||||
key-uid
|
||||
#(.saveAccountAndLogin
|
||||
^js (status)
|
||||
multiaccount-data
|
||||
hashed-password
|
||||
settings
|
||||
config
|
||||
accounts-data)))
|
||||
|
||||
(defn save-multiaccount-and-login-with-keycard
|
||||
"NOTE: chat-key is a whisper private key sent from keycard"
|
||||
[key-uid multiaccount-data password settings config accounts-data chat-key]
|
||||
|
||||
@@ -61,14 +61,10 @@
|
||||
value (reagent/atom "")
|
||||
focused? (atom false)]
|
||||
(fn [{:keys [scanned-value theme blur? on-change-text on-blur on-focus on-clear on-scan on-detect-ens
|
||||
on-detect-address
|
||||
ens-regex address-regex
|
||||
valid-ens-or-address?]}]
|
||||
on-detect-address address-regex valid-ens-or-address?]}]
|
||||
(let [on-change (fn [text]
|
||||
(when (not= @value text)
|
||||
(let [ens? (when ens-regex
|
||||
(boolean (re-matches ens-regex text)))
|
||||
address? (when address-regex
|
||||
(let [address? (when address-regex
|
||||
(boolean (re-matches address-regex text)))]
|
||||
(if (> (count text) 0)
|
||||
(reset! status :typing)
|
||||
@@ -76,9 +72,9 @@
|
||||
(reset! value text)
|
||||
(when on-change-text
|
||||
(on-change-text text))
|
||||
(when (and ens? on-detect-ens)
|
||||
(when (and on-detect-ens (> (count text) 0))
|
||||
(reset! status :loading)
|
||||
(on-detect-ens text))
|
||||
(on-detect-ens text #(reset! status :typing)))
|
||||
(when (and address? on-detect-address)
|
||||
(reset! status :loading)
|
||||
(on-detect-address text)))))
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
(ns quo.components.wallet.confirmation-progress.component-spec
|
||||
(:require [quo.core :as quo]
|
||||
[reagent.core :as reagent]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(defn- get-test-data
|
||||
[{:keys [state network]
|
||||
:or {state :pending network :mainnet}}]
|
||||
{:counter (reagent/atom 0)
|
||||
:total-box 85
|
||||
:progress-value "10"
|
||||
:network network
|
||||
:state state
|
||||
:customization-color :blue})
|
||||
|
||||
(h/describe "Confirmation Progress"
|
||||
(h/test "component renders when state is sending and network is optimism"
|
||||
(h/render [quo/confirmation-propgress
|
||||
(get-test-data {:state :sending
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
|
||||
(h/test "component renders when state is confirmed and network is optimism"
|
||||
(h/render [quo/confirmation-propgress
|
||||
(get-test-data {:state :confirmed
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
|
||||
(h/test "component renders when state is finalising and network is optimism"
|
||||
(h/render [quo/confirmation-propgress
|
||||
(get-test-data {:state :finalising
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
|
||||
(h/test "component renders when state is finalized and network is optimism"
|
||||
(h/render [quo/confirmation-propgress
|
||||
(get-test-data {:state :finalized
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
|
||||
(h/test "component renders when state is error and network is optimism"
|
||||
(h/render [quo/confirmation-propgress
|
||||
(get-test-data {:state :error
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
|
||||
(h/test "component renders when state is sending and network is arbitrum"
|
||||
(h/render [quo/confirmation-propgress
|
||||
(get-test-data {:state :sending
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
|
||||
(h/test "component renders when state is confirmed and network is arbitrum"
|
||||
(h/render [quo/confirmation-propgress
|
||||
(get-test-data {:state :confirmed
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
|
||||
(h/test "component renders when state is finalising and network is arbitrum"
|
||||
(h/render [quo/confirmation-propgress
|
||||
(get-test-data {:state :finalising
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
|
||||
(h/test "component renders when state is finalized and network is arbitrum"
|
||||
(h/render [quo/confirmation-propgress
|
||||
(get-test-data {:state :finalized
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
|
||||
(h/test "component renders when state is error and network is arbitrum"
|
||||
(h/render [quo/confirmation-propgress
|
||||
(get-test-data {:state :error
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :progress-box)))
|
||||
|
||||
(h/test "component renders when state is pending and network is mainnet"
|
||||
(h/render [quo/confirmation-propgress (get-test-data {})])
|
||||
(h/is-truthy (h/get-by-label-text :mainnet-progress-box)))
|
||||
|
||||
(h/test "component renders when state is sending and network is mainnet"
|
||||
(h/render [quo/confirmation-propgress (get-test-data {:state :sending})])
|
||||
(h/is-truthy (h/get-by-label-text :mainnet-progress-box)))
|
||||
|
||||
(h/test "component renders when state is confirmed and network is mainnet"
|
||||
(h/render [quo/confirmation-propgress (get-test-data {:state :confirmed})])
|
||||
(h/is-truthy (h/get-by-label-text :mainnet-progress-box)))
|
||||
|
||||
(h/test "component renders when state is finalising and network is mainnet"
|
||||
(h/render [quo/confirmation-propgress (get-test-data {:state :finalising})])
|
||||
(h/is-truthy (h/get-by-label-text :mainnet-progress-box)))
|
||||
|
||||
(h/test "component renders when state is finalized and network is mainnet"
|
||||
(h/render [quo/confirmation-propgress (get-test-data {:state :finalized})])
|
||||
(h/is-truthy (h/get-by-label-text :mainnet-progress-box)))
|
||||
|
||||
(h/test "component renders when state is error and network is mainnet"
|
||||
(h/render [quo/confirmation-propgress (get-test-data {:state :error})])
|
||||
(h/is-truthy (h/get-by-label-text :mainnet-progress-box))))
|
||||
@@ -0,0 +1,9 @@
|
||||
(ns quo.components.wallet.confirmation-progress.style)
|
||||
|
||||
(def progress-box-container
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:padding-horizontal 12
|
||||
:padding-bottom 10
|
||||
:padding-top 4
|
||||
:flex-wrap :wrap})
|
||||
@@ -0,0 +1,69 @@
|
||||
(ns quo.components.wallet.confirmation-progress.view
|
||||
(:require [quo.components.wallet.confirmation-progress.style :as style]
|
||||
[quo.components.wallet.progress-bar.view :as progress-box]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(def ^:private max-progress 100)
|
||||
(def ^:private min-progress 0)
|
||||
|
||||
(defn- calculate-box-state
|
||||
[state counter index]
|
||||
(cond
|
||||
(and (= state :sending) (>= counter index) (< index 3)) :confirmed
|
||||
(and (= state :confirmed) (>= counter index) (< index 5)) :confirmed
|
||||
(and (= state :finalising) (>= counter index) (< index 5)) :confirmed
|
||||
(and (= state :finalising) (>= counter index) (> index 4) (< index 20)) :finalized
|
||||
(and (= state :finalized) (>= counter index) (< index 5)) :confirmed
|
||||
(and (= state :finalized) (>= counter index) (> index 4)) :finalized
|
||||
(and (= state :error) (>= counter index) (< index 2)) :error
|
||||
:else :pending))
|
||||
|
||||
(defn- calculate-box-state-sidenet
|
||||
[state]
|
||||
(case state
|
||||
:error :error
|
||||
(:confirmed :finalising :finalized) :finalized
|
||||
:pending))
|
||||
|
||||
(defn- calculate-progressed-value
|
||||
[state progress-value]
|
||||
(case state
|
||||
:finalising progress-value
|
||||
:finalized max-progress
|
||||
min-progress))
|
||||
|
||||
(defn- progress-boxes-mainnet
|
||||
[{:keys [state counter total-box]}]
|
||||
[rn/view
|
||||
{:accessibility-label :mainnet-progress-box
|
||||
:style style/progress-box-container}
|
||||
(let [numbers (range 1 total-box)]
|
||||
(doall (for [n numbers]
|
||||
[progress-box/view
|
||||
{:state (calculate-box-state state counter n)
|
||||
:customization-color :blue
|
||||
:key n}])))])
|
||||
|
||||
(defn- progress-boxes-sidenet
|
||||
[{:keys [state progress-value]}]
|
||||
[rn/view
|
||||
{:accessibility-label :progress-box
|
||||
:style style/progress-box-container}
|
||||
[progress-box/view
|
||||
{:state (calculate-box-state-sidenet state)
|
||||
:customization-color :success}]
|
||||
[progress-box/view
|
||||
{:state (calculate-box-state-sidenet state)
|
||||
:full-width? true
|
||||
:progressed-value (calculate-progressed-value state progress-value)
|
||||
:customization-color :blue}]])
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [network] :as props}]
|
||||
(case network
|
||||
:mainnet [progress-boxes-mainnet props]
|
||||
(:arbitrum :optimism) [progress-boxes-sidenet props]
|
||||
nil))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
@@ -39,7 +39,7 @@
|
||||
:width 8
|
||||
:borderRadius 3
|
||||
:borderColor colors/neutral-80-opa-5
|
||||
:backgroundColor (colors/custom-color (:customization-color props) 50)})))
|
||||
:backgroundColor (colors/resolve-color (:customization-color props) theme)})))
|
||||
|
||||
(h/test "finalized state with customtization-color blue in dark mode"
|
||||
(let [theme :dark
|
||||
@@ -51,7 +51,7 @@
|
||||
:width 8
|
||||
:borderRadius 3
|
||||
:borderColor colors/neutral-80-opa-5
|
||||
:backgroundColor (colors/custom-color (:customization-color props) 60)})))
|
||||
:backgroundColor (colors/resolve-color (:customization-color props) theme)})))
|
||||
|
||||
(h/test "finalized state with customtization-color army in light mode"
|
||||
(let [theme :light
|
||||
@@ -63,7 +63,7 @@
|
||||
:width 8
|
||||
:borderRadius 3
|
||||
:borderColor colors/neutral-80-opa-5
|
||||
:backgroundColor (colors/custom-color (:customization-color props) 50)})))
|
||||
:backgroundColor (colors/resolve-color (:customization-color props) theme)})))
|
||||
|
||||
(h/test "confirmed state in light mode"
|
||||
(let [theme :light
|
||||
@@ -75,7 +75,7 @@
|
||||
:width 8
|
||||
:borderRadius 3
|
||||
:borderColor colors/neutral-80-opa-5
|
||||
:backgroundColor colors/success-50})))
|
||||
:backgroundColor (colors/resolve-color :success theme)})))
|
||||
|
||||
(h/test "confirmed state in dark mode"
|
||||
(let [theme :dark
|
||||
@@ -99,7 +99,7 @@
|
||||
:width 8
|
||||
:borderRadius 3
|
||||
:borderColor colors/neutral-80-opa-5
|
||||
:backgroundColor colors/danger-50})))
|
||||
:backgroundColor (colors/resolve-color :danger theme)})))
|
||||
|
||||
(h/test "error state in dark mode"
|
||||
(let [theme :dark
|
||||
@@ -111,4 +111,4 @@
|
||||
:width 8
|
||||
:borderRadius 3
|
||||
:borderColor colors/white-opa-5
|
||||
:backgroundColor colors/danger-60}))))
|
||||
:backgroundColor (colors/resolve-color :danger theme)}))))
|
||||
|
||||
@@ -3,31 +3,48 @@
|
||||
[quo.foundations.colors :as colors]))
|
||||
|
||||
(defn- border-and-background-color
|
||||
[customization-color]
|
||||
[customization-color theme]
|
||||
{:light {:pending {:border-color colors/neutral-80-opa-5
|
||||
:background-color colors/neutral-5}
|
||||
:confirmed {:border-color colors/neutral-80-opa-5
|
||||
:background-color (colors/custom-color :success 50)}
|
||||
:background-color (colors/resolve-color :success theme)}
|
||||
:finalized {:border-color colors/neutral-80-opa-5
|
||||
:background-color (colors/custom-color customization-color 50)}
|
||||
:background-color (colors/resolve-color customization-color theme)}
|
||||
:error {:border-color colors/neutral-80-opa-5
|
||||
:background-color (colors/custom-color :danger 50)}}
|
||||
:background-color (colors/resolve-color :danger theme)}}
|
||||
:dark {:pending {:border-color colors/neutral-70
|
||||
:background-color colors/neutral-80}
|
||||
:confirmed {:border-color colors/white-opa-5
|
||||
:background-color (colors/custom-color :success 60)}
|
||||
:background-color (colors/resolve-color :success theme)}
|
||||
:finalized {:border-color colors/neutral-80-opa-5
|
||||
:background-color (colors/custom-color customization-color 60)}
|
||||
:background-color (colors/resolve-color customization-color theme)}
|
||||
:error {:border-color colors/white-opa-5
|
||||
:background-color (colors/custom-color :danger 60)}}})
|
||||
:background-color (colors/resolve-color :danger theme)}}})
|
||||
|
||||
(def max-value 100)
|
||||
|
||||
(defn root-container
|
||||
[{:keys [customization-color state theme]}]
|
||||
(let [{:keys [background-color border-color]} (get-in (border-and-background-color customization-color)
|
||||
[theme state])]
|
||||
[{:keys [customization-color state theme full-width?]}]
|
||||
(let [{:keys [background-color border-color]} (get-in (border-and-background-color customization-color
|
||||
theme)
|
||||
[theme (if full-width? :pending state)])]
|
||||
{:height 12
|
||||
:flex (when full-width? 1)
|
||||
:width (when (not full-width?) 8)
|
||||
:border-radius 3
|
||||
:border-width 1
|
||||
:border-color border-color
|
||||
:background-color background-color
|
||||
:margin-horizontal 1
|
||||
:margin-vertical 2}))
|
||||
|
||||
(defn progressed-bar
|
||||
[{:keys [customization-color state theme progressed-value]}]
|
||||
(let [{:keys [background-color]} (get-in (border-and-background-color customization-color theme)
|
||||
[theme state])
|
||||
progress (if (> progressed-value max-value) max-value progressed-value)]
|
||||
{:height 12
|
||||
:width 8
|
||||
:margin-top -1
|
||||
:width (str progress "%")
|
||||
:border-radius 3
|
||||
:border-width 1
|
||||
:border-color border-color
|
||||
:background-color background-color}))
|
||||
|
||||
@@ -5,9 +5,11 @@
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn- view-internal
|
||||
[props]
|
||||
[{:keys [full-width?] :as props}]
|
||||
[rn/view
|
||||
{:accessibility-label :progress-bar
|
||||
:style (style/root-container props)}])
|
||||
:style (style/root-container props)}
|
||||
(when full-width?
|
||||
[rn/view {:style (style/progressed-bar props)}])])
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
(defn container
|
||||
[networks? theme]
|
||||
{:width 335
|
||||
{:width "100%"
|
||||
:height (if networks? 90 56)
|
||||
:border-radius 16
|
||||
:border-width 1
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
(ns quo.components.wallet.transaction-progress.component-spec
|
||||
(:require [quo.core :as quo]
|
||||
[reagent.core :as reagent]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(defn- get-test-data
|
||||
[{:keys [state network]
|
||||
:or {state :pending network :mainnet}}]
|
||||
{:title "Title"
|
||||
:tag-name "Doodle"
|
||||
:tag-number "120"
|
||||
:network network
|
||||
:customization-color :blue
|
||||
:networks [{:network :mainnet
|
||||
:state state
|
||||
:counter (reagent/atom 0)
|
||||
:total-box 85
|
||||
:progress 30
|
||||
:epoch-number "123"}
|
||||
{:network :optimism
|
||||
:state state
|
||||
:progress "50"
|
||||
:epoch-number "123"}
|
||||
{:network :arbitrum
|
||||
:state state
|
||||
:progress "30"
|
||||
:epoch-number "123"}]
|
||||
:on-press (fn []
|
||||
(js/alert "Transaction progress item pressed"))})
|
||||
|
||||
(h/describe "Transaction Progress"
|
||||
(h/test "component renders without props"
|
||||
(h/render [quo/transaction-progress])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is pending and network is mainnet"
|
||||
(h/render [quo/transaction-progress (get-test-data {:network :optimism-arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is sending and network is optimism-arbitrum"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :sending
|
||||
:network :optimism-arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is confirmed and network is optimism-arbitrum"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :confirmed
|
||||
:network :optimism-arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is finalising and network is optimism-arbitrum"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :finalising
|
||||
:network :optimism-arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is finalized and network is optimism-arbitrum"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :finalized
|
||||
:network :optimism-arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is error and network is optimism-arbitrum"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :error
|
||||
:network :optimism-arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is sending and network is optimism"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :sending
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is confirmed and network is optimism"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :confirmed
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is finalising and network is optimism"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :finalising
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is finalized and network is optimism"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :finalized
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is error and network is optimism"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :error
|
||||
:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is sending and network is arbitrum"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :sending
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is confirmed and network is arbitrum"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :confirmed
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is finalising and network is arbitrum"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :finalising
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is finalized and network is arbitrum"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :finalized
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is error and network is arbitrum"
|
||||
(h/render [quo/transaction-progress
|
||||
(get-test-data {:state :error
|
||||
:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is pending and network is mainnet"
|
||||
(h/render [quo/transaction-progress (get-test-data {})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is sending and network is mainnet"
|
||||
(h/render [quo/transaction-progress (get-test-data {:state :sending})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is confirmed and network is mainnet"
|
||||
(h/render [quo/transaction-progress (get-test-data {:state :confirmed})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is finalising and network is mainnet"
|
||||
(h/render [quo/transaction-progress (get-test-data {:state :finalising})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is finalized and network is mainnet"
|
||||
(h/render [quo/transaction-progress (get-test-data {:state :finalized})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "component renders when state is error and network is mainnet"
|
||||
(h/render [quo/transaction-progress (get-test-data {:state :error})])
|
||||
(h/is-truthy (h/get-by-label-text :transaction-progress)))
|
||||
|
||||
(h/test "mainnet progress box is visible network is mainnet"
|
||||
(h/render [quo/transaction-progress (get-test-data {})])
|
||||
(h/is-truthy (h/get-by-label-text :mainnet-progress-box)))
|
||||
|
||||
(h/test "arbitrum-optimism progress box is visible network is optimism-arbitrum"
|
||||
(h/render [quo/transaction-progress (get-test-data {:network :optimism-arbitrum})])
|
||||
(h/is-truthy (h/get-all-by-label-text :progress-box)))
|
||||
|
||||
(h/test "arbitrum progress box is visible network is arbitrum"
|
||||
(h/render [quo/transaction-progress (get-test-data {:network :arbitrum})])
|
||||
(h/is-truthy (h/get-all-by-label-text :progress-box)))
|
||||
|
||||
(h/test "optimism progress box is visible network is optimism"
|
||||
(h/render [quo/transaction-progress (get-test-data {:network :optimism})])
|
||||
(h/is-truthy (h/get-all-by-label-text :progress-box)))
|
||||
|
||||
(h/test "title is visible network is optimism-arbitrum"
|
||||
(h/render [quo/transaction-progress (get-test-data {:network :optimism-arbitrum})])
|
||||
(h/is-truthy (h/get-by-text "Title")))
|
||||
|
||||
(h/test "title is visible network is mainnet"
|
||||
(h/render [quo/transaction-progress (get-test-data {})])
|
||||
(h/is-truthy (h/get-by-text "Title")))
|
||||
|
||||
(h/test "title is visible network is optimism"
|
||||
(h/render [quo/transaction-progress (get-test-data {:network :optimism})])
|
||||
(h/is-truthy (h/get-by-text "Title")))
|
||||
|
||||
(h/test "title is visible network is arbitrum"
|
||||
(h/render [quo/transaction-progress (get-test-data {:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-text "Title")))
|
||||
|
||||
(h/test "context tag is visible network is optimism-arbitrum"
|
||||
(h/render [quo/transaction-progress (get-test-data {:network :optimism-arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :context-tag)))
|
||||
|
||||
(h/test "context tag is visible network is mainnet"
|
||||
(h/render [quo/transaction-progress (get-test-data {})])
|
||||
(h/is-truthy (h/get-by-label-text :context-tag)))
|
||||
|
||||
(h/test "context tag is visible network is optimism"
|
||||
(h/render [quo/transaction-progress (get-test-data {:network :optimism})])
|
||||
(h/is-truthy (h/get-by-label-text :context-tag)))
|
||||
|
||||
(h/test "context tag is visible network is optimism"
|
||||
(h/render [quo/transaction-progress (get-test-data {:network :arbitrum})])
|
||||
(h/is-truthy (h/get-by-label-text :context-tag))))
|
||||
@@ -0,0 +1,38 @@
|
||||
(ns quo.components.wallet.transaction-progress.style
|
||||
(:require [quo.foundations.colors :as colors]))
|
||||
|
||||
(def title-text-container
|
||||
{:flex 1})
|
||||
|
||||
(def icon
|
||||
{:margin-right 4})
|
||||
|
||||
(defn box-style
|
||||
[theme]
|
||||
{:border-radius 16
|
||||
:border-width 1
|
||||
:border-color (colors/theme-colors colors/neutral-10 colors/neutral-80 theme)})
|
||||
|
||||
(def title-container
|
||||
{:align-items :center
|
||||
:flex-direction :row
|
||||
:padding-left 12
|
||||
:padding-top 8
|
||||
:padding-right 8
|
||||
:padding-bottom 4})
|
||||
|
||||
(def status-row-container
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:flex 1
|
||||
:padding-horizontal 12
|
||||
:padding-top 8
|
||||
:padding-bottom 4})
|
||||
|
||||
(defn context-tag-container
|
||||
[theme]
|
||||
{:padding-horizontal 12
|
||||
:padding-bottom 8
|
||||
:flex-direction :row
|
||||
:border-bottom-width 1
|
||||
:border-color (colors/theme-colors colors/neutral-10 colors/neutral-80 theme)})
|
||||
@@ -0,0 +1,187 @@
|
||||
(ns quo.components.wallet.transaction-progress.view
|
||||
(:require [quo.components.buttons.button.view :as button]
|
||||
[quo.components.icon :as icons]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.components.tags.context-tag.view :as context-tag]
|
||||
[quo.components.wallet.confirmation-progress.view :as confirmation-progress]
|
||||
[quo.components.wallet.transaction-progress.style :as style]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(def ^:private max-mainnet-verifications 4)
|
||||
(def ^:private max-sidenet-verifications 1)
|
||||
|
||||
(defn- icon-internal
|
||||
([icon]
|
||||
(icon-internal icon nil 20))
|
||||
([icon color]
|
||||
(icon-internal icon color 20))
|
||||
([icon color size]
|
||||
[rn/view {:style style/icon}
|
||||
[icons/icon
|
||||
icon
|
||||
{:color color
|
||||
:size size
|
||||
:no-color (when (not color) true)}]]))
|
||||
|
||||
(defn- text-internal
|
||||
[{:keys [weight size accessibility-label color]
|
||||
:or {weight :semi-bold
|
||||
size :paragraph-1}}
|
||||
title]
|
||||
[text/text
|
||||
{:accessibility-label accessibility-label
|
||||
:ellipsize-mode :tail
|
||||
:number-of-lines 1
|
||||
:weight weight
|
||||
:size size
|
||||
:style {:color color}}
|
||||
title])
|
||||
|
||||
(defn- network-type-text
|
||||
[state]
|
||||
(case state
|
||||
(:sending :pending) (i18n/label :t/pending-on)
|
||||
(:confirmed :finalising) (i18n/label :t/confirmed-on)
|
||||
:finalized (i18n/label :t/finalized-on)
|
||||
:error (i18n/label :t/failed-on)
|
||||
nil))
|
||||
|
||||
(defn- calculate-counter
|
||||
[counter]
|
||||
(if (< counter 4) counter max-mainnet-verifications))
|
||||
|
||||
(defn mainnet-label
|
||||
[counter]
|
||||
(str counter "/" max-mainnet-verifications))
|
||||
|
||||
(defn subnet-label
|
||||
[counter]
|
||||
(str counter "/" max-sidenet-verifications))
|
||||
|
||||
(defn- text-steps
|
||||
[network state epoch-number counter]
|
||||
(let [steps (case network
|
||||
:mainnet
|
||||
{:pending (mainnet-label 0)
|
||||
:sending (mainnet-label (calculate-counter counter))
|
||||
:confirmed (mainnet-label (calculate-counter counter))
|
||||
:finalising (mainnet-label (calculate-counter counter))
|
||||
:finalized (i18n/label :t/epoch-number {:number epoch-number})
|
||||
:error (mainnet-label 0)}
|
||||
(or :optimism :arbitrum)
|
||||
{:pending (subnet-label 0)
|
||||
:sending (subnet-label 0)
|
||||
:confirmed (subnet-label 0)
|
||||
:finalising (subnet-label 1)
|
||||
:finalized (i18n/label :t/epoch-number {:number epoch-number})
|
||||
:error (subnet-label 0)}
|
||||
nil)]
|
||||
(get steps state)))
|
||||
|
||||
(defn- get-status-icon
|
||||
[theme state]
|
||||
(case state
|
||||
(:pending :sending) {:icon :i/pending-state
|
||||
:color (colors/theme-colors colors/neutral-50
|
||||
colors/neutral-40
|
||||
theme)}
|
||||
(:confirmed :finalising) {:icon :i/positive-state
|
||||
:color (colors/resolve-color :success theme)}
|
||||
:finalized {:icon :i/diamond}
|
||||
:error {:icon :i/negative-state
|
||||
:color (colors/resolve-color :danger theme)}
|
||||
nil))
|
||||
|
||||
(defn- get-network
|
||||
[networks network]
|
||||
(some #(when (= (:network %) network) %)
|
||||
networks))
|
||||
|
||||
(defn- calculate-error-state
|
||||
[networks]
|
||||
(some #(= (:state %) :error) networks))
|
||||
|
||||
(defn- title-internal
|
||||
[{:keys [title theme networks]}]
|
||||
[rn/view {:style style/title-container}
|
||||
[icon-internal :i/placeholder (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)]
|
||||
[rn/view {:style style/title-text-container}
|
||||
[text-internal nil title]]
|
||||
(when (calculate-error-state networks)
|
||||
[button/button
|
||||
{:size 24
|
||||
:icon-left :i/refresh}
|
||||
(i18n/label :t/retry)])])
|
||||
|
||||
(defn- tag-internal
|
||||
[tag-photo tag-name tag-number theme]
|
||||
[rn/view {:style (style/context-tag-container theme)}
|
||||
[context-tag/view
|
||||
{:size 24
|
||||
:collectible tag-photo
|
||||
:collectible-name tag-name
|
||||
:collectible-number tag-number
|
||||
:type :collectible}]])
|
||||
|
||||
(defn- get-network-text
|
||||
[network]
|
||||
(case network
|
||||
:arbitrum (i18n/label :t/arbitrum)
|
||||
:mainnet (i18n/label :t/mainnet)
|
||||
:optimism (i18n/label :t/optimism)
|
||||
nil))
|
||||
|
||||
(defn- status-row
|
||||
[{:keys [theme state network epoch-number counter]}]
|
||||
(let [{:keys [icon color]} (get-status-icon theme state)]
|
||||
[rn/view {:style style/status-row-container}
|
||||
[icon-internal icon color 16]
|
||||
[rn/view {:style style/title-text-container}
|
||||
[text-internal
|
||||
{:weight :regular
|
||||
:size :paragraph-2}
|
||||
(str (network-type-text state) " " (get-network-text network))]]
|
||||
[rn/view
|
||||
[text-internal
|
||||
{:weight :regular
|
||||
:size :paragraph-2
|
||||
:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}
|
||||
(text-steps network state epoch-number counter)]]]))
|
||||
|
||||
(defn- view-network
|
||||
[{:keys [theme state epoch-number counter total-box progress network]}]
|
||||
[:<>
|
||||
[status-row
|
||||
{:theme theme
|
||||
:state state
|
||||
:network network
|
||||
:epoch-number epoch-number
|
||||
:counter counter}]
|
||||
[confirmation-progress/view
|
||||
{:state state
|
||||
:network network
|
||||
:counter counter
|
||||
:total-box total-box
|
||||
:progress-value progress}]])
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [title on-press accessibility-label theme tag-photo tag-name tag-number networks]
|
||||
:or {accessibility-label :transaction-progress}}]
|
||||
[rn/touchable-without-feedback
|
||||
{:on-press on-press
|
||||
:accessibility-label accessibility-label}
|
||||
[rn/view {:style (style/box-style theme)}
|
||||
[title-internal
|
||||
{:title title
|
||||
:theme theme
|
||||
:networks networks}]
|
||||
[tag-internal tag-photo tag-name tag-number theme]
|
||||
(for [network networks]
|
||||
^{:key (:network network)}
|
||||
(let [assoc-props #(get-network networks %)]
|
||||
[view-network (assoc-props (:network network))]))]])
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
@@ -146,6 +146,7 @@
|
||||
quo.components.wallet.account-origin.view
|
||||
quo.components.wallet.account-overview.view
|
||||
quo.components.wallet.address-text.view
|
||||
quo.components.wallet.confirmation-progress.view
|
||||
quo.components.wallet.keypair.view
|
||||
quo.components.wallet.network-amount.view
|
||||
quo.components.wallet.network-bridge.view
|
||||
@@ -154,6 +155,7 @@
|
||||
quo.components.wallet.progress-bar.view
|
||||
quo.components.wallet.summary-info.view
|
||||
quo.components.wallet.token-input.view
|
||||
quo.components.wallet.transaction-progress.view
|
||||
quo.components.wallet.transaction-summary.view
|
||||
quo.components.wallet.wallet-activity.view
|
||||
quo.components.wallet.wallet-overview.view))
|
||||
@@ -389,6 +391,7 @@
|
||||
(def account-origin quo.components.wallet.account-origin.view/view)
|
||||
(def account-overview quo.components.wallet.account-overview.view/view)
|
||||
(def address-text quo.components.wallet.address-text.view/view)
|
||||
(def confirmation-propgress quo.components.wallet.confirmation-progress.view/view)
|
||||
(def keypair quo.components.wallet.keypair.view/view)
|
||||
(def network-amount quo.components.wallet.network-amount.view/view)
|
||||
(def network-bridge quo.components.wallet.network-bridge.view/view)
|
||||
@@ -399,4 +402,5 @@
|
||||
(def token-input quo.components.wallet.token-input.view/view)
|
||||
(def wallet-overview quo.components.wallet.wallet-overview.view/view)
|
||||
(def wallet-activity quo.components.wallet.wallet-activity.view/view)
|
||||
(def transaction-progress quo.components.wallet.transaction-progress.view/view)
|
||||
(def transaction-summary quo.components.wallet.transaction-summary.view/view)
|
||||
|
||||
@@ -80,6 +80,7 @@
|
||||
[quo.components.wallet.account-card.component-spec]
|
||||
[quo.components.wallet.account-origin.component-spec]
|
||||
[quo.components.wallet.account-overview.component-spec]
|
||||
[quo.components.wallet.confirmation-progress.component-spec]
|
||||
[quo.components.wallet.keypair.component-spec]
|
||||
[quo.components.wallet.network-amount.component-spec]
|
||||
[quo.components.wallet.network-bridge.component-spec]
|
||||
@@ -87,6 +88,7 @@
|
||||
[quo.components.wallet.progress-bar.component-spec]
|
||||
[quo.components.wallet.summary-info.component-spec]
|
||||
[quo.components.wallet.token-input.component-spec]
|
||||
[quo.components.wallet.transaction-progress.component-spec]
|
||||
[quo.components.wallet.transaction-summary.component-spec]
|
||||
[quo.components.wallet.wallet-activity.component-spec]
|
||||
[quo.components.wallet.wallet-overview.component-spec]))
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
{:db (update-in db [:chats chat-id] merge chat)}))
|
||||
|
||||
(rf/defn load-chat
|
||||
{:events [:chats-list/load-chat]}
|
||||
[_ chat-id]
|
||||
{:json-rpc/call [{:method "wakuext_chat"
|
||||
:params [chat-id]
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
(ns status-im.commands.core
|
||||
(:require
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.wallet.utils :as wallet.utils]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/defn handle-prepare-accept-request-address-for-transaction
|
||||
{:events [::prepare-accept-request-address-for-transaction]}
|
||||
[{:keys [db]} message]
|
||||
{:db (assoc db
|
||||
:commands/select-account
|
||||
{:message message
|
||||
:from (wallet.utils/get-default-account (:profile/wallet-accounts
|
||||
db))})
|
||||
:show-select-acc-sheet nil})
|
||||
|
||||
(rf/defn set-selected-account
|
||||
{:events [::set-selected-account]}
|
||||
[{:keys [db]} _ account]
|
||||
{:db (-> (assoc-in db [:commands/select-account :from] account)
|
||||
(assoc :bottom-sheet/show? false))})
|
||||
|
||||
(rf/defn handle-accept-request-address-for-transaction
|
||||
{:events [::accept-request-address-for-transaction]}
|
||||
[{:keys [db]} message-id address]
|
||||
{:db (dissoc db :commands/select-account)
|
||||
:json-rpc/call [{:method "wakuext_acceptRequestAddressForTransaction"
|
||||
:params [message-id address]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:transport/message-sent %])}]})
|
||||
|
||||
(rf/defn handle-decline-request-address-for-transaction
|
||||
{:events [::decline-request-address-for-transaction]}
|
||||
[_ message-id]
|
||||
{:json-rpc/call [{:method "wakuext_declineRequestAddressForTransaction"
|
||||
:params [message-id]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:transport/message-sent %])}]})
|
||||
|
||||
(rf/defn handle-decline-request-transaction
|
||||
{:events [::decline-request-transaction]}
|
||||
[cofx message-id]
|
||||
{:json-rpc/call [{:method "wakuext_declineRequestTransaction"
|
||||
:params [message-id]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:transport/message-sent %])}]})
|
||||
@@ -74,6 +74,7 @@
|
||||
:adminSettings :admin-settings
|
||||
:tokenPermissions :token-permissions
|
||||
:communityTokensMetadata :tokens-metadata
|
||||
:introMessage :intro-message
|
||||
:muteTill :muted-till})
|
||||
(update :admin-settings
|
||||
set/rename-keys
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
(ns status-im.contact.chat
|
||||
(:require
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im2.contexts.contacts.events :as contact]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/defn contact-code-submitted
|
||||
{:events [:contact.ui/contact-code-submitted]
|
||||
:interceptors [(re-frame/inject-cofx :random-id-generator)]}
|
||||
[{{:contacts/keys [new-identity]} :db :as cofx} new-contact? nickname]
|
||||
(let [{:keys [public-key ens-name]} new-identity]
|
||||
(rf/merge cofx
|
||||
#(if new-contact?
|
||||
(contact/send-contact-request % public-key)
|
||||
{:dispatch [:chat.ui/start-chat public-key ens-name]})
|
||||
#(when new-contact?
|
||||
(navigation/navigate-back %)))))
|
||||
@@ -1,13 +0,0 @@
|
||||
(ns status-im.contact.core
|
||||
(:require
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/defn open-contact-toggle-list
|
||||
{:events [:contact.ui/start-group-chat-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(rf/merge cofx
|
||||
{:db (assoc db
|
||||
:group/selected-contacts #{}
|
||||
:new-chat-name "")}
|
||||
(navigation/navigate-to :contact-toggle-list nil)))
|
||||
@@ -85,12 +85,3 @@
|
||||
(assoc acc public-key (enrich-contact contact profile-pictures-visibility own-public-key)))
|
||||
{}
|
||||
contacts))
|
||||
|
||||
(defn get-blocked-contacts
|
||||
[contacts]
|
||||
(reduce (fn [acc {:keys [public-key] :as contact}]
|
||||
(if (:blocked? contact)
|
||||
(conj acc public-key)
|
||||
acc))
|
||||
#{}
|
||||
contacts))
|
||||
|
||||
+19
-14
@@ -91,11 +91,11 @@
|
||||
{:chainId :chain-id
|
||||
:removed :removed?})
|
||||
name-details)]
|
||||
{:db (reduce (fn [db {:keys [username removed?] :as name-detail}]
|
||||
{:db (reduce (fn [db {:keys [username removed? chain-id] :as name-detail}]
|
||||
(if removed?
|
||||
(update-in db [:ens/names] dissoc username)
|
||||
(let [old (get-in db [:ens/names username])]
|
||||
(assoc-in db [:ens/names username] (merge old name-detail)))))
|
||||
(update-in db [:ens/names chain-id] dissoc username)
|
||||
(let [old (get-in db [:ens/names chain-id username])]
|
||||
(assoc-in db [:ens/names chain-id username] (merge old name-detail)))))
|
||||
db
|
||||
name-details)}))
|
||||
|
||||
@@ -103,8 +103,8 @@
|
||||
{:events [:ens/save-username]}
|
||||
[{:keys [db] :as cofx} custom-domain? username redirect-to-summary? connected?]
|
||||
(let [name (fullname custom-domain? username)
|
||||
names (get-in db [:ens/names] [])
|
||||
chain-id (chain/chain-id db)]
|
||||
chain-id (chain/chain-id db)
|
||||
names (get-in db [:ens/names chain-id] [])]
|
||||
(rf/merge cofx
|
||||
(cond-> {:dispatch-n [[:ens/update-usernames [{:username name :chain-id chain-id}]]]}
|
||||
connected? (assoc :json-rpc/call
|
||||
@@ -240,7 +240,8 @@
|
||||
{:events [::set-username-candidate]}
|
||||
[{:keys [db]} username]
|
||||
(let [{:keys [custom-domain?]} (:ens/registration db)
|
||||
usernames (into #{} (keys (get-in db [:ens/names])))
|
||||
chain-id (chain/chain-id db)
|
||||
usernames (into #{} (keys (get-in db [:ens/names chain-id])))
|
||||
state (state custom-domain? username usernames)]
|
||||
(reset! resolve-last-id (random/id))
|
||||
(merge
|
||||
@@ -310,20 +311,23 @@
|
||||
(rf/defn store-name-address
|
||||
{:events [::address-resolved]}
|
||||
[{:keys [db]} username address]
|
||||
{:db (assoc-in db [:ens/names username :address] address)})
|
||||
(let [chain-id (chain/chain-id db)]
|
||||
{:db (assoc-in db [:ens/names chain-id username :address] address)}))
|
||||
|
||||
(rf/defn store-name-public-key
|
||||
{:events [::public-key-resolved]}
|
||||
[{:keys [db]} username public-key]
|
||||
{:db (assoc-in db [:ens/names username :public-key] public-key)})
|
||||
(let [chain-id (chain/chain-id db)]
|
||||
{:db (assoc-in db [:ens/names chain-id username :public-key] public-key)}))
|
||||
|
||||
(rf/defn store-expiration-date
|
||||
{:events [::get-expiration-time-success]}
|
||||
[{:keys [now db]} username timestamp]
|
||||
{:db (-> db
|
||||
(assoc-in [:ens/names username :expiration-date]
|
||||
(datetime/timestamp->year-month-day-date timestamp))
|
||||
(assoc-in [:ens/names username :releasable?] (<= timestamp now)))})
|
||||
(let [chain-id (chain/chain-id db)]
|
||||
{:db (-> db
|
||||
(assoc-in [:ens/names chain-id username :expiration-date]
|
||||
(datetime/timestamp->year-month-day-date timestamp))
|
||||
(assoc-in [:ens/names chain-id username :releasable?] (<= timestamp now)))}))
|
||||
|
||||
(rf/defn navigate-to-name
|
||||
{:events [::navigate-to-name]}
|
||||
@@ -352,7 +356,8 @@
|
||||
(rf/defn remove-username
|
||||
{:events [::remove-username]}
|
||||
[{:keys [db] :as cofx} name]
|
||||
(let [names (get-in db [:ens/names] [])
|
||||
(let [chain-id (chain/chain-id db)
|
||||
names (get-in db [:ens/names chain-id] [])
|
||||
preferred-name (get-in db [:profile/profile :preferred-name])
|
||||
new-names (remove #(= name %) (keys names))
|
||||
{:keys [chain-id username]} (get-in names [name])]
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
status-im.chat.models.input
|
||||
status-im.chat.models.loading
|
||||
status-im.contact.block
|
||||
status-im.contact.chat
|
||||
status-im.contact.core
|
||||
status-im.currency.core
|
||||
status-im.ethereum.subscriptions
|
||||
status-im.fleet.core
|
||||
@@ -43,12 +41,12 @@
|
||||
status-im.visibility-status-popover.core
|
||||
status-im.visibility-status-updates.core
|
||||
status-im.waku.core
|
||||
status-im.wallet-connect.core
|
||||
status-im.wallet.accounts.core
|
||||
status-im.wallet.choose-recipient.core
|
||||
[status-im.wallet.core :as wallet]
|
||||
status-im.wallet.custom-tokens.core
|
||||
[status-im2.common.biometric.events :as biometric]
|
||||
status-im2.common.standard-authentication.events
|
||||
[status-im2.common.theme.core :as theme]
|
||||
[status-im2.common.universal-links :as universal-links]
|
||||
[status-im2.constants :as constants]
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[status-im.node.core :as node]
|
||||
[status-im2.config :as config]
|
||||
[status-im2.constants :as constants]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
@@ -78,10 +77,9 @@
|
||||
[{:keys [db now] :as cofx} fleet]
|
||||
(let [old-fleet (get-in db [:profile/profile :fleet])]
|
||||
(when (not= fleet old-fleet)
|
||||
(rf/merge
|
||||
(multiaccounts.update/multiaccount-update
|
||||
cofx
|
||||
(multiaccounts.update/multiaccount-update :fleet fleet {})
|
||||
(node/prepare-new-config
|
||||
{:on-success
|
||||
#(re-frame/dispatch
|
||||
[:multiaccounts.update.callback/save-settings-success])})))))
|
||||
:fleet
|
||||
fleet
|
||||
{:on-success
|
||||
#(re-frame/dispatch [:logout])}))))
|
||||
|
||||
@@ -11,13 +11,11 @@
|
||||
[status-im.multiaccounts.model :as multiaccounts.model]
|
||||
[status-im.popover.core :as popover]
|
||||
[status-im.utils.deprecated-types :as types]
|
||||
[status-im.utils.keychain.core :as keychain]
|
||||
[status-im2.constants :as constants]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.address :as address]
|
||||
[utils.datetime :as datetime]
|
||||
[utils.ethereum.eip.eip55 :as eip55]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.security.core :as security]))
|
||||
@@ -183,26 +181,28 @@
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :setup-step] nil)
|
||||
(dissoc :intro-wizard))}
|
||||
(multiaccounts.create/on-multiaccount-created
|
||||
{:recovered (or recovered (get-in db [:intro-wizard :recovering?]))
|
||||
:derived {constants/path-wallet-root-keyword
|
||||
{:public-key wallet-root-public-key
|
||||
:address (eip55/address->checksum wallet-root-address)}
|
||||
constants/path-whisper-keyword
|
||||
{:public-key whisper-public-key
|
||||
:address (eip55/address->checksum whisper-address)}
|
||||
constants/path-default-wallet-keyword
|
||||
{:public-key wallet-public-key
|
||||
:address (eip55/address->checksum wallet-address)}}
|
||||
:address address
|
||||
:public-key public-key
|
||||
:keycard-instance-uid instance-uid
|
||||
:key-uid (address/normalized-hex key-uid)
|
||||
:keycard-pairing pairing
|
||||
:keycard-paired-on paired-on
|
||||
:chat-key whisper-private-key}
|
||||
encryption-public-key
|
||||
{}))))
|
||||
;; NOTE: Disabling as keycard not functional and this needs to be moved to
|
||||
;; status-go
|
||||
#_(multiaccounts.create/on-multiaccount-created
|
||||
{:recovered (or recovered (get-in db [:intro-wizard :recovering?]))
|
||||
:derived {constants/path-wallet-root-keyword
|
||||
{:public-key wallet-root-public-key
|
||||
:address (eip55/address->checksum wallet-root-address)}
|
||||
constants/path-whisper-keyword
|
||||
{:public-key whisper-public-key
|
||||
:address (eip55/address->checksum whisper-address)}
|
||||
constants/path-default-wallet-keyword
|
||||
{:public-key wallet-public-key
|
||||
:address (eip55/address->checksum wallet-address)}}
|
||||
:address address
|
||||
:public-key public-key
|
||||
:keycard-instance-uid instance-uid
|
||||
:key-uid (address/normalized-hex key-uid)
|
||||
:keycard-pairing pairing
|
||||
:keycard-paired-on paired-on
|
||||
:chat-key whisper-private-key}
|
||||
encryption-public-key
|
||||
{}))))
|
||||
|
||||
(rf/defn return-to-keycard-login
|
||||
[{:keys [db] :as cofx}]
|
||||
@@ -278,7 +278,7 @@
|
||||
{:db (-> db
|
||||
(assoc-in [:profile/profiles-overview key-uid :keycard-pairing] pairing)
|
||||
(assoc :profile/login account)
|
||||
(assoc :auth-method keychain/auth-method-none)
|
||||
(assoc :auth-method "none")
|
||||
(update :keycard dissoc :flow :migration-password)
|
||||
(dissoc :recovered-account?))
|
||||
::finish-migration [account settings password encryption-pass login-params]}))
|
||||
|
||||
@@ -489,14 +489,15 @@
|
||||
(log/warn "sign-typed-data not implemented" args))
|
||||
|
||||
(defn save-multiaccount-and-login
|
||||
[{:keys [key-uid multiaccount-data password settings node-config accounts-data]}]
|
||||
(native-module/save-account-and-login
|
||||
key-uid
|
||||
(types/clj->json multiaccount-data)
|
||||
password
|
||||
(types/clj->json settings)
|
||||
node-config
|
||||
(types/clj->json accounts-data)))
|
||||
[_]
|
||||
;; NOTE: disabling as we don't support keycard for now and it's using an outdated endpoint
|
||||
#_(native-module/save-account-and-login
|
||||
key-uid
|
||||
(types/clj->json multiaccount-data)
|
||||
password
|
||||
(types/clj->json settings)
|
||||
node-config
|
||||
(types/clj->json accounts-data)))
|
||||
|
||||
(defn login
|
||||
[{:keys [key-uid multiaccount-data password]}]
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
(:require
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[status-im.node.core :as node]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
@@ -11,13 +10,11 @@
|
||||
[{:keys [db now] :as cofx} log-level]
|
||||
(let [old-log-level (get-in db [:profile/profile :log-level])]
|
||||
(when (not= old-log-level log-level)
|
||||
(rf/merge cofx
|
||||
(multiaccounts.update/multiaccount-update
|
||||
:log-level
|
||||
log-level
|
||||
{})
|
||||
(node/prepare-new-config
|
||||
{:on-success #(re-frame/dispatch [:logout])})))))
|
||||
(multiaccounts.update/multiaccount-update
|
||||
cofx
|
||||
:log-level
|
||||
log-level
|
||||
{:on-success #(re-frame/dispatch [:logout])}))))
|
||||
|
||||
(rf/defn show-change-log-level-confirmation
|
||||
{:events [:log-level.ui/log-level-selected]}
|
||||
|
||||
@@ -2,17 +2,10 @@
|
||||
(:require
|
||||
[native-module.core :as native-module]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.data-store.settings :as data-store.settings]
|
||||
[status-im.node.core :as node]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.utils.deprecated-types :as types]
|
||||
[status-im.utils.signing-phrase.core :as signing-phrase]
|
||||
[status-im2.config :as config]
|
||||
[status-im2.constants :as constants]
|
||||
[utils.ethereum.eip.eip55 :as eip55]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.security.core :as security]))
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn normalize-derived-data-keys
|
||||
[derived-data]
|
||||
@@ -82,134 +75,3 @@
|
||||
(rf/defn save-multiaccount-and-login-with-keycard
|
||||
[_ args]
|
||||
{:keycard/save-multiaccount-and-login args})
|
||||
|
||||
(re-frame/reg-fx
|
||||
::save-account-and-login
|
||||
(fn [[key-uid multiaccount-data hashed-password settings config accounts-data]]
|
||||
(native-module/save-account-and-login
|
||||
key-uid
|
||||
multiaccount-data
|
||||
hashed-password
|
||||
settings
|
||||
config
|
||||
accounts-data)))
|
||||
|
||||
(rf/defn save-account-and-login
|
||||
[_ key-uid multiaccount-data password settings node-config accounts-data]
|
||||
{::save-account-and-login [key-uid
|
||||
(types/clj->json multiaccount-data)
|
||||
password
|
||||
(types/clj->json settings)
|
||||
node-config
|
||||
(types/clj->json accounts-data)]})
|
||||
|
||||
(defn prepare-accounts-data
|
||||
[multiaccount]
|
||||
[(let [{:keys [public-key address]}
|
||||
(get-in multiaccount [:derived constants/path-default-wallet-keyword])]
|
||||
{:public-key public-key
|
||||
:address (eip55/address->checksum address)
|
||||
:color colors/blue-persist
|
||||
:wallet true
|
||||
:path constants/path-default-wallet
|
||||
:name (i18n/label :t/main-account)})
|
||||
(let [{:keys [compressed-key public-key address name]}
|
||||
(get-in multiaccount [:derived constants/path-whisper-keyword])]
|
||||
{:public-key public-key
|
||||
:compressed-key compressed-key
|
||||
:address (eip55/address->checksum address)
|
||||
:name name
|
||||
:path constants/path-whisper
|
||||
:chat true})])
|
||||
|
||||
(rf/defn on-multiaccount-created
|
||||
[{:keys [signing-phrase random-guid-generator db] :as cofx}
|
||||
{:keys [address chat-key keycard-instance-uid key-uid
|
||||
keycard-pairing keycard-paired-on mnemonic recovered]
|
||||
:as multiaccount}
|
||||
password
|
||||
{:keys [save-mnemonic? login?] :or {login? true save-mnemonic? false}}]
|
||||
(let [[wallet-account
|
||||
{:keys [public-key
|
||||
compressed-key
|
||||
name]} :as accounts-data]
|
||||
(prepare-accounts-data
|
||||
multiaccount)
|
||||
multiaccount-data {:name name
|
||||
:address address
|
||||
:key-uid key-uid
|
||||
:keycard-pairing keycard-pairing}
|
||||
keycard-multiaccount? (boolean keycard-pairing)
|
||||
eip1581-address (get-in multiaccount
|
||||
[:derived
|
||||
constants/path-eip1581-keyword
|
||||
:address])
|
||||
new-multiaccount
|
||||
(cond->
|
||||
(merge
|
||||
{;; address of the master key
|
||||
:address address
|
||||
;; sha256 of master public key
|
||||
:key-uid key-uid
|
||||
;; The address from which we derive any wallet
|
||||
:wallet-root-address
|
||||
(get-in multiaccount
|
||||
[:derived
|
||||
constants/path-wallet-root-keyword
|
||||
:address])
|
||||
:name name
|
||||
;; public key of the chat account
|
||||
:public-key public-key
|
||||
;; compressed key of the chat account
|
||||
:compressed-key compressed-key
|
||||
;; default address for Dapps
|
||||
:dapps-address (:address wallet-account)
|
||||
:latest-derived-path 0
|
||||
:signing-phrase signing-phrase
|
||||
:backup-enabled? true
|
||||
:installation-id (random-guid-generator)
|
||||
;; default mailserver (history node) setting
|
||||
:use-mailservers? true
|
||||
:recovered recovered}
|
||||
config/default-multiaccount)
|
||||
;; The address from which we derive any chat
|
||||
;; account/encryption keys
|
||||
eip1581-address
|
||||
(assoc :eip1581-address eip1581-address)
|
||||
save-mnemonic?
|
||||
(assoc :mnemonic mnemonic)
|
||||
keycard-multiaccount?
|
||||
(assoc :keycard-instance-uid keycard-instance-uid
|
||||
:keycard-pairing keycard-pairing
|
||||
:keycard-paired-on keycard-paired-on))
|
||||
db (assoc db
|
||||
:profile/login {:key-uid key-uid
|
||||
:name name
|
||||
:password password
|
||||
:creating? true
|
||||
:processing true}
|
||||
:profile/profile new-multiaccount
|
||||
:profile/wallet-accounts [wallet-account]
|
||||
:networks/current-network config/default-network
|
||||
:networks/networks (data-store.settings/rpc->networks config/default-networks))
|
||||
settings (assoc new-multiaccount
|
||||
:networks/current-network config/default-network
|
||||
:networks/networks config/default-networks)]
|
||||
(rf/merge cofx
|
||||
{:db db}
|
||||
(if keycard-multiaccount?
|
||||
(save-multiaccount-and-login-with-keycard
|
||||
{:key-uid key-uid
|
||||
:multiaccount-data multiaccount-data
|
||||
:password password
|
||||
:settings settings
|
||||
:node-config (node/get-new-config db)
|
||||
:accounts-data accounts-data
|
||||
:chat-key chat-key})
|
||||
(save-account-and-login
|
||||
key-uid
|
||||
multiaccount-data
|
||||
(native-module/sha3 (security/safe-unmask-data password))
|
||||
settings
|
||||
(node/get-new-config db)
|
||||
accounts-data)))))
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.node.core :as node]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[utils.ethereum.chain :as chain]
|
||||
[utils.i18n :as i18n]
|
||||
@@ -117,12 +116,10 @@
|
||||
(rf/defn save-network-settings
|
||||
{:events [::save-network-settings-pressed]}
|
||||
[{:keys [db] :as cofx} network]
|
||||
(rf/merge cofx
|
||||
{:db (assoc db :networks/current-network network)
|
||||
:json-rpc/call [{:method "settings_saveSetting"
|
||||
:params [:networks/current-network network]
|
||||
:on-success #()}]}
|
||||
(node/prepare-new-config {:on-success #(re-frame/dispatch [:logout])})))
|
||||
{:db (assoc db :networks/current-network network)
|
||||
:json-rpc/call [{:method "settings_saveSetting"
|
||||
:params [:networks/current-network network]
|
||||
:on-success #(re-frame/dispatch [:logout])}]})
|
||||
|
||||
(rf/defn remove-network
|
||||
{:events [::remove-network-confirmed]}
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
(ns status-im.node.core
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[native-module.core :as native-module]
|
||||
[re-frame.core :as re-frame]
|
||||
[react-native.platform :as platform]
|
||||
[status-im.utils.deprecated-types :as types]
|
||||
[status-im2.config :as config]
|
||||
[utils.re-frame :as rf]))
|
||||
[status-im2.config :as config]))
|
||||
|
||||
(defn- add-custom-bootnodes
|
||||
[config network all-bootnodes]
|
||||
@@ -196,32 +193,4 @@
|
||||
:always
|
||||
(add-log-level log-level))))
|
||||
|
||||
(defn get-new-config
|
||||
[db]
|
||||
(types/clj->json (get-multiaccount-node-config db)))
|
||||
|
||||
(rf/defn save-new-config
|
||||
"Saves a new status-go config for the current account
|
||||
This RPC method is the only way to change the node config of an account.
|
||||
NOTE: it is better used indirectly through `prepare-new-config`,
|
||||
which will take care of building up the proper config based on settings in
|
||||
app-db"
|
||||
{:events [::save-new-config]}
|
||||
[_ config {:keys [on-success]}]
|
||||
{:json-rpc/call [{:method "settings_saveSetting"
|
||||
:params [:node-config config]
|
||||
:on-success on-success}]})
|
||||
|
||||
(rf/defn prepare-new-config
|
||||
"Use this function to apply settings to the current account node config"
|
||||
[{:keys [db]} {:keys [on-success]}]
|
||||
(let [key-uid (get-in db [:profile/profile :key-uid])]
|
||||
{::prepare-new-config [key-uid
|
||||
(get-new-config db)
|
||||
#(re-frame/dispatch
|
||||
[::save-new-config % {:on-success on-success}])]}))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::prepare-new-config
|
||||
(fn [[key-uid config callback]]
|
||||
(native-module/prepare-dir-and-update-config key-uid config callback)))
|
||||
|
||||
@@ -60,10 +60,17 @@
|
||||
{:state state
|
||||
:username username}))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:ens/current-names
|
||||
:<- [:ens/names]
|
||||
:<- [:chain-id]
|
||||
(fn [[all-names chain-id]]
|
||||
(get all-names chain-id)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:ens.name/screen
|
||||
:<- [:get-screen-params :ens-name-details]
|
||||
:<- [:ens/names]
|
||||
:<- [:ens/current-names]
|
||||
(fn [[name ens]]
|
||||
(let [{:keys [address public-key expiration-date releasable?]} (get ens name)
|
||||
pending? (nil? address)]
|
||||
@@ -79,7 +86,7 @@
|
||||
|
||||
(re-frame/reg-sub
|
||||
:ens.main/screen
|
||||
:<- [:ens/names]
|
||||
:<- [:ens/current-names]
|
||||
:<- [:profile/profile]
|
||||
:<- [:ens/preferred-name]
|
||||
:<- [:ens/registrations]
|
||||
|
||||
@@ -7,12 +7,16 @@
|
||||
[utils.i18n :as i18n])
|
||||
(:require-macros [status-im.utils.views :as views]))
|
||||
|
||||
(defn hide-sheet-and-dispatch
|
||||
[event]
|
||||
(re-frame/dispatch [:bottom-sheet/hide-old])
|
||||
(re-frame/dispatch event))
|
||||
|
||||
(defn- normal-mode-settings-data
|
||||
[{:keys [network-name
|
||||
current-log-level
|
||||
waku-bloom-filter-mode
|
||||
light-client-enabled?
|
||||
transactions-management-enabled?
|
||||
wakuv2-flag
|
||||
current-fleet
|
||||
webview-debug]}]
|
||||
(keep
|
||||
@@ -49,19 +53,12 @@
|
||||
:accessory :text
|
||||
:accessory-text current-fleet
|
||||
:chevron true}
|
||||
(if wakuv2-flag
|
||||
{:size :small
|
||||
:title (i18n/label :t/wakuv2-settings)
|
||||
:accessibility-label :wakuv2-settings-button
|
||||
:on-press
|
||||
#(re-frame/dispatch [:wakuv2.ui/enter-settings-pressed])
|
||||
:chevron true}
|
||||
{:size :small
|
||||
:title (i18n/label :t/bootnodes)
|
||||
:accessibility-label :bootnodes-settings-button
|
||||
:on-press
|
||||
#(re-frame/dispatch [:navigate-to :bootnodes-settings])
|
||||
:chevron true})
|
||||
{:size :small
|
||||
:title (i18n/label :t/wakuv2-settings)
|
||||
:accessibility-label :wakuv2-settings-button
|
||||
:on-press
|
||||
#(re-frame/dispatch [:wakuv2.ui/enter-settings-pressed])
|
||||
:chevron true}
|
||||
{:size :small
|
||||
:title (i18n/label :t/rpc-usage-info)
|
||||
:accessibility-label :rpc-usage-info
|
||||
@@ -76,6 +73,15 @@
|
||||
:on-press
|
||||
#(re-frame/dispatch [:navigate-to :peers-stats])
|
||||
:chevron true}
|
||||
{:size :small
|
||||
:title (i18n/label :t/light-client-enabled)
|
||||
:accessibility-label :light-client-enabled
|
||||
:container-margin-bottom 8
|
||||
:on-press
|
||||
#(re-frame/dispatch
|
||||
[:wakuv2.ui/toggle-light-client (not light-client-enabled?)])
|
||||
:accessory :switch
|
||||
:active light-client-enabled?}
|
||||
{:size :small
|
||||
:title (i18n/label :t/transactions-management-enabled)
|
||||
:accessibility-label :transactions-management-enabled
|
||||
@@ -94,16 +100,7 @@
|
||||
#(re-frame/dispatch
|
||||
[:profile.settings/change-webview-debug (not webview-debug)])
|
||||
:accessory :switch
|
||||
:active webview-debug}
|
||||
{:size :small
|
||||
:title (i18n/label :t/waku-bloom-filter-mode)
|
||||
:accessibility-label :waku-bloom-filter-mode-settings-switch
|
||||
:container-margin-bottom 8
|
||||
:on-press
|
||||
#(re-frame/dispatch
|
||||
[:multiaccounts.ui/waku-bloom-filter-mode-switched (not waku-bloom-filter-mode)])
|
||||
:accessory :switch
|
||||
:active waku-bloom-filter-mode}]))
|
||||
:active webview-debug}]))
|
||||
|
||||
(defn- flat-list-data
|
||||
[options]
|
||||
@@ -117,10 +114,9 @@
|
||||
|
||||
(views/defview advanced-settings
|
||||
[]
|
||||
(views/letsubs [{:keys [webview-debug]} [:profile/profile]
|
||||
(views/letsubs [webview-debug [:profile/webview-debug]
|
||||
light-client-enabled? [:profile/light-client-enabled?]
|
||||
network-name [:network-name]
|
||||
waku-bloom-filter-mode [:waku/bloom-filter-mode]
|
||||
wakuv2-flag [:waku/v2-flag]
|
||||
transactions-management-enabled? [:wallet-legacy/transactions-management-enabled?]
|
||||
current-log-level [:log-level/current-log-level]
|
||||
current-fleet [:fleets/current-fleet]]
|
||||
@@ -129,10 +125,9 @@
|
||||
{:network-name network-name
|
||||
:current-log-level current-log-level
|
||||
:transactions-management-enabled? transactions-management-enabled?
|
||||
:light-client-enabled? light-client-enabled?
|
||||
:current-fleet current-fleet
|
||||
:dev-mode? false
|
||||
:wakuv2-flag wakuv2-flag
|
||||
:waku-bloom-filter-mode waku-bloom-filter-mode
|
||||
:webview-debug webview-debug})
|
||||
:key-fn (fn [_ i] (str i))
|
||||
:render-fn render-item}]))
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
(ns status-im.ui.screens.fleet-settings.views
|
||||
(:require
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.node.core :as node]
|
||||
[status-im.ui.components.icons.icons :as icons]
|
||||
[status-im.ui.components.list.views :as list]
|
||||
[status-im.ui.components.react :as react]
|
||||
|
||||
@@ -46,7 +46,8 @@
|
||||
:key :your-data-belongs-to-you-description}]
|
||||
[react/view {:style styles/intro-button}
|
||||
[quo/button
|
||||
{:on-press #(re-frame/dispatch [:set-in [:my-profile/seed :step] :12-words])}
|
||||
{:on-press #(do (re-frame/dispatch [:set-in [:my-profile/seed :step] :12-words])
|
||||
(re-frame/dispatch [:profile.settings/mnemonic-was-shown]))}
|
||||
(i18n/label :t/ok-continue)]]])
|
||||
|
||||
(defn six-words
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
(ns status-im.ui.screens.wallet.send.views
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs] :as views])
|
||||
(:require-macros [status-im.utils.views :as views])
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.commands.core :as commands]
|
||||
[status-im.ui.components.bottom-panel.views :as bottom-panel]
|
||||
[status-im.ui.components.chat-icon.screen :as chat-icon]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.components.core :as components.core]
|
||||
@@ -129,47 +127,6 @@
|
||||
" "
|
||||
(:code wallet-currency))])))
|
||||
|
||||
(defn select-account-sheet
|
||||
[{:keys [from message]}]
|
||||
[react/view {:style (styles/acc-sheet)}
|
||||
[header
|
||||
{:small-screen? false
|
||||
:label :t/select-account}]
|
||||
[react/view
|
||||
{:flex-direction :row
|
||||
:padding-horizontal 24
|
||||
:align-items :center
|
||||
:margin-vertical 16}]
|
||||
[components.core/list-header
|
||||
(i18n/label :t/from-capitalized)]
|
||||
[react/view {:flex-direction :row :flex 1 :align-items :center}
|
||||
[react/view {:flex 1}
|
||||
[render-account from nil ::commands/set-selected-account]]]
|
||||
[toolbar/toolbar
|
||||
{:left
|
||||
[react/view {:padding-horizontal 8}
|
||||
[components.core/button
|
||||
{:type :secondary
|
||||
:on-press #(re-frame/dispatch [:set :commands/select-account nil])}
|
||||
(i18n/label :t/cancel)]]
|
||||
:right
|
||||
[components.core/button
|
||||
{:accessibility-label :select-account-bottom-sheet
|
||||
:disabled (nil? from)
|
||||
:on-press #(re-frame/dispatch
|
||||
[::commands/accept-request-address-for-transaction
|
||||
(:message-id message)
|
||||
(:address from)])}
|
||||
(i18n/label :t/share)]}]])
|
||||
|
||||
(defview select-account
|
||||
[]
|
||||
(letsubs [data [:commands/select-account]]
|
||||
[bottom-panel/animated-bottom-panel
|
||||
data
|
||||
select-account-sheet
|
||||
#(re-frame/dispatch [:hide-select-acc-sheet])]))
|
||||
|
||||
(views/defview request-transaction
|
||||
[_]
|
||||
(views/letsubs [{:keys [amount-error amount-text from token sign-enabled?] :as tx}
|
||||
|
||||
@@ -6,10 +6,6 @@
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(def auth-method-biometric "biometric")
|
||||
(def auth-method-biometric-prepare "biometric-prepare")
|
||||
(def auth-method-none "none")
|
||||
|
||||
(defn- whisper-key-name
|
||||
[address]
|
||||
(str address "-whisper"))
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
(ns ^{:doc "Pairing utils"} status-im.utils.pairing)
|
||||
|
||||
(defn has-paired-installations?
|
||||
[cofx]
|
||||
(let [our-installation-id (get-in cofx [:db :profile/profile :installation-id])]
|
||||
(->>
|
||||
(get-in cofx [:db :pairing/installations])
|
||||
vals
|
||||
(some (fn [{:keys [enabled? installation-id]}]
|
||||
(and (not= installation-id our-installation-id)
|
||||
enabled?))))))
|
||||
@@ -1,120 +0,0 @@
|
||||
(ns status-im.utils.snoopy
|
||||
(:require
|
||||
["react-native/Libraries/vendor/emitter/EventEmitter" :refer [EventEmitter]]
|
||||
["rn-snoopy" :default snoopy]
|
||||
["rn-snoopy/stream/bars" :default bars]
|
||||
["rn-snoopy/stream/buffer" :default buffer]
|
||||
["rn-snoopy/stream/filter" :default sn-filter]
|
||||
[clojure.string :as string]
|
||||
[status-im2.config :as config]))
|
||||
|
||||
(defn create-filter
|
||||
[f]
|
||||
(fn [^js message]
|
||||
(let [method (.-method message)
|
||||
module (.-module message)
|
||||
^js args (.-args message)
|
||||
first-arg (when (pos? (.-length args))
|
||||
(aget args 0))]
|
||||
(f {:method method
|
||||
:module module
|
||||
:first-arg first-arg}))))
|
||||
|
||||
(defn status-module-filter
|
||||
[{:keys [method module first-arg]}]
|
||||
(or (= module "Status")
|
||||
(and (= module "RCTNativeAppEventEmitter")
|
||||
(= method "emit")
|
||||
(= first-arg "gethEvent"))
|
||||
(and
|
||||
(string? method)
|
||||
(string/starts-with? method "<callback for Status."))))
|
||||
|
||||
(defn timer-filter
|
||||
[{:keys [method]}]
|
||||
(contains? #{"callTimers" "createTimer"} method))
|
||||
|
||||
(defn websocket-filter
|
||||
[{:keys [module first-arg]}]
|
||||
(or (= module "WebSocketModule")
|
||||
(and (= module "RCTDeviceEventEmitter")
|
||||
(contains? #{"websocketFailed" "websocketMessage"} first-arg))))
|
||||
|
||||
(defn ui-manager-filter
|
||||
[{:keys [module]}]
|
||||
(= module "UIManager"))
|
||||
|
||||
(defn touches-filter
|
||||
[{:keys [method module]}]
|
||||
(and (= module "RCTEventEmitter")
|
||||
(= method "receiveTouches")))
|
||||
|
||||
(defn native-animation-filter
|
||||
[{:keys [method module]}]
|
||||
(or (= module "NativeAnimatedModule")
|
||||
(and
|
||||
(string? method)
|
||||
(string/starts-with? method "<callback for NativeAnimatedModule."))))
|
||||
|
||||
(defn keyboard-observer-filter
|
||||
[{:keys [module]}]
|
||||
;; mostly all calls to KeyboardObserver are done by FlatList
|
||||
(= module "KeyboardObserver"))
|
||||
|
||||
(defn threshold-warnings
|
||||
[{:keys [filter-fn label tick? print-events? threshold events threshold-message]}]
|
||||
(.subscribe ^js
|
||||
((bars
|
||||
(fn [^js a] (.-length a))
|
||||
threshold
|
||||
tick?
|
||||
true
|
||||
label
|
||||
threshold-message)
|
||||
((buffer)
|
||||
((sn-filter (create-filter filter-fn)
|
||||
print-events?)
|
||||
events)))))
|
||||
|
||||
;; In order to enable snoopy set SNOOPY=1 in .env file.
|
||||
;; By default events are not printed and you will see warnings only when
|
||||
;; the number of events is exceeding the threshold.
|
||||
;; For debugging UI perf, in particular the number of bridge calls caused
|
||||
;; by view components set `:print-events?=true` for `ui-manager-filter`,
|
||||
;; and then collect printed data in logs.
|
||||
(defn subscribe!
|
||||
[]
|
||||
(when config/snoopy-enabled?
|
||||
(let [emitter-class EventEmitter
|
||||
emitter (emitter-class.)
|
||||
events (.stream snoopy emitter)]
|
||||
(threshold-warnings
|
||||
{:filter-fn (constantly true)
|
||||
:label "all messages"
|
||||
:threshold-message "too many calls to bridge, something suspicious is happening"
|
||||
:tick? false
|
||||
:print-events? false
|
||||
:threshold 400
|
||||
:events events})
|
||||
|
||||
(threshold-warnings
|
||||
{:filter-fn timer-filter
|
||||
:label "timer"
|
||||
:threshold-message "too many setTimeout/setInterval calls"
|
||||
:tick? false
|
||||
:print-events? false
|
||||
:threshold 70
|
||||
:events events})
|
||||
|
||||
(threshold-warnings
|
||||
{:filter-fn ui-manager-filter
|
||||
:label "timer"
|
||||
:threshold-message (str
|
||||
"too many calls to UIManager, most likely during navigation. "
|
||||
"Please consider preloading of screens or lazy loading of some components")
|
||||
:tick? false
|
||||
:print-events? true
|
||||
;; todo(rasom): revisit this number when/if
|
||||
;; https://github.com/status-im/status-mobile/pull/2849 will be merged
|
||||
:threshold 200
|
||||
:events events}))))
|
||||
@@ -1,31 +0,0 @@
|
||||
(ns status-im.utils.wallet-connect
|
||||
(:require
|
||||
["@react-native-async-storage/async-storage" :default AsyncStorage]
|
||||
["@walletconnect/client" :refer [CLIENT_EVENTS] :default WalletConnectClient]
|
||||
[clojure.string :as string]
|
||||
[status-im2.config :as config]))
|
||||
|
||||
(defn init
|
||||
[on-success on-error]
|
||||
(-> ^js WalletConnectClient
|
||||
(.init (clj->js {:controller true
|
||||
:projectId config/wallet-connect-project-id
|
||||
:logger "debug"
|
||||
:metadata config/default-wallet-connect-metadata
|
||||
:storageOptions {:asyncStorage ^js AsyncStorage}}))
|
||||
(.then on-success)
|
||||
(.catch on-error)))
|
||||
|
||||
(defn session-request-event [] (.-request (.-session CLIENT_EVENTS)))
|
||||
|
||||
(defn session-created-event [] (.-created (.-session CLIENT_EVENTS)))
|
||||
|
||||
(defn session-deleted-event [] (.-deleted (.-session CLIENT_EVENTS)))
|
||||
|
||||
(defn session-proposal-event [] (.-proposal (.-session CLIENT_EVENTS)))
|
||||
|
||||
(defn session-updated-event [] (.-updated (.-session CLIENT_EVENTS)))
|
||||
|
||||
(defn url?
|
||||
[url]
|
||||
(string/starts-with? url "wc:"))
|
||||
@@ -2,22 +2,11 @@
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[status-im.node.core :as node]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/defn switch-waku-bloom-filter-mode
|
||||
{:events [:multiaccounts.ui/waku-bloom-filter-mode-switched]}
|
||||
[cofx enabled?]
|
||||
(rf/merge cofx
|
||||
(multiaccounts.update/multiaccount-update
|
||||
:waku-bloom-filter-mode
|
||||
enabled?
|
||||
{})
|
||||
(node/prepare-new-config
|
||||
{:on-success #(re-frame/dispatch [:logout])})))
|
||||
|
||||
(def address-regex #"/ip4/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/tcp/\d{1,5}/p2p/[a-zA-Z0-9]+")
|
||||
|
||||
@@ -108,13 +97,16 @@
|
||||
vals
|
||||
(map #(vector (:name %1) (:address %1)))
|
||||
(into {}))]
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:profile/profile :wakuv2-config :CustomNodes] new-nodes)
|
||||
(dissoc :wakuv2-nodes/manage :wakuv2-nodes/list))
|
||||
:dispatch [:navigate-back]}
|
||||
(node/prepare-new-config
|
||||
{:on-success #(re-frame/dispatch [:logout])}))))
|
||||
{:db (-> db
|
||||
(assoc-in [:profile/profile :wakuv2-config :CustomNodes] new-nodes)
|
||||
(dissoc :wakuv2-nodes/manage :wakuv2-nodes/list))
|
||||
:json-rpc/call [{:method "wakuext_setCustomNodes"
|
||||
:params [{:customNodes new-nodes}]
|
||||
:on-success #(log/info "updated custom nodes")
|
||||
:on-error #(log/error "failed to set custom nodes"
|
||||
{:error %
|
||||
:custom-nodes new-nodes})}]
|
||||
:dispatch [:navigate-back]}))
|
||||
|
||||
(rf/defn show-delete-node-confirmation
|
||||
{:events [:wakuv2.ui/delete-pressed]}
|
||||
@@ -131,3 +123,17 @@
|
||||
(rf/merge cofx
|
||||
(delete id)
|
||||
(navigation/navigate-back)))
|
||||
|
||||
(rf/defn toggle-light-client
|
||||
{:events [:wakuv2.ui/toggle-light-client]}
|
||||
[{:keys [db]} enabled?]
|
||||
{:db (assoc-in db [:profile/profile :wakuv2-config :LightClient] enabled?)
|
||||
|
||||
:json-rpc/call [{:method "wakuext_setLightClient"
|
||||
:params [{:enabled enabled?}]
|
||||
:on-success (fn []
|
||||
(log/info "light client set successfully" enabled?)
|
||||
(re-frame/dispatch [:logout]))
|
||||
:on-error #(log/error "failed to set light client"
|
||||
{:error %
|
||||
:enabled? enabled?})}]})
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
[status-im.ethereum.ens :as ens]
|
||||
[status-im.ethereum.tokens :as tokens]
|
||||
[status-im.qr-scanner.core :as qr-scaner]
|
||||
[status-im.utils.wallet-connect :as wallet-connect]
|
||||
[status-im.wallet.utils :as wallet.utils]
|
||||
[status-im2.common.router :as router]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
@@ -173,11 +172,7 @@
|
||||
(if (links/universal-link? uri)
|
||||
{:dispatch [:universal-links/handle-url uri]}
|
||||
{:browser/show-browser-selection uri})
|
||||
(if (wallet-connect/url? uri)
|
||||
{:ui/show-error "Wallet Connect not implemented"}
|
||||
;; Re-enable with https://github.com/status-im/status-mobile/issues/13429
|
||||
;; {:dispatch [::qr-scaner/handle-wallet-connect-uri {:data uri}]}
|
||||
{:ui/show-error (i18n/label :t/wallet-invalid-address {:data uri})}))))
|
||||
{:ui/show-error (i18n/label :t/wallet-invalid-address {:data uri})})))
|
||||
|
||||
(rf/defn qr-scanner-result
|
||||
{:events [:wallet-legacy.send/qr-scanner-result]}
|
||||
|
||||
@@ -1074,7 +1074,7 @@
|
||||
|
||||
;;TODO: this could be replaced by a single API call on status-go side
|
||||
(re-frame/reg-fx :wallet-legacy/initialize-wallet
|
||||
(fn [[network-id network callback]]
|
||||
(fn [[network-id _network callback]]
|
||||
(-> (js/Promise.all
|
||||
(clj->js
|
||||
[(js/Promise.
|
||||
@@ -1082,24 +1082,6 @@
|
||||
(json-rpc/call {:method "accounts_getAccounts"
|
||||
:on-success resolve-fn
|
||||
:on-error reject})))
|
||||
(js/Promise.
|
||||
(fn [resolve-fn _]
|
||||
(json-rpc/call
|
||||
{:method "wallet_addEthereumChain"
|
||||
:params
|
||||
[{:isTest false
|
||||
:tokenOverrides []
|
||||
:rpcUrl (get-in network [:config :UpstreamConfig :URL])
|
||||
:chainColor "green"
|
||||
:chainName (:name network)
|
||||
:nativeCurrencyDecimals 10
|
||||
:shortName "erc20"
|
||||
:layer 1
|
||||
:chainId (int network-id)
|
||||
:enabled false
|
||||
:fallbackURL (get-in network [:config :UpstreamConfig :URL])}]
|
||||
:on-success resolve-fn
|
||||
:on-error (fn [_] (resolve-fn nil))})))
|
||||
(js/Promise.
|
||||
(fn [resolve-fn _]
|
||||
(json-rpc/call {:method "wallet_getTokens"
|
||||
|
||||
@@ -1,288 +0,0 @@
|
||||
(ns status-im.wallet-connect.core
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.browser.core :as browser]
|
||||
[status-im.signing.core :as signing]
|
||||
[status-im.utils.deprecated-types :as types]
|
||||
[status-im.utils.wallet-connect :as wallet-connect]
|
||||
[status-im2.config :as config]
|
||||
[status-im2.constants :as constants]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.address :as address]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/defn proposal-handler
|
||||
{:events [:wallet-connect/proposal]}
|
||||
[{:keys [db] :as cofx} request-event]
|
||||
(let [proposal (types/js->clj request-event)
|
||||
proposer (:proposer proposal)
|
||||
metadata (:metadata proposer)]
|
||||
{:db (assoc db
|
||||
:wallet-connect/proposal proposal
|
||||
:wallet-connect/proposal-metadata metadata)
|
||||
:show-wallet-connect-sheet nil}))
|
||||
|
||||
(rf/defn session-connected
|
||||
{:events [:wallet-connect/created]}
|
||||
[{:keys [db]} session]
|
||||
(let [session (merge (types/js->clj session) {:wc-version 2})
|
||||
client (get db :wallet-connect/client)]
|
||||
(log/debug "[wallet connect] session created - " session)
|
||||
{:show-wallet-connect-success-sheet nil
|
||||
:db (assoc db
|
||||
:wallet-connect/session-connected session
|
||||
:wallet-connect/sessions (types/js->clj
|
||||
(.-values
|
||||
(.-session
|
||||
client))))}))
|
||||
|
||||
(rf/defn manage-app
|
||||
{:events [:wallet-connect/manage-app]}
|
||||
[{:keys [db]} session]
|
||||
(let [session (types/js->clj session)]
|
||||
{:db (assoc db
|
||||
:wallet-connect/session-managed session
|
||||
:wallet-connect/showing-app-management-sheet? true)
|
||||
:show-wallet-connect-app-management-sheet nil}))
|
||||
|
||||
(rf/defn request-handler
|
||||
{:events [:wallet-connect/request]}
|
||||
[{:keys [db] :as cofx} request-event]
|
||||
(let [request (types/js->clj request-event)
|
||||
params (:request request)
|
||||
pending-requests (or (:wallet-connect/pending-requests db) [])
|
||||
new-pending-requests (conj pending-requests request)
|
||||
client (get db :wallet-connect/client)
|
||||
topic (:topic request)]
|
||||
{:db (assoc db :wallet-connect/pending-requests new-pending-requests)
|
||||
:dispatch [:wallet-connect/request-received request]}))
|
||||
|
||||
(rf/defn request-handler-test
|
||||
{:events [:wallet-connect/request-test]}
|
||||
[{:keys [db] :as cofx}]
|
||||
{:show-wallet-connect-sheet nil})
|
||||
|
||||
(defn subscribe-to-events
|
||||
[^js wallet-connect-client]
|
||||
(.on wallet-connect-client
|
||||
(wallet-connect/session-request-event)
|
||||
#(re-frame/dispatch [:wallet-connect/request %]))
|
||||
(.on wallet-connect-client
|
||||
(wallet-connect/session-created-event)
|
||||
#(re-frame/dispatch [:wallet-connect/created %]))
|
||||
(.on wallet-connect-client
|
||||
(wallet-connect/session-deleted-event)
|
||||
#(re-frame/dispatch [:wallet-connect/update-sessions]))
|
||||
(.on wallet-connect-client
|
||||
(wallet-connect/session-updated-event)
|
||||
#(re-frame/dispatch [:wallet-connect/update-sessions]))
|
||||
(.on wallet-connect-client
|
||||
(wallet-connect/session-proposal-event)
|
||||
#(re-frame/dispatch [:wallet-connect/proposal %])))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wc-2-init
|
||||
(fn []
|
||||
(wallet-connect/init
|
||||
#(re-frame/dispatch [:wallet-connect/client-init %])
|
||||
#(log/error "[wallet-connect]" %))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wc-2-subscribe-to-events
|
||||
(fn [client]
|
||||
(subscribe-to-events client)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wc-2-client-approve-proposal
|
||||
(fn [[client proposal response]]
|
||||
(-> ^js client
|
||||
(.approve (clj->js {:proposal proposal :response response}))
|
||||
(.then #(log/debug "[wallet-connect] session proposal approved"))
|
||||
(.catch #(log/error "[wallet-connect] session proposal approval error:" %)))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wc-2-client-reject-proposal
|
||||
(fn [[client proposal]]
|
||||
(-> ^js client
|
||||
(.reject (clj->js {:proposal proposal}))
|
||||
(.then #(log/debug "[wallet-connect] session proposal rejected"))
|
||||
(.catch #(log/error "[wallet-connect] " %)))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wc-2-client-disconnect
|
||||
(fn [[client topic]]
|
||||
(-> ^js client
|
||||
(.disconnect (clj->js {:topic topic}))
|
||||
(.then #(log/debug "[wallet-connect] session disconnected - topic " topic))
|
||||
(.catch #(log/error "[wallet-connect] " %)))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wc-2-change-session
|
||||
(fn [[client topic accounts]]
|
||||
(-> ^js client
|
||||
(.update (clj->js {:topic topic
|
||||
:state {:accounts accounts}}))
|
||||
(.then #(log/debug "[wallet-connect] session topic " topic
|
||||
" changed to account " (first accounts)))
|
||||
(.catch #(log/error "[wallet-connect] " %)))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wc-2-pair
|
||||
(fn [[client uri]]
|
||||
(.pair client (clj->js {:uri uri}))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wc-2-respond
|
||||
(fn [[client response]]
|
||||
(.respond client (clj->js response))))
|
||||
|
||||
(rf/defn approve-proposal
|
||||
{:events [:wallet-connect/approve-proposal]}
|
||||
[{:keys [db]} account]
|
||||
(let [client (get db :wallet-connect/client)
|
||||
proposal (get db :wallet-connect/proposal)
|
||||
topic (:topic proposal)
|
||||
permissions (:permissions proposal)
|
||||
blockchain (:blockchain permissions)
|
||||
proposal-chain-ids (map #(last (string/split % #":")) (:chains blockchain))
|
||||
available-chain-ids (map #(get-in % [:config :NetworkId]) (vals (get db :networks/networks)))
|
||||
supported-chain-ids (filter (fn [chain-id] #(boolean (some #{chain-id} available-chain-ids)))
|
||||
proposal-chain-ids)
|
||||
address (:address account)
|
||||
accounts (map #(str "eip155:" % ":" (address/normalized-hex address))
|
||||
supported-chain-ids)
|
||||
;; TODO: Check for unsupported
|
||||
metadata (get db :wallet-connect/proposal-metadata)
|
||||
response {:state {:accounts accounts}
|
||||
:metadata config/default-wallet-connect-metadata}]
|
||||
{:hide-wallet-connect-sheet nil
|
||||
:wc-2-client-approve-proposal [client proposal response]}))
|
||||
|
||||
(rf/defn reject-proposal
|
||||
{:events [:wallet-connect/reject-proposal]}
|
||||
[{:keys [db]} account]
|
||||
(let [client (get db :wallet-connect/client)
|
||||
proposal (get db :wallet-connect/proposal)]
|
||||
{:hide-wallet-connect-sheet nil
|
||||
:wc-2-client-reject-proposal client}))
|
||||
|
||||
(rf/defn change-session-account
|
||||
{:events [:wallet-connect/change-session-account]}
|
||||
[{:keys [db]} topic account]
|
||||
(let [client (get db :wallet-connect/client)
|
||||
sessions (get db :wallet-connect/sessions)
|
||||
session (first (filter #(= (:topic %) topic) sessions))
|
||||
permissions (:permissions session)
|
||||
blockchain (:blockchain permissions)
|
||||
proposal-chain-ids (map #(last (string/split % #":")) (:chains blockchain))
|
||||
address (:address account)
|
||||
available-chain-ids (map #(get-in % [:config :NetworkId]) (vals (get db :networks/networks)))
|
||||
supported-chain-ids (filter (fn [chain-id] #(boolean (some #{chain-id} available-chain-ids)))
|
||||
proposal-chain-ids)
|
||||
accounts (map #(str "eip155:" % ":" (address/normalized-hex address))
|
||||
supported-chain-ids)]
|
||||
{:db (assoc db
|
||||
:wallet-connect/showing-app-management-sheet?
|
||||
false)
|
||||
:hide-wallet-connect-app-management-sheet nil
|
||||
:wc-2-change-session [client topic accounts]}))
|
||||
|
||||
(rf/defn disconnect-session
|
||||
{:events [:wallet-connect/disconnect]}
|
||||
[{:keys [db]} topic]
|
||||
(let [client (get db :wallet-connect/client)]
|
||||
{:hide-wallet-connect-app-management-sheet nil
|
||||
:hide-wallet-connect-success-sheet nil
|
||||
:wc-2-client-disconnect [client topic]
|
||||
:db (-> db
|
||||
(assoc :wallet-connect/sessions
|
||||
(types/js->clj (.-values (.-session client))))
|
||||
(dissoc :wallet-connect/session-managed))}))
|
||||
|
||||
(rf/defn pair-session
|
||||
{:events [:wallet-connect/pair]}
|
||||
[{:keys [db]} {:keys [data]}]
|
||||
(let [client (get db :wallet-connect/client)]
|
||||
{:db (assoc db :wallet-connect/scanned-uri data)
|
||||
:dispatch [:navigate-back]
|
||||
:wc-2-pair [client data]}))
|
||||
|
||||
(rf/defn wallet-connect-client-initate
|
||||
{:events [:wallet-connect/client-init]}
|
||||
[{:keys [db] :as cofx} ^js client]
|
||||
{:db (assoc db
|
||||
:wallet-connect/client client
|
||||
:wallet-connect/sessions (types/js->clj (.-values (.-session
|
||||
client))))
|
||||
:wc-2-subscribe-to-events client})
|
||||
|
||||
(rf/defn update-sessions
|
||||
{:events [:wallet-connect/update-sessions]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [client (get db :wallet-connect/client)]
|
||||
{:db (-> db
|
||||
(assoc :wallet-connect/sessions (types/js->clj (.-values (.-session client))))
|
||||
(dissoc :wallet-connect/session-managed))}))
|
||||
|
||||
(rf/defn wallet-connect-complete-transaction
|
||||
{:events [:wallet-connect.dapp/transaction-on-result]}
|
||||
[{:keys [db]} message-id topic result]
|
||||
(let [client (get db :wallet-connect/client)
|
||||
response {:topic topic
|
||||
:response {:jsonrpc "2.0"
|
||||
:id message-id
|
||||
:result result}}]
|
||||
{:db (assoc db :wallet-connect/response response)
|
||||
:wc-2-respond [client response]}))
|
||||
|
||||
(rf/defn wallet-connect-send-async
|
||||
[cofx {:keys [method params id] :as payload} message-id topic]
|
||||
(let [message? (browser/web3-sign-message? method)
|
||||
dapps-address (get-in cofx [:db :profile/profile :dapps-address])
|
||||
accounts (get-in cofx [:db :multiaccount/visible-accounts])
|
||||
typed? (and (not= constants/web3-personal-sign method)
|
||||
(not= constants/web3-eth-sign method))]
|
||||
(if (or message? (= constants/web3-send-transaction method))
|
||||
(let [[address data] (cond (and (= method constants/web3-keycard-sign-typed-data)
|
||||
(not (vector? params)))
|
||||
;; We don't use signer argument for keycard sign-typed-data
|
||||
["0x0" params]
|
||||
message? (browser/normalize-sign-message-params
|
||||
params
|
||||
typed?)
|
||||
:else [nil nil])]
|
||||
(when (or (not message?) (and address data))
|
||||
(signing/sign cofx
|
||||
(merge
|
||||
(if message?
|
||||
{:message {:address address
|
||||
:data data
|
||||
:v4 (= constants/web3-sign-typed-data-v4 method)
|
||||
:typed? typed?
|
||||
:pinless? (= method constants/web3-keycard-sign-typed-data)
|
||||
:from address}}
|
||||
{:tx-obj (-> params
|
||||
first
|
||||
(update :from #(or % dapps-address))
|
||||
(dissoc :gasPrice))})
|
||||
{:on-result [:wallet-connect.dapp/transaction-on-result message-id topic]
|
||||
:on-error [:wallet-connect.dapp/transaction-on-error message-id topic]}))))
|
||||
(when (#{"eth_accounts" "eth_coinbase"} method)
|
||||
(wallet-connect-complete-transaction
|
||||
cofx
|
||||
message-id
|
||||
topic
|
||||
(if (= method "eth_coinbase") dapps-address [dapps-address]))))))
|
||||
|
||||
(rf/defn wallet-connect-send-async-read-only
|
||||
[{:keys [db] :as cofx} {:keys [method] :as payload} message-id topic]
|
||||
(wallet-connect-send-async cofx payload message-id topic))
|
||||
|
||||
(rf/defn process-request
|
||||
{:events [:wallet-connect/request-received]}
|
||||
[{:keys [db] :as cofx} session-request]
|
||||
(let [pending-requests (get db :wallet-connect/pending-requests)
|
||||
{:keys [topic request]} session-request
|
||||
{:keys [id]} request]
|
||||
(wallet-connect-send-async-read-only cofx request id topic)))
|
||||
@@ -6,8 +6,10 @@
|
||||
[status-im2.common.confirmation-drawer.view :as confirmation-drawer]
|
||||
[status-im2.common.mute-drawer.view :as mute-drawer]
|
||||
[status-im2.common.muting.helpers :refer [format-mute-till]]
|
||||
[status-im2.config :as config]
|
||||
[status-im2.constants :as constants]
|
||||
[status-im2.contexts.communities.actions.chat.view :as chat-actions]
|
||||
[status-im2.contexts.chat.actions.view :as chat-actions]
|
||||
[status-im2.contexts.communities.actions.chat.view :as communities-chat-actions]
|
||||
[status-im2.contexts.contacts.drawers.nickname-drawer.view :as nickname-drawer]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
@@ -253,16 +255,6 @@
|
||||
:chevron? true
|
||||
:add-divider? add-divider?}))
|
||||
|
||||
;; TODO(OmarBasem): Requires design input.
|
||||
(defn fetch-messages-entry
|
||||
[]
|
||||
(entry {:icon :i/save
|
||||
:label (i18n/label :t/fetch-messages)
|
||||
:on-press #(js/alert "TODO: to be implemented, requires design input")
|
||||
:danger? false
|
||||
:accessibility-label :fetch-messages
|
||||
:sub-label nil
|
||||
:chevron? true}))
|
||||
|
||||
(defn remove-from-contacts-entry
|
||||
[contact]
|
||||
@@ -419,8 +411,8 @@
|
||||
[(mark-as-read-entry chat-id needs-divider?)
|
||||
(mute-chat-entry chat-id chat-type muted-till)
|
||||
(notifications-entry false)
|
||||
(when inside-chat?
|
||||
(fetch-messages-entry))
|
||||
(when (and config/fetch-messages-enabled? inside-chat?)
|
||||
(chat-actions/fetch-messages chat-id))
|
||||
(when (or (not group-chat) public?)
|
||||
(show-qr-entry))
|
||||
(when-not group-chat
|
||||
@@ -481,7 +473,7 @@
|
||||
constants/private-group-chat-type
|
||||
[private-group-chat-actions chat inside-chat?]
|
||||
constants/community-chat-type
|
||||
[chat-actions/actions chat inside-chat?]
|
||||
[communities-chat-actions/actions chat inside-chat?]
|
||||
nil))
|
||||
|
||||
(defn group-details-actions
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
(ns status-im2.common.standard-authentication.core
|
||||
(:require
|
||||
status-im2.common.standard-authentication.standard-auth.button.view
|
||||
status-im2.common.standard-authentication.password-input.view
|
||||
status-im2.common.standard-authentication.standard-auth.slide-button.view))
|
||||
|
||||
(def button status-im2.common.standard-authentication.standard-auth.button.view/view)
|
||||
(def password-input status-im2.common.standard-authentication.password-input.view/view)
|
||||
(def slide-button status-im2.common.standard-authentication.standard-auth.slide-button.view/view)
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn view
|
||||
[{:keys [on-enter-password button-label button-icon-left]}]
|
||||
[{:keys [on-enter-password on-press-biometrics button-label button-icon-left]}]
|
||||
(let [{:keys [key-uid customization-color] :as profile} (rf/sub [:profile/profile-with-image])
|
||||
{:keys [error processing password]} (rf/sub [:profile/login])
|
||||
sign-in-enabled? (rf/sub [:sign-in-enabled?])]
|
||||
@@ -32,20 +32,21 @@
|
||||
:customization-color customization-color
|
||||
:size 24}]]
|
||||
[password-input/view
|
||||
{:processing processing
|
||||
:error error
|
||||
:default-password password
|
||||
:sign-in-enabled? sign-in-enabled?}]
|
||||
[rn/view {:style style/enter-password-button}
|
||||
[quo/button
|
||||
{:size 40
|
||||
:type :primary
|
||||
:customization-color (or customization-color :primary)
|
||||
:accessibility-label :login-button
|
||||
:icon-left button-icon-left
|
||||
:disabled? (or (not sign-in-enabled?) processing)
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:set-in [:profile/login :key-uid] key-uid])
|
||||
(rf/dispatch [:profile.login/verify-database-password password
|
||||
#(on-enter-password password)]))}
|
||||
button-label]]]]]))
|
||||
{:on-press-biometrics on-press-biometrics
|
||||
:processing processing
|
||||
:error error
|
||||
:default-password password
|
||||
:sign-in-enabled? sign-in-enabled?}]
|
||||
[quo/button
|
||||
{:size 40
|
||||
:container-style style/enter-password-button
|
||||
:type :primary
|
||||
:customization-color (or customization-color :primary)
|
||||
:accessibility-label :login-button
|
||||
:icon-left button-icon-left
|
||||
:disabled? (or (not sign-in-enabled?) processing)
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:set-in [:profile/login :key-uid] key-uid])
|
||||
(rf/dispatch [:profile.login/verify-database-password password
|
||||
#(on-enter-password password)]))}
|
||||
button-label]]]]))
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
(ns status-im2.common.standard-authentication.events
|
||||
(:require
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/reg-event-fx :standard-auth/on-biometric-success
|
||||
(fn [{:keys [db]} [callback]]
|
||||
(let [key-uid (get-in db [:profile/profile :key-uid])]
|
||||
{:fx [[:keychain/get-user-password [key-uid callback]]]})))
|
||||
@@ -4,3 +4,7 @@
|
||||
{:margin-top 8
|
||||
:flex-direction :row
|
||||
:align-items :center})
|
||||
|
||||
(def auth-button
|
||||
{:align-self :flex-end
|
||||
:margin-left 8})
|
||||
|
||||
@@ -27,21 +27,30 @@
|
||||
(rf/dispatch [:set-in [:profile/login :error] ""]))
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [default-password theme shell?]}]
|
||||
[{:keys [default-password theme shell? on-press-biometrics]}]
|
||||
(let [{:keys [error processing]} (rf/sub [:profile/login])
|
||||
error-message (get-error-message error)
|
||||
error? (boolean (seq error-message))]
|
||||
[:<>
|
||||
[quo/input
|
||||
{:type :password
|
||||
:blur? true
|
||||
:disabled? processing
|
||||
:placeholder (i18n/label :t/type-your-password)
|
||||
:auto-focus true
|
||||
:error? error?
|
||||
:label (i18n/label :t/profile-password)
|
||||
:on-change-text on-change-password
|
||||
:default-value (security/safe-unmask-data default-password)}]
|
||||
[rn/view {:style {:flex-direction :row}}
|
||||
[quo/input
|
||||
{:container-style {:flex 1}
|
||||
:type :password
|
||||
:blur? true
|
||||
:disabled? processing
|
||||
:placeholder (i18n/label :t/type-your-password)
|
||||
:auto-focus true
|
||||
:error? error?
|
||||
:label (i18n/label :t/profile-password)
|
||||
:on-change-text on-change-password
|
||||
:default-value (security/safe-unmask-data default-password)}]
|
||||
(when on-press-biometrics
|
||||
[quo/button
|
||||
{:container-style style/auth-button
|
||||
:on-press on-press-biometrics
|
||||
:icon-only? true
|
||||
:type :outline}
|
||||
:i/face-id])]
|
||||
(when error?
|
||||
[rn/view {:style style/error-message}
|
||||
[quo/info-message
|
||||
@@ -60,10 +69,7 @@
|
||||
:shell? shell?}]))}
|
||||
[rn/text
|
||||
{:style {:text-decoration-line :underline
|
||||
:color (colors/theme-colors
|
||||
(colors/custom-color :danger 50)
|
||||
(colors/custom-color :danger 60)
|
||||
theme)}
|
||||
:color (colors/resolve-color :danger theme)}
|
||||
:size :paragraph-2
|
||||
:suppress-highlighting true}
|
||||
(i18n/label :t/forgot-password)]]])]))
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
(ns status-im2.common.standard-authentication.standard-auth.authorize
|
||||
(:require
|
||||
[native-module.core :as native-module]
|
||||
[react-native.touch-id :as biometric]
|
||||
[status-im2.common.standard-authentication.enter-password.view :as enter-password]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
[utils.re-frame :as rf]
|
||||
[utils.security.core :as security]))
|
||||
|
||||
(defn reset-password
|
||||
[]
|
||||
@@ -12,33 +14,49 @@
|
||||
(rf/dispatch [:set-in [:profile/login :error] ""]))
|
||||
|
||||
(defn authorize
|
||||
[{:keys [on-enter-password biometric-auth? on-auth-success on-auth-fail on-close
|
||||
[{:keys [biometric-auth? on-auth-success on-auth-fail on-close
|
||||
auth-button-label theme blur? auth-button-icon-left]}]
|
||||
(biometric/get-supported-type
|
||||
(fn [biometric-type]
|
||||
(if (and biometric-auth? biometric-type)
|
||||
(biometric/authenticate
|
||||
{:reason (i18n/label :t/biometric-auth-confirm-message)
|
||||
:on-success (fn [response]
|
||||
(when on-auth-success (on-auth-success response))
|
||||
(log/info "response" response))
|
||||
:on-fail (fn [error]
|
||||
(log/error "Authentication Failed. Error:" error)
|
||||
(when on-auth-fail (on-auth-fail error))
|
||||
(rf/dispatch [:show-bottom-sheet
|
||||
{:theme theme
|
||||
:shell? blur?
|
||||
:content (fn []
|
||||
[enter-password/view
|
||||
{:on-enter-password on-enter-password}])}]))})
|
||||
(do
|
||||
(reset-password)
|
||||
(rf/dispatch [:show-bottom-sheet
|
||||
{:on-close on-close
|
||||
:theme theme
|
||||
:shell? blur?
|
||||
:content (fn []
|
||||
[enter-password/view
|
||||
{:on-enter-password on-enter-password
|
||||
:button-icon-left auth-button-icon-left
|
||||
:button-label auth-button-label}])}]))))))
|
||||
(let [handle-auth-success (fn [biometric?]
|
||||
(fn [entered-password]
|
||||
(let [sha3-pwd (if biometric?
|
||||
(str (security/safe-unmask-data entered-password))
|
||||
(native-module/sha3 (str (security/safe-unmask-data
|
||||
entered-password))))]
|
||||
(on-auth-success sha3-pwd))))
|
||||
password-login (fn [{:keys [on-press-biometrics]}]
|
||||
(rf/dispatch [:show-bottom-sheet
|
||||
{:on-close on-close
|
||||
:theme theme
|
||||
:shell? blur?
|
||||
:content (fn []
|
||||
[enter-password/view
|
||||
{:on-enter-password (handle-auth-success
|
||||
false)
|
||||
:on-press-biometrics on-press-biometrics
|
||||
:button-icon-left auth-button-icon-left
|
||||
:button-label auth-button-label}])}]))
|
||||
; biometrics-login recursively passes itself as a parameter because if the user
|
||||
; fails biometric auth they will be shown the password bottom sheet with an option
|
||||
; to retrigger biometric auth, so they can endlessly repeat this cycle.
|
||||
biometrics-login (fn [on-press-biometrics]
|
||||
(rf/dispatch [:dismiss-keyboard])
|
||||
(biometric/authenticate
|
||||
{:reason (i18n/label :t/biometric-auth-confirm-message)
|
||||
:on-success (fn [_response]
|
||||
(on-close)
|
||||
(rf/dispatch [:standard-auth/on-biometric-success
|
||||
(handle-auth-success true)]))
|
||||
:on-fail (fn [error]
|
||||
(on-close)
|
||||
(log/error "Authentication Failed. Error:" error)
|
||||
(when on-auth-fail (on-auth-fail error))
|
||||
(password-login {:on-press-biometrics
|
||||
#(on-press-biometrics
|
||||
on-press-biometrics)}))}))]
|
||||
(biometric/get-supported-type
|
||||
(fn [biometric-type]
|
||||
(if (and biometric-auth? biometric-type)
|
||||
(biometrics-login biometrics-login)
|
||||
(do
|
||||
(reset-password)
|
||||
(password-login {})))))))
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
(ns status-im2.common.standard-authentication.standard-auth.button.view
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[quo.theme :as quo.theme]
|
||||
[reagent.core :as reagent]
|
||||
[status-im2.common.standard-authentication.standard-auth.authorize :as authorize]))
|
||||
|
||||
(defn- view-internal
|
||||
[_]
|
||||
(let [reset-slider? (reagent/atom false)
|
||||
on-close #(reset! reset-slider? true)]
|
||||
(fn [{:keys [biometric-auth?
|
||||
customization-color
|
||||
auth-button-label
|
||||
on-enter-password
|
||||
on-auth-success
|
||||
on-press
|
||||
on-auth-fail
|
||||
auth-button-icon-left
|
||||
size
|
||||
button-label
|
||||
theme
|
||||
blur?
|
||||
container-style
|
||||
icon-left]}]
|
||||
[quo/button
|
||||
{:size size
|
||||
:container-style container-style
|
||||
:customization-color customization-color
|
||||
:icon-left icon-left
|
||||
:on-press (if on-press
|
||||
on-press
|
||||
#(authorize/authorize {:on-close on-close
|
||||
:auth-button-icon-left auth-button-icon-left
|
||||
:theme theme
|
||||
:blur? blur?
|
||||
:on-enter-password on-enter-password
|
||||
:biometric-auth? biometric-auth?
|
||||
:on-auth-success on-auth-success
|
||||
:on-auth-fail on-auth-fail
|
||||
:auth-button-label auth-button-label}))}
|
||||
button-label])))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
@@ -4,17 +4,21 @@
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[status-im2.common.standard-authentication.standard-auth.authorize :as authorize]))
|
||||
[status-im2.common.standard-authentication.standard-auth.authorize :as authorize]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- view-internal
|
||||
[_]
|
||||
(let [reset-slider? (reagent/atom false)
|
||||
on-close #(reset! reset-slider? true)]
|
||||
(fn [{:keys [biometric-auth?
|
||||
track-text
|
||||
(let [reset-slider? (reagent/atom false)
|
||||
on-close (fn []
|
||||
(js/setTimeout
|
||||
#(reset! reset-slider? true)
|
||||
200))
|
||||
auth-method (rf/sub [:auth-method])
|
||||
biometric-auth? (= auth-method "biometric")]
|
||||
(fn [{:keys [track-text
|
||||
customization-color
|
||||
auth-button-label
|
||||
on-enter-password
|
||||
on-auth-success
|
||||
on-auth-fail
|
||||
auth-button-icon-left
|
||||
@@ -32,7 +36,6 @@
|
||||
:auth-button-icon-left auth-button-icon-left
|
||||
:theme theme
|
||||
:blur? blur?
|
||||
:on-enter-password on-enter-password
|
||||
:biometric-auth? biometric-auth?
|
||||
:on-auth-success on-auth-success
|
||||
:on-auth-fail on-auth-fail
|
||||
|
||||
@@ -172,3 +172,4 @@
|
||||
(def shell-navigation-disabled? false)
|
||||
|
||||
(def community-accounts-selection-enabled? false)
|
||||
(def fetch-messages-enabled? (enabled? (get-config :FETCH_MESSAGES_ENABLED "1")))
|
||||
|
||||
@@ -390,3 +390,6 @@
|
||||
(def ^:const account-default-customization-color :blue)
|
||||
|
||||
(def ^:const wallet-account-name-max-length 20)
|
||||
|
||||
(def ^:const status-address-domain ".stateofus.eth")
|
||||
(def ^:const eth-address-domain ".eth")
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
(ns status-im2.contexts.add-new-contact.events-test
|
||||
(:require
|
||||
[cljs.test :refer-macros [deftest are]]
|
||||
matcher-combinators.test
|
||||
[status-im2.contexts.add-new-contact.events :as events]))
|
||||
|
||||
(def user-ukey
|
||||
@@ -18,10 +19,10 @@
|
||||
;;; unit tests (no app-db involved)
|
||||
|
||||
(deftest validate-contact-test
|
||||
(are [i e] (= (events/validate-contact (events/init-contact
|
||||
{:user-public-key user-ukey
|
||||
:input i}))
|
||||
(events/init-contact e))
|
||||
(are [i e] (match? (events/validate-contact (events/init-contact
|
||||
{:user-public-key user-ukey
|
||||
:input i}))
|
||||
(events/init-contact e))
|
||||
|
||||
"" {:user-public-key user-ukey
|
||||
:input ""
|
||||
@@ -90,7 +91,7 @@
|
||||
|
||||
(deftest set-new-identity-test
|
||||
(with-redefs [events/dispatcher (fn [& args] args)]
|
||||
(are [i edb] (= (events/set-new-identity {:db db} i nil) edb)
|
||||
(are [i edb] (match? (events/set-new-identity {:db db} i nil) edb)
|
||||
|
||||
"" {:db db}
|
||||
|
||||
|
||||
@@ -4,6 +4,19 @@
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn fetch-messages!
|
||||
[chat-id]
|
||||
(rf/dispatch [:hide-bottom-sheet])
|
||||
(rf/dispatch [:chat/fetch-messages chat-id]))
|
||||
|
||||
(defn fetch-messages
|
||||
[chat-id]
|
||||
{:icon :i/download
|
||||
:right-icon :i/chevron-right
|
||||
:accessibility-label :chat-fetch-messages
|
||||
:on-press (partial fetch-messages! chat-id)
|
||||
:label (i18n/label :t/fetch-messages)})
|
||||
|
||||
(defn new-chat
|
||||
[]
|
||||
[quo/action-drawer
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
(ns status-im2.contexts.chat.composer.link-preview.events-test
|
||||
(:require
|
||||
[cljs.test :refer [deftest is testing]]
|
||||
matcher-combinators.test
|
||||
[status-im2.contexts.chat.composer.link-preview.events :as events]))
|
||||
|
||||
(def url-github "https://github.com")
|
||||
@@ -20,17 +21,17 @@
|
||||
(let [cofx {:db {:chat/link-previews {:unfurled {}
|
||||
:cache {}
|
||||
:request-id "123"}}}]
|
||||
(is (= {:db {:chat/link-previews {:cache {}}}}
|
||||
(events/unfurl-urls cofx " ")))))
|
||||
(is (match? {:db {:chat/link-previews {:cache {}}}}
|
||||
(events/unfurl-urls cofx " ")))))
|
||||
|
||||
(testing "fetches parsed URLs"
|
||||
(let [cofx {:db {:chat/link-previews {:unfurled {}
|
||||
:cache {}
|
||||
:request-id "123"}}}]
|
||||
(is (= {:json-rpc/call [{:method "wakuext_getTextURLs"
|
||||
:params [url-github]}]}
|
||||
(remove-rpc-callbacks
|
||||
(events/unfurl-urls cofx url-github)))))))
|
||||
(is (match? {:json-rpc/call [{:method "wakuext_getTextURLs"
|
||||
:params [url-github]}]}
|
||||
(remove-rpc-callbacks
|
||||
(events/unfurl-urls cofx url-github)))))))
|
||||
|
||||
(deftest unfurl-parsed-urls-test
|
||||
(with-redefs [events/new-request-id (constantly request-id)]
|
||||
@@ -38,30 +39,30 @@
|
||||
(let [cofx {:db {:chat/link-previews
|
||||
{:cache {}
|
||||
:unfurled []}}}]
|
||||
(is (= {:db {:chat/link-previews
|
||||
{:request-id request-id
|
||||
:cache {}
|
||||
:unfurled [{:url url-github :loading? true}
|
||||
{:url url-gitlab :loading? true}]}}
|
||||
:json-rpc/call [{:method "wakuext_unfurlURLs"
|
||||
:params [[url-github url-gitlab]]}]}
|
||||
(remove-rpc-callbacks
|
||||
(events/unfurl-parsed-urls cofx [url-github url-gitlab]))))))
|
||||
(is (match? {:db {:chat/link-previews
|
||||
{:request-id request-id
|
||||
:cache {}
|
||||
:unfurled [{:url url-github :loading? true}
|
||||
{:url url-gitlab :loading? true}]}}
|
||||
:json-rpc/call [{:method "wakuext_unfurlURLs"
|
||||
:params [[url-github url-gitlab]]}]}
|
||||
(remove-rpc-callbacks
|
||||
(events/unfurl-parsed-urls cofx [url-github url-gitlab]))))))
|
||||
|
||||
(testing "nothing unfurled, 1 cached URL and the other stale"
|
||||
(let [cache {url-github preview-github}
|
||||
cofx {:db {:chat/link-previews
|
||||
{:cache cache
|
||||
:unfurled []}}}]
|
||||
(is (= {:db {:chat/link-previews
|
||||
{:request-id request-id
|
||||
:cache cache
|
||||
:unfurled [preview-github
|
||||
{:url url-gitlab :loading? true}]}}
|
||||
:json-rpc/call [{:method "wakuext_unfurlURLs"
|
||||
:params [[url-gitlab]]}]}
|
||||
(remove-rpc-callbacks
|
||||
(events/unfurl-parsed-urls cofx [url-github url-gitlab]))))))
|
||||
(is (match? {:db {:chat/link-previews
|
||||
{:request-id request-id
|
||||
:cache cache
|
||||
:unfurled [preview-github
|
||||
{:url url-gitlab :loading? true}]}}
|
||||
:json-rpc/call [{:method "wakuext_unfurlURLs"
|
||||
:params [[url-gitlab]]}]}
|
||||
(remove-rpc-callbacks
|
||||
(events/unfurl-parsed-urls cofx [url-github url-gitlab]))))))
|
||||
|
||||
(testing "does nothing when the URLs are identical to the last cleared ones"
|
||||
(let [cofx {:db {:chat/link-previews
|
||||
@@ -75,24 +76,24 @@
|
||||
cofx {:db {:chat/link-previews
|
||||
{:cache cache
|
||||
:unfurled [preview-github]}}}]
|
||||
(is (= {:db {:chat/link-previews
|
||||
{:request-id request-id
|
||||
:cache cache
|
||||
:unfurled []}}}
|
||||
(remove-rpc-callbacks
|
||||
(events/unfurl-parsed-urls cofx []))))))
|
||||
(is (match? {:db {:chat/link-previews
|
||||
{:request-id request-id
|
||||
:cache cache
|
||||
:unfurled []}}}
|
||||
(remove-rpc-callbacks
|
||||
(events/unfurl-parsed-urls cofx []))))))
|
||||
|
||||
(testing "2 unfurled, 2 cached URLs"
|
||||
(let [cache {url-github preview-github url-gitlab preview-gitlab}
|
||||
cofx {:db {:chat/link-previews
|
||||
{:cache cache
|
||||
:unfurled [preview-github preview-gitlab]}}}]
|
||||
(is (= {:db {:chat/link-previews
|
||||
{:request-id request-id
|
||||
:cache cache
|
||||
:unfurled [preview-github preview-gitlab]}}}
|
||||
(remove-rpc-callbacks
|
||||
(events/unfurl-parsed-urls cofx [url-github url-gitlab]))))))
|
||||
(is (match? {:db {:chat/link-previews
|
||||
{:request-id request-id
|
||||
:cache cache
|
||||
:unfurled [preview-github preview-gitlab]}}}
|
||||
(remove-rpc-callbacks
|
||||
(events/unfurl-parsed-urls cofx [url-github url-gitlab]))))))
|
||||
|
||||
(testing "1 unfurled, 1 successful in the cache, 1 failed in the cache"
|
||||
(let [cache {url-github preview-github
|
||||
@@ -100,25 +101,25 @@
|
||||
cofx {:db {:chat/link-previews
|
||||
{:cache cache
|
||||
:unfurled [preview-github]}}}]
|
||||
(is (= {:db {:chat/link-previews
|
||||
{:request-id request-id
|
||||
:cache cache
|
||||
:unfurled [preview-github]}}}
|
||||
(events/unfurl-parsed-urls cofx [url-github url-gitlab])))))
|
||||
(is (match? {:db {:chat/link-previews
|
||||
{:request-id request-id
|
||||
:cache cache
|
||||
:unfurled [preview-github]}}}
|
||||
(events/unfurl-parsed-urls cofx [url-github url-gitlab])))))
|
||||
|
||||
(testing "nothing unfurled, 1 failed in the cache"
|
||||
(let [cache {url-gitlab (assoc preview-gitlab :failed? true)}
|
||||
cofx {:db {:chat/link-previews
|
||||
{:cache cache
|
||||
:unfurled []}}}]
|
||||
(is (= {:db {:chat/link-previews
|
||||
{:request-id request-id
|
||||
:cache cache
|
||||
:unfurled [{:url url-github :loading? true}]}}
|
||||
:json-rpc/call [{:method "wakuext_unfurlURLs"
|
||||
:params [[url-github]]}]}
|
||||
(remove-rpc-callbacks
|
||||
(events/unfurl-parsed-urls cofx [url-github url-gitlab]))))))
|
||||
(is (match? {:db {:chat/link-previews
|
||||
{:request-id request-id
|
||||
:cache cache
|
||||
:unfurled [{:url url-github :loading? true}]}}
|
||||
:json-rpc/call [{:method "wakuext_unfurlURLs"
|
||||
:params [[url-github]]}]}
|
||||
(remove-rpc-callbacks
|
||||
(events/unfurl-parsed-urls cofx [url-github url-gitlab]))))))
|
||||
|
||||
(testing "empties unfurled collection when there are no valid previews"
|
||||
(let [unknown-url "https://github.abcdef"
|
||||
@@ -127,12 +128,12 @@
|
||||
cofx {:db {:chat/link-previews
|
||||
{:cache cache
|
||||
:unfurled [preview-github]}}}]
|
||||
(is (= {:db {:chat/link-previews
|
||||
{:request-id request-id
|
||||
:cache cache
|
||||
:unfurled []}}}
|
||||
(remove-rpc-callbacks
|
||||
(events/unfurl-parsed-urls cofx [unknown-url]))))))))
|
||||
(is (match? {:db {:chat/link-previews
|
||||
{:request-id request-id
|
||||
:cache cache
|
||||
:unfurled []}}}
|
||||
(remove-rpc-callbacks
|
||||
(events/unfurl-parsed-urls cofx [unknown-url]))))))))
|
||||
|
||||
(deftest unfurl-parsed-urls-success-test
|
||||
(testing "does nothing if the success request-id is different than the current one"
|
||||
@@ -152,12 +153,12 @@
|
||||
cofx
|
||||
request-id
|
||||
{:linkPreviews [preview-gitlab]})]
|
||||
(is (= {:chat/link-previews
|
||||
{:request-id request-id
|
||||
:unfurled [preview-github preview-gitlab]
|
||||
:cache {url-github preview-github
|
||||
url-gitlab preview-gitlab}}}
|
||||
db))))
|
||||
(is (match? {:chat/link-previews
|
||||
{:request-id request-id
|
||||
:unfurled [preview-github preview-gitlab]
|
||||
:cache {url-github preview-github
|
||||
url-gitlab preview-gitlab}}}
|
||||
db))))
|
||||
|
||||
(testing "identify and write failed preview in the cache"
|
||||
(let [preview-youtube {:url "https://youtube.com" :thumbnail nil}
|
||||
@@ -172,13 +173,13 @@
|
||||
request-id
|
||||
{:linkPreviews [preview-github
|
||||
preview-youtube]})]
|
||||
(is (= {:chat/link-previews
|
||||
{:request-id request-id
|
||||
:unfurled [preview-github preview-youtube]
|
||||
:cache {(:url preview-youtube) preview-youtube
|
||||
url-github preview-github
|
||||
url-gitlab {:url "https://gitlab.com" :failed? true}}}}
|
||||
db)))))
|
||||
(is (match? {:chat/link-previews
|
||||
{:request-id request-id
|
||||
:unfurled [preview-github preview-youtube]
|
||||
:cache {(:url preview-youtube) preview-youtube
|
||||
url-github preview-github
|
||||
url-gitlab {:url "https://gitlab.com" :failed? true}}}}
|
||||
db)))))
|
||||
|
||||
(deftest clear-link-previews-test
|
||||
(let [cache {url-github preview-github}
|
||||
@@ -186,22 +187,22 @@
|
||||
{:db {:chat/link-previews {:unfurled [preview-github]
|
||||
:request-id request-id
|
||||
:cache cache}}})]
|
||||
(is (= {:db {:chat/link-previews {:cache cache
|
||||
:cleared #{url-github}}}}
|
||||
effects))))
|
||||
(is (match? {:db {:chat/link-previews {:cache cache
|
||||
:cleared #{url-github}}}}
|
||||
effects))))
|
||||
|
||||
(deftest reset-unfurled-test
|
||||
(let [cache {url-github preview-github}]
|
||||
(is (= {:db {:chat/link-previews {:cache cache}}}
|
||||
(events/reset-unfurled
|
||||
{:db {:chat/link-previews {:unfurled [preview-github]
|
||||
:request-id request-id
|
||||
:cleared #{url-github}
|
||||
:cache cache}}})))))
|
||||
(is (match? {:db {:chat/link-previews {:cache cache}}}
|
||||
(events/reset-unfurled
|
||||
{:db {:chat/link-previews {:unfurled [preview-github]
|
||||
:request-id request-id
|
||||
:cleared #{url-github}
|
||||
:cache cache}}})))))
|
||||
|
||||
(deftest reset-all-test
|
||||
(is (= {:db {:non-related-key :some-value}}
|
||||
(events/reset-all
|
||||
{:db {:non-related-key :some-value
|
||||
:chat/link-previews {:request-id request-id
|
||||
:any-other-key "farewell"}}}))))
|
||||
(is (match? {:db {:non-related-key :some-value}}
|
||||
(events/reset-all
|
||||
{:db {:non-related-key :some-value
|
||||
:chat/link-previews {:request-id request-id
|
||||
:any-other-key "farewell"}}}))))
|
||||
|
||||
@@ -434,3 +434,11 @@
|
||||
{:events [:chat/check-last-chat]}
|
||||
[{:keys [db]}]
|
||||
{:effects.chat/open-last-chat (get-in db [:profile/profile :key-uid])})
|
||||
|
||||
(rf/defn fetch-messages
|
||||
{:events [:chat/fetch-messages]}
|
||||
[_ chat-id]
|
||||
{:json-rpc/call [{:method "wakuext_fetchMessages"
|
||||
:params [{:id chat-id}]
|
||||
:on-success #()
|
||||
:on-error #(log/error "failed to fetch messages for chat" chat-id %)}]})
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
(close))
|
||||
|
||||
(defn confirm-button
|
||||
[selected-images sending-image close]
|
||||
[{:keys [selected-images sending-image close customization-color]}]
|
||||
(when (not= selected-images sending-image)
|
||||
[linear-gradient/linear-gradient
|
||||
{:colors [:black :transparent]
|
||||
@@ -43,7 +43,8 @@
|
||||
:end {:x 0 :y 0}
|
||||
:style (style/gradient-container (safe-area/get-bottom))}
|
||||
[quo/button
|
||||
{:container-style {:align-self :stretch
|
||||
{:customization-color customization-color
|
||||
:container-style {:align-self :stretch
|
||||
:margin-horizontal 20
|
||||
:margin-top 12}
|
||||
:on-press #(on-press-confirm-selection selected-images close)
|
||||
@@ -94,10 +95,11 @@
|
||||
[{:keys [scroll-enabled on-scroll current-scroll close] :as sheet}]
|
||||
(rf/dispatch [:photo-selector/get-photos-for-selected-album])
|
||||
(rf/dispatch [:photo-selector/camera-roll-get-albums])
|
||||
(let [album? (reagent/atom false)
|
||||
sending-image (into [] (vals (rf/sub [:chats/sending-image])))
|
||||
selected-images (reagent/atom sending-image)
|
||||
window-width (:width (rn/get-window))]
|
||||
(let [album? (reagent/atom false)
|
||||
customization-color (rf/sub [:profile/customization-color])
|
||||
sending-image (into [] (vals (rf/sub [:chats/sending-image])))
|
||||
selected-images (reagent/atom sending-image)
|
||||
window-width (:width (rn/get-window))]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [camera-roll-photos (rf/sub [:camera-roll/photos])
|
||||
@@ -140,7 +142,11 @@
|
||||
(rf/dispatch [:photo-selector/camera-roll-loading-more true])
|
||||
(rf/dispatch [:photo-selector/get-photos-for-selected-album
|
||||
end-cursor])))}]
|
||||
[confirm-button @selected-images sending-image close]]
|
||||
[confirm-button
|
||||
{:close close
|
||||
:customization-color customization-color
|
||||
:selected-images @selected-images
|
||||
:sending-image sending-image}]]
|
||||
[rn/view {:style style/buttons-container}
|
||||
[quo/dropdown
|
||||
{:type dropdown-type
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
(ns status-im2.contexts.communities.actions.accounts-selection.style
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]))
|
||||
|
||||
(def screen-horizontal-padding 20)
|
||||
|
||||
(def container
|
||||
{:flex 1})
|
||||
|
||||
(def page-top
|
||||
{:padding-vertical 12
|
||||
:padding-horizontal screen-horizontal-padding})
|
||||
|
||||
(def content
|
||||
{:margin-bottom 20
|
||||
:padding-horizontal screen-horizontal-padding})
|
||||
|
||||
(defn bottom-actions
|
||||
[]
|
||||
{:position :absolute
|
||||
:background-color (colors/theme-colors colors/white colors/neutral-95)
|
||||
:bottom 0
|
||||
:left 0
|
||||
:right 0
|
||||
:padding-horizontal screen-horizontal-padding
|
||||
:padding-vertical 12
|
||||
:flex 1})
|
||||
@@ -4,11 +4,12 @@
|
||||
[react-native.core :as rn]
|
||||
[react-native.gesture :as gesture]
|
||||
[status-im2.common.password-authentication.view :as password-authentication]
|
||||
[status-im2.contexts.communities.actions.request-to-join.style :as style]
|
||||
[status-im2.contexts.communities.actions.accounts-selection.style :as style]
|
||||
[status-im2.contexts.communities.actions.community-rules.view :as community-rules]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn join-community-and-navigate-back
|
||||
(defn- join-community-and-navigate-back
|
||||
[id]
|
||||
(rf/dispatch [:password-authentication/show
|
||||
{:content (fn [] [password-authentication/view])}
|
||||
@@ -17,24 +18,46 @@
|
||||
{:community-id id :password %}])}])
|
||||
(rf/dispatch [:navigate-back]))
|
||||
|
||||
(defn- page-top
|
||||
[{:keys [community-name logo-uri]}]
|
||||
[rn/view {:style style/page-top}
|
||||
[quo/text
|
||||
{:size :heading-1
|
||||
:weight :semi-bold}
|
||||
(i18n/label :t/request-to-join)]
|
||||
[quo/context-tag
|
||||
{:type :community
|
||||
:size 24
|
||||
:community-logo logo-uri
|
||||
:community-name community-name
|
||||
:container-style {:margin-top 8}}]])
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(fn []
|
||||
(let [{:keys [_name
|
||||
id
|
||||
_images]} (rf/sub [:get-screen-params])]
|
||||
[rn/view {:flex 1}
|
||||
[gesture/scroll-view {:style {:flex 1}}
|
||||
[rn/view style/page-container
|
||||
[rn/view {:style (style/bottom-container)}
|
||||
[quo/button
|
||||
{:accessibility-label :cancel
|
||||
:on-press #(rf/dispatch [:navigate-back])
|
||||
:type :grey
|
||||
:container-style style/cancel-button}
|
||||
(i18n/label :t/cancel)]
|
||||
[quo/button
|
||||
{:accessibility-label :join-community-button
|
||||
:on-press #(join-community-and-navigate-back id)
|
||||
:container-style {:flex 1}}
|
||||
(i18n/label :t/request-to-join)]]]]])))
|
||||
(let [{id :community-id} (rf/sub [:get-screen-params])
|
||||
{:keys [name color images]} (rf/sub [:communities/community id])]
|
||||
[rn/view {:style style/container}
|
||||
[quo/page-nav
|
||||
{:text-align :left
|
||||
:icon-name :i/close
|
||||
:on-press #(rf/dispatch [:navigate-back])
|
||||
:accessibility-label :back-button}]
|
||||
[page-top
|
||||
{:community-name name
|
||||
:logo-uri (get-in images [:thumbnail :uri])}]
|
||||
[gesture/scroll-view
|
||||
[rn/view {:style style/content}
|
||||
[quo/text
|
||||
{:style {:margin-top 24}
|
||||
:accessibility-label :community-rules-title
|
||||
:weight :semi-bold
|
||||
:size :paragraph-1}
|
||||
(i18n/label :t/community-rules)]
|
||||
[community-rules/view id]]]
|
||||
[rn/view {:style (style/bottom-actions)}
|
||||
[quo/slide-button
|
||||
{:size :size-48
|
||||
:track-text (i18n/label :t/slide-to-request-to-join)
|
||||
:track-icon :i/face-id
|
||||
:customization-color color
|
||||
:on-complete #(join-community-and-navigate-back id)}]]]))
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
[status-im2.common.mute-drawer.view :as mute-drawer]
|
||||
[status-im2.common.muting.helpers :refer [format-mute-till]]
|
||||
[status-im2.common.not-implemented :as not-implemented]
|
||||
[status-im2.config :as config]
|
||||
[status-im2.contexts.chat.actions.view :as chat-actions]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
@@ -83,13 +85,6 @@
|
||||
:on-press not-implemented/alert
|
||||
:label (i18n/label :t/pinned-messages)})
|
||||
|
||||
(defn- action-fetch-messages
|
||||
[]
|
||||
{:icon :i/download
|
||||
:right-icon :i/chevron-right
|
||||
:accessibility-label :chat-fetch-messages
|
||||
:on-press not-implemented/alert
|
||||
:label (i18n/label :t/fetch-messages)})
|
||||
|
||||
(defn- action-invite-people
|
||||
[]
|
||||
@@ -141,7 +136,8 @@
|
||||
(action-mark-as-read)
|
||||
(action-toggle-muted chat-id muted muted-till chat-type)
|
||||
(action-notification-settings)
|
||||
(action-fetch-messages)
|
||||
(when config/fetch-messages-enabled?
|
||||
(chat-actions/fetch-messages chat-id))
|
||||
(action-invite-people)
|
||||
(action-qr-code)
|
||||
(action-share)]]]
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
(ns status-im2.contexts.communities.actions.community-rules.style)
|
||||
|
||||
(def community-rule
|
||||
{:flex 1
|
||||
:align-items :flex-start
|
||||
:margin-top 16})
|
||||
|
||||
(def community-rule-text
|
||||
{:margin-left 6
|
||||
:flex 1})
|
||||
@@ -0,0 +1,16 @@
|
||||
(ns status-im2.contexts.communities.actions.community-rules.view
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[status-im2.contexts.communities.actions.community-rules.style :as style]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn view
|
||||
[id]
|
||||
(let [rules (rf/sub [:communities/rules id])]
|
||||
[rn/view {:style style/community-rule}
|
||||
[quo/text
|
||||
{:style style/community-rule-text
|
||||
:weight :regular
|
||||
:size :paragraph-2}
|
||||
rules]]))
|
||||
@@ -1,6 +1,7 @@
|
||||
(ns status-im2.contexts.communities.discover.events-test
|
||||
(:require
|
||||
[cljs.test :refer-macros [deftest are]]
|
||||
matcher-combinators.test
|
||||
[status-im2.contexts.communities.discover.events :as events]))
|
||||
|
||||
(deftest rename-contract-community-key-test
|
||||
@@ -13,7 +14,7 @@
|
||||
:3f9e77b8-97c7 "3f9e77b8-97c7"))
|
||||
|
||||
(deftest rename-contract-community-keys-test
|
||||
(are [i e] (= (events/rename-contract-community-keys i) e)
|
||||
(are [i e] (match? (events/rename-contract-community-keys i) e)
|
||||
|
||||
{:contractCommunities
|
||||
["0x032aa2439b14eb2caaf724223951da89de1530fbfa5d5a639b93b82cd5341713fd"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
(ns status-im2.contexts.communities.overview.events-test
|
||||
(:require [cljs.test :refer [deftest is]]
|
||||
matcher-combinators.test
|
||||
[native-module.core :as native-module]
|
||||
[status-im2.contexts.communities.overview.events :as sut]))
|
||||
|
||||
@@ -14,10 +15,10 @@
|
||||
:params [account-pub-key community-id []]
|
||||
:on-success [:communities/sign-data community-id password]
|
||||
:on-error [:communities/requested-to-join-error community-id]}]]]}]
|
||||
(is (= expected
|
||||
(sut/request-to-join cofx
|
||||
[{:community-id community-id
|
||||
:password password}])))))
|
||||
(is (match? expected
|
||||
(sut/request-to-join cofx
|
||||
[{:community-id community-id
|
||||
:password password}])))))
|
||||
|
||||
(deftest sign-data-test
|
||||
(let [cofx {:db {}}
|
||||
@@ -32,8 +33,8 @@
|
||||
:on-success [:communities/request-to-join-with-signatures
|
||||
community-id addresses-to-reveal]
|
||||
:on-error [:communities/requested-to-join-error community-id]}]]]}]
|
||||
(is (= expected
|
||||
(sut/sign-data cofx [community-id password sign-params])))))
|
||||
(is (match? expected
|
||||
(sut/sign-data cofx [community-id password sign-params])))))
|
||||
|
||||
(deftest request-to-join-with-signatures-test
|
||||
(let [cofx {:db {}}
|
||||
@@ -49,5 +50,6 @@
|
||||
:on-success [:communities/requested-to-join]
|
||||
:on-error [:communities/requested-to-join-error
|
||||
community-id]}]]]}]
|
||||
(is (= expected
|
||||
(sut/request-to-join-with-signatures cofx [community-id addresses-to-reveal signatures])))))
|
||||
(is (match? expected
|
||||
(sut/request-to-join-with-signatures cofx
|
||||
[community-id addresses-to-reveal signatures])))))
|
||||
|
||||
@@ -173,7 +173,7 @@
|
||||
(i18n/label :t/join-open-community)]])))
|
||||
|
||||
(defn join-community
|
||||
[{:keys [joined color permissions token-permissions] :as community}
|
||||
[{:keys [joined color permissions token-permissions id] :as community}
|
||||
pending?]
|
||||
(let [access-type (get-access-type (:access permissions))
|
||||
unknown-access? (= access-type :unknown-access)
|
||||
@@ -185,7 +185,7 @@
|
||||
[quo/button
|
||||
{:on-press
|
||||
(if config/community-accounts-selection-enabled?
|
||||
#(rf/dispatch [:open-modal :community-account-selection community])
|
||||
#(rf/dispatch [:open-modal :community-account-selection {:community-id id}])
|
||||
#(rf/dispatch [:open-modal :community-requests-to-join community]))
|
||||
|
||||
:accessibility-label :show-request-to-join-screen-button
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
[status-im2.common.parallax.view :as parallax]
|
||||
[status-im2.common.parallax.whitelist :as whitelist]
|
||||
[status-im2.common.resources :as resources]
|
||||
[status-im2.common.standard-authentication.core :as standard-auth]
|
||||
[status-im2.contexts.onboarding.enable-biometrics.style :as style]
|
||||
[status-im2.navigation.state :as state]
|
||||
[utils.i18n :as i18n]
|
||||
@@ -31,13 +30,13 @@
|
||||
(rf/sub [:profile/customization-color]))
|
||||
syncing-results? (= :syncing-results @state/root-id)]
|
||||
[rn/view {:style (style/buttons insets)}
|
||||
[standard-auth/button
|
||||
[quo/button
|
||||
{:size 40
|
||||
:accessibility-label :enable-biometrics-button
|
||||
:icon-left :i/face-id
|
||||
:customization-color profile-color
|
||||
:on-press #(rf/dispatch [:onboarding/enable-biometrics])
|
||||
:button-label (i18n/label :t/biometric-enable-button {:bio-type-label bio-type-label})}]
|
||||
:on-press #(rf/dispatch [:onboarding/enable-biometrics])}
|
||||
(i18n/label :t/biometric-enable-button {:bio-type-label bio-type-label})]
|
||||
[quo/button
|
||||
{:accessibility-label :maybe-later-button
|
||||
:background :blur
|
||||
|
||||
@@ -133,13 +133,18 @@
|
||||
{:db (dissoc db :onboarding/profile)
|
||||
:dispatch [:navigate-to-within-stack [:create-profile :new-to-status]]})
|
||||
|
||||
(rf/reg-event-fx :onboarding/set-auth-method
|
||||
(fn [{:keys [db]} [auth-method]]
|
||||
{:db (assoc db :auth-method auth-method)}))
|
||||
|
||||
(rf/defn onboarding-new-account-finalize-setup
|
||||
{:events [:onboarding/finalize-setup]}
|
||||
[{:keys [db]}]
|
||||
(let [masked-password (get-in db [:onboarding/profile :password])
|
||||
key-uid (get-in db [:profile/profile :key-uid])
|
||||
syncing? (get-in db [:onboarding/profile :syncing?])
|
||||
biometric-enabled? (= (get-in db [:onboarding/profile :auth-method])
|
||||
auth-method (get-in db [:onboarding/profile :auth-method])
|
||||
biometric-enabled? (= auth-method
|
||||
constants/auth-method-biometric)]
|
||||
(cond-> {:db (assoc db :onboarding/generated-keys? true)}
|
||||
biometric-enabled?
|
||||
@@ -149,9 +154,9 @@
|
||||
masked-password
|
||||
(security/hash-masked-password masked-password))
|
||||
:on-success (fn []
|
||||
(if syncing?
|
||||
(rf/dispatch [:onboarding/navigate-to-enable-notifications])
|
||||
(log/error "successfully saved biometrics")))
|
||||
(rf/dispatch [:onboarding/set-auth-method auth-method])
|
||||
(when syncing?
|
||||
(rf/dispatch [:onboarding/navigate-to-enable-notifications])))
|
||||
:on-error #(log/error "failed to save biometrics"
|
||||
{:key-uid key-uid
|
||||
:error %})}))))
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
(ns status-im2.contexts.profile.create.events
|
||||
(:require
|
||||
[native-module.core :as native-module]
|
||||
[status-im2.contexts.emoji-picker.utils :as emoji-picker.utils]
|
||||
[status-im2.contexts.profile.config :as profile.config]
|
||||
status-im2.contexts.profile.create.effects
|
||||
[utils.re-frame :as rf]
|
||||
@@ -14,4 +15,5 @@
|
||||
:displayName display-name
|
||||
:password (native-module/sha3 (security/safe-unmask-data password))
|
||||
:imagePath (profile.config/strip-file-prefix image-path)
|
||||
:customizationColor color)})
|
||||
:customizationColor color
|
||||
:emoji (emoji-picker.utils/random-emoji))})
|
||||
|
||||
@@ -125,7 +125,7 @@
|
||||
accounts tokens custom-tokens favourites]))]
|
||||
:check-eip1559-activation {:network-id network-id}}
|
||||
(not (:universal-links/handling db))
|
||||
(assoc :chat/open-last-chat (get-in db [:profile/profile :key-uid]))
|
||||
(assoc :effects.chat/open-last-chat (get-in db [:profile/profile :key-uid]))
|
||||
notifications-enabled?
|
||||
(assoc :effects/push-notifications-enable nil))
|
||||
(contacts/initialize-contacts)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
[react-native.safe-area :as safe-area]
|
||||
[reagent.core :as reagent]
|
||||
[status-im2.common.confirmation-drawer.view :as confirmation-drawer]
|
||||
[status-im2.common.standard-authentication.password-input.view :as password-input]
|
||||
[status-im2.common.standard-authentication.core :as standard-authentication]
|
||||
[status-im2.config :as config]
|
||||
[status-im2.constants :as constants]
|
||||
[status-im2.contexts.onboarding.common.background.view :as background]
|
||||
@@ -205,7 +205,7 @@
|
||||
:customization-color (or customization-color :primary)
|
||||
:profile-picture profile-picture
|
||||
:card-style style/login-profile-card}]
|
||||
[password-input/view
|
||||
[standard-authentication/password-input
|
||||
{:shell? true
|
||||
:default-password password}]]
|
||||
[quo/button
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
(ns status-im2.contexts.profile.recover.events
|
||||
(:require
|
||||
[native-module.core :as native-module]
|
||||
[status-im2.contexts.emoji-picker.utils :as emoji-picker.utils]
|
||||
[status-im2.contexts.profile.config :as profile.config]
|
||||
status-im2.contexts.profile.recover.effects
|
||||
[utils.re-frame :as rf]
|
||||
@@ -18,4 +19,5 @@
|
||||
:mnemonic (security/safe-unmask-data seed-phrase)
|
||||
:password (native-module/sha3 (security/safe-unmask-data password))
|
||||
:imagePath (profile.config/strip-file-prefix image-path)
|
||||
:customizationColor color})})
|
||||
:customizationColor color
|
||||
:emoji (emoji-picker.utils/random-emoji)})})
|
||||
|
||||
@@ -1,12 +1,19 @@
|
||||
(ns status-im2.contexts.profile.rpc
|
||||
(:require
|
||||
clojure.set
|
||||
[clojure.string :as string]
|
||||
[utils.ens.core :as utils.ens]))
|
||||
|
||||
(defn rpc->wakuv2-config
|
||||
[wakuv2-config]
|
||||
(-> wakuv2-config
|
||||
(clojure.set/rename-keys {:LightClient :light-client})))
|
||||
|
||||
(defn rpc->profiles-overview
|
||||
[{:keys [customizationColor keycard-pairing] :as profile}]
|
||||
(if (map? profile)
|
||||
(-> profile
|
||||
(update :wakuv2-config rpc->wakuv2-config)
|
||||
(dissoc :customizationColor)
|
||||
(assoc :customization-color (keyword customizationColor))
|
||||
(assoc :ens-name? (utils.ens/is-valid-eth-name? (:name profile)))
|
||||
|
||||
@@ -138,3 +138,10 @@
|
||||
{:events [:profile.settings/update-local-picture]}
|
||||
[cofx pics]
|
||||
(optimistic-profile-update cofx :images pics))
|
||||
|
||||
(rf/defn mark-mnemonic-as-shown
|
||||
{:events [:profile.settings/mnemonic-was-shown]}
|
||||
[cofx]
|
||||
{:json-rpc/call [{:method "settings_mnemonicWasShown"
|
||||
:on-success #(log/debug "mnemonic was marked as shown")
|
||||
:on-error #(log/error "mnemonic was not marked as shown" %)}]})
|
||||
|
||||
@@ -170,6 +170,7 @@
|
||||
[status-im2.contexts.quo-preview.wallet.account-origin :as account-origin]
|
||||
[status-im2.contexts.quo-preview.wallet.account-overview :as
|
||||
account-overview]
|
||||
[status-im2.contexts.quo-preview.wallet.confirmation-progress :as confirmation-progress]
|
||||
[status-im2.contexts.quo-preview.wallet.keypair :as keypair]
|
||||
[status-im2.contexts.quo-preview.wallet.network-amount :as network-amount]
|
||||
[status-im2.contexts.quo-preview.wallet.network-bridge :as network-bridge]
|
||||
@@ -178,6 +179,7 @@
|
||||
[status-im2.contexts.quo-preview.wallet.progress-bar :as progress-bar]
|
||||
[status-im2.contexts.quo-preview.wallet.summary-info :as summary-info]
|
||||
[status-im2.contexts.quo-preview.wallet.token-input :as token-input]
|
||||
[status-im2.contexts.quo-preview.wallet.transaction-progress :as transaction-progress]
|
||||
[status-im2.contexts.quo-preview.wallet.transaction-summary :as
|
||||
transaction-summary]
|
||||
[status-im2.contexts.quo-preview.wallet.wallet-activity :as wallet-activity]
|
||||
@@ -464,6 +466,8 @@
|
||||
{:name :account-origin :component account-origin/view}
|
||||
{:name :account-overview
|
||||
:component account-overview/view}
|
||||
{:name :confirmation-progress
|
||||
:component confirmation-progress/view}
|
||||
{:name :keypair :component keypair/view}
|
||||
{:name :network-amount :component network-amount/view}
|
||||
{:name :network-bridge :component network-bridge/view}
|
||||
@@ -473,6 +477,7 @@
|
||||
{:name :summary-info :component summary-info/view}
|
||||
{:name :token-input :component token-input/view}
|
||||
{:name :wallet-activity :component wallet-activity/view}
|
||||
{:name :transaction-progress :component transaction-progress/view}
|
||||
{:name :transaction-summary :component transaction-summary/view}
|
||||
{:name :wallet-overview
|
||||
:component wallet-overview/view}]
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
(ns status-im2.contexts.quo-preview.wallet.confirmation-progress
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[status-im2.contexts.quo-preview.preview :as preview]))
|
||||
|
||||
(def descriptor
|
||||
[{:type :text
|
||||
:key :progress-value}
|
||||
{:type :select
|
||||
:key :network
|
||||
:options [{:key :mainnet}
|
||||
{:key :optimism}
|
||||
{:key :arbitrum}]}
|
||||
{:type :select
|
||||
:key :state
|
||||
:options [{:key :pending}
|
||||
{:key :sending}
|
||||
{:key :confirmed}
|
||||
{:key :finalising}
|
||||
{:key :finalized}
|
||||
{:key :error}]}
|
||||
(preview/customization-color-option)])
|
||||
|
||||
(def total-box 85)
|
||||
(def counter (reagent/atom 0))
|
||||
(def interval-id (reagent/atom nil))
|
||||
(def interval-ms 50)
|
||||
|
||||
(defn- stop-interval
|
||||
[]
|
||||
(when @interval-id
|
||||
(js/clearInterval @interval-id)
|
||||
(reset! interval-id nil)))
|
||||
|
||||
(defn- clear-counter
|
||||
[]
|
||||
(reset! counter 0))
|
||||
|
||||
(defn- update-counter
|
||||
[state]
|
||||
(let [new-counter-value (inc @counter)]
|
||||
(if (or (and (= state :pending) (> new-counter-value 0))
|
||||
(and (= state :sending) (> new-counter-value 2))
|
||||
(and (= state :confirmed) (> new-counter-value 4))
|
||||
(and (= state :finalising) (> new-counter-value 18))
|
||||
(and (= state :finalized) (> new-counter-value total-box))
|
||||
(and (= state :error) (> new-counter-value 2)))
|
||||
(stop-interval)
|
||||
(reset! counter new-counter-value))))
|
||||
|
||||
(defn- start-interval
|
||||
[state]
|
||||
(reset! interval-id
|
||||
(js/setInterval
|
||||
(fn []
|
||||
(update-counter state))
|
||||
interval-ms)))
|
||||
|
||||
(defn- f-view
|
||||
[state]
|
||||
(fn []
|
||||
(rn/use-effect
|
||||
(fn []
|
||||
(start-interval (:state @state))
|
||||
(clear-counter)
|
||||
(fn []
|
||||
(stop-interval)))
|
||||
[(:state @state)])
|
||||
[preview/preview-container {:state state :descriptor descriptor}
|
||||
[quo/confirmation-propgress
|
||||
(assoc @state
|
||||
:counter
|
||||
@counter)]]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [state (reagent/atom
|
||||
{:total-box total-box
|
||||
:progress-value "10"
|
||||
:network :mainnet
|
||||
:state :pending
|
||||
:customization-color :blue})]
|
||||
[:f> f-view state]))
|
||||
@@ -1,6 +1,7 @@
|
||||
(ns status-im2.contexts.quo-preview.wallet.progress-bar
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[status-im2.contexts.quo-preview.preview :as preview]))
|
||||
|
||||
@@ -11,11 +12,17 @@
|
||||
{:key :confirmed}
|
||||
{:key :finalized}
|
||||
{:key :error}]}
|
||||
{:key :full-width?
|
||||
:type :boolean}
|
||||
{:key :progressed-value
|
||||
:type :text}
|
||||
(preview/customization-color-option)])
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [state (reagent/atom {:state :pending
|
||||
:full-width? false
|
||||
:progressed-value "10"
|
||||
:customization-color :blue})]
|
||||
(fn []
|
||||
[preview/preview-container
|
||||
@@ -23,4 +30,5 @@
|
||||
:descriptor descriptor
|
||||
:component-container-style {:padding-top 40
|
||||
:align-items :center}}
|
||||
[quo/progress-bar @state]])))
|
||||
[rn/view {:style {:flex-direction :row}}
|
||||
[quo/progress-bar @state]]])))
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
(ns status-im2.contexts.quo-preview.wallet.transaction-progress
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[status-im2.common.resources :as resources]
|
||||
[status-im2.contexts.quo-preview.preview :as preview]))
|
||||
|
||||
(def descriptor
|
||||
[{:type :text
|
||||
:key :title}
|
||||
{:type :text
|
||||
:key :tag-name}
|
||||
{:type :text
|
||||
:key :epoch-number-mainnet}
|
||||
{:type :text
|
||||
:key :epoch-number-optimism}
|
||||
{:type :text
|
||||
:key :epoch-number-arbitrum}
|
||||
{:type :text
|
||||
:key :tag-number}
|
||||
{:type :text
|
||||
:key :optimism-progress-percentage}
|
||||
{:type :text
|
||||
:key :arbitrum-progress-percentage}
|
||||
{:type :select
|
||||
:key :network
|
||||
:options [{:key :mainnet}
|
||||
{:key :optimism}
|
||||
{:key :arbitrum}
|
||||
{:key :optimism-arbitrum}]}
|
||||
{:type :select
|
||||
:key :state-mainnet
|
||||
:options [{:key :pending}
|
||||
{:key :sending}
|
||||
{:key :confirmed}
|
||||
{:key :finalising}
|
||||
{:key :finalized}
|
||||
{:key :error}]}
|
||||
{:type :select
|
||||
:key :state-optimism
|
||||
:options [{:key :pending}
|
||||
{:key :sending}
|
||||
{:key :confirmed}
|
||||
{:key :finalising}
|
||||
{:key :finalized}
|
||||
{:key :error}]}
|
||||
{:type :select
|
||||
:key :state-arbitrum
|
||||
:options [{:key :pending}
|
||||
{:key :sending}
|
||||
{:key :confirmed}
|
||||
{:key :finalising}
|
||||
{:key :finalized}
|
||||
{:key :error}]}
|
||||
(preview/customization-color-option)])
|
||||
|
||||
(def total-box 85)
|
||||
(def counter (reagent/atom 0))
|
||||
(def interval-id (reagent/atom nil))
|
||||
(def interval-ms 50)
|
||||
|
||||
(defn- stop-interval
|
||||
[]
|
||||
(when @interval-id
|
||||
(js/clearInterval @interval-id)
|
||||
(reset! interval-id nil)))
|
||||
|
||||
(defn- clear-counter
|
||||
[]
|
||||
(reset! counter 0))
|
||||
|
||||
(defn- update-counter
|
||||
[state]
|
||||
(let [new-counter-value (inc @counter)]
|
||||
(if (or (and (= state :pending) (> new-counter-value 0))
|
||||
(and (= state :sending) (> new-counter-value 2))
|
||||
(and (= state :confirmed) (> new-counter-value 4))
|
||||
(and (= state :finalising) (> new-counter-value 18))
|
||||
(and (= state :finalized) (> new-counter-value total-box))
|
||||
(and (= state :error) (> new-counter-value 2)))
|
||||
(stop-interval)
|
||||
(reset! counter new-counter-value))))
|
||||
|
||||
(defn- start-interval
|
||||
[state]
|
||||
(reset! interval-id
|
||||
(js/setInterval
|
||||
(fn []
|
||||
(update-counter state))
|
||||
interval-ms)))
|
||||
|
||||
(defn- get-networks
|
||||
[state]
|
||||
(case (:network state)
|
||||
:mainnet [{:network :mainnet
|
||||
:state (:state-mainnet state)
|
||||
:counter @counter
|
||||
:total-box total-box
|
||||
:epoch-number (:epoch-number-mainnet state)}]
|
||||
:optimism [{:network :optimism
|
||||
:state (:state-optimism state)
|
||||
:progress (:optimism-progress-percentage state)
|
||||
:epoch-number (:epoch-number-optimism state)}]
|
||||
:arbitrum [{:network :arbitrum
|
||||
:state (:state-arbitrum state)
|
||||
:progress (:arbitrum-progress-percentage state)
|
||||
:epoch-number (:epoch-number-arbitrum state)}]
|
||||
:optimism-arbitrum [{:network :optimism
|
||||
:state (:state-optimism state)
|
||||
:progress (:optimism-progress-percentage state)
|
||||
:epoch-number (:epoch-number-optimism state)}
|
||||
{:network :arbitrum
|
||||
:state (:state-arbitrum state)
|
||||
:progress (:arbitrum-progress-percentage state)
|
||||
:epoch-number (:epoch-number-arbitrum state)}]))
|
||||
|
||||
(defn- f-view
|
||||
[state]
|
||||
(fn []
|
||||
(rn/use-effect
|
||||
(fn []
|
||||
(start-interval (:state-mainnet @state))
|
||||
(clear-counter)
|
||||
(fn []
|
||||
(stop-interval)))
|
||||
[(:state-mainnet @state)])
|
||||
[preview/preview-container {:state state :descriptor descriptor}
|
||||
[quo/transaction-progress
|
||||
(assoc @state
|
||||
:networks
|
||||
(get-networks @state))]]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [state (reagent/atom
|
||||
{:title "Title"
|
||||
:counter 40
|
||||
:total-box total-box
|
||||
:tag-name "Doodle"
|
||||
:tag-number "120"
|
||||
:epoch-number-mainnet "181,329"
|
||||
:epoch-number-optimism "181,329"
|
||||
:epoch-number-arbitrum "181,329"
|
||||
:optimism-progress-percentage "10"
|
||||
:arbitrum-progress-percentage "10"
|
||||
:network :mainnet
|
||||
:state-mainnet :pending
|
||||
:state-arbitrum :pending
|
||||
:state-optimism :pending
|
||||
:customization-color :blue
|
||||
:tag-photo (resources/get-mock-image :collectible)
|
||||
:on-press (fn []
|
||||
(js/alert "Transaction progress item pressed"))})]
|
||||
[:f> f-view state]))
|
||||
@@ -122,10 +122,13 @@
|
||||
:on-error [:activity-center/process-notification-failure notification-id
|
||||
:notification/mark-as-read]}]}))
|
||||
|
||||
(rf/defn mark-as-read-success
|
||||
{:events [:activity-center.notifications/mark-as-read-success]}
|
||||
[cofx notification]
|
||||
(notifications-reconcile cofx [(assoc notification :read true)]))
|
||||
(defn mark-as-read-success
|
||||
[_ [{:keys [chat-id] :as notification}]]
|
||||
{:fx [(when chat-id
|
||||
[:dispatch [:chats-list/load-chat chat-id]])
|
||||
[:dispatch [:activity-center.notifications/reconcile [(assoc notification :read true)]]]]})
|
||||
|
||||
(rf/reg-event-fx :activity-center.notifications/mark-as-read-success mark-as-read-success)
|
||||
|
||||
(rf/defn mark-as-unread
|
||||
{:events [:activity-center.notifications/mark-as-unread]}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
(ns status-im2.contexts.shell.activity-center.events-test
|
||||
(:require
|
||||
[cljs.test :refer [deftest is testing]]
|
||||
matcher-combinators.test
|
||||
[status-im2.constants :as constants]
|
||||
[status-im2.contexts.shell.activity-center.events :as events]
|
||||
[status-im2.contexts.shell.activity-center.notification-types :as types]
|
||||
@@ -14,18 +15,18 @@
|
||||
|
||||
(deftest open-activity-center-test
|
||||
(testing "opens the activity center with default filters"
|
||||
(is (= {:db {}
|
||||
:fx [[:dispatch [:open-modal :activity-center {}]]
|
||||
[:dispatch-later [{:ms 1000 :dispatch [:activity-center/mark-as-seen]}]]]}
|
||||
(events/open-activity-center {:db {}} [nil]))))
|
||||
(is (match? {:db {}
|
||||
:fx [[:dispatch [:open-modal :activity-center {}]]
|
||||
[:dispatch-later [{:ms 1000 :dispatch [:activity-center/mark-as-seen]}]]]}
|
||||
(events/open-activity-center {:db {}} [nil]))))
|
||||
|
||||
(testing "opens the activity center with filters enabled"
|
||||
(is (= {:db {:activity-center {:filter {:status :unread :type types/contact-request}}}
|
||||
:fx [[:dispatch [:open-modal :activity-center {}]]
|
||||
[:dispatch-later [{:ms 1000 :dispatch [:activity-center/mark-as-seen]}]]]}
|
||||
(events/open-activity-center {:db {}}
|
||||
[{:filter-type types/contact-request
|
||||
:filter-status :unread}])))))
|
||||
(is (match? {:db {:activity-center {:filter {:status :unread :type types/contact-request}}}
|
||||
:fx [[:dispatch [:open-modal :activity-center {}]]
|
||||
[:dispatch-later [{:ms 1000 :dispatch [:activity-center/mark-as-seen]}]]]}
|
||||
(events/open-activity-center {:db {}}
|
||||
[{:filter-type types/contact-request
|
||||
:filter-status :unread}])))))
|
||||
|
||||
(deftest process-notification-failure-test
|
||||
(testing "logs and returns nil"
|
||||
@@ -34,11 +35,11 @@
|
||||
notification-id
|
||||
:some-action-name
|
||||
:some-error)))
|
||||
(is (= {:args ["Failed to :some-action-name"
|
||||
{:notification-id notification-id
|
||||
:error :some-error}]
|
||||
:level :warn}
|
||||
(last @h/logs)))))
|
||||
(is (match? {:args ["Failed to :some-action-name"
|
||||
{:notification-id notification-id
|
||||
:error :some-error}]
|
||||
:level :warn}
|
||||
(last @h/logs)))))
|
||||
|
||||
;;;; Mark as read/unread
|
||||
|
||||
@@ -53,25 +54,21 @@
|
||||
(testing "dispatches RPC call"
|
||||
(let [notif {:id "0x1" :read false :type types/one-to-one-chat}
|
||||
cofx {:db {:activity-center {:notifications [notif]}}}]
|
||||
(is (= {:json-rpc/call
|
||||
[{:method "wakuext_markActivityCenterNotificationsRead"
|
||||
:params [[(:id notif)]]
|
||||
:on-success [:activity-center.notifications/mark-as-read-success notif]
|
||||
:on-error [:activity-center/process-notification-failure (:id notif)
|
||||
:notification/mark-as-read]}]}
|
||||
(events/mark-as-read cofx (:id notif)))))))
|
||||
(is (match? {:json-rpc/call
|
||||
[{:method "wakuext_markActivityCenterNotificationsRead"
|
||||
:params [[(:id notif)]]
|
||||
:on-success [:activity-center.notifications/mark-as-read-success notif]
|
||||
:on-error [:activity-center/process-notification-failure (:id notif)
|
||||
:notification/mark-as-read]}]}
|
||||
(events/mark-as-read cofx (:id notif)))))))
|
||||
|
||||
(deftest mark-as-read-success-test
|
||||
(let [f-args (atom [])
|
||||
cofx {:db {}}
|
||||
notif {:id "0x1" :read false :type types/one-to-one-chat}]
|
||||
(with-redefs [events/notifications-reconcile
|
||||
(fn [& args]
|
||||
(reset! f-args args)
|
||||
:result)]
|
||||
(is (= :result (events/mark-as-read-success cofx notif)))
|
||||
(is (= [cofx [(assoc notif :read true)]]
|
||||
@f-args)))))
|
||||
(let [cofx {:db {}}
|
||||
notif {:id "0x1" :read false :type types/one-to-one-chat :chat-id "chat-id"}
|
||||
expected-fx {:fx [[:dispatch [:chats-list/load-chat "chat-id"]]
|
||||
[:dispatch
|
||||
[:activity-center.notifications/reconcile [(assoc notif :read true)]]]]}]
|
||||
(is (match? expected-fx (events/mark-as-read-success cofx [notif])))))
|
||||
|
||||
(deftest mark-as-unread-test
|
||||
(testing "does nothing if the notification ID cannot be found in the app db"
|
||||
@@ -84,13 +81,13 @@
|
||||
(testing "dispatches RPC call"
|
||||
(let [notif {:id "0x1" :read true :type types/one-to-one-chat}
|
||||
cofx {:db {:activity-center {:notifications [notif]}}}]
|
||||
(is (= {:json-rpc/call
|
||||
[{:method "wakuext_markActivityCenterNotificationsUnread"
|
||||
:params [[(:id notif)]]
|
||||
:on-success [:activity-center.notifications/mark-as-unread-success notif]
|
||||
:on-error [:activity-center/process-notification-failure (:id notif)
|
||||
:notification/mark-as-unread]}]}
|
||||
(events/mark-as-unread cofx (:id notif)))))))
|
||||
(is (match? {:json-rpc/call
|
||||
[{:method "wakuext_markActivityCenterNotificationsUnread"
|
||||
:params [[(:id notif)]]
|
||||
:on-success [:activity-center.notifications/mark-as-unread-success notif]
|
||||
:on-error [:activity-center/process-notification-failure (:id notif)
|
||||
:notification/mark-as-unread]}]}
|
||||
(events/mark-as-unread cofx (:id notif)))))))
|
||||
|
||||
(deftest mark-as-unread-success-test
|
||||
(let [f-args (atom [])
|
||||
@@ -101,19 +98,19 @@
|
||||
(reset! f-args args)
|
||||
:reconciliation-result)]
|
||||
(is (= :reconciliation-result (events/mark-as-unread-success cofx notif)))
|
||||
(is (= [cofx [(assoc notif :read false)]]
|
||||
@f-args)))))
|
||||
(is (match? [cofx [(assoc notif :read false)]]
|
||||
@f-args)))))
|
||||
|
||||
;;;; Acceptance/dismissal
|
||||
|
||||
(deftest accept-notification-test
|
||||
(is (= {:json-rpc/call
|
||||
[{:method "wakuext_acceptActivityCenterNotifications"
|
||||
:params [[notification-id]]
|
||||
:on-success [:activity-center.notifications/accept-success notification-id]
|
||||
:on-error [:activity-center/process-notification-failure notification-id
|
||||
:notification/accept]}]}
|
||||
(events/accept-notification {:db {}} notification-id))))
|
||||
(is (match? {:json-rpc/call
|
||||
[{:method "wakuext_acceptActivityCenterNotifications"
|
||||
:params [[notification-id]]
|
||||
:on-success [:activity-center.notifications/accept-success notification-id]
|
||||
:on-error [:activity-center/process-notification-failure notification-id
|
||||
:notification/accept]}]}
|
||||
(events/accept-notification {:db {}} notification-id))))
|
||||
|
||||
(deftest accept-notification-success-test
|
||||
(testing "does nothing if the notification ID cannot be found in the app db"
|
||||
@@ -129,18 +126,18 @@
|
||||
notif-2-accepted (assoc notif-2 :accepted true :read true)
|
||||
cofx {:db {:activity-center {:filter {:type types/no-type :status :all}
|
||||
:notifications [notif-2 notif-1]}}}]
|
||||
(is (= {:fx [[:dispatch [:chat/ensure-chats []]]
|
||||
[:dispatch [:activity-center.notifications/reconcile [notif-2-accepted]]]]}
|
||||
(events/accept-notification-success cofx [(:id notif-2) nil]))))))
|
||||
(is (match? {:fx [[:dispatch [:chat/ensure-chats []]]
|
||||
[:dispatch [:activity-center.notifications/reconcile [notif-2-accepted]]]]}
|
||||
(events/accept-notification-success cofx [(:id notif-2) nil]))))))
|
||||
|
||||
(deftest dismiss-notification-test
|
||||
(is (= {:json-rpc/call
|
||||
[{:method "wakuext_dismissActivityCenterNotifications"
|
||||
:params [[notification-id]]
|
||||
:on-success [:activity-center.notifications/dismiss-success notification-id]
|
||||
:on-error [:activity-center/process-notification-failure notification-id
|
||||
:notification/dismiss]}]}
|
||||
(events/dismiss-notification {:db {}} notification-id))))
|
||||
(is (match? {:json-rpc/call
|
||||
[{:method "wakuext_dismissActivityCenterNotifications"
|
||||
:params [[notification-id]]
|
||||
:on-success [:activity-center.notifications/dismiss-success notification-id]
|
||||
:on-error [:activity-center/process-notification-failure notification-id
|
||||
:notification/dismiss]}]}
|
||||
(events/dismiss-notification {:db {}} notification-id))))
|
||||
|
||||
(deftest dismiss-notification-success-test
|
||||
(testing "does nothing if the notification ID cannot be found in the app db"
|
||||
@@ -156,11 +153,11 @@
|
||||
notif-2-dismissed (assoc notif-2 :dismissed true :read true)
|
||||
cofx {:db {:activity-center {:filter {:type types/no-type :status :all}
|
||||
:notifications [notif-2 notif-1]}}}]
|
||||
(is (= {:db {:activity-center {:filter {:type 0 :status :all}
|
||||
:notifications [notif-2-dismissed notif-1]}}
|
||||
:dispatch-n [[:activity-center.notifications/fetch-unread-count]
|
||||
[:activity-center.notifications/fetch-pending-contact-requests]]}
|
||||
(events/dismiss-notification-success cofx (:id notif-2)))))))
|
||||
(is (match? {:db {:activity-center {:filter {:type 0 :status :all}
|
||||
:notifications [notif-2-dismissed notif-1]}}
|
||||
:dispatch-n [[:activity-center.notifications/fetch-unread-count]
|
||||
[:activity-center.notifications/fetch-pending-contact-requests]]}
|
||||
(events/dismiss-notification-success cofx (:id notif-2)))))))
|
||||
|
||||
;;;; Contact verification
|
||||
|
||||
@@ -208,41 +205,41 @@
|
||||
:type types/contact-verification})
|
||||
|
||||
(deftest contact-verification-decline-test
|
||||
(is (= {:json-rpc/call
|
||||
[{:method "wakuext_declineContactVerificationRequest"
|
||||
:params [notification-id]
|
||||
:on-success [:activity-center/reconcile-notifications-from-response]
|
||||
:on-error [:activity-center/process-notification-failure notification-id
|
||||
:contact-verification/decline]}]}
|
||||
(events/contact-verification-decline {:db {}} notification-id))))
|
||||
(is (match? {:json-rpc/call
|
||||
[{:method "wakuext_declineContactVerificationRequest"
|
||||
:params [notification-id]
|
||||
:on-success [:activity-center/reconcile-notifications-from-response]
|
||||
:on-error [:activity-center/process-notification-failure notification-id
|
||||
:contact-verification/decline]}]}
|
||||
(events/contact-verification-decline {:db {}} notification-id))))
|
||||
|
||||
(deftest contact-verification-reply-test
|
||||
(let [reply "The answer is 42"]
|
||||
(is (= {:json-rpc/call
|
||||
[{:method "wakuext_acceptContactVerificationRequest"
|
||||
:params [notification-id reply]
|
||||
:on-success [:activity-center/reconcile-notifications-from-response]
|
||||
:on-error [:activity-center/process-notification-failure notification-id
|
||||
:contact-verification/reply]}]}
|
||||
(events/contact-verification-reply {:db {}} notification-id reply)))))
|
||||
(is (match? {:json-rpc/call
|
||||
[{:method "wakuext_acceptContactVerificationRequest"
|
||||
:params [notification-id reply]
|
||||
:on-success [:activity-center/reconcile-notifications-from-response]
|
||||
:on-error [:activity-center/process-notification-failure notification-id
|
||||
:contact-verification/reply]}]}
|
||||
(events/contact-verification-reply {:db {}} notification-id reply)))))
|
||||
|
||||
(deftest contact-verification-mark-as-trusted-test
|
||||
(is (= {:json-rpc/call
|
||||
[{:method "wakuext_verifiedTrusted"
|
||||
:params [{:id notification-id}]
|
||||
:on-success [:activity-center/reconcile-notifications-from-response]
|
||||
:on-error [:activity-center/process-notification-failure notification-id
|
||||
:contact-verification/mark-as-trusted]}]}
|
||||
(events/contact-verification-mark-as-trusted {:db {}} notification-id))))
|
||||
(is (match? {:json-rpc/call
|
||||
[{:method "wakuext_verifiedTrusted"
|
||||
:params [{:id notification-id}]
|
||||
:on-success [:activity-center/reconcile-notifications-from-response]
|
||||
:on-error [:activity-center/process-notification-failure notification-id
|
||||
:contact-verification/mark-as-trusted]}]}
|
||||
(events/contact-verification-mark-as-trusted {:db {}} notification-id))))
|
||||
|
||||
(deftest contact-verification-mark-as-untrustworthy-test
|
||||
(is (= {:json-rpc/call
|
||||
[{:method "wakuext_verifiedUntrustworthy"
|
||||
:params [{:id notification-id}]
|
||||
:on-success [:activity-center/reconcile-notifications-from-response]
|
||||
:on-error [:activity-center/process-notification-failure notification-id
|
||||
:contact-verification/mark-as-untrustworthy]}]}
|
||||
(events/contact-verification-mark-as-untrustworthy {:db {}} notification-id))))
|
||||
(is (match? {:json-rpc/call
|
||||
[{:method "wakuext_verifiedUntrustworthy"
|
||||
:params [{:id notification-id}]
|
||||
:on-success [:activity-center/reconcile-notifications-from-response]
|
||||
:on-error [:activity-center/process-notification-failure notification-id
|
||||
:contact-verification/mark-as-untrustworthy]}]}
|
||||
(events/contact-verification-mark-as-untrustworthy {:db {}} notification-id))))
|
||||
|
||||
;;;; Notification reconciliation
|
||||
|
||||
@@ -256,17 +253,17 @@
|
||||
cofx {:db {:activity-center
|
||||
{:filter {:type types/no-type :status :all}
|
||||
:notifications [notif-2 notif-1]}}}]
|
||||
(is (= {:db {:activity-center
|
||||
{:filter {:type types/no-type :status :all}
|
||||
:notifications [new-notif-4 new-notif-3 new-notif-2]}}
|
||||
:dispatch-n [[:activity-center.notifications/fetch-unread-count]
|
||||
[:activity-center.notifications/fetch-pending-contact-requests]]}
|
||||
(events/notifications-reconcile
|
||||
cofx
|
||||
[(assoc notif-1 :deleted true) ; will be removed
|
||||
new-notif-2
|
||||
new-notif-3
|
||||
new-notif-4])))))
|
||||
(is (match? {:db {:activity-center
|
||||
{:filter {:type types/no-type :status :all}
|
||||
:notifications [new-notif-4 new-notif-3 new-notif-2]}}
|
||||
:dispatch-n [[:activity-center.notifications/fetch-unread-count]
|
||||
[:activity-center.notifications/fetch-pending-contact-requests]]}
|
||||
(events/notifications-reconcile
|
||||
cofx
|
||||
[(assoc notif-1 :deleted true) ; will be removed
|
||||
new-notif-2
|
||||
new-notif-3
|
||||
new-notif-4])))))
|
||||
|
||||
(testing "All tab + Unread filter"
|
||||
(let [notif-1 {:id "0x1" :read false :type types/one-to-one-chat}
|
||||
@@ -278,18 +275,18 @@
|
||||
cofx {:db {:activity-center
|
||||
{:filter {:type types/no-type :status :unread}
|
||||
:notifications [notif-5 notif-2 notif-1]}}}]
|
||||
(is (= {:db {:activity-center
|
||||
{:filter {:type types/no-type :status :unread}
|
||||
:notifications [new-notif-3 notif-1]}}
|
||||
:dispatch-n [[:activity-center.notifications/fetch-unread-count]
|
||||
[:activity-center.notifications/fetch-pending-contact-requests]]}
|
||||
(events/notifications-reconcile
|
||||
cofx
|
||||
[new-notif-2 ; will be removed because it's read
|
||||
new-notif-3 ; will be inserted
|
||||
new-notif-4 ; will be ignored because it's read
|
||||
(assoc notif-5 :deleted true) ; will be removed
|
||||
])))))
|
||||
(is (match? {:db {:activity-center
|
||||
{:filter {:type types/no-type :status :unread}
|
||||
:notifications [new-notif-3 notif-1]}}
|
||||
:dispatch-n [[:activity-center.notifications/fetch-unread-count]
|
||||
[:activity-center.notifications/fetch-pending-contact-requests]]}
|
||||
(events/notifications-reconcile
|
||||
cofx
|
||||
[new-notif-2 ; will be removed because it's read
|
||||
new-notif-3 ; will be inserted
|
||||
new-notif-4 ; will be ignored because it's read
|
||||
(assoc notif-5 :deleted true) ; will be removed
|
||||
])))))
|
||||
|
||||
(testing "Contact request tab + All filter"
|
||||
(let [notif-1 {:id "0x1" :read true :type types/contact-request}
|
||||
@@ -301,18 +298,18 @@
|
||||
cofx {:db {:activity-center
|
||||
{:filter {:type types/contact-request :status :all}
|
||||
:notifications [notif-5 notif-2 notif-1]}}}]
|
||||
(is (= {:db {:activity-center
|
||||
{:filter {:type types/contact-request :status :all}
|
||||
:notifications [new-notif-3 new-notif-2 notif-1]}}
|
||||
:dispatch-n [[:activity-center.notifications/fetch-unread-count]
|
||||
[:activity-center.notifications/fetch-pending-contact-requests]]}
|
||||
(events/notifications-reconcile
|
||||
cofx
|
||||
[new-notif-2 ; will be updated
|
||||
new-notif-3 ; will be inserted
|
||||
new-notif-4 ; will be ignored because it's not a contact request
|
||||
(assoc notif-5 :deleted true) ; will be removed
|
||||
])))))
|
||||
(is (match? {:db {:activity-center
|
||||
{:filter {:type types/contact-request :status :all}
|
||||
:notifications [new-notif-3 new-notif-2 notif-1]}}
|
||||
:dispatch-n [[:activity-center.notifications/fetch-unread-count]
|
||||
[:activity-center.notifications/fetch-pending-contact-requests]]}
|
||||
(events/notifications-reconcile
|
||||
cofx
|
||||
[new-notif-2 ; will be updated
|
||||
new-notif-3 ; will be inserted
|
||||
new-notif-4 ; will be ignored because it's not a contact request
|
||||
(assoc notif-5 :deleted true) ; will be removed
|
||||
])))))
|
||||
|
||||
(testing "Contact request tab + Unread filter"
|
||||
(let [notif-1 {:id "0x1" :read false :type types/contact-request}
|
||||
@@ -326,20 +323,20 @@
|
||||
{:filter {:type types/contact-request
|
||||
:status :unread}
|
||||
:notifications [notif-6 notif-2 notif-1]}}}]
|
||||
(is (= {:db {:activity-center
|
||||
{:filter {:type types/contact-request
|
||||
:status :unread}
|
||||
:notifications [new-notif-3 notif-1]}}
|
||||
:dispatch-n [[:activity-center.notifications/fetch-unread-count]
|
||||
[:activity-center.notifications/fetch-pending-contact-requests]]}
|
||||
(events/notifications-reconcile
|
||||
cofx
|
||||
[new-notif-2 ; will be removed because it's read
|
||||
new-notif-3 ; will be inserted
|
||||
new-notif-4 ; will be ignored because it's read
|
||||
new-notif-5 ; will be ignored because it's not a contact request
|
||||
(assoc notif-6 :deleted true) ; will be removed
|
||||
])))))
|
||||
(is (match? {:db {:activity-center
|
||||
{:filter {:type types/contact-request
|
||||
:status :unread}
|
||||
:notifications [new-notif-3 notif-1]}}
|
||||
:dispatch-n [[:activity-center.notifications/fetch-unread-count]
|
||||
[:activity-center.notifications/fetch-pending-contact-requests]]}
|
||||
(events/notifications-reconcile
|
||||
cofx
|
||||
[new-notif-2 ; will be removed because it's read
|
||||
new-notif-3 ; will be inserted
|
||||
new-notif-4 ; will be ignored because it's read
|
||||
new-notif-5 ; will be ignored because it's not a contact request
|
||||
(assoc notif-6 :deleted true) ; will be removed
|
||||
])))))
|
||||
|
||||
;; Sorting by timestamp and ID is compatible with what the backend does when
|
||||
;; returning paginated results.
|
||||
@@ -354,15 +351,15 @@
|
||||
cofx {:db {:activity-center
|
||||
{:notifications [notif-1 notif-3 notif-4 notif-2
|
||||
notif-5]}}}]
|
||||
(is (= {:db {:activity-center
|
||||
{:notifications [notif-5
|
||||
new-notif-4
|
||||
notif-3
|
||||
notif-2
|
||||
new-notif-1]}}
|
||||
:dispatch-n [[:activity-center.notifications/fetch-unread-count]
|
||||
[:activity-center.notifications/fetch-pending-contact-requests]]}
|
||||
(events/notifications-reconcile cofx [new-notif-1 new-notif-4]))))))
|
||||
(is (match? {:db {:activity-center
|
||||
{:notifications [notif-5
|
||||
new-notif-4
|
||||
notif-3
|
||||
notif-2
|
||||
new-notif-1]}}
|
||||
:dispatch-n [[:activity-center.notifications/fetch-unread-count]
|
||||
[:activity-center.notifications/fetch-pending-contact-requests]]}
|
||||
(events/notifications-reconcile cofx [new-notif-1 new-notif-4]))))))
|
||||
|
||||
(deftest remove-pending-contact-request-test
|
||||
(testing "removes notification from all related filter types and status"
|
||||
@@ -376,26 +373,27 @@
|
||||
notif-2 ; will be removed
|
||||
notif-1 ; will be ignored because it's not from the same author
|
||||
]}}}]
|
||||
(is (= {:db {:activity-center {:notifications [notif-3 notif-1]}}}
|
||||
(events/notifications-remove-pending-contact-request cofx author))))))
|
||||
(is (match? {:db {:activity-center {:notifications [notif-3 notif-1]}}}
|
||||
(events/notifications-remove-pending-contact-request cofx author))))))
|
||||
|
||||
;;;; Notifications fetching and pagination
|
||||
|
||||
(deftest notifications-fetch-first-page-test
|
||||
(testing "fetches first page"
|
||||
(let [cofx {:db {}}]
|
||||
(is (= {:db {:activity-center {:filter {:type types/one-to-one-chat
|
||||
:status :unread}
|
||||
:loading? true}}
|
||||
:json-rpc/call [{:method "wakuext_activityCenterNotifications"
|
||||
:params [{:cursor ""
|
||||
:limit (:notifications-per-page events/defaults)
|
||||
:activityTypes [types/one-to-one-chat]
|
||||
:readType events/read-type-unread}]
|
||||
:on-success [:activity-center.notifications/fetch-success true]
|
||||
:on-error [:activity-center.notifications/fetch-error
|
||||
types/one-to-one-chat :unread]}]}
|
||||
(events/notifications-fetch-first-page cofx {:filter-type types/one-to-one-chat}))))))
|
||||
(is (match? {:db {:activity-center {:filter {:type types/one-to-one-chat
|
||||
:status :unread}
|
||||
:loading? true}}
|
||||
:json-rpc/call [{:method "wakuext_activityCenterNotifications"
|
||||
:params [{:cursor ""
|
||||
:limit (:notifications-per-page
|
||||
events/defaults)
|
||||
:activityTypes [types/one-to-one-chat]
|
||||
:readType events/read-type-unread}]
|
||||
:on-success [:activity-center.notifications/fetch-success true]
|
||||
:on-error [:activity-center.notifications/fetch-error
|
||||
types/one-to-one-chat :unread]}]}
|
||||
(events/notifications-fetch-first-page cofx {:filter-type types/one-to-one-chat}))))))
|
||||
|
||||
(deftest notifications-fetch-next-next-page-test
|
||||
(testing "does not fetch next page when pagination cursor reached the end"
|
||||
@@ -413,12 +411,12 @@
|
||||
(reset! f-args args)
|
||||
:result)]
|
||||
(is (= :result (events/notifications-fetch-next-page cofx)))
|
||||
(is (= [cofx
|
||||
{:cursor cursor
|
||||
:filter-type types/one-to-one-chat
|
||||
:filter-status :unread
|
||||
:reset-data? false}]
|
||||
@f-args))))))
|
||||
(is (match? [cofx
|
||||
{:cursor cursor
|
||||
:filter-type types/one-to-one-chat
|
||||
:filter-status :unread
|
||||
:reset-data? false}]
|
||||
@f-args))))))
|
||||
|
||||
(deftest notifications-fetch-error-test
|
||||
(testing "resets loading state"
|
||||
@@ -427,23 +425,23 @@
|
||||
:filter {:status :unread
|
||||
:type types/one-to-one-chat}
|
||||
:cursor ""}}}]
|
||||
(is (= {:db {:activity-center {:filter {:status :unread
|
||||
:type types/one-to-one-chat}
|
||||
:cursor ""}}}
|
||||
(events/notifications-fetch-error cofx :dummy-error))))))
|
||||
(is (match? {:db {:activity-center {:filter {:status :unread
|
||||
:type types/one-to-one-chat}
|
||||
:cursor ""}}}
|
||||
(events/notifications-fetch-error cofx :dummy-error))))))
|
||||
|
||||
(deftest seen-state-test
|
||||
(testing "update seen state"
|
||||
(is (= {:db {:activity-center {:seen? true}}}
|
||||
(events/reconcile-seen-state {:db {}} true))))
|
||||
(is (match? {:db {:activity-center {:seen? true}}}
|
||||
(events/reconcile-seen-state {:db {}} true))))
|
||||
|
||||
(testing "update seen state when the user is on other screen"
|
||||
(is (= {:db {:view-id :chats-stack
|
||||
:activity-center {:seen? false}}}
|
||||
(events/reconcile-seen-state {:db {:view-id :chats-stack}} false))))
|
||||
(is (match? {:db {:view-id :chats-stack
|
||||
:activity-center {:seen? false}}}
|
||||
(events/reconcile-seen-state {:db {:view-id :chats-stack}} false))))
|
||||
|
||||
(testing "update seen state when the user is on activity center"
|
||||
(is (= {:db {:view-id :activity-center
|
||||
:activity-center {:seen? false}}
|
||||
:dispatch [:activity-center/mark-as-seen]}
|
||||
(events/reconcile-seen-state {:db {:view-id :activity-center}} false)))))
|
||||
(is (match? {:db {:view-id :activity-center
|
||||
:activity-center {:seen? false}}
|
||||
:dispatch [:activity-center/mark-as-seen]}
|
||||
(events/reconcile-seen-state {:db {:view-id :activity-center}} false)))))
|
||||
|
||||
@@ -17,6 +17,5 @@
|
||||
(def load-chats-stack? (reagent/atom false))
|
||||
(def load-wallet-stack? (reagent/atom false))
|
||||
(def load-browser-stack? (reagent/atom false))
|
||||
|
||||
;NOTE temporary while we support old wallet
|
||||
(def load-new-wallet? (reagent/atom false))
|
||||
(def load-new-wallet? (reagent/atom true))
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
[status-im2.contexts.syncing.utils :as sync-utils]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.security.core :as security]
|
||||
[utils.transforms :as transforms]))
|
||||
|
||||
(rf/defn local-pairing-update-role
|
||||
@@ -97,7 +96,7 @@
|
||||
|
||||
(rf/defn preparations-for-connection-string
|
||||
{:events [:syncing/get-connection-string]}
|
||||
[{:keys [db] :as cofx} entered-password on-valid-connection-string]
|
||||
[{:keys [db] :as cofx} sha3-pwd on-valid-connection-string]
|
||||
(let [error (get-in db [:profile/login :error])
|
||||
handle-connection (fn [response]
|
||||
(when (sync-utils/valid-connection-string? response)
|
||||
@@ -105,8 +104,7 @@
|
||||
(rf/dispatch [:syncing/update-role constants/local-pairing-role-sender])
|
||||
(rf/dispatch [:hide-bottom-sheet])))]
|
||||
(when-not (and error (string/blank? error))
|
||||
(let [key-uid (get-in db [:profile/login :key-uid])
|
||||
sha3-pwd (native-module/sha3 (str (security/safe-unmask-data entered-password)))
|
||||
(let [key-uid (get-in db [:profile/profile :key-uid])
|
||||
config-map (.stringify js/JSON
|
||||
(clj->js {:senderConfig {:keyUID key-uid
|
||||
:keystorePath ""
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
(reset! code nil)
|
||||
(reset! timestamp nil)
|
||||
(reset! valid-for-ms code-valid-for-ms))
|
||||
on-enter-password (fn [entered-password]
|
||||
on-auth-success (fn [entered-password]
|
||||
(rf/dispatch [:syncing/get-connection-string entered-password
|
||||
set-code]))]
|
||||
(fn []
|
||||
@@ -124,8 +124,7 @@
|
||||
:size :size-40
|
||||
:track-text (i18n/label :t/slide-to-reveal-code)
|
||||
:customization-color customization-color
|
||||
:on-enter-password on-enter-password
|
||||
:biometric-auth? false
|
||||
:on-auth-success on-auth-success
|
||||
:auth-button-label (i18n/label :t/reveal-sync-code)
|
||||
:auth-button-icon-left :i/reveal}]])]]
|
||||
[rn/view {:style style/sync-code}
|
||||
|
||||
@@ -43,8 +43,8 @@
|
||||
:bottom-action-props {:customization-color @account-color
|
||||
:disabled? (string/blank? @account-name)
|
||||
:on-press #(rf/dispatch [:wallet/add-account
|
||||
nil
|
||||
{:type :watch
|
||||
{:sha3-pwd nil
|
||||
:type :watch
|
||||
:account-name @account-name
|
||||
:emoji @account-emoji
|
||||
:color @account-color}
|
||||
|
||||
@@ -107,3 +107,7 @@
|
||||
:networks networks-list
|
||||
:state :default
|
||||
:customization-color :blue}])
|
||||
|
||||
(def secret-phrase
|
||||
["witch" "collapse" "practice" "feed" "shame" "open" "lion"
|
||||
"collapse" "umbrella" "fabric" "sadness" "obligue"])
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
(ns status-im2.contexts.wallet.create-account.backup-recovery-phrase.style
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.platform :as platform]))
|
||||
|
||||
(def header-container
|
||||
{:margin-horizontal 20
|
||||
:margin-vertical 12})
|
||||
|
||||
(defn seed-phrase-container
|
||||
[theme]
|
||||
{:margin-horizontal 20
|
||||
:padding-horizontal 12
|
||||
:border-width 1
|
||||
:border-color (colors/theme-colors colors/neutral-10 colors/neutral-80 theme)
|
||||
:border-radius 16
|
||||
:background-color (colors/theme-colors colors/white colors/neutral-80-opa-40 theme)
|
||||
:flex-direction :row})
|
||||
|
||||
(def word-item
|
||||
{:align-items :center
|
||||
:flex-direction :row})
|
||||
|
||||
(defn separator
|
||||
[theme]
|
||||
{:margin-vertical 12
|
||||
:margin-horizontal 12
|
||||
:border-width (when platform/ios? 1)
|
||||
:border-right-width (when platform/android? 1)
|
||||
:border-color (colors/theme-colors colors/neutral-10 colors/neutral-80 theme)
|
||||
:border-style :dashed})
|
||||
|
||||
(def step-item
|
||||
{:flex-direction :row
|
||||
:margin-vertical 8
|
||||
:align-items :center})
|
||||
|
||||
(def blur-container
|
||||
{:position :absolute
|
||||
:left 0
|
||||
:right 0
|
||||
:top 0
|
||||
:bottom 0
|
||||
:border-radius 16
|
||||
:overflow :hidden})
|
||||
|
||||
(defn blur
|
||||
[theme]
|
||||
{:style {:flex 1}
|
||||
:blur-radius 20
|
||||
:blur-type (quo.theme/theme-value :light :dark theme)
|
||||
:blur-amount 20})
|
||||
|
||||
(def slide-button
|
||||
{:position :absolute
|
||||
:bottom 12
|
||||
:left 0
|
||||
:right 0})
|
||||
|
||||
(defn description-text
|
||||
[theme]
|
||||
{:margin-horizontal 40
|
||||
:text-align :center
|
||||
:color (colors/theme-colors colors/neutral-80-opa-70 colors/white-opa-70 theme)})
|
||||
@@ -0,0 +1,95 @@
|
||||
(ns status-im2.contexts.wallet.create-account.backup-recovery-phrase.view
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[status-im2.contexts.wallet.common.temp :as temp]
|
||||
[status-im2.contexts.wallet.create-account.backup-recovery-phrase.style :as style]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- word-item
|
||||
[item index _ increment]
|
||||
[rn/view {:style style/word-item}
|
||||
[quo/counter {:type :grey} (+ index increment)]
|
||||
[quo/text {:style {:margin-left 4}} item]])
|
||||
|
||||
(defn- words-column
|
||||
[words first-half?]
|
||||
[rn/flat-list
|
||||
{:style {:padding-vertical 8}
|
||||
:data (if first-half? (subvec words 0 6) (subvec words 6))
|
||||
:separator [rn/view {:style {:height 12}}]
|
||||
:render-fn word-item
|
||||
:render-data (if first-half? 1 7)
|
||||
:scroll-enabled false}])
|
||||
|
||||
(defn- step-item
|
||||
[item index _ checked?]
|
||||
[rn/view {:style style/step-item}
|
||||
[quo/selectors
|
||||
{:type :checkbox
|
||||
:on-change #(swap! checked? assoc (keyword (str index)) %)}]
|
||||
[quo/text {:style {:margin-left 12}} (i18n/label item)]])
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [theme]}]
|
||||
(let [step-labels [:t/backup-step-1 :t/backup-step-2 :t/backup-step-3
|
||||
:t/backup-step-4]
|
||||
checked? (reagent/atom
|
||||
{:0 false
|
||||
:1 false
|
||||
:2 false
|
||||
:3 false})
|
||||
revealed? (reagent/atom false)
|
||||
{:keys [customization-color]} (rf/sub [:profile/profile])]
|
||||
(fn []
|
||||
[rn/view {:style {:flex 1}}
|
||||
[quo/page-nav
|
||||
{:icon-name :i/close
|
||||
:on-press #(rf/dispatch [:navigate-back])
|
||||
:accessibility-label :top-bar}]
|
||||
[quo/text-combinations
|
||||
{:container-style style/header-container
|
||||
:title (i18n/label :t/backup-recovery-phrase)
|
||||
:description (i18n/label :t/backup-recovery-phrase-description)}]
|
||||
[rn/view {:style (style/seed-phrase-container theme)}
|
||||
[words-column temp/secret-phrase true]
|
||||
[rn/view {:style (style/separator theme)}]
|
||||
[words-column temp/secret-phrase false]
|
||||
(when-not @revealed?
|
||||
[rn/view {:style style/blur-container}
|
||||
[blur/view (style/blur theme)]])]
|
||||
(when-not @revealed?
|
||||
[rn/view
|
||||
{:style {:padding-horizontal 20
|
||||
:padding-top 20}}
|
||||
[quo/text
|
||||
{:weight :semi-bold
|
||||
:style {:margin-bottom 8}} (i18n/label :t/how-to-backup)]
|
||||
[rn/flat-list
|
||||
{:data step-labels
|
||||
:render-fn step-item
|
||||
:render-data checked?
|
||||
:scroll-enabled false}]])
|
||||
(if @revealed?
|
||||
[rn/view {:style style/slide-button}
|
||||
[quo/bottom-actions
|
||||
{:button-one-label (i18n/label :t/i-have-written)
|
||||
:button-one-props {:disabled? (some false? (vals @checked?))
|
||||
:customization-color customization-color
|
||||
:on-press #(js/alert "To be implemented")}}]
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:style (style/description-text theme)}
|
||||
(i18n/label :t/next-you-will)]]
|
||||
[quo/bottom-actions
|
||||
{:button-one-label (i18n/label :t/reveal-phrase)
|
||||
:button-one-props {:disabled? (some false? (vals @checked?))
|
||||
:customization-color customization-color
|
||||
:on-press #(reset! revealed? true)}
|
||||
:container-style style/slide-button}])])))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
@@ -8,6 +8,24 @@
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn keypair-options
|
||||
[]
|
||||
[quo/action-drawer
|
||||
[[{:icon :i/add
|
||||
:accessibility-label :generate-new-keypair
|
||||
:label (i18n/label :t/generate-new-keypair)
|
||||
:on-press #(rf/dispatch [:navigate-to :wallet-backup-recovery-phrase])}
|
||||
{:icon :i/seed
|
||||
:accessibility-label :import-using-phrase
|
||||
:label (i18n/label :t/import-using-phrase)
|
||||
:add-divider? true}
|
||||
{:icon :i/keycard-card
|
||||
:accessibility-label :import-from-keycard
|
||||
:label (i18n/label :t/import-from-keycard)}
|
||||
{:icon :i/key
|
||||
:accessibility-label :import-private-key
|
||||
:label (i18n/label :t/import-private-key)}]]])
|
||||
|
||||
(def accounts
|
||||
[{:account-props {:customization-color :turquoise
|
||||
:size 32
|
||||
@@ -38,7 +56,8 @@
|
||||
:title (i18n/label :t/keypairs)
|
||||
:description (i18n/label :t/keypairs-description)
|
||||
:button-icon :i/add
|
||||
:button-on-press #(js/alert "not implemented")
|
||||
:button-on-press #(rf/dispatch [:show-bottom-sheet
|
||||
{:content keypair-options}])
|
||||
:customization-color customization-color}]
|
||||
[quo/keypair
|
||||
(merge
|
||||
|
||||
@@ -118,14 +118,14 @@
|
||||
{:size :size-48
|
||||
:track-text (i18n/label :t/slide-to-create-account)
|
||||
:customization-color @account-color
|
||||
:on-enter-password (fn [entered-password]
|
||||
:on-auth-success (fn [entered-password]
|
||||
(prn entered-password)
|
||||
(rf/dispatch [:wallet/derive-address-and-add-account
|
||||
entered-password
|
||||
{:emoji @emoji
|
||||
{:sha3-pwd entered-password
|
||||
:emoji @emoji
|
||||
:color @account-color
|
||||
:path @derivation-path
|
||||
:account-name @account-name}]))
|
||||
:biometric-auth? false
|
||||
:auth-button-label (i18n/label :t/confirm)
|
||||
:container-style (style/slide-button-container bottom)}]])))
|
||||
|
||||
|
||||
@@ -3,17 +3,17 @@
|
||||
[camel-snake-kebab.core :as csk]
|
||||
[camel-snake-kebab.extras :as cske]
|
||||
[clojure.string :as string]
|
||||
[native-module.core :as native-module]
|
||||
[quo.foundations.colors :as colors]
|
||||
[react-native.background-timer :as background-timer]
|
||||
[status-im2.common.data-store.wallet :as data-store]
|
||||
[status-im2.contexts.wallet.item-types :as item-types]
|
||||
[status-im2.contexts.wallet.temp :as temp]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.ethereum.chain :as chain]
|
||||
[utils.ethereum.eip.eip55 :as eip55]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.number]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.security.core :as security]
|
||||
[utils.transforms :as types]))
|
||||
|
||||
(rf/reg-event-fx :wallet/show-account-created-toast
|
||||
@@ -141,9 +141,8 @@
|
||||
{:db (dissoc db :wallet/scanned-address :wallet/send-address)})
|
||||
|
||||
(rf/reg-event-fx :wallet/create-derived-addresses
|
||||
(fn [{:keys [db]} [password {:keys [path]} on-success]]
|
||||
(let [{:keys [wallet-root-address]} (:profile/profile db)
|
||||
sha3-pwd (native-module/sha3 (str (security/safe-unmask-data password)))]
|
||||
(fn [{:keys [db]} [{:keys [sha3-pwd path]} on-success]]
|
||||
(let [{:keys [wallet-root-address]} (:profile/profile db)]
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method "wallet_getDerivedAddresses"
|
||||
:params [sha3-pwd wallet-root-address [path]]
|
||||
@@ -160,11 +159,10 @@
|
||||
|
||||
(rf/reg-event-fx :wallet/add-account
|
||||
(fn [{:keys [db]}
|
||||
[password {:keys [emoji account-name color type] :or {type :generated}}
|
||||
[{:keys [sha3-pwd emoji account-name color type] :or {type :generated}}
|
||||
{:keys [public-key address path]}]]
|
||||
(let [lowercase-address (if address (string/lower-case address) address)
|
||||
key-uid (get-in db [:profile/profile :key-uid])
|
||||
sha3-pwd (native-module/sha3 (security/safe-unmask-data password))
|
||||
account-config {:key-uid (when (= type :generated) key-uid)
|
||||
:wallet false
|
||||
:chat false
|
||||
@@ -183,11 +181,11 @@
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/derive-address-and-add-account
|
||||
(fn [_ [password account-details]]
|
||||
(fn [_ [account-details]]
|
||||
(let [on-success (fn [derived-address-details]
|
||||
(rf/dispatch [:wallet/add-account password account-details
|
||||
(rf/dispatch [:wallet/add-account account-details
|
||||
(first derived-address-details)]))]
|
||||
{:fx [[:dispatch [:wallet/create-derived-addresses password account-details on-success]]]})))
|
||||
{:fx [[:dispatch [:wallet/create-derived-addresses account-details on-success]]]})))
|
||||
|
||||
(rf/defn get-ethereum-chains
|
||||
{:events [:wallet/get-ethereum-chains]}
|
||||
@@ -327,6 +325,45 @@
|
||||
{:event :wallet/get-collectible-details-done
|
||||
:response response})))))
|
||||
|
||||
(rf/reg-event-fx :wallet/find-ens
|
||||
(fn [{:keys [db]} [input contacts chain-id cb]]
|
||||
(let [result (if (empty? input)
|
||||
[]
|
||||
(filter #(string/starts-with? (or (:ens-name %) "") input) contacts))]
|
||||
(if (and input (empty? result))
|
||||
(rf/dispatch [:wallet/search-ens input chain-id cb ".stateofus.eth"])
|
||||
{:db (assoc db
|
||||
:wallet/local-suggestions
|
||||
(map #(assoc % :type item-types/saved-address) result)
|
||||
:wallet/valid-ens-or-address? (not-empty result))}))))
|
||||
|
||||
(rf/reg-event-fx :wallet/search-ens
|
||||
(fn [_ [input chain-id cb domain]]
|
||||
(let [ens (if (string/includes? input ".") input (str input domain))]
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method "ens_addressOf"
|
||||
:params [chain-id ens]
|
||||
:on-success #(rf/dispatch [:wallet/set-ens-address % ens])
|
||||
:on-error (fn []
|
||||
(if (= domain ".stateofus.eth")
|
||||
(rf/dispatch [:wallet/search-ens input chain-id cb ".eth"])
|
||||
(do
|
||||
(rf/dispatch [:wallet/set-ens-address nil ens])
|
||||
(cb))))}]]]})))
|
||||
|
||||
(rf/reg-event-fx :wallet/set-ens-address
|
||||
(fn [{:keys [db]} [result ens]]
|
||||
{:db (assoc db
|
||||
:wallet/local-suggestions (if result
|
||||
[{:type item-types/address
|
||||
:ens ens
|
||||
:address (eip55/address->checksum result)
|
||||
:networks [:ethereum :optimism]}]
|
||||
[])
|
||||
:wallet/valid-ens-or-address? (boolean result))}))
|
||||
|
||||
|
||||
|
||||
(rf/reg-event-fx :wallet/fetch-address-suggestions
|
||||
(fn [{:keys [db]} [address]]
|
||||
{:db (assoc db
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user