Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2883ac177d |
@@ -51,6 +51,7 @@ in {
|
||||
};
|
||||
|
||||
# Package version adjustments
|
||||
gradle = super.gradle_8.override { java = super.openjdk17_headless; };
|
||||
nodejs = super.nodejs_20;
|
||||
ruby = super.ruby_3_1;
|
||||
yarn = super.yarn.override { nodejs = super.nodejs_20; };
|
||||
|
||||
+2
-18
@@ -6,16 +6,8 @@ let
|
||||
# For testing local version of nixpkgs
|
||||
#nixpkgsSrc = (import <nixpkgs> { }).lib.cleanSource "/home/jakubgs/work/nixpkgs";
|
||||
|
||||
# We follow release 24-05 of nixpkgs
|
||||
# https://github.com/NixOS/nixpkgs/releases/tag/24.05
|
||||
nixpkgsSrc = builtins.fetchTarball {
|
||||
url = "https://github.com/NixOS/nixpkgs/archive/df27247e6f3e636c119e2610bf12d38b5e98cc79.tar.gz";
|
||||
sha256 = "sha256:0bbvimk7xb7akrx106mmsiwf9nzxnssisqmqffla03zz51d0kz2n";
|
||||
};
|
||||
|
||||
# FIXME: remove this additional source when nixpkgs includes gradle 8.8 in stable channel
|
||||
# We use a commit from the unstable channel of nixpkgs for gradle 8.8
|
||||
gradleNixpkgsSrc = builtins.fetchTarball {
|
||||
nixpkgsSrc = builtins.fetchTarball {
|
||||
url = "https://github.com/NixOS/nixpkgs/archive/48d567fc7b299de90f70a48e4263e31f690ba03e.tar.gz";
|
||||
sha256 = "sha256:0zynbk52khdfhg4qfv26h3r5156xff5p0cga2cin7b07i7lqminh";
|
||||
};
|
||||
@@ -29,14 +21,6 @@ let
|
||||
# Override some packages and utilities
|
||||
pkgsOverlay = import ./overlay.nix;
|
||||
|
||||
# FIXME: remove this additional source when nixpkgs includes gradle 8.8 in stable channel
|
||||
gradleOverlay = final: prev: {
|
||||
gradle = (import gradleNixpkgsSrc {
|
||||
inherit (prev) system;
|
||||
config = defaultConfig // config;
|
||||
}).gradle_8.override { java = prev.openjdk17_headless; };
|
||||
};
|
||||
|
||||
# Fix for lack of Android SDK for M1 Macs.
|
||||
systemOverride = let
|
||||
inherit (builtins) currentSystem getEnv;
|
||||
@@ -51,5 +35,5 @@ in
|
||||
(import nixpkgsSrc) {
|
||||
config = defaultConfig // config;
|
||||
system = systemOverride;
|
||||
overlays = [ pkgsOverlay gradleOverlay ];
|
||||
overlays = [ pkgsOverlay ];
|
||||
}
|
||||
|
||||
@@ -180,17 +180,17 @@
|
||||
},
|
||||
"shards.staging": {
|
||||
"tcp/p2p/waku/boot": {
|
||||
"boot-01.do-ams3.shards.staging": "/dns4/boot-01.do-ams3.shards.staging.status.im/tcp/30303/p2p/16Uiu2HAmQE7FXQc6iZHdBzYfw3qCSDa9dLc1wsBJKoP4aZvztq2d",
|
||||
"boot-01.do-ams3.shards.staging": "/dns4/boot-01.do-ams3.shards.staging.status.im/tcp/30303/p2p/16Uiu2HAmEqqio4UR1SWqAc7KY19t6qyDvtmyjreZpzUBJvb4u65R",
|
||||
"boot-01.gc-us-central1-a.shards.staging": "/dns4/boot-01.gc-us-central1-a.shards.staging.status.im/tcp/30303/p2p/16Uiu2HAmGAA54bBTE78MYidSy3P7Q9yAWFNTAEReJYD69VRvtL5r",
|
||||
"boot-01.ac-cn-hongkong-c.shards.staging": "/dns4/boot-01.ac-cn-hongkong-c.shards.staging.status.im/tcp/30303/p2p/16Uiu2HAmNTpGnyZ8W1BK2sXEmgSCNWiyDKgRU3NBR2DXST2HzxRU"
|
||||
},
|
||||
"enr/p2p/waku/boot": {
|
||||
"boot-01.do-ams3.shards.staging": "enr:-QEQuEBuiQgFlJNcv255042zwyl4pOBOivakX8N30Dr9vaaEU2q8-7N4GVY4Hk87iEKELjlIXTpE9Wj6EQq1lrBuc7ayAYJpZIJ2NIJpcISPxvrpim11bHRpYWRkcnO4YAAtNihib290LTAxLmRvLWFtczMuc3RhdHVzLnN0YWdpbmcuc3RhdHVzLmltBnZfAC82KGJvb3QtMDEuZG8tYW1zMy5zdGF0dXMuc3RhZ2luZy5zdGF0dXMuaW0GAbveA4Jyc40AEAUAAQAgAEAAgAEAiXNlY3AyNTZrMaEDq-yGgpuoUG6NKkbIDRmrMiT-bEVzFlpWLEK_rF3yKUaDdGNwgnZfg3VkcIIjKIV3YWt1Mg0",
|
||||
"boot-01.do-ams3.shards.staging": "enr:-QEQuEDsh6FgAb_36cReaX7W4gWx_7_GNpsUki7bXMoMrrrWij5pDEyV3guR-urDW_6GJTAzpQiJV61F-CfNn_NxPbY-AYJpZIJ2NIJpcISPxvrpim11bHRpYWRkcnO4YAAtNihib290LTAxLmRvLWFtczMuc2hhcmRzLnN0YWdpbmcuc3RhdHVzLmltBnZfAC82KGJvb3QtMDEuZG8tYW1zMy5zaGFyZHMuc3RhZ2luZy5zdGF0dXMuaW0GAbveA4Jyc40AEAUAAQAgAEAAgAEAiXNlY3AyNTZrMaEDIH8BcuEzgnmwPQTu7BPYyg4u4om7K9qekKA2gT_H2wSDdGNwgnZfg3VkcIIjKIV3YWt1Mg0",
|
||||
"boot-01.gc-us-central1-a.shards.staging": "enr:-QEiuECWCuk1CoefbPYUV_cff27t-471k_QhJ_MvgOUQmRE4vgI6h9fD4LgXy7TZNSFXeBBP9haWJB7lx8Wujx-LPmhrAYJpZIJ2NIJpcIRoxQVgim11bHRpYWRkcnO4cgA2NjFib290LTAxLmdjLXVzLWNlbnRyYWwxLWEuc2hhcmRzLnN0YWdpbmcuc3RhdHVzLmltBnZfADg2MWJvb3QtMDEuZ2MtdXMtY2VudHJhbDEtYS5zaGFyZHMuc3RhZ2luZy5zdGF0dXMuaW0GAbveA4Jyc40AEAUAAQAgAEAAgAEAiXNlY3AyNTZrMaEDNAvlGjekD1YV4WpmjwArGAH2g9kHFJnMRfgUhcIkoA2DdGNwgnZfg3VkcIIjKIV3YWt1Mg0",
|
||||
"boot-01.ac-cn-hongkong-c.shards.staging": "enr:-QEiuEAcHWW7aNBtJhigTCAnKu9-H1b98SWpBJkGm3PAxth5QjJA0kdiabOfou4HgCD6RuyZEnFE5L8ymahouw3kWRiWAYJpZIJ2NIJpcIQvTKi6im11bHRpYWRkcnO4cgA2NjFib290LTAxLmFjLWNuLWhvbmdrb25nLWMuc2hhcmRzLnN0YWdpbmcuc3RhdHVzLmltBnZfADg2MWJvb3QtMDEuYWMtY24taG9uZ2tvbmctYy5zaGFyZHMuc3RhZ2luZy5zdGF0dXMuaW0GAbveA4Jyc40AEAUAAQAgAEAAgAEAiXNlY3AyNTZrMaEDkbgV7oqPNmFtX5FzSPi9WH8kkmrPB1R3n9xRXge91M-DdGNwgnZfg3VkcIIjKIV3YWt1Mg0"
|
||||
},
|
||||
"wss/p2p/waku/boot": {
|
||||
"boot-01.do-ams3.shards.staging": "/dns4/boot-01.do-ams3.shards.staging.status.im/tcp/443/wss/p2p/16Uiu2HAmQE7FXQc6iZHdBzYfw3qCSDa9dLc1wsBJKoP4aZvztq2d",
|
||||
"boot-01.do-ams3.shards.staging": "/dns4/boot-01.do-ams3.shards.staging.status.im/tcp/443/wss/p2p/16Uiu2HAmEqqio4UR1SWqAc7KY19t6qyDvtmyjreZpzUBJvb4u65R",
|
||||
"boot-01.gc-us-central1-a.shards.staging": "/dns4/boot-01.gc-us-central1-a.shards.staging.status.im/tcp/443/wss/p2p/16Uiu2HAmGAA54bBTE78MYidSy3P7Q9yAWFNTAEReJYD69VRvtL5r",
|
||||
"boot-01.ac-cn-hongkong-c.shards.staging": "/dns4/boot-01.ac-cn-hongkong-c.shards.staging.status.im/tcp/443/wss/p2p/16Uiu2HAmNTpGnyZ8W1BK2sXEmgSCNWiyDKgRU3NBR2DXST2HzxRU"
|
||||
},
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 999 B |
Binary file not shown.
|
Before Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 31 KiB |
@@ -256,10 +256,9 @@
|
||||
{:events [:pairing/pair-and-sync]}
|
||||
[cofx installation-id]
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method "wakuext_enableInstallationAndSync"
|
||||
:params [{:installationId installation-id}]
|
||||
:js-response true
|
||||
:on-success [:sanitize-messages-and-process-response]}]]]})
|
||||
[{:method "wakuext_enableInstallationAndSync"
|
||||
:params [{:installationId installation-id}]
|
||||
:on-success #(log/debug "successfully synced devices")}]]]})
|
||||
|
||||
(rf/defn enable-installation-success
|
||||
{:events [:pairing.callback/enable-installation-success]}
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
:accessibility-label :receive}]
|
||||
(when swap-action
|
||||
[action-button
|
||||
{:icon :i/transaction
|
||||
{:icon :i/swap
|
||||
:text (i18n/label :t/swap)
|
||||
:on-press swap-action
|
||||
:theme theme
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
:type type
|
||||
:include-button? include-button?})
|
||||
style)}
|
||||
[icons/icon (or icon :i/info)
|
||||
[icons/icon icon
|
||||
{:color (style/get-color-by-type theme type :icon)
|
||||
:no-color no-icon-color?
|
||||
:size (or icon-size 16)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
(ns quo.components.list-items.network-list.view
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[quo.components.icon :as icon]
|
||||
[quo.components.list-items.network-list.style :as style]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.theme :as quo.theme]
|
||||
@@ -43,8 +42,8 @@
|
||||
[:map {:closed true}
|
||||
[:network-image :int]
|
||||
[:label :string]
|
||||
[:fiat-value {:optional true} [:maybe :string]]
|
||||
[:token-value {:optional true} [:maybe :string]]
|
||||
[:fiat-value :string]
|
||||
[:token-value :string]
|
||||
[:container-style {:optional true} [:maybe :map]]
|
||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
|
||||
[:state {:optional true} [:enum :pressed :active :disabled :default]]
|
||||
@@ -52,7 +51,7 @@
|
||||
:any])
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [fiat-value token-value on-press container-style state customization-color]
|
||||
[{:keys [on-press container-style state customization-color]
|
||||
:as props
|
||||
:or {customization-color :blue}}]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
@@ -68,8 +67,6 @@
|
||||
:on-press (when-not (= state :disabled) on-press)
|
||||
:accessibility-label :network-list}
|
||||
[info props]
|
||||
(if (or token-value fiat-value)
|
||||
[values props]
|
||||
[icon/icon :i/chevron-right])]))
|
||||
[values props]]))
|
||||
|
||||
(def view (schema/instrument #'view-internal ?schema))
|
||||
|
||||
@@ -4,10 +4,12 @@
|
||||
[container-style]
|
||||
(merge container-style
|
||||
{:flex-direction :row
|
||||
:flex 1
|
||||
:align-items :flex-start}))
|
||||
|
||||
(def index
|
||||
{:margin-left 5})
|
||||
|
||||
(def text-container
|
||||
{:margin-left 8})
|
||||
{:margin-left 8
|
||||
:flex 1})
|
||||
|
||||
@@ -60,8 +60,7 @@
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [type account-props token-props networks? values]}]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
address (or (:address account-props) (:address token-props))]
|
||||
(let [theme (quo.theme/use-theme)]
|
||||
[rn/view
|
||||
{:style (style/container networks? theme)}
|
||||
[rn/view
|
||||
@@ -90,13 +89,12 @@
|
||||
(get-in account-props [:status-account :name])]
|
||||
[rn/view
|
||||
{:style (style/dot-divider theme)}]])
|
||||
(when address
|
||||
[text/text
|
||||
{:size (when (not= type :account) :paragraph-2)
|
||||
:weight (when (= type :account) :semi-bold)
|
||||
:style {:color (when (not= type :account)
|
||||
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme))}}
|
||||
address])]]]
|
||||
[text/text
|
||||
{:size (when (not= type :account) :paragraph-2)
|
||||
:weight (when (= type :account) :semi-bold)
|
||||
:style {:color (when (not= type :account)
|
||||
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme))}}
|
||||
(or (:address account-props) (:address token-props))]]]]
|
||||
(when networks?
|
||||
[:<>
|
||||
[rn/view
|
||||
|
||||
@@ -75,16 +75,3 @@
|
||||
|
||||
(def fiat-amount
|
||||
{:color colors/neutral-50})
|
||||
|
||||
(def gradient-common
|
||||
{:width 64
|
||||
:position :absolute
|
||||
:top 0
|
||||
:bottom 0
|
||||
:z-index 1})
|
||||
|
||||
(def gradient-start
|
||||
(assoc gradient-common :left 0))
|
||||
|
||||
(def gradient-end
|
||||
(assoc gradient-common :right 0))
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
[quo.foundations.colors :as colors]
|
||||
quo.theme
|
||||
[react-native.core :as rn]
|
||||
[react-native.linear-gradient :as linear-gradient]
|
||||
[schema.core :as schema]))
|
||||
|
||||
(def ?schema
|
||||
@@ -19,7 +18,6 @@
|
||||
[:catn
|
||||
[:props
|
||||
[:map {:closed true}
|
||||
[:get-ref {:optional true} [:maybe fn?]]
|
||||
[:type {:optional true} [:maybe [:enum :pay :receive]]]
|
||||
[:status {:optional true} [:maybe [:enum :default :typing :disabled :loading]]]
|
||||
[:token {:optional true} [:maybe :string]]
|
||||
@@ -44,65 +42,26 @@
|
||||
[:container-style {:optional true} [:maybe :map]]]]]
|
||||
:any])
|
||||
|
||||
(def icon-size 32)
|
||||
(def container-padding (* 2 (:padding (style/row-1 false))))
|
||||
(def max-cursor-position 5)
|
||||
|
||||
(defn view-internal
|
||||
[{:keys [type status token value fiat-value show-approval-label? error? network-tag-props
|
||||
approval-label-props default-value auto-focus? input-disabled? enable-swap?
|
||||
currency-symbol on-change-text show-keyboard? get-ref
|
||||
currency-symbol on-change-text show-keyboard?
|
||||
container-style on-swap-press on-token-press on-max-press on-input-focus]}]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
pay? (= type :pay)
|
||||
disabled? (= status :disabled)
|
||||
loading? (= status :loading)
|
||||
typing? (= status :typing)
|
||||
controlled-input? (some? value)
|
||||
[container-width
|
||||
set-container-width] (rn/use-state)
|
||||
[overflow?
|
||||
set-overflow?] (rn/use-state false)
|
||||
[cursor-close-to-start?
|
||||
set-cursor-close-to-start?] (rn/use-state false)
|
||||
[label-width
|
||||
set-label-width] (rn/use-state 0)
|
||||
input-ref (rn/use-ref-atom nil)
|
||||
set-input-ref (rn/use-callback (fn [ref]
|
||||
(reset! input-ref ref)
|
||||
(when get-ref (get-ref ref)))
|
||||
[])
|
||||
focus-input (rn/use-callback (fn []
|
||||
(some-> @input-ref
|
||||
(oops/ocall "focus")))
|
||||
[input-ref])
|
||||
on-layout-container (rn/use-callback
|
||||
(fn [e]
|
||||
(let [width (oops/oget e "nativeEvent.layout.width")]
|
||||
(set-container-width width))))
|
||||
on-layout-text-input (rn/use-callback
|
||||
(fn [e]
|
||||
(let [width (oops/oget e "nativeEvent.layout.width")
|
||||
max-width (- container-width
|
||||
icon-size
|
||||
container-padding
|
||||
(* label-width 2))]
|
||||
(set-overflow? (> width max-width))))
|
||||
[container-width label-width])
|
||||
on-layout-label (rn/use-callback
|
||||
(fn [e]
|
||||
(let [width (oops/oget e "nativeEvent.layout.width")]
|
||||
(set-label-width width))))
|
||||
on-selection-change (rn/use-callback
|
||||
(fn [e]
|
||||
(let [selection-start (oops/oget e
|
||||
"nativeEvent.selection.start")]
|
||||
(set-cursor-close-to-start?
|
||||
(< selection-start max-cursor-position)))))]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
pay? (= type :pay)
|
||||
disabled? (= status :disabled)
|
||||
loading? (= status :loading)
|
||||
typing? (= status :typing)
|
||||
controlled-input? (some? value)
|
||||
input-ref (rn/use-ref-atom nil)
|
||||
set-input-ref (rn/use-callback (fn [ref] (reset! input-ref ref)) [])
|
||||
focus-input (rn/use-callback (fn []
|
||||
(some-> @input-ref
|
||||
(oops/ocall "focus")))
|
||||
[input-ref])]
|
||||
[rn/view
|
||||
{:style container-style
|
||||
:accessibility-label :swap-input
|
||||
:on-layout on-layout-container}
|
||||
:accessibility-label :swap-input}
|
||||
[rn/view {:style (style/content typing? theme)}
|
||||
[rn/view
|
||||
{:style (style/row-1 loading?)}
|
||||
@@ -116,43 +75,25 @@
|
||||
[rn/pressable
|
||||
{:style style/input-container
|
||||
:on-press focus-input}
|
||||
[rn/view {:style {:flex-shrink 1}}
|
||||
(when (and overflow? typing? (not cursor-close-to-start?))
|
||||
[linear-gradient/linear-gradient
|
||||
{:start {:x 0 :y 0}
|
||||
:end {:x 1 :y 0}
|
||||
:colors [(colors/theme-colors colors/white colors/neutral-100 theme)
|
||||
(colors/theme-colors colors/white-opa-10 colors/neutral-100-opa-10 theme)]
|
||||
:style style/gradient-start}])
|
||||
(when (and overflow? disabled?)
|
||||
[linear-gradient/linear-gradient
|
||||
{:start {:x 0 :y 0}
|
||||
:end {:x 1 :y 0}
|
||||
:colors [(colors/theme-colors colors/white-opa-10 colors/neutral-100-opa-10 theme)
|
||||
(colors/theme-colors colors/white colors/neutral-100 theme)]
|
||||
:style style/gradient-end}])
|
||||
[rn/text-input
|
||||
(cond-> {:ref set-input-ref
|
||||
:style (style/input disabled? error? theme)
|
||||
:placeholder-text-color (colors/theme-colors colors/neutral-40
|
||||
colors/neutral-50
|
||||
theme)
|
||||
:keyboard-type :numeric
|
||||
:editable (not input-disabled?)
|
||||
:auto-focus auto-focus?
|
||||
:on-focus on-input-focus
|
||||
:on-change-text on-change-text
|
||||
:on-layout on-layout-text-input
|
||||
:on-selection-change on-selection-change
|
||||
:show-soft-input-on-focus show-keyboard?
|
||||
:default-value default-value
|
||||
:placeholder "0"}
|
||||
controlled-input? (assoc :value value))]]
|
||||
[rn/text-input
|
||||
(cond-> {:ref set-input-ref
|
||||
:style (style/input disabled? error? theme)
|
||||
:placeholder-text-color (colors/theme-colors colors/neutral-40
|
||||
colors/neutral-50
|
||||
theme)
|
||||
:keyboard-type :numeric
|
||||
:editable (not input-disabled?)
|
||||
:auto-focus auto-focus?
|
||||
:on-focus on-input-focus
|
||||
:on-change-text on-change-text
|
||||
:show-soft-input-on-focus show-keyboard?
|
||||
:default-value default-value
|
||||
:placeholder "0"}
|
||||
controlled-input? (assoc :value value))]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :semi-bold
|
||||
:style (style/token-symbol theme)
|
||||
:on-layout on-layout-label}
|
||||
{:size :paragraph-2
|
||||
:weight :semi-bold
|
||||
:style (style/token-symbol theme)}
|
||||
token]]
|
||||
(when (and pay? enable-swap?)
|
||||
[buttons/button
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
(def transaction-icon
|
||||
{:send :i/send
|
||||
:swap :i/transaction
|
||||
:swap :i/swap
|
||||
:bridge :i/bridge})
|
||||
|
||||
(defn transaction-header
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
(def transaction-icon
|
||||
{:receive :i/receive
|
||||
:send :i/send
|
||||
:swap :i/transaction
|
||||
:swap :i/swap
|
||||
:bridge :i/bridge
|
||||
:buy :i/buy
|
||||
:destroy :i/destroy
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
(take 7)))
|
||||
|
||||
(defn recovery-phrase-screen
|
||||
[{:keys [banner-offset initial-insets keypair title on-success render-controls]}]
|
||||
[{:keys [banner-offset initial-insets keypair title recovering-keypair? render-controls]}]
|
||||
(reagent/with-let [keyboard-shown? (reagent/atom false)
|
||||
keyboard-show-listener (.addListener rn/keyboard
|
||||
"keyboardDidShow"
|
||||
@@ -120,20 +120,14 @@
|
||||
(reset! seed-phrase new-phrase))
|
||||
on-submit (fn []
|
||||
(swap! seed-phrase clean-seed-phrase)
|
||||
(rf/dispatch
|
||||
[:profile.recover/validate-recovery-phrase
|
||||
(security/mask-data @seed-phrase)
|
||||
{:on-success (fn [mnemonic key-uid]
|
||||
(if on-success
|
||||
(on-success
|
||||
{:key-uid key-uid
|
||||
:phrase mnemonic
|
||||
:on-error
|
||||
set-invalid-seed-phrase})
|
||||
(rf/dispatch
|
||||
[:onboarding/seed-phrase-validated
|
||||
mnemonic key-uid])))
|
||||
:on-error set-invalid-seed-phrase}]))]
|
||||
(if recovering-keypair?
|
||||
(rf/dispatch [:wallet/seed-phrase-entered
|
||||
(security/mask-data
|
||||
@seed-phrase)
|
||||
set-invalid-seed-phrase])
|
||||
(rf/dispatch [:onboarding/seed-phrase-entered
|
||||
(security/mask-data @seed-phrase)
|
||||
set-invalid-seed-phrase])))]
|
||||
(let [words-coll (mnemonic/passphrase->words @seed-phrase)
|
||||
last-word (peek words-coll)
|
||||
pick-suggested-word (fn [pressed-word]
|
||||
@@ -197,7 +191,7 @@
|
||||
[rn/view {:style style/keyboard-container}
|
||||
[quo/predictive-keyboard
|
||||
{:type suggestions-state
|
||||
:blur? (not on-success)
|
||||
:blur? (not recovering-keypair?)
|
||||
:text suggestions-text
|
||||
:words (keyboard-suggestions last-word)
|
||||
:on-press pick-suggested-word}]])])
|
||||
@@ -206,7 +200,7 @@
|
||||
(.remove keyboard-hide-listener))))
|
||||
|
||||
(defn screen
|
||||
[{:keys [title keypair navigation-icon on-success render-controls]}]
|
||||
[{:keys [title keypair navigation-icon recovering-keypair? render-controls]}]
|
||||
(let [[insets _] (rn/use-state (safe-area/get-insets))
|
||||
banner-offset (rf/sub [:alert-banners/top-margin])]
|
||||
[rn/view {:style style/full-layout}
|
||||
@@ -215,22 +209,21 @@
|
||||
{:margin-top (:top insets)
|
||||
:background :blur
|
||||
:icon-name (or navigation-icon
|
||||
(if on-success :i/close :i/arrow-left))
|
||||
(if recovering-keypair? :i/close :i/arrow-left))
|
||||
:on-press #(rf/dispatch [:navigate-back])}]
|
||||
[recovery-phrase-screen
|
||||
{:title title
|
||||
:keypair keypair
|
||||
:render-controls render-controls
|
||||
:banner-offset banner-offset
|
||||
:initial-insets insets
|
||||
:on-success on-success}]]]))
|
||||
{:title title
|
||||
:keypair keypair
|
||||
:render-controls render-controls
|
||||
:banner-offset banner-offset
|
||||
:initial-insets insets
|
||||
:recovering-keypair? recovering-keypair?}]]]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [{:keys [on-success]} (rf/sub [:get-screen-params])]
|
||||
(let [{:keys [recovering-keypair?]} (rf/sub [:get-screen-params])]
|
||||
(rn/use-unmount
|
||||
(when-not on-success
|
||||
#(rf/dispatch [:onboarding/clear-navigated-to-enter-seed-phrase-from-screen])))
|
||||
#(rf/dispatch [:onboarding/clear-navigated-to-enter-seed-phrase-from-screen]))
|
||||
[screen
|
||||
{:title (i18n/label :t/use-recovery-phrase)
|
||||
:on-success on-success}]))
|
||||
{:title (i18n/label :t/use-recovery-phrase)
|
||||
:recovering-keypair? recovering-keypair?}]))
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
:generate-keys1 (js/require "../resources/images/ui2/generating-keys-1.png")
|
||||
:ethereum-address (js/require "../resources/images/ui2/ethereum-address.png")
|
||||
:use-keycard (js/require "../resources/images/ui2/keycard.png")
|
||||
:check-your-keycard (js/require "../resources/images/ui2/check-your-keycard.png")
|
||||
:onboarding-illustration (js/require "../resources/images/ui2/onboarding_illustration.png")
|
||||
:qr-code (js/require "../resources/images/ui2/qr-code.png")
|
||||
:keycard-logo (js/require "../resources/images/ui2/keycard-logo.png")
|
||||
|
||||
@@ -45,15 +45,3 @@
|
||||
#(rf/dispatch [:profile.login/login-with-biometric-if-available
|
||||
(get-in db [:profile/login :key-uid])]))
|
||||
:shell? true}]]]})))
|
||||
|
||||
(rf/reg-fx :effects.centralized-metrics/track
|
||||
(fn [event]
|
||||
(native-module/add-centralized-metric event)))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:centralized-metrics/track
|
||||
(fn [{:keys [db]} [event-name data]]
|
||||
(let [event-id (name event-name)]
|
||||
(when (push-event? db)
|
||||
{:fx [[:effects.centralized-metrics/track
|
||||
(tracking/key-value-event event-id data)]]}))))
|
||||
|
||||
@@ -4,20 +4,20 @@
|
||||
[react-native.platform :as platform]))
|
||||
|
||||
(defn key-value-event
|
||||
[event-name event-value]
|
||||
[event-name val-key value]
|
||||
{:metric
|
||||
{:eventName event-name
|
||||
:platform platform/os
|
||||
:appVersion build/app-short-version
|
||||
:eventValue event-value}})
|
||||
:eventValue {val-key value}}})
|
||||
|
||||
(defn user-journey-event
|
||||
[action]
|
||||
(key-value-event "user-journey" {:action action}))
|
||||
(key-value-event "user-journey" :action action))
|
||||
|
||||
(defn navigation-event
|
||||
[view-id]
|
||||
(key-value-event "navigation" {:viewId view-id}))
|
||||
(key-value-event "navigation" :viewId view-id))
|
||||
|
||||
(def ^:const app-started-event "app-started")
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
(user-journey-event app-started-event)
|
||||
|
||||
:centralized-metrics/toggle-centralized-metrics
|
||||
(key-value-event "events.metrics-enabled" {:enabled second-parameter})
|
||||
(key-value-event "events.metrics-enabled" :enabled second-parameter)
|
||||
|
||||
:set-view-id
|
||||
(track-view-id-event second-parameter)
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
:platform platform-os
|
||||
:appVersion app-version
|
||||
:eventValue {val-key value}}}]
|
||||
(is (= expected (tracking/key-value-event event-name {val-key value}))))))
|
||||
(is (= expected (tracking/key-value-event event-name val-key value))))))
|
||||
|
||||
(deftest user-journey-event-test
|
||||
(testing "creates correct user journey event"
|
||||
|
||||
+19
-17
@@ -11,23 +11,25 @@
|
||||
|
||||
(defn view
|
||||
[{:keys [contact-id]}]
|
||||
(let [customization-color (rf/sub [:profile/customization-color])
|
||||
[primary-name _] (rf/sub [:contacts/contact-two-names-by-identity contact-id])
|
||||
{:keys [contact-request-state
|
||||
community-id]} (rf/sub [:chats/current-chat-chat-view])
|
||||
chat-type (rf/sub [:chats/chat-type])
|
||||
community-chat? (= chat-type :community-chat)
|
||||
joined (when community-chat?
|
||||
(rf/sub [:communities/community-joined community-id]))
|
||||
pending? (when community-chat?
|
||||
(rf/sub [:communities/my-pending-request-to-join community-id]))
|
||||
contact-request-send? (or (not contact-request-state)
|
||||
(= contact-request-state
|
||||
constants/contact-request-state-none))
|
||||
contact-request-received? (= contact-request-state
|
||||
constants/contact-request-state-received)
|
||||
contact-request-pending? (= contact-request-state
|
||||
constants/contact-request-state-sent)]
|
||||
(let [customization-color (rf/sub [:profile/customization-color])
|
||||
[primary-name _] (rf/sub [:contacts/contact-two-names-by-identity
|
||||
contact-id])
|
||||
{:keys [contact-request-state community-id]} (rf/sub [:chats/current-chat-chat-view])
|
||||
chat-type (rf/sub [:chats/chat-type])
|
||||
community-chat? (= chat-type :community-chat)
|
||||
joined (when community-chat?
|
||||
(rf/sub [:communities/community-joined
|
||||
community-id]))
|
||||
pending? (when community-chat?
|
||||
(rf/sub [:communities/my-pending-request-to-join
|
||||
community-id]))
|
||||
contact-request-send? (or (not contact-request-state)
|
||||
(= contact-request-state
|
||||
constants/contact-request-state-none))
|
||||
contact-request-received? (= contact-request-state
|
||||
constants/contact-request-state-received)
|
||||
contact-request-pending? (= contact-request-state
|
||||
constants/contact-request-state-sent)]
|
||||
[rn/view {:style style/container}
|
||||
[quo/permission-context
|
||||
{:blur? true
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
(ns status-im.contexts.chat.messenger.messages.list.style
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[quo.foundations.shadows :as shadows]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[status-im.contexts.chat.messenger.messages.constants :as messages.constants]))
|
||||
|
||||
(def permission-context-height 46)
|
||||
(def distance-from-last-message 4)
|
||||
|
||||
(defn keyboard-avoiding-container
|
||||
[theme]
|
||||
@@ -13,13 +13,70 @@
|
||||
:background-color (colors/theme-colors colors/white colors/neutral-95 theme)
|
||||
:z-index 2})
|
||||
|
||||
(def permission-context-sheet {:flex 3}) ; Pushes composer to bottom
|
||||
(defn background-container
|
||||
[background-color background-opacity top-margin]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:opacity background-opacity}
|
||||
{:background-color background-color
|
||||
:position :absolute
|
||||
:top 0
|
||||
:left 0
|
||||
:right 0
|
||||
:height (+ top-margin messages.constants/header-container-radius)}))
|
||||
|
||||
(defn list-paddings
|
||||
[add-padding-bottom?]
|
||||
(let [{:keys [top bottom]} (safe-area/get-insets)]
|
||||
;; WARNING: the flat-list is reversed, so the paddings are applied inverted
|
||||
{:padding-top (if add-padding-bottom?
|
||||
(+ distance-from-last-message permission-context-height bottom)
|
||||
distance-from-last-message)
|
||||
:padding-bottom (+ top messages.constants/top-bar-height)}))
|
||||
(defn header-bottom-container
|
||||
[bottom top-margin]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:bottom bottom}
|
||||
{:margin-top top-margin}))
|
||||
|
||||
(defn header-bottom-part
|
||||
[theme]
|
||||
{:background-color (colors/theme-colors colors/white colors/neutral-95 theme)
|
||||
:padding-horizontal 20
|
||||
:border-radius 20})
|
||||
|
||||
(defn header-bottom-shadow
|
||||
[theme]
|
||||
(assoc
|
||||
(shadows/get 2 theme :inverted)
|
||||
:left 0
|
||||
:right 0
|
||||
:height 40
|
||||
:position :absolute
|
||||
:border-radius 20))
|
||||
|
||||
(defn header-image
|
||||
[scale top left theme]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:transform [{:scale scale}]
|
||||
:top top
|
||||
:left left}
|
||||
{:position :absolute
|
||||
:border-width 4
|
||||
:border-radius 50
|
||||
:background-color (colors/theme-colors colors/white colors/neutral-95 theme)
|
||||
:border-color (colors/theme-colors colors/white colors/neutral-95 theme)}))
|
||||
|
||||
(defn user-name-container
|
||||
[top left]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:top top
|
||||
:left left}
|
||||
{:z-index -1}))
|
||||
|
||||
(def user-name
|
||||
{:align-items :center
|
||||
:flex-direction :row
|
||||
:margin-top 52})
|
||||
|
||||
(defn bio-and-actions
|
||||
[top]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:top top}
|
||||
{:row-gap 16}))
|
||||
|
||||
(defn permission-context-sheet
|
||||
[margin-bottom?]
|
||||
{:flex 3 ;; Pushes composer to bottom
|
||||
:margin-bottom (when margin-bottom? permission-context-height)})
|
||||
|
||||
@@ -10,9 +10,11 @@
|
||||
[react-native.hooks :as hooks]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[status-im.common.home.actions.view :as home.actions]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.chat.messenger.composer.constants :as composer.constants]
|
||||
[status-im.contexts.chat.messenger.messages.constants :as messages.constants]
|
||||
[status-im.contexts.chat.messenger.messages.content.view :as message]
|
||||
[status-im.contexts.chat.messenger.messages.list.state :as state]
|
||||
[status-im.contexts.chat.messenger.messages.list.style :as style]
|
||||
@@ -22,6 +24,7 @@
|
||||
[utils.re-frame :as rf]
|
||||
[utils.worklets.chat.messenger.messages :as worklets]))
|
||||
|
||||
(def ^:const distance-from-last-message 4)
|
||||
(def ^:const loading-indicator-page-loading-height 100)
|
||||
|
||||
(defn list-key-fn [{:keys [message-id value]}] (or message-id value))
|
||||
@@ -191,9 +194,10 @@
|
||||
context (rf/sub [:chats/current-chat-message-list-view-context])
|
||||
able-to-send-message? (:able-to-send-message? context)
|
||||
messages (rf/sub [:chats/raw-chat-messages-stream chat-id])
|
||||
add-padding-bottom? (and community-channel? (not able-to-send-message?))
|
||||
recording? (rf/sub [:chats/recording?])]
|
||||
[rn/view {:style style/permission-context-sheet}
|
||||
margin-bottom? (and community-channel? (not able-to-send-message?))
|
||||
recording? (rf/sub [:chats/recording?])
|
||||
top-margin (+ (safe-area/get-top) messages.constants/top-bar-height)]
|
||||
[rn/view {:style (style/permission-context-sheet margin-bottom?)}
|
||||
[rn/view {:style {:flex-shrink 1}} ;; Keeps flat list on top
|
||||
[reanimated/flat-list
|
||||
{:key-fn list-key-fn
|
||||
@@ -233,7 +237,8 @@
|
||||
:style {:background-color (colors/theme-colors colors/white
|
||||
colors/neutral-95
|
||||
theme)}
|
||||
:content-container-style (style/list-paddings add-padding-bottom?)
|
||||
:content-container-style {:padding-top distance-from-last-message
|
||||
:padding-bottom top-margin}
|
||||
:inverted true
|
||||
:on-layout #(on-layout
|
||||
{:event %
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
(ns status-im.contexts.keycard.authorise.view
|
||||
(:require [quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[status-im.common.events-helper :as events-helper]
|
||||
[status-im.common.standard-authentication.core :as standard-auth]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.security.core :as security]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [profile-name (rf/sub [:profile/name])
|
||||
profile-picture (rf/sub [:profile/image])
|
||||
customization-color (rf/sub [:profile/customization-color])]
|
||||
[:<>
|
||||
[quo/page-nav
|
||||
{:key :header
|
||||
:background :blur
|
||||
:icon-name :i/close
|
||||
:on-press events-helper/navigate-back}]
|
||||
[quo/page-top
|
||||
{:title (i18n/label :t/authorise-with-password)
|
||||
:description :context-tag
|
||||
:context-tag {:full-name profile-name
|
||||
:profile-picture profile-picture
|
||||
:customization-color customization-color}}]
|
||||
[rn/view {:style {:flex 1 :padding-horizontal 20 :justify-content :space-between}}
|
||||
[quo/text (i18n/label :t/migrate-key-pair-authorise)]
|
||||
[standard-auth/slide-button
|
||||
{:size :size-48
|
||||
:container-style {}
|
||||
:customization-color customization-color
|
||||
:track-text (i18n/label :t/slide-to-authorise)
|
||||
:on-auth-success #(println "TBD" (security/safe-unmask-data %))
|
||||
:auth-button-label (i18n/label :t/confirm)}]]]))
|
||||
@@ -1,36 +0,0 @@
|
||||
(ns status-im.contexts.keycard.check.view
|
||||
(:require [quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[status-im.common.events-helper :as events-helper]
|
||||
[status-im.common.resources :as resources]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
[:<>
|
||||
[quo/page-nav
|
||||
{:key :header
|
||||
:background :blur
|
||||
:icon-name :i/arrow-left
|
||||
:on-press events-helper/navigate-back}]
|
||||
[quo/page-top
|
||||
{:title (i18n/label :t/check-keycard)
|
||||
:description :text
|
||||
:description-text (i18n/label :t/see-keycard-ready)}]
|
||||
[rn/view {:style {:flex 1 :align-items :center :justify-content :center}}
|
||||
[rn/image
|
||||
{:resize-mode :contain
|
||||
:source (resources/get-image :check-your-keycard)}]]
|
||||
[quo/divider-label (i18n/label :t/tips-scan-keycard)]
|
||||
[rn/view {:style {:padding-horizontal 10}}
|
||||
[quo/markdown-list
|
||||
{:container-style {:padding-vertical 10}
|
||||
:description (i18n/label :t/remove-phone-case)}]
|
||||
[quo/markdown-list
|
||||
{:container-style {:padding-bottom 25}
|
||||
:description (i18n/label :t/keep-card-steady)}]]
|
||||
[quo/button
|
||||
{:on-press #(rf/dispatch [:keycard/connect])
|
||||
:container-style {:margin-horizontal 20}}
|
||||
(i18n/label :t/ready-to-scan)]])
|
||||
@@ -10,15 +10,10 @@
|
||||
|
||||
(defonce ^:private active-listeners (atom []))
|
||||
|
||||
(defn unregister-card-events
|
||||
(defn register-card-events
|
||||
[]
|
||||
(doseq [listener @active-listeners]
|
||||
(keycard/remove-event-listener listener))
|
||||
(reset! active-listeners nil))
|
||||
|
||||
(defn register-card-events
|
||||
[]
|
||||
(unregister-card-events)
|
||||
(reset! active-listeners
|
||||
[(keycard/on-card-connected #(rf/dispatch [:keycard/on-card-connected]))
|
||||
(keycard/on-card-disconnected #(rf/dispatch [:keycard/on-card-disconnected]))
|
||||
@@ -28,9 +23,7 @@
|
||||
(keycard/on-nfc-timeout #(rf/dispatch [:keycard.ios/on-nfc-timeout])))
|
||||
(keycard/on-nfc-enabled #(rf/dispatch [:keycard/on-check-nfc-enabled-success true]))
|
||||
(keycard/on-nfc-disabled #(rf/dispatch [:keycard/on-check-nfc-enabled-success false]))]))
|
||||
|
||||
(rf/reg-fx :effects.keycard/register-card-events register-card-events)
|
||||
(rf/reg-fx :effects.keycard/unregister-card-events unregister-card-events)
|
||||
|
||||
(defn check-nfc-enabled
|
||||
[]
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
(ns status-im.contexts.keycard.empty.view
|
||||
(:require [quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[status-im.common.events-helper :as events-helper]
|
||||
[status-im.common.resources :as resources]
|
||||
[status-im.contexts.keycard.sheets.migrate.view :as sheets.migrate]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
[:<>
|
||||
[quo/page-nav
|
||||
{:key :header
|
||||
:background :blur
|
||||
:icon-name :i/arrow-left
|
||||
:on-press events-helper/navigate-back}]
|
||||
[quo/page-top
|
||||
{:title (i18n/label :t/keycard-empty)
|
||||
:description :text
|
||||
:description-text (i18n/label :t/what-to-do)}]
|
||||
[rn/view {:style {:padding-horizontal 28 :padding-top 20}}
|
||||
[quo/small-option-card
|
||||
{:variant :main
|
||||
:title (i18n/label :t/import-key-pair-keycard)
|
||||
:subtitle (i18n/label :t/use-keycard-login-sign)
|
||||
:button-label (i18n/label :t/import-profile-key-pair)
|
||||
:accessibility-label :get-keycard
|
||||
:image (resources/get-image :generate-keys)
|
||||
:on-press #(rf/dispatch [:show-bottom-sheet
|
||||
{:theme :dark
|
||||
:content (fn [] [sheets.migrate/view])}])}]]
|
||||
[quo/information-box
|
||||
{:type :default
|
||||
:style {:margin-top 32 :margin-horizontal 28}}
|
||||
(i18n/label :t/empty-card-info)]])
|
||||
@@ -1,42 +0,0 @@
|
||||
(ns status-im.contexts.keycard.error.view
|
||||
(:require [quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[status-im.common.events-helper :as events-helper]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(def titles
|
||||
{:keycard/error.keycard-wrong {:title "Keycard is not empty"
|
||||
:description "You can’t use it to store new keys right now"}
|
||||
:keycard/error.keycard-unpaired {:title "Keycard is full"
|
||||
:description "All pairing slots are occupied"}
|
||||
:keycard/error.keycard-frozen {:title "Keycard is locked"
|
||||
:description "You can’t use it right now"}
|
||||
:keycard/error.keycard-locked {:title "Keycard is locked"
|
||||
:description "You can’t use it right now"}})
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [{:keys [top bottom]} (safe-area/get-insets)
|
||||
error (rf/sub [:keycard/application-info-error])
|
||||
{:keys [title description]} (get titles error)]
|
||||
[quo/overlay
|
||||
{:type :shell
|
||||
:container-style {:padding-top top
|
||||
:padding-bottom bottom}}
|
||||
[quo/page-nav
|
||||
{:key :header
|
||||
:background :blur
|
||||
:icon-name :i/arrow-left
|
||||
:on-press events-helper/navigate-back}]
|
||||
[quo/page-top
|
||||
{:title title
|
||||
:description :text
|
||||
:description-text description}]
|
||||
[rn/view {:height 226}]
|
||||
[rn/view {:padding-horizontal 20}
|
||||
[quo/info-message
|
||||
{:container-style {:padding-top 15}
|
||||
:icon :i/info
|
||||
:size :default}
|
||||
"To unlock or factory reset the Keycard, please use the Status desktop app. If you'd like this features on mobile, feel free to upvote them and discuss in the Status community."]]]))
|
||||
@@ -1,8 +1,8 @@
|
||||
(ns status-im.contexts.keycard.events
|
||||
(:require [re-frame.core :as rf]
|
||||
status-im.contexts.keycard.login.events
|
||||
status-im.contexts.keycard.nfc-sheet.events
|
||||
status-im.contexts.keycard.pin.events
|
||||
status-im.contexts.keycard.sheet.events
|
||||
status-im.contexts.keycard.sign.events
|
||||
[status-im.contexts.keycard.utils :as keycard.utils]
|
||||
[taoensso.timbre :as log]))
|
||||
@@ -14,9 +14,7 @@
|
||||
(rf/reg-event-fx :keycard.ios/on-nfc-user-cancelled
|
||||
(fn [{:keys [db]}]
|
||||
(log/debug "[keycard] nfc user cancelled")
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :pin :status] nil)
|
||||
(assoc-in [:keycard :on-nfc-cancelled-event-vector] nil))
|
||||
{:db (assoc-in db [:keycard :pin :status] nil)
|
||||
:fx [(when-let [on-nfc-cancelled-event-vector (get-in db [:keycard :on-nfc-cancelled-event-vector])]
|
||||
[:dispatch on-nfc-cancelled-event-vector])]}))
|
||||
|
||||
@@ -44,6 +42,12 @@
|
||||
{:db (assoc-in db [:keycard :card-connected?] false)
|
||||
:fx [[:dispatch-later [{:ms 500 :dispatch [:keycard.ios/start-nfc]}]]]}))
|
||||
|
||||
(rf/reg-event-fx :keycard/get-application-info
|
||||
(fn [_ [{:keys [on-success on-failure]}]]
|
||||
(log/debug "[keycard] get-application-info")
|
||||
{:effects.keycard/get-application-info {:on-success on-success
|
||||
:on-failure on-failure}}))
|
||||
|
||||
(rf/reg-event-fx :keycard/on-retrieve-pairings-success
|
||||
(fn [{:keys [db]} [pairings]]
|
||||
{:db (assoc-in db [:keycard :pairings] pairings)
|
||||
@@ -56,7 +60,7 @@
|
||||
|
||||
(rf/reg-event-fx :keycard/on-action-with-pin-error
|
||||
(fn [{:keys [db]} [error]]
|
||||
(log/debug "[keycard] on-action-with-pin-error: " error)
|
||||
(log/debug "[keycard] get keys error: " error)
|
||||
(let [tag-was-lost? (keycard.utils/tag-lost? (:error error))
|
||||
pin-retries-count (keycard.utils/pin-retries (:error error))]
|
||||
(if tag-was-lost?
|
||||
@@ -65,52 +69,7 @@
|
||||
{:effects.utils/show-popup {:title "wrong-keycard"}}
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :application-info :pin-retry-counter] pin-retries-count)
|
||||
(assoc-in [:keycard :pin :status] :error))
|
||||
:fx [[:dispatch [:keycard/disconnect]]
|
||||
(update-in [:keycard :pin] assoc :status :error))
|
||||
:fx [[:dispatch [:keycard/hide-connection-sheet]]
|
||||
(when (zero? pin-retries-count)
|
||||
[:effects.utils/show-popup {:title "frozen-keycard"}])]})))))
|
||||
|
||||
(rf/reg-event-fx :keycard/on-get-application-info-success
|
||||
(fn [{:keys [db]} [application-info {:keys [key-uid on-success-fx]}]]
|
||||
(if-let [error (keycard.utils/validate-application-info key-uid application-info)]
|
||||
(case error
|
||||
:keycard/error.not-keycard
|
||||
{:fx [[:dispatch [:keycard/disconnect]]
|
||||
[:dispatch [:open-modal :screen/keycard.not-keycard]]]}
|
||||
:keycard/error.keycard-blank
|
||||
{:fx [[:dispatch [:keycard/disconnect]]
|
||||
[:dispatch [:open-modal :screen/keycard.empty]]]}
|
||||
{:db (assoc-in db [:keycard :application-info-error] error)
|
||||
:fx [[:dispatch [:keycard/disconnect]]
|
||||
[:dispatch [:open-modal :screen/keycard.error]]]})
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :application-info] application-info)
|
||||
(assoc-in [:keycard :pin :status] :verifying))
|
||||
:fx on-success-fx})))
|
||||
|
||||
(rf/reg-event-fx :keycard/get-application-info
|
||||
(fn [_ [{:keys [on-success on-failure]}]]
|
||||
{:effects.keycard/get-application-info {:on-success on-success :on-failure on-failure}}))
|
||||
|
||||
(rf/reg-event-fx :keycard/cancel-connection
|
||||
(fn [{:keys [db]}]
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :on-card-connected-event-vector] nil)
|
||||
(assoc-in [:keycard :on-nfc-cancelled-event-vector] nil))}))
|
||||
|
||||
(rf/reg-event-fx :keycard/disconnect
|
||||
(fn [_ _]
|
||||
{:fx [[:dispatch [:keycard/cancel-connection]]
|
||||
[:dispatch [:keycard/hide-connection-sheet]]]}))
|
||||
|
||||
(rf/reg-event-fx :keycard/connect
|
||||
(fn [{:keys [db]} [args]]
|
||||
(let [connected? (get-in db [:keycard :card-connected?])
|
||||
event-vector [:keycard/get-application-info
|
||||
{:on-success #(rf/dispatch [:keycard/on-get-application-info-success % args])}]]
|
||||
{:db (assoc-in db [:keycard :on-card-connected-event-vector] event-vector)
|
||||
:fx [[:dispatch
|
||||
[:keycard/show-connection-sheet
|
||||
{:on-cancel-event-vector [:keycard/cancel-connection]}]]
|
||||
(when connected?
|
||||
[:dispatch event-vector])]})))
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
(ns status-im.contexts.keycard.login.events
|
||||
(:require [utils.re-frame :as rf]))
|
||||
(:require [status-im.contexts.keycard.utils :as keycard.utils]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/reg-event-fx :keycard.login/on-get-keys-success
|
||||
(fn [{:keys [db]} [data]]
|
||||
@@ -14,7 +16,7 @@
|
||||
:password encryption-public-key
|
||||
:key-uid key-uid
|
||||
:name (:name profile)))
|
||||
:fx [[:dispatch [:keycard/disconnect]]
|
||||
:fx [[:dispatch [:keycard/hide-connection-sheet]]
|
||||
[:effects.keycard/login-with-keycard
|
||||
{:password encryption-public-key
|
||||
:whisper-private-key whisper-private-key
|
||||
@@ -31,8 +33,36 @@
|
||||
:password encryption-public-key
|
||||
:key-uid key-uid
|
||||
:name (:name profile)))
|
||||
:fx [[:dispatch [:keycard/disconnect]]
|
||||
:fx [[:dispatch [:keycard/hide-connection-sheet]]
|
||||
[:effects.keycard/login-with-keycard
|
||||
{:password encryption-public-key
|
||||
:whisper-private-key whisper-private-key
|
||||
:key-uid key-uid}]]}))))
|
||||
|
||||
(rf/reg-event-fx :keycard.login/on-get-application-info-success
|
||||
(fn [{:keys [db]} [application-info {:keys [key-uid on-read-fx]}]]
|
||||
(let [error (keycard.utils/validate-application-info key-uid application-info)]
|
||||
(if error
|
||||
{:effects.utils/show-popup {:title (str error)}}
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :application-info] application-info)
|
||||
(assoc-in [:keycard :pin :status] :verifying))
|
||||
:fx on-read-fx}))))
|
||||
|
||||
(rf/reg-event-fx :keycard.login/cancel-reading-card
|
||||
(fn [{:keys [db]}]
|
||||
{:db (assoc-in db [:keycard :on-card-connected-event-vector] nil)}))
|
||||
|
||||
(rf/reg-event-fx :keycard/read-card
|
||||
(fn [{:keys [db]} [args]]
|
||||
(let [connected? (get-in db [:keycard :card-connected?])
|
||||
event-vector [:keycard/get-application-info
|
||||
{:on-success #(rf/dispatch [:keycard.login/on-get-application-info-success %
|
||||
args])}]]
|
||||
(log/debug "[keycard] proceed-to-login")
|
||||
{:db (assoc-in db [:keycard :on-card-connected-event-vector] event-vector)
|
||||
:fx [[:dispatch
|
||||
[:keycard/show-connection-sheet
|
||||
{:on-cancel-event-vector [:keycard.login/cancel-reading-card]}]]
|
||||
(when connected?
|
||||
[:dispatch event-vector])]})))
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
(ns status-im.contexts.keycard.not-keycard.view
|
||||
(:require [quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[status-im.common.events-helper :as events-helper]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [{:keys [top bottom]} (safe-area/get-insets)]
|
||||
[quo/overlay
|
||||
{:type :shell
|
||||
:container-style {:padding-top top
|
||||
:padding-bottom bottom}}
|
||||
[quo/page-nav
|
||||
{:key :header
|
||||
:background :blur
|
||||
:icon-name :i/arrow-left
|
||||
:on-press events-helper/navigate-back}]
|
||||
[quo/page-top
|
||||
{:title (i18n/label :t/oops-not-keycard)
|
||||
:description :text
|
||||
:description-text (i18n/label :t/make-sure-keycard)}]
|
||||
[rn/view {:flex 1}]
|
||||
[rn/view {:padding-horizontal 20}
|
||||
[quo/button {:on-press #(rf/dispatch [:keycard/connect])}
|
||||
(i18n/label :t/try-again)]]]))
|
||||
@@ -1,55 +0,0 @@
|
||||
(ns status-im.contexts.keycard.pin.create.view
|
||||
(:require [clojure.string :as string]
|
||||
[quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[status-im.constants :as constants]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(defn view
|
||||
[{:keys [on-complete]}]
|
||||
(let [[pin set-pin] (rn/use-state "")
|
||||
[first-pin set-first-pin] (rn/use-state "")
|
||||
[error? set-error] (rn/use-state false)
|
||||
[stage set-stage] (rn/use-state :create)
|
||||
pin-empty? (string/blank? pin)
|
||||
on-delete (rn/use-callback
|
||||
(fn []
|
||||
(set-error false)
|
||||
(if (= (count pin) 1)
|
||||
(do
|
||||
(set-pin "")
|
||||
(set-stage :create))
|
||||
(when (and pin (pos? (count pin)))
|
||||
(set-pin (.slice pin 0 -1)))))
|
||||
[pin])
|
||||
on-press (rn/use-callback
|
||||
(fn [new-symbol]
|
||||
(let [new-pin (str pin new-symbol)]
|
||||
(when (<= (count new-pin) constants/pincode-length)
|
||||
(set-pin new-pin)
|
||||
(when (= constants/pincode-length (count new-pin))
|
||||
(if (= :repeat stage)
|
||||
(if (= first-pin new-pin)
|
||||
(on-complete new-pin)
|
||||
(set-error true))
|
||||
(do
|
||||
(set-pin "")
|
||||
(set-first-pin new-pin)
|
||||
(set-stage :repeat)))))))
|
||||
[pin stage first-pin])]
|
||||
[rn/view {:style {:padding-bottom 12 :flex 1}}
|
||||
[quo/drawer-top
|
||||
{:title (if (= :create stage)
|
||||
(i18n/label :t/create-keycard-pin)
|
||||
(i18n/label :t/repeat-keycard-pin))}]
|
||||
[rn/view {:style {:flex 1 :justify-content :center :align-items :center :padding-vertical 34}}
|
||||
[quo/pin-input
|
||||
{:blur? false
|
||||
:number-of-pins constants/pincode-length
|
||||
:number-of-filled-pins (count pin)
|
||||
:error? error?
|
||||
:info (when error? (i18n/label :t/pin-not-match))}]]
|
||||
[quo/numbered-keyboard
|
||||
{:delete-key? (not pin-empty?)
|
||||
:on-delete on-delete
|
||||
:on-press on-press}]]))
|
||||
+9
-7
@@ -1,16 +1,18 @@
|
||||
(ns status-im.contexts.keycard.nfc-sheet.events
|
||||
(ns status-im.contexts.keycard.sheet.events
|
||||
(:require [re-frame.core :as rf]
|
||||
[react-native.platform :as platform]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(rf/reg-event-fx :keycard/show-connection-sheet-component
|
||||
(fn [{:keys [db]} [{:keys [on-cancel-event-vector]}]]
|
||||
{:db (assoc-in db [:keycard :connection-sheet-opts] {:on-close #(rf/dispatch on-cancel-event-vector)})
|
||||
:fx [[:dismiss-keyboard true]
|
||||
[:show-nfc-sheet nil]]}))
|
||||
|
||||
(rf/reg-event-fx :keycard/show-connection-sheet
|
||||
(fn [{:keys [db]} [{:keys [on-cancel-event-vector]} :as args]]
|
||||
(fn [_ [args]]
|
||||
(if platform/android?
|
||||
{:db (assoc-in db
|
||||
[:keycard :connection-sheet-opts]
|
||||
{:on-close #(rf/dispatch on-cancel-event-vector)})
|
||||
:fx [[:dismiss-keyboard true]
|
||||
[:show-nfc-sheet nil]]}
|
||||
{:dispatch [:keycard/show-connection-sheet-component args]}
|
||||
{:effects.keycard.ios/start-nfc
|
||||
{:on-success
|
||||
(fn []
|
||||
+5
-6
@@ -1,9 +1,8 @@
|
||||
(ns status-im.contexts.keycard.nfc-sheet.view
|
||||
(ns status-im.contexts.keycard.sheet.view
|
||||
(:require [quo.foundations.colors :as colors]
|
||||
quo.theme
|
||||
[react-native.core :as rn]
|
||||
[status-im.common.resources :as resources]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn connect-keycard
|
||||
@@ -19,13 +18,13 @@
|
||||
:padding-vertical 30
|
||||
:background-color (colors/theme-colors colors/white colors/neutral-95 theme)}}
|
||||
[rn/text {:style {:font-size 26 :color "#9F9FA5" :margin-bottom 36}}
|
||||
(i18n/label :t/ready-to-scan)]
|
||||
"Ready to Scan"]
|
||||
[rn/image
|
||||
{:source (resources/get-image :nfc-prompt)}]
|
||||
[rn/text {:style {:font-size 16 :color :white :margin-vertical 36}}
|
||||
(if connected?
|
||||
(i18n/label :t/connected-dont-move)
|
||||
(i18n/label :t/hold-phone-near-keycard))]
|
||||
"Connected. Don’t move your card."
|
||||
"Hold your phone near a Status Keycard")]
|
||||
[rn/pressable
|
||||
{:on-press (fn []
|
||||
(when on-close (on-close))
|
||||
@@ -34,4 +33,4 @@
|
||||
[rn/view
|
||||
{:style {:background-color "#8E8E93" :flex 1 :align-items :center :padding 18 :border-radius 10}}
|
||||
[rn/text {:style {:color :white :font-size 16}}
|
||||
(i18n/label :t/cancel)]]]]]))
|
||||
"Cancel"]]]]]))
|
||||
@@ -1,38 +0,0 @@
|
||||
(ns status-im.contexts.keycard.sheets.migrate.view
|
||||
(:require [quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [profile-name (rf/sub [:profile/name])
|
||||
profile-picture (rf/sub [:profile/image])
|
||||
customization-color (rf/sub [:profile/customization-color])
|
||||
recovery-phrase-backed-up? (rf/sub [:profile/recovery-phrase-backed-up?])]
|
||||
[:<>
|
||||
[quo/drawer-top
|
||||
{:type :context-tag
|
||||
:context-tag-type :default
|
||||
:title (i18n/label :t/migrate-key-pair-keycard)
|
||||
:full-name profile-name
|
||||
:profile-picture profile-picture
|
||||
:customization-color customization-color}]
|
||||
[rn/view {:style {:padding-horizontal 20}}
|
||||
[quo/text {}
|
||||
(i18n/label :t/migrate-key-pair-keycard-default-key {:name profile-name})]
|
||||
[quo/information-box
|
||||
{:type :default
|
||||
:style {:margin-top 20 :margin-bottom 12}}
|
||||
(i18n/label :t/migrate-key-pair-keycard-info)]]
|
||||
[quo/bottom-actions
|
||||
{:actions :two-actions
|
||||
:button-one-label (i18n/label :t/continue)
|
||||
:button-one-props {:on-press #(if recovery-phrase-backed-up?
|
||||
(rf/dispatch [:open-modal :screen/use-recovery-phrase
|
||||
{:on-success (fn [])}])
|
||||
(rf/dispatch [:open-modal :screen/backup-recovery-phrase
|
||||
{:on-success (fn [])}]))}
|
||||
:button-two-label (i18n/label :t/cancel)
|
||||
:button-two-props {:type :grey
|
||||
:on-press #(rf/dispatch [:hide-bottom-sheet])}}]]))
|
||||
@@ -14,17 +14,16 @@
|
||||
path (get-in db [:wallet :accounts current-address :path])
|
||||
key-uid (get-in db [:profile/profile :key-uid])]
|
||||
{:fx [[:dispatch
|
||||
[:keycard/connect
|
||||
{:key-uid key-uid
|
||||
:on-success-fx [[:effects.keycard/sign
|
||||
{:pin pin-text
|
||||
:path path
|
||||
:hash (utils.address/naked-address tx-hash)
|
||||
:on-success
|
||||
#(do
|
||||
(rf/dispatch [:keycard/disconnect])
|
||||
(rf/dispatch
|
||||
[:wallet/proceed-with-transactions-signatures
|
||||
(get-signature-map tx-hash %)]))
|
||||
:on-failure #(rf/dispatch [:keycard/on-action-with-pin-error
|
||||
%])}]]}]]]})))
|
||||
[:keycard/read-card
|
||||
{:key-uid key-uid
|
||||
:on-read-fx [[:effects.keycard/sign
|
||||
{:pin pin-text
|
||||
:path path
|
||||
:hash (utils.address/naked-address tx-hash)
|
||||
:on-success
|
||||
#(do
|
||||
(rf/dispatch [:keycard/hide-connection-sheet])
|
||||
(rf/dispatch
|
||||
[:wallet/proceed-with-transactions-signatures
|
||||
(get-signature-map tx-hash %)]))
|
||||
:on-failure #(rf/dispatch [:keycard/on-action-with-pin-error %])}]]}]]]})))
|
||||
|
||||
@@ -18,31 +18,28 @@
|
||||
(defn validate-application-info
|
||||
[profile-key-uid {:keys [key-uid paired? pin-retry-counter puk-retry-counter] :as application-info}]
|
||||
(let [profile-mismatch? (or (nil? profile-key-uid) (not= profile-key-uid key-uid))]
|
||||
(log/debug "[keycard]" "login-with-keycard"
|
||||
(log/debug "[keycard] login-with-keycard"
|
||||
"empty application info" (empty? application-info)
|
||||
"no key-uid" (empty? key-uid)
|
||||
"profile-mismatch?" profile-mismatch?
|
||||
"no pairing" paired?)
|
||||
(cond
|
||||
(empty? application-info)
|
||||
:keycard/error.not-keycard
|
||||
:not-keycard
|
||||
|
||||
(empty? (:key-uid application-info))
|
||||
:keycard/error.keycard-blank
|
||||
:keycard-blank
|
||||
|
||||
profile-mismatch?
|
||||
:keycard/error.keycard-wrong
|
||||
:keycard-wrong
|
||||
|
||||
(not paired?)
|
||||
:keycard/error.keycard-unpaired
|
||||
:keycard-unpaired
|
||||
|
||||
(and (zero? pin-retry-counter)
|
||||
(or (nil? puk-retry-counter)
|
||||
(pos? puk-retry-counter)))
|
||||
:keycard/error.keycard-frozen
|
||||
|
||||
(zero? puk-retry-counter)
|
||||
:keycard/error.keycard-locked
|
||||
nil
|
||||
|
||||
:else
|
||||
nil)))
|
||||
|
||||
@@ -131,6 +131,15 @@
|
||||
[:open-modal :screen/onboarding.enable-biometrics]
|
||||
[:open-modal :screen/onboarding.enable-notifications])}))
|
||||
|
||||
(rf/defn seed-phrase-entered
|
||||
{:events [:onboarding/seed-phrase-entered]}
|
||||
[_ seed-phrase on-error]
|
||||
{:multiaccount/validate-mnemonic [seed-phrase
|
||||
(fn [mnemonic key-uid]
|
||||
(re-frame/dispatch [:onboarding/seed-phrase-validated
|
||||
mnemonic key-uid]))
|
||||
on-error]})
|
||||
|
||||
(rf/defn seed-phrase-validated
|
||||
{:events [:onboarding/seed-phrase-validated]}
|
||||
[{:keys [db]} seed-phrase key-uid]
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
(ns status-im.contexts.onboarding.syncing.progress.style
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]
|
||||
[react-native.safe-area :as safe-area]))
|
||||
[quo.foundations.colors :as colors]))
|
||||
|
||||
(def absolute-fill
|
||||
{:position :absolute
|
||||
@@ -18,7 +17,6 @@
|
||||
:bottom 0
|
||||
:left 0
|
||||
:right 0
|
||||
:padding-top (safe-area/get-top)
|
||||
:padding-bottom 20
|
||||
:background-color (when-not in-onboarding? colors/neutral-80-opa-80-blur)})
|
||||
|
||||
|
||||
@@ -15,14 +15,16 @@
|
||||
|
||||
(defn page-title
|
||||
[pairing-progress?]
|
||||
[quo/page-top
|
||||
{:title (i18n/label (if pairing-progress?
|
||||
:t/sync-devices-title
|
||||
:t/sync-devices-error-title))
|
||||
:description :text
|
||||
:description-text (i18n/label (if pairing-progress?
|
||||
:t/sync-devices-sub-title
|
||||
:t/sync-devices-error-sub-title))}])
|
||||
[quo/text-combinations
|
||||
{:container-style {:margin-top 56 :margin-horizontal 20}
|
||||
:title (i18n/label (if pairing-progress?
|
||||
:t/sync-devices-title
|
||||
:t/sync-devices-error-title))
|
||||
:description (i18n/label (if pairing-progress?
|
||||
:t/sync-devices-sub-title
|
||||
:t/sync-devices-error-sub-title))
|
||||
:title-accessibility-label :progress-screen-title
|
||||
:description-accessibility-label :progress-screen-sub-title}])
|
||||
|
||||
(defn- navigate-to-enter-seed-phrase
|
||||
[]
|
||||
@@ -40,41 +42,32 @@
|
||||
|
||||
(defn try-again-button
|
||||
[profile-color logged-in?]
|
||||
(let [number-of-actions (if logged-in? :one-action :two-actions)
|
||||
try-again-label (i18n/label :t/try-again)
|
||||
try-again-props {:type (if logged-in? :primary :grey)
|
||||
:accessibility-label :try-again-later-button
|
||||
:customization-color profile-color
|
||||
:container-style {:flex 1}
|
||||
:size 40
|
||||
:on-press #(try-again logged-in?)}
|
||||
recovery-phrase-label (i18n/label :t/recovery-phrase)
|
||||
recovery-phrase-props {:type :primary
|
||||
:accessibility-label :try-seed-phrase-button
|
||||
:customization-color profile-color
|
||||
:container-style {:flex 1}
|
||||
:size 40
|
||||
:on-press navigate-to-enter-seed-phrase}
|
||||
buttons (if logged-in?
|
||||
{:button-one-label try-again-label
|
||||
:button-one-props try-again-props}
|
||||
{:button-one-label recovery-phrase-label
|
||||
:button-one-props recovery-phrase-props
|
||||
:button-two-label try-again-label
|
||||
:button-two-props try-again-props})]
|
||||
[quo/bottom-actions
|
||||
(assoc buttons
|
||||
:actions number-of-actions
|
||||
:blur? true)]))
|
||||
[quo/bottom-actions
|
||||
{:actions (if logged-in? :one-action :two-actions)
|
||||
:blur? true
|
||||
:button-one-label (i18n/label :t/recovery-phrase)
|
||||
:button-one-props {:type :primary
|
||||
:accessibility-label :try-seed-phrase-button
|
||||
:customization-color profile-color
|
||||
:container-style {:flex 1}
|
||||
:size 40
|
||||
:on-press navigate-to-enter-seed-phrase}
|
||||
(if logged-in? :button-one-label :button-two-label)
|
||||
(i18n/label :t/try-again)
|
||||
(if logged-in? :button-one-props :button-two-props)
|
||||
{:type (if logged-in? :primary :grey)
|
||||
:accessibility-label :try-again-later-button
|
||||
:customization-color profile-color
|
||||
:container-style {:flex 1}
|
||||
:size 40
|
||||
:on-press #(try-again logged-in?)}}])
|
||||
|
||||
(defn- illustration
|
||||
[pairing-progress?]
|
||||
[rn/image
|
||||
{:resize-mode :contain
|
||||
:style (style/page-illustration (:width (rn/get-window)))
|
||||
:source (resources/get-image (if pairing-progress?
|
||||
:syncing-devices
|
||||
:syncing-wrong))}])
|
||||
:source (resources/get-image (if pairing-progress? :syncing-devices :syncing-wrong))}])
|
||||
|
||||
(defn view
|
||||
[in-onboarding?]
|
||||
@@ -90,7 +83,7 @@
|
||||
[quo/page-nav {:type :no-title :background :blur}]
|
||||
[page-title pairing-progress?]
|
||||
[illustration pairing-progress?]
|
||||
(when-not pairing-progress?
|
||||
(when-not (pairing-progress pairing-status)
|
||||
[try-again-button profile-color logged-in?])]))
|
||||
|
||||
(defn view-onboarding
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
:title "floating button page"
|
||||
:description "press right icon to swap button type"
|
||||
:text-align :left
|
||||
:right-side [{:icon-name :i/transaction
|
||||
:right-side [{:icon-name :i/swap
|
||||
:on-press #(swap! slide? not)}]
|
||||
:background :blur
|
||||
:icon-name :i/close
|
||||
|
||||
@@ -242,13 +242,12 @@
|
||||
{:on-complete
|
||||
(fn [pin-text]
|
||||
(rf/dispatch
|
||||
[:keycard/connect
|
||||
{:key-uid key-uid
|
||||
:on-success-fx [[:effects.keycard/get-keys
|
||||
{:pin pin-text
|
||||
:on-success #(rf/dispatch [:keycard.login/on-get-keys-success %])
|
||||
:on-failure #(rf/dispatch [:keycard/on-action-with-pin-error
|
||||
%])}]]}]))}]
|
||||
[:keycard/read-card
|
||||
{:key-uid key-uid
|
||||
:on-read-fx [[:effects.keycard/get-keys
|
||||
{:pin pin-text
|
||||
:on-success #(rf/dispatch [:keycard.login/on-get-keys-success %])
|
||||
:on-failure #(rf/dispatch [:keycard/on-action-with-pin-error %])}]]}]))}]
|
||||
[password-input])]
|
||||
(when-not keycard-pairing
|
||||
[quo/button
|
||||
|
||||
@@ -1,31 +1,9 @@
|
||||
(ns status-im.contexts.profile.recover.effects
|
||||
(:require
|
||||
[native-module.core :as native-module]
|
||||
[promesa.core :as promesa]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.security.core :as security]
|
||||
[utils.transforms :as transforms]))
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/reg-fx :effects.profile/restore-and-login
|
||||
(fn [request]
|
||||
;;"node.login" signal will be triggered as a callback
|
||||
(native-module/restore-account-and-login request)))
|
||||
|
||||
(defn validate-mnemonic
|
||||
[mnemonic]
|
||||
(-> mnemonic
|
||||
(security/safe-unmask-data)
|
||||
(native-module/validate-mnemonic)
|
||||
(promesa/then (fn [result]
|
||||
(let [{:keys [keyUID]} (transforms/json->clj result)]
|
||||
{:key-uid keyUID})))))
|
||||
|
||||
(rf/reg-fx :effects.profile/validate-recovery-phrase
|
||||
(fn [[mnemonic on-success on-error]]
|
||||
(-> (validate-mnemonic mnemonic)
|
||||
(promesa/then (fn [{:keys [key-uid]}]
|
||||
(when (fn? on-success)
|
||||
(on-success mnemonic key-uid))))
|
||||
(promesa/catch (fn [error]
|
||||
(when (and error (fn? on-error))
|
||||
(on-error error)))))))
|
||||
|
||||
@@ -24,7 +24,3 @@
|
||||
:imagePath (profile.config/strip-file-prefix image-path)
|
||||
:customizationColor (or color constants/profile-default-color)
|
||||
:fetchBackup true)}))
|
||||
|
||||
(rf/reg-event-fx :profile.recover/validate-recovery-phrase
|
||||
(fn [_ [phrase {:keys [on-success on-error]}]]
|
||||
{:effects.profile/validate-recovery-phrase [phrase on-success on-error]}))
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
(ns status-im.contexts.profile.settings.list-items
|
||||
(:require [status-im.common.not-implemented :as not-implemented]
|
||||
[status-im.config :as config]
|
||||
[status-im.feature-flags :as ff]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
@@ -55,9 +54,9 @@
|
||||
:image :icon
|
||||
:blur? true
|
||||
:action :arrow})
|
||||
(when (ff/enabled? ::ff/keycard.migrate-profile)
|
||||
(when config/show-not-implemented-features?
|
||||
{:title (i18n/label :t/keycard)
|
||||
:on-press #(rf/dispatch [:open-modal :screen/settings.keycard])
|
||||
:on-press not-implemented/alert
|
||||
:image-props :i/keycard
|
||||
:image :icon
|
||||
:blur? true
|
||||
|
||||
@@ -49,14 +49,13 @@
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
insets (safe-area/get-insets)
|
||||
customization-color (rf/sub [:profile/customization-color])
|
||||
scroll-y (reanimated/use-shared-value 0)
|
||||
profile (rf/sub [:profile/profile])
|
||||
recovery-phrase-backed-up? (rf/sub [:profile/recovery-phrase-backed-up?])
|
||||
full-name (profile.utils/displayed-name profile)
|
||||
on-scroll (rn/use-callback #(scroll-handler % scroll-y))]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
insets (safe-area/get-insets)
|
||||
customization-color (rf/sub [:profile/customization-color])
|
||||
scroll-y (reanimated/use-shared-value 0)
|
||||
profile (rf/sub [:profile/profile])
|
||||
full-name (profile.utils/displayed-name profile)
|
||||
on-scroll (rn/use-callback #(scroll-handler % scroll-y))]
|
||||
[quo/overlay {:type :shell}
|
||||
[rn/view
|
||||
{:style (style/navigation-wrapper {:customization-color customization-color
|
||||
@@ -80,7 +79,7 @@
|
||||
profile)}}])}]}]]
|
||||
[rn/flat-list
|
||||
{:header [settings.header/view {:scroll-y scroll-y}]
|
||||
:data (settings.items/items (not recovery-phrase-backed-up?))
|
||||
:data (settings.items/items (boolean (seq (:mnemonic profile))))
|
||||
:shows-vertical-scroll-indicator false
|
||||
:render-fn settings-category-view
|
||||
:get-item-layout get-item-layout
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
(ns status-im.contexts.settings.keycard.view
|
||||
(:require [quo.core :as quo]
|
||||
[quo.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
[status-im.common.events-helper :as events-helper]
|
||||
[status-im.common.resources :as resources]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [keycard-profile? (rf/sub [:keycard/keycard-profile?])]
|
||||
[:<>
|
||||
[quo/page-nav
|
||||
{:key :header
|
||||
:background :blur
|
||||
:icon-name :i/arrow-left
|
||||
:on-press events-helper/navigate-back}]
|
||||
[quo/page-top
|
||||
{:title (i18n/label :t/keycard)}]
|
||||
(if keycard-profile?
|
||||
[:<>]
|
||||
[rn/view {:style {:padding-horizontal 28 :padding-top 20}}
|
||||
[quo/small-option-card
|
||||
{:variant :main
|
||||
:title (i18n/label :t/get-keycard)
|
||||
:subtitle (i18n/label :t/secure-wallet-card)
|
||||
:button-label (i18n/label :t/buy-keycard)
|
||||
:accessibility-label :get-keycard
|
||||
:image (resources/get-image :generate-keys)
|
||||
:on-press #()}]
|
||||
[rn/view {:style {:margin-top 24}}
|
||||
[quo/text
|
||||
{:style {:margin-bottom 12
|
||||
:color colors/white-opa-70}
|
||||
:size :paragraph-2
|
||||
:weight :medium}
|
||||
(i18n/label :t/own-keycard)]]
|
||||
[quo/small-option-card
|
||||
{:variant :icon
|
||||
:title (i18n/label :t/setup-keycard)
|
||||
:subtitle (i18n/label :t/ready-keycard)
|
||||
:accessibility-label :setup-keycard
|
||||
:image (resources/get-image :use-keycard)
|
||||
:on-press #(rf/dispatch [:open-modal :screen/keycard.check])}]])]))
|
||||
@@ -160,7 +160,7 @@
|
||||
|
||||
(defn wallet-validate-seed-phrase
|
||||
[_ [seed-phrase on-success on-error]]
|
||||
{:fx [[:effects.profile/validate-recovery-phrase [seed-phrase on-success on-error]]]})
|
||||
{:fx [[:multiaccount/validate-mnemonic [seed-phrase on-success on-error]]]})
|
||||
|
||||
(rf/reg-event-fx :wallet/validate-seed-phrase wallet-validate-seed-phrase)
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
seed-phrase-masked (security/mask-data "seed phrase")
|
||||
on-success #(prn "success")
|
||||
on-error #(prn "error")
|
||||
expected {:fx [[:effects.profile/validate-recovery-phrase
|
||||
expected {:fx [[:multiaccount/validate-mnemonic
|
||||
[seed-phrase-masked on-success on-error]]]}]
|
||||
(is (= expected
|
||||
(sut/wallet-validate-seed-phrase
|
||||
|
||||
+8
-5
@@ -6,21 +6,24 @@
|
||||
[react-native.platform :as platform]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.settings.wallet.saved-addresses.sheets.remove-address.view :as remove-address]
|
||||
[status-im.contexts.wallet.common.utils :as utils]
|
||||
[status-im.contexts.wallet.common.utils.networks :as network-utils]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn view
|
||||
[{:keys [name full-address chain-short-names address customization-color] :as opts}]
|
||||
(let [open-send-flow (rn/use-callback
|
||||
[{:keys [name full-address chain-short-names address] :as opts}]
|
||||
(let [[_ splitted-address] (network-utils/split-network-full-address address)
|
||||
open-send-flow (rn/use-callback
|
||||
(fn []
|
||||
(rf/dispatch [:hide-bottom-sheet])
|
||||
(rf/dispatch [:pop-to-root :shell-stack])
|
||||
(js/setTimeout #(rf/dispatch [:wallet/select-send-address
|
||||
{:address full-address
|
||||
:recipient
|
||||
{:label name
|
||||
:customization-color
|
||||
customization-color
|
||||
{:label
|
||||
(utils/get-shortened-address
|
||||
splitted-address)
|
||||
:recipient-type :saved-address}
|
||||
:stack-id :wallet-select-address
|
||||
:start-flow? true}])
|
||||
|
||||
@@ -61,6 +61,16 @@
|
||||
|
||||
(rf/reg-event-fx :wallet/seed-phrase-validated seed-phrase-validated)
|
||||
|
||||
(defn seed-phrase-entered
|
||||
[_ [seed-phrase on-error]]
|
||||
{:fx [[:multiaccount/validate-mnemonic
|
||||
[seed-phrase
|
||||
(fn [mnemonic key-uid]
|
||||
(rf/dispatch [:wallet/seed-phrase-validated mnemonic key-uid on-error]))
|
||||
on-error]]]})
|
||||
|
||||
(rf/reg-event-fx :wallet/seed-phrase-entered seed-phrase-entered)
|
||||
|
||||
(defn store-account-generated-with-mnemonic
|
||||
[{:keys [db]} [{:keys [new-account-data keypair-name]}]]
|
||||
(let [new-account (update new-account-data :mnemonic security/mask-data)]
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
(ns status-im.contexts.profile.backup-recovery-phrase.style
|
||||
(ns status-im.contexts.wallet.add-account.create-account.new-keypair.backup-recovery-phrase.style
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]
|
||||
[react-native.platform :as platform]))
|
||||
+19
-18
@@ -1,4 +1,4 @@
|
||||
(ns status-im.contexts.profile.backup-recovery-phrase.view
|
||||
(ns status-im.contexts.wallet.add-account.create-account.new-keypair.backup-recovery-phrase.view
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[native-module.core :as native-module]
|
||||
@@ -6,7 +6,8 @@
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.contexts.profile.backup-recovery-phrase.style :as style]
|
||||
[status-im.contexts.wallet.add-account.create-account.new-keypair.backup-recovery-phrase.style :as
|
||||
style]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.security.core :as security]))
|
||||
@@ -44,20 +45,20 @@
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(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)
|
||||
customization-color (rf/sub [:profile/customization-color])
|
||||
{:keys [on-success]} (rf/sub [:get-screen-params])
|
||||
seed-phrase (reagent/atom [])
|
||||
random-phrase (reagent/atom [])]
|
||||
(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)
|
||||
customization-color (rf/sub [:profile/customization-color])
|
||||
seed-phrase (reagent/atom [])
|
||||
random-phrase (reagent/atom [])]
|
||||
(fn []
|
||||
(let [theme (quo.theme/use-theme)]
|
||||
|
||||
(rn/use-mount
|
||||
(fn []
|
||||
(native-module/get-random-mnemonic #(reset! seed-phrase (string/split % #"\s")))
|
||||
@@ -106,10 +107,10 @@
|
||||
:button-one-label (i18n/label :t/i-have-written)
|
||||
:button-one-props {:disabled? (some false? (vals @checked?))
|
||||
:customization-color customization-color
|
||||
:on-press #(on-success {:masked-seed-phrase
|
||||
(security/mask-data
|
||||
@seed-phrase)
|
||||
:random-phrase @random-phrase})}}]
|
||||
:on-press #(rf/dispatch [:wallet/store-new-seed-phrase
|
||||
{:seed-phrase (security/mask-data
|
||||
@seed-phrase)
|
||||
:random-phrase @random-phrase}])}}]
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:style (style/description-text theme)}
|
||||
@@ -16,21 +16,13 @@
|
||||
[[{:icon :i/add
|
||||
:accessibility-label :generate-new-keypair
|
||||
:label (i18n/label :t/generate-new-keypair)
|
||||
:on-press #(rf/dispatch [:navigate-to :screen/backup-recovery-phrase
|
||||
{:on-success (fn [{:keys [masked-seed-phrase random-phrase]}]
|
||||
(rf/dispatch [:wallet/store-new-seed-phrase
|
||||
{:seed-phrase masked-seed-phrase
|
||||
:random-phrase
|
||||
random-phrase}]))}])}
|
||||
:on-press #(rf/dispatch [:navigate-to :screen/wallet.backup-recovery-phrase])}
|
||||
{:icon :i/seed
|
||||
:accessibility-label :import-using-phrase
|
||||
:label (i18n/label :t/import-using-phrase)
|
||||
:add-divider? true
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:navigate-to :screen/use-recovery-phrase
|
||||
{:on-success (fn [{:keys [key-uid phrase on-error]}]
|
||||
(rf/dispatch [:wallet/seed-phrase-validated
|
||||
phrase key-uid on-error]))}]))}
|
||||
:on-press #(rf/dispatch [:navigate-to :screen/wallet.enter-seed-phrase
|
||||
{:recovering-keypair? true}])}
|
||||
(when (ff/enabled? ::ff/wallet.import-private-key)
|
||||
{:icon :i/key
|
||||
:accessibility-label :import-private-key
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
(ns status-im.contexts.wallet.buy-crypto.events
|
||||
(:require [re-frame.core :as rf]
|
||||
[react-native.core :as rn]
|
||||
[status-im.contexts.wallet.sheets.buy-network-selection.view :as buy-network-selection]
|
||||
[status-im.contexts.wallet.sheets.select-asset.view :as select-asset]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(rf/reg-event-fx :wallet.buy-crypto/select-provider
|
||||
(fn [{:keys [db]} [{:keys [account provider recurrent?]}]]
|
||||
(let [swap-network (get-in db [:wallet :ui :swap :network])]
|
||||
{:db (-> db
|
||||
(assoc-in [:wallet :ui :buy-crypto :account] account)
|
||||
(assoc-in [:wallet :ui :buy-crypto :provider] provider)
|
||||
(assoc-in [:wallet :ui :buy-crypto :recurrent?] recurrent?))
|
||||
:fx [(if swap-network
|
||||
[:dispatch [:wallet.buy-crypto/select-network swap-network]]
|
||||
[:dispatch
|
||||
[:show-bottom-sheet
|
||||
{:content
|
||||
(fn []
|
||||
[buy-network-selection/view
|
||||
{:provider provider
|
||||
:account account}])}]])]})))
|
||||
|
||||
(rf/reg-event-fx :wallet.buy-crypto/select-network
|
||||
(fn [{:keys [db]} [network]]
|
||||
(let [provider (get-in db [:wallet :ui :buy-crypto :provider])
|
||||
network-chain-id (:chain-id network)
|
||||
supported-tokens (:supported-tokens provider)
|
||||
supported-tokens-on-network (set (map :symbol
|
||||
(filter (fn [token]
|
||||
(= (:chain-id token) network-chain-id))
|
||||
supported-tokens)))]
|
||||
{:db (assoc-in db [:wallet :ui :buy-crypto :network] network)
|
||||
:fx [[:dispatch
|
||||
[:show-bottom-sheet
|
||||
{:content
|
||||
(fn []
|
||||
[select-asset/view
|
||||
{:title (i18n/label :t/select-asset-to-buy)
|
||||
:network network
|
||||
:provider provider
|
||||
:on-select (fn [token]
|
||||
(rf/dispatch [:wallet/get-crypto-on-ramp-url {:token token}]))
|
||||
:hide-token-fn (fn [_ token]
|
||||
(not (contains? supported-tokens-on-network
|
||||
(:symbol token))))}])}]]]})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/get-crypto-on-ramp-url
|
||||
(fn [{:keys [db]} [{:keys [token]}]]
|
||||
(let [account (get-in db [:wallet :ui :buy-crypto :account])
|
||||
provider (get-in db [:wallet :ui :buy-crypto :provider])
|
||||
network (get-in db [:wallet :ui :buy-crypto :network])
|
||||
recurrent? (get-in db [:wallet :ui :buy-crypto :recurrent?])
|
||||
provider-id (:id provider)
|
||||
parameters {:symbol (:symbol token)
|
||||
:destAddress (:address account)
|
||||
:chainID (:chain-id network)
|
||||
:isRecurrent recurrent?}]
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method "wallet_getCryptoOnRampURL"
|
||||
:params [provider-id parameters]
|
||||
:on-success (fn [url]
|
||||
(rf/dispatch [:navigate-back])
|
||||
(rf/dispatch [:wallet.buy-crypto/clean-all])
|
||||
(rn/open-url url))
|
||||
:on-error [:wallet/log-rpc-error {:event :wallet/get-crypto-on-ramps}]}]]]})))
|
||||
|
||||
(rf/reg-event-fx :wallet.buy-crypto/clean-all
|
||||
(fn [{:keys [db]}]
|
||||
{:db (update-in db [:wallet :ui] dissoc :buy-crypto)}))
|
||||
@@ -8,20 +8,19 @@
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn get-bottom-sheet-args
|
||||
[switcher-type params]
|
||||
[switcher-type]
|
||||
(case switcher-type
|
||||
:account-options {:content account-options/view
|
||||
:hide-handle? true}
|
||||
:select-account {:content (fn []
|
||||
[select-account/view params])}
|
||||
:select-account {:content select-account/view}
|
||||
nil))
|
||||
|
||||
(defn- on-dapps-press
|
||||
[switcher-type params]
|
||||
(rf/dispatch [:show-bottom-sheet (get-bottom-sheet-args switcher-type params)]))
|
||||
[switcher-type]
|
||||
(rf/dispatch [:show-bottom-sheet (get-bottom-sheet-args switcher-type)]))
|
||||
|
||||
(defn view
|
||||
[{:keys [type on-press accessibility-label icon-name switcher-type margin-top params]
|
||||
[{:keys [type on-press accessibility-label icon-name switcher-type margin-top]
|
||||
:or {icon-name :i/close
|
||||
accessibility-label :top-bar
|
||||
switcher-type :account-options
|
||||
@@ -46,6 +45,6 @@
|
||||
(when-not sending-collectible?
|
||||
{:content-type :account-switcher
|
||||
:customization-color color
|
||||
:on-press #(on-dapps-press switcher-type params)
|
||||
:on-press #(on-dapps-press switcher-type)
|
||||
:emoji emoji
|
||||
:type (when watch-only? :watch-only)})]}]))
|
||||
|
||||
@@ -32,11 +32,9 @@
|
||||
:selected)}]))
|
||||
|
||||
(defn view
|
||||
[{:keys [content-container-style search-text on-token-press preselected-token-symbol chain-ids]
|
||||
[{:keys [content-container-style search-text on-token-press preselected-token-symbol]
|
||||
:or {content-container-style {:padding-horizontal 8}}}]
|
||||
(let [filtered-tokens (rf/sub [:wallet/current-viewing-account-tokens-filtered
|
||||
{:query search-text
|
||||
:chain-ids chain-ids}])
|
||||
(let [filtered-tokens (rf/sub [:wallet/current-viewing-account-tokens-filtered {:query search-text}])
|
||||
currency (rf/sub [:profile/currency])
|
||||
currency-symbol (rf/sub [:profile/currency-symbol])]
|
||||
[gesture/flat-list
|
||||
|
||||
@@ -47,8 +47,8 @@
|
||||
(rf/dispatch [:wallet/bridge-select-token params]))})
|
||||
|
||||
(defn- action-swap
|
||||
[{:keys [token asset-to-receive token-symbol testnet-mode?]}]
|
||||
{:icon :i/transaction
|
||||
[{:keys [token token-symbol testnet-mode?]}]
|
||||
{:icon :i/swap
|
||||
:accessibility-label :swap
|
||||
:label (i18n/label :t/swap)
|
||||
:disabled? testnet-mode?
|
||||
@@ -56,7 +56,6 @@
|
||||
(rf/dispatch [:hide-bottom-sheet])
|
||||
(rf/dispatch [:wallet.swap/start
|
||||
{:asset-to-pay (or token {:symbol token-symbol})
|
||||
:asset-to-receive asset-to-receive
|
||||
:open-new-screen? true}]))})
|
||||
|
||||
(defn- action-manage-tokens
|
||||
@@ -76,26 +75,23 @@
|
||||
|
||||
(defn token-value-drawer
|
||||
[token watch-only? entry-point]
|
||||
(let [token-symbol (:token token)
|
||||
token-data (first (rf/sub [:wallet/current-viewing-account-tokens-filtered
|
||||
{:query token-symbol}]))
|
||||
selected-account (rf/sub [:wallet/current-viewing-account-address])
|
||||
token-owners (rf/sub [:wallet/operable-addresses-with-token-symbol token-symbol])
|
||||
testnet-mode? (rf/sub [:profile/test-networks-enabled?])
|
||||
receive-token-symbol (if (= token-symbol "SNT") "ETH" "SNT")
|
||||
asset-to-receive (rf/sub [:wallet/token-by-symbol receive-token-symbol])
|
||||
params (cond-> {:start-flow? true
|
||||
:owners token-owners
|
||||
:testnet-mode? testnet-mode?
|
||||
:asset-to-receive asset-to-receive}
|
||||
selected-account
|
||||
(assoc :token token-data
|
||||
:stack-id :screen/wallet.accounts
|
||||
:has-balance? (-> (get-in token [:values :fiat-unformatted-value])
|
||||
(money/greater-than (money/bignumber "0"))))
|
||||
(not selected-account)
|
||||
(assoc :token-symbol token-symbol
|
||||
:stack-id :wallet-stack))]
|
||||
(let [token-symbol (:token token)
|
||||
token-data (first (rf/sub [:wallet/current-viewing-account-tokens-filtered
|
||||
{:query token-symbol}]))
|
||||
selected-account (rf/sub [:wallet/current-viewing-account-address])
|
||||
token-owners (rf/sub [:wallet/operable-addresses-with-token-symbol token-symbol])
|
||||
testnet-mode? (rf/sub [:profile/test-networks-enabled?])
|
||||
params (cond-> {:start-flow? true
|
||||
:owners token-owners
|
||||
:testnet-mode? testnet-mode?}
|
||||
selected-account
|
||||
(assoc :token token-data
|
||||
:stack-id :screen/wallet.accounts
|
||||
:has-balance? (-> (get-in token [:values :fiat-unformatted-value])
|
||||
(money/greater-than (money/bignumber "0"))))
|
||||
(not selected-account)
|
||||
(assoc :token-symbol token-symbol
|
||||
:stack-id :wallet-stack))]
|
||||
[quo/action-drawer
|
||||
[(cond->> [(when (ff/enabled? ::ff/wallet.assets-modal-manage-tokens)
|
||||
(action-manage-tokens watch-only?))
|
||||
|
||||
@@ -15,17 +15,13 @@
|
||||
[full-name]
|
||||
(first (string/split full-name #" ")))
|
||||
|
||||
(defn cut-fiat-balance
|
||||
[balance decimals]
|
||||
(defn cut-fiat-balance-to-two-decimals
|
||||
[balance]
|
||||
(let [valid-balance? (and balance
|
||||
(or (number? balance) (.-toFixed balance)))]
|
||||
(as-> balance $
|
||||
(if valid-balance? $ 0)
|
||||
(.toFixed $ decimals))))
|
||||
|
||||
(defn cut-fiat-balance-to-two-decimals
|
||||
[balance]
|
||||
(cut-fiat-balance balance 2))
|
||||
(.toFixed $ 2))))
|
||||
|
||||
(defn prettify-balance
|
||||
[currency-symbol balance]
|
||||
@@ -155,10 +151,6 @@
|
||||
[accounts address]
|
||||
(some #(when (= (:address %) address) %) accounts))
|
||||
|
||||
(defn get-default-account
|
||||
[accounts]
|
||||
(some #(when (:default-account? %) %) accounts))
|
||||
|
||||
(defn calculate-token-fiat-value
|
||||
"Returns the token fiat value for provided raw balance"
|
||||
[{:keys [currency balance token]}]
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
[native-module.core :as native-module]
|
||||
[promesa.core :as promesa]
|
||||
[status-im.common.json-rpc.events :as json-rpc]
|
||||
[status-im.contexts.profile.recover.effects :as profile.recover.effects]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.security.core :as security]
|
||||
@@ -27,6 +26,26 @@
|
||||
:paths paths}
|
||||
on-success))))
|
||||
|
||||
(defn validate-mnemonic
|
||||
[mnemonic]
|
||||
(-> mnemonic
|
||||
(security/safe-unmask-data)
|
||||
(native-module/validate-mnemonic)
|
||||
(promesa/then (fn [result]
|
||||
(let [{:keys [keyUID]} (transforms/json->clj result)]
|
||||
{:key-uid keyUID})))))
|
||||
|
||||
(rf/reg-fx
|
||||
:multiaccount/validate-mnemonic
|
||||
(fn [[mnemonic on-success on-error]]
|
||||
(-> (validate-mnemonic mnemonic)
|
||||
(promesa/then (fn [{:keys [key-uid]}]
|
||||
(when (fn? on-success)
|
||||
(on-success mnemonic key-uid))))
|
||||
(promesa/catch (fn [error]
|
||||
(when (and error (fn? on-error))
|
||||
(on-error error)))))))
|
||||
|
||||
(defn create-account-from-private-key
|
||||
[private-key]
|
||||
(-> private-key
|
||||
@@ -62,7 +81,7 @@
|
||||
|
||||
(defn import-missing-keypair-by-seed-phrase
|
||||
[keypair-key-uid seed-phrase password]
|
||||
(-> (profile.recover.effects/validate-mnemonic seed-phrase)
|
||||
(-> (validate-mnemonic seed-phrase)
|
||||
(promesa/then
|
||||
(fn [{:keys [key-uid]}]
|
||||
(if (not= keypair-key-uid key-uid)
|
||||
|
||||
@@ -28,108 +28,95 @@
|
||||
{:fx [[:dispatch [:wallet/stop-get-suggested-routes]]
|
||||
[:dispatch [:wallet/clean-suggested-routes]]]}))
|
||||
|
||||
(defn- add-not-enough-assets-data
|
||||
[send-data chosen-route]
|
||||
(-> send-data
|
||||
(assoc :route chosen-route
|
||||
:loading-suggested-routes? false
|
||||
:suggested-routes {:best []}
|
||||
:enough-assets? false)
|
||||
(update :sender-network-values send-utils/reset-loading-network-amounts-to-zero)
|
||||
(update :receiver-network-values send-utils/reset-loading-network-amounts-to-zero)))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/suggested-routes-success
|
||||
(fn [{:keys [db]} [suggested-routes-data enough-assets?]]
|
||||
(if-not enough-assets?
|
||||
{:db (update-in db [:wallet :ui :send] add-not-enough-assets-data (:best suggested-routes-data))}
|
||||
(let [chosen-route (:best suggested-routes-data)
|
||||
{:keys [token collectible token-display-name
|
||||
receiver-networks
|
||||
receiver-network-values
|
||||
sender-network-values tx-type
|
||||
disabled-from-chain-ids
|
||||
from-locked-amounts]} (get-in db [:wallet :ui :send])
|
||||
token-decimals (if collectible 0 (:decimals token))
|
||||
native-token? (and token (= token-display-name "ETH"))
|
||||
routes-available? (pos? (count chosen-route))
|
||||
token-networks (:networks token)
|
||||
token-networks-ids (when token-networks
|
||||
(map #(:chain-id %) token-networks))
|
||||
from-network-amounts-by-chain (send-utils/network-amounts-by-chain
|
||||
{:route chosen-route
|
||||
:token-decimals token-decimals
|
||||
:native-token? native-token?
|
||||
:receiver? false})
|
||||
to-network-amounts-by-chain (send-utils/network-amounts-by-chain
|
||||
{:route chosen-route
|
||||
:token-decimals token-decimals
|
||||
:native-token? native-token?
|
||||
:receiver? true})
|
||||
sender-possible-chain-ids (map :chain-id sender-network-values)
|
||||
sender-network-values (if routes-available?
|
||||
(send-utils/network-amounts
|
||||
{:network-values
|
||||
(if (= tx-type :tx/bridge)
|
||||
from-network-amounts-by-chain
|
||||
(send-utils/add-zero-values-to-network-values
|
||||
from-network-amounts-by-chain
|
||||
sender-possible-chain-ids))
|
||||
:disabled-chain-ids disabled-from-chain-ids
|
||||
:receiver-networks receiver-networks
|
||||
:token-networks-ids token-networks-ids
|
||||
:from-locked-amounts from-locked-amounts
|
||||
:tx-type tx-type
|
||||
:receiver? false})
|
||||
(rf/reg-event-fx :wallet/suggested-routes-success
|
||||
(fn [{:keys [db]} [suggested-routes-data]]
|
||||
(let [chosen-route (:best suggested-routes-data)
|
||||
{:keys [token collectible token-display-name
|
||||
receiver-networks
|
||||
receiver-network-values
|
||||
sender-network-values tx-type
|
||||
disabled-from-chain-ids
|
||||
from-locked-amounts]} (get-in db [:wallet :ui :send])
|
||||
token-decimals (if collectible 0 (:decimals token))
|
||||
native-token? (and token (= token-display-name "ETH"))
|
||||
routes-available? (pos? (count chosen-route))
|
||||
token-networks (:networks token)
|
||||
token-networks-ids (when token-networks
|
||||
(map #(:chain-id %) token-networks))
|
||||
from-network-amounts-by-chain (send-utils/network-amounts-by-chain
|
||||
{:route chosen-route
|
||||
:token-decimals token-decimals
|
||||
:native-token? native-token?
|
||||
:receiver? false})
|
||||
to-network-amounts-by-chain (send-utils/network-amounts-by-chain
|
||||
{:route chosen-route
|
||||
:token-decimals token-decimals
|
||||
:native-token? native-token?
|
||||
:receiver? true})
|
||||
sender-possible-chain-ids (map :chain-id sender-network-values)
|
||||
sender-network-values (if routes-available?
|
||||
(send-utils/network-amounts
|
||||
{:network-values
|
||||
(if (= tx-type :tx/bridge)
|
||||
from-network-amounts-by-chain
|
||||
(send-utils/add-zero-values-to-network-values
|
||||
from-network-amounts-by-chain
|
||||
sender-possible-chain-ids))
|
||||
:disabled-chain-ids disabled-from-chain-ids
|
||||
:receiver-networks receiver-networks
|
||||
:token-networks-ids token-networks-ids
|
||||
:from-locked-amounts from-locked-amounts
|
||||
:tx-type tx-type
|
||||
:receiver? false})
|
||||
(send-utils/reset-loading-network-amounts-to-zero
|
||||
sender-network-values))
|
||||
receiver-network-values (if routes-available?
|
||||
(send-utils/network-amounts
|
||||
{:network-values to-network-amounts-by-chain
|
||||
:disabled-chain-ids disabled-from-chain-ids
|
||||
:receiver-networks receiver-networks
|
||||
:token-networks-ids token-networks-ids
|
||||
:tx-type tx-type
|
||||
:receiver? true})
|
||||
(cond->
|
||||
(send-utils/reset-loading-network-amounts-to-zero
|
||||
sender-network-values))
|
||||
receiver-network-values (if routes-available?
|
||||
(send-utils/network-amounts
|
||||
{:network-values to-network-amounts-by-chain
|
||||
:disabled-chain-ids disabled-from-chain-ids
|
||||
:receiver-networks receiver-networks
|
||||
:token-networks-ids token-networks-ids
|
||||
:tx-type tx-type
|
||||
:receiver? true})
|
||||
(cond->
|
||||
(send-utils/reset-loading-network-amounts-to-zero
|
||||
receiver-network-values)
|
||||
receiver-network-values)
|
||||
|
||||
(not= tx-type :tx/bridge)
|
||||
send-utils/safe-add-type-edit))
|
||||
network-links (when routes-available?
|
||||
(send-utils/network-links chosen-route
|
||||
sender-network-values
|
||||
receiver-network-values))]
|
||||
{:db (update-in db
|
||||
[:wallet :ui :send]
|
||||
assoc
|
||||
:suggested-routes suggested-routes-data
|
||||
:route chosen-route
|
||||
:from-values-by-chain from-network-amounts-by-chain
|
||||
:to-values-by-chain to-network-amounts-by-chain
|
||||
:sender-network-values sender-network-values
|
||||
:receiver-network-values receiver-network-values
|
||||
:network-links network-links
|
||||
:loading-suggested-routes? false
|
||||
:enough-assets? true)}))))
|
||||
(not= tx-type :tx/bridge)
|
||||
send-utils/safe-add-type-edit))
|
||||
network-links (when routes-available?
|
||||
(send-utils/network-links chosen-route
|
||||
sender-network-values
|
||||
receiver-network-values))]
|
||||
{:db (update-in db
|
||||
[:wallet :ui :send]
|
||||
assoc
|
||||
:suggested-routes suggested-routes-data
|
||||
:route chosen-route
|
||||
:from-values-by-chain from-network-amounts-by-chain
|
||||
:to-values-by-chain to-network-amounts-by-chain
|
||||
:sender-network-values sender-network-values
|
||||
:receiver-network-values receiver-network-values
|
||||
:network-links network-links
|
||||
:loading-suggested-routes? false)})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/suggested-routes-error
|
||||
(rf/reg-event-fx :wallet/suggested-routes-error
|
||||
(fn [{:keys [db]} [error-message]]
|
||||
{:db (-> db
|
||||
(update-in [:wallet :ui :send] dissoc :route)
|
||||
(update-in [:wallet :ui :send :sender-network-values]
|
||||
send-utils/reset-loading-network-amounts-to-zero)
|
||||
(update-in [:wallet :ui :send :receiver-network-values]
|
||||
send-utils/reset-loading-network-amounts-to-zero)
|
||||
(assoc-in [:wallet :ui :send :loading-suggested-routes?] false)
|
||||
(assoc-in [:wallet :ui :send :suggested-routes] {:best []}))
|
||||
:fx [[:dispatch
|
||||
[:toasts/upsert
|
||||
{:id :send-transaction-error
|
||||
:type :negative
|
||||
:text error-message}]]]}))
|
||||
(let [cleaned-sender-network-values (-> (get-in db [:wallet :ui :send :sender-network-values])
|
||||
(send-utils/reset-loading-network-amounts-to-zero))
|
||||
cleaned-receiver-network-values (-> (get-in db [:wallet :ui :send :receiver-network-values])
|
||||
(send-utils/reset-loading-network-amounts-to-zero))]
|
||||
{:db (-> db
|
||||
(update-in [:wallet :ui :send] dissoc :route)
|
||||
(assoc-in [:wallet :ui :send :sender-network-values] cleaned-sender-network-values)
|
||||
(assoc-in [:wallet :ui :send :receiver-network-values] cleaned-receiver-network-values)
|
||||
(assoc-in [:wallet :ui :send :loading-suggested-routes?] false)
|
||||
(assoc-in [:wallet :ui :send :suggested-routes] {:best []}))
|
||||
:fx [[:dispatch
|
||||
[:toasts/upsert
|
||||
{:id :send-transaction-error
|
||||
:type :negative
|
||||
:text error-message}]]]})))
|
||||
|
||||
(rf/reg-event-fx :wallet/clean-send-address
|
||||
(fn [{:keys [db]}]
|
||||
@@ -391,7 +378,8 @@
|
||||
from-locked-amounts bridge-to-chain-id]
|
||||
:or {token updated-token}} (get-in db [:wallet :ui :send])
|
||||
test-networks-enabled? (get-in db [:profile/profile :test-networks-enabled?])
|
||||
networks (get-in db [:wallet :networks (if test-networks-enabled? :test :prod)])
|
||||
networks ((if test-networks-enabled? :test :prod)
|
||||
(get-in db [:wallet :networks]))
|
||||
network-chain-ids (map :chain-id networks)
|
||||
token-decimal (when token (:decimals token))
|
||||
token-id (utils/format-token-id token collectible)
|
||||
@@ -521,43 +509,40 @@
|
||||
[routes]
|
||||
(map data-store/new->old-route-path routes))
|
||||
|
||||
(def ^:private best-routes-fix
|
||||
(comp ->old-route-paths
|
||||
remove-invalid-bonder-fees-routes
|
||||
remove-multichain-routes))
|
||||
|
||||
(def ^:private candidates-fix
|
||||
(comp ->old-route-paths remove-invalid-bonder-fees-routes))
|
||||
|
||||
(defn- fix-routes
|
||||
[data]
|
||||
(-> data
|
||||
(data-store/rpc->suggested-routes)
|
||||
(update :best best-routes-fix)
|
||||
(update :candidates candidates-fix)))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/handle-suggested-routes
|
||||
(fn [{:keys [db]} [data]]
|
||||
(let [{send :send swap? :swap} (-> db :wallet :ui)
|
||||
skip-processing-routes? (:skip-processing-suggested-routes? send)]
|
||||
(when (or swap? (not skip-processing-routes?))
|
||||
(let [{error-code :code
|
||||
:as error} (:ErrorResponse data)
|
||||
enough-assets? (not (and (:Best data) (= error-code "WR-002")))
|
||||
failure? (and error enough-assets? (not swap?))
|
||||
error-message (if (zero? error-code) "An error occurred" (:details error))]
|
||||
(when failure?
|
||||
(log/error "failed to get suggested routes (async)"
|
||||
{:event :wallet/handle-suggested-routes
|
||||
:error error-message}))
|
||||
{:fx [[:dispatch
|
||||
(cond
|
||||
(and failure? swap?) [:wallet/swap-proposal-error error-message]
|
||||
failure? [:wallet/suggested-routes-error error-message]
|
||||
swap? [:wallet/swap-proposal-success (fix-routes data)]
|
||||
:else [:wallet/suggested-routes-success (fix-routes data)
|
||||
enough-assets?])]]})))))
|
||||
(let [swap? (get-in db [:wallet :ui :swap])
|
||||
{:keys [code details] :as error-response} (-> data :ErrorResponse)
|
||||
skip-processing-suggested-routes? (get-in db
|
||||
[:wallet :ui :send
|
||||
:skip-processing-suggested-routes?])
|
||||
process-response? (and (not swap?)
|
||||
(not skip-processing-suggested-routes?))]
|
||||
(if (and (not swap?) error-response)
|
||||
(let [error-message (if (= code "0") "An error occurred" details)]
|
||||
(log/error "failed to get suggested routes (async)"
|
||||
{:event :wallet/handle-suggested-routes
|
||||
:error error-message})
|
||||
{:fx [(cond
|
||||
swap?
|
||||
[:dispatch [:wallet/swap-proposal-error error-message]]
|
||||
process-response?
|
||||
[:dispatch [:wallet/suggested-routes-error error-message]])]})
|
||||
(let [best-routes-fix (comp ->old-route-paths
|
||||
remove-invalid-bonder-fees-routes
|
||||
remove-multichain-routes)
|
||||
candidates-fix (comp ->old-route-paths
|
||||
remove-invalid-bonder-fees-routes)
|
||||
routes (-> data
|
||||
(data-store/rpc->suggested-routes)
|
||||
(update :best best-routes-fix)
|
||||
(update :candidates candidates-fix))]
|
||||
{:fx [(cond
|
||||
swap?
|
||||
[:dispatch [:wallet/swap-proposal-success routes]]
|
||||
process-response?
|
||||
[:dispatch [:wallet/suggested-routes-success routes]])]})))))
|
||||
|
||||
(rf/reg-event-fx :wallet/add-authorized-transaction
|
||||
(fn [{:keys [db]} [transaction]]
|
||||
|
||||
@@ -41,8 +41,6 @@
|
||||
:mixedcase-address "0x7bcDfc75c431"
|
||||
:public-key "0x04371e2d9d66b82f056bc128064"
|
||||
:removed false}
|
||||
:wallet/current-viewing-account-color :purple
|
||||
:wallet/wallet-send-enough-assets? true
|
||||
:wallet/wallet-send-token {:symbol :eth
|
||||
:networks [{:source 879
|
||||
:short-name "eth"
|
||||
|
||||
@@ -121,7 +121,7 @@
|
||||
[quo/alert-banner
|
||||
{:action? true
|
||||
:text (i18n/label :t/not-enough-assets-to-pay-gas-fees)
|
||||
:button-text (i18n/label :t/add-eth)
|
||||
:button-text (i18n/label :t/buy-eth)
|
||||
:on-button-press #(rf/dispatch [:show-bottom-sheet
|
||||
{:content buy-token/view}])}])
|
||||
|
||||
@@ -140,26 +140,6 @@
|
||||
|
||||
:else (rf/dispatch [:wallet/stop-and-clean-suggested-routes])))
|
||||
|
||||
(defn- get-fee-formatted
|
||||
[route]
|
||||
(when-let [native-currency-symbol (-> route first :from :native-currency-symbol)]
|
||||
(rf/sub [:wallet/wallet-send-fee-fiat-formatted native-currency-symbol])))
|
||||
|
||||
(defn- insufficient-asset-amount?
|
||||
[{:keys [token-symbol owned-eth-token input-state no-routes-found? limit-exceeded?
|
||||
sender-network-values enough-assets?]}]
|
||||
(let [eth-selected? (= token-symbol (string/upper-case constants/mainnet-short-name))
|
||||
zero-owned-eth? (money/equal-to (:total-balance owned-eth-token) 0)
|
||||
input-at-max-owned-amount? (money/equal-to
|
||||
(controlled-input/value-bn input-state)
|
||||
(controlled-input/upper-limit-bn input-state))
|
||||
exceeded-input? (if eth-selected?
|
||||
input-at-max-owned-amount?
|
||||
zero-owned-eth?)]
|
||||
(and (or no-routes-found? limit-exceeded?)
|
||||
(seq sender-network-values)
|
||||
(or exceeded-input? (not enough-assets?)))))
|
||||
|
||||
(defn view
|
||||
;; crypto-decimals, limit-crypto and initial-crypto-currency? args are needed
|
||||
;; for component tests only
|
||||
@@ -174,129 +154,147 @@
|
||||
enabled-from-chain-ids :enabled-from-chain-ids
|
||||
from-enabled-networks :from-enabled-networks
|
||||
:or {initial-crypto-currency? true}}]
|
||||
(let [view-id (rf/sub [:view-id])
|
||||
active-screen? (= view-id current-screen-id)
|
||||
bottom (safe-area/get-bottom)
|
||||
[crypto-currency?
|
||||
set-crypto-currency] (rn/use-state initial-crypto-currency?)
|
||||
handle-on-confirm (fn [amount]
|
||||
(rf/dispatch [:wallet/set-token-amount-to-send
|
||||
{:amount amount
|
||||
:stack-id current-screen-id}]))
|
||||
{fiat-currency :currency} (rf/sub [:profile/profile])
|
||||
{token-symbol :symbol
|
||||
(let [view-id (rf/sub [:view-id])
|
||||
active-screen? (= view-id current-screen-id)
|
||||
bottom (safe-area/get-bottom)
|
||||
[crypto-currency? set-crypto-currency] (rn/use-state initial-crypto-currency?)
|
||||
on-navigate-back on-navigate-back
|
||||
handle-on-confirm (fn [amount]
|
||||
(rf/dispatch [:wallet/set-token-amount-to-send
|
||||
{:amount amount
|
||||
:stack-id current-screen-id}]))
|
||||
{fiat-currency :currency} (rf/sub [:profile/profile])
|
||||
{token-symbol :symbol
|
||||
token-networks :networks
|
||||
:as token} (rf/sub [:wallet/wallet-send-token])
|
||||
send-from-locked-amounts (rf/sub [:wallet/wallet-send-from-locked-amounts])
|
||||
:as
|
||||
token} (rf/sub [:wallet/wallet-send-token])
|
||||
send-from-locked-amounts (rf/sub [:wallet/wallet-send-from-locked-amounts])
|
||||
{:keys [total-balance]
|
||||
:as token-by-symbol} (rf/sub [:wallet/token-by-symbol
|
||||
(str token-symbol)
|
||||
enabled-from-chain-ids])
|
||||
token-balance (or default-limit-crypto total-balance)
|
||||
usd-conversion-rate (utils/token-usd-price token)
|
||||
currency (rf/sub [:profile/currency])
|
||||
conversion-rate (-> token
|
||||
:market-values-per-currency
|
||||
currency
|
||||
:price)
|
||||
token-decimals (-> token
|
||||
utils/token-usd-price
|
||||
utils/one-cent-value
|
||||
utils/calc-max-crypto-decimals)
|
||||
[input-state set-input-state] (rn/use-state controlled-input/init-state)
|
||||
clear-input! #(set-input-state controlled-input/delete-all)
|
||||
currency-symbol (rf/sub [:profile/currency-symbol])
|
||||
loading-routes? (rf/sub [:wallet/wallet-send-loading-suggested-routes?])
|
||||
route (rf/sub [:wallet/wallet-send-route])
|
||||
on-confirm (or default-on-confirm handle-on-confirm)
|
||||
crypto-decimals (or token-decimals default-crypto-decimals)
|
||||
max-limit (if crypto-currency?
|
||||
(utils/cut-crypto-decimals-to-fit-usd-cents
|
||||
token-balance
|
||||
usd-conversion-rate)
|
||||
(utils/cut-fiat-balance-to-two-decimals
|
||||
(money/crypto->fiat token-balance conversion-rate)))
|
||||
input-value (controlled-input/input-value input-state)
|
||||
valid-input? (not (or (controlled-input/empty-value? input-state)
|
||||
(controlled-input/input-error input-state)))
|
||||
amount-in-crypto (if crypto-currency?
|
||||
input-value
|
||||
(number/remove-trailing-zeroes
|
||||
(.toFixed (/ input-value conversion-rate)
|
||||
crypto-decimals)))
|
||||
total-amount-receiver (rf/sub [:wallet/total-amount true])
|
||||
amount-text (str (number/remove-trailing-zeroes
|
||||
(.toFixed total-amount-receiver
|
||||
(min token-decimals 6)))
|
||||
" "
|
||||
token-symbol)
|
||||
show-select-asset-sheet #(rf/dispatch
|
||||
[:show-bottom-sheet
|
||||
{:content (fn []
|
||||
[select-asset-bottom-sheet
|
||||
clear-input!])}])
|
||||
sender-network-values (rf/sub [:wallet/wallet-send-sender-network-values])
|
||||
receiver-network-values (rf/sub [:wallet/wallet-send-receiver-network-values])
|
||||
tx-type (rf/sub [:wallet/wallet-send-tx-type])
|
||||
unsupported-token-in-receiver? (and (not= tx-type :tx/bridge)
|
||||
(->> receiver-network-values
|
||||
(remove #(= (:type %) :add))
|
||||
(every? #(= (:type %) :not-available))))
|
||||
suggested-routes (rf/sub [:wallet/wallet-send-suggested-routes])
|
||||
routes (when suggested-routes
|
||||
(or (:best suggested-routes) []))
|
||||
no-routes-found? (and
|
||||
(every-network-value-is-zero? sender-network-values)
|
||||
(some? routes)
|
||||
(not loading-routes?)
|
||||
(not unsupported-token-in-receiver?))
|
||||
receiver-networks (rf/sub [:wallet/wallet-send-receiver-networks])
|
||||
receiver-preferred-networks (rf/sub [:wallet/wallet-send-receiver-preferred-networks])
|
||||
receiver-preferred-network? (set receiver-preferred-networks)
|
||||
sending-to-unpreferred-networks? (some (comp not receiver-preferred-network?)
|
||||
receiver-networks)
|
||||
input-error (controlled-input/input-error input-state)
|
||||
limit-exceeded? (controlled-input/upper-limit-exceeded? input-state)
|
||||
current-address (rf/sub [:wallet/current-viewing-account-address])
|
||||
current-color (rf/sub [:wallet/current-viewing-account-color])
|
||||
enough-assets? (rf/sub [:wallet/wallet-send-enough-assets?])
|
||||
owned-eth-token (rf/sub [:wallet/token-by-symbol
|
||||
(string/upper-case constants/mainnet-short-name)
|
||||
enabled-from-chain-ids])
|
||||
not-enough-asset? (insufficient-asset-amount?
|
||||
{:enough-assets? enough-assets?
|
||||
:token-symbol token-symbol
|
||||
:owned-eth-token owned-eth-token
|
||||
:input-state input-state
|
||||
:no-routes-found? no-routes-found?
|
||||
:limit-exceeded? limit-exceeded?
|
||||
:sender-network-values sender-network-values})
|
||||
should-try-again? (and (not limit-exceeded?)
|
||||
no-routes-found?
|
||||
(not not-enough-asset?))
|
||||
show-no-routes? (and (or no-routes-found? limit-exceeded?)
|
||||
(not-empty sender-network-values)
|
||||
(not not-enough-asset?))
|
||||
confirm-disabled? (or (nil? route)
|
||||
(empty? route)
|
||||
(not valid-input?))
|
||||
fee-formatted (when (or (not confirm-disabled?) not-enough-asset?)
|
||||
(get-fee-formatted route))
|
||||
request-fetch-routes (fn [bounce-duration-ms]
|
||||
(fetch-routes
|
||||
{:amount amount-in-crypto
|
||||
:valid-input? valid-input?
|
||||
:bounce-duration-ms bounce-duration-ms
|
||||
:token token
|
||||
:reset-amounts-to-zero? (and limit-exceeded?
|
||||
(some? routes))}))
|
||||
swap-between-fiat-and-crypto (fn []
|
||||
(if crypto-currency?
|
||||
(set-input-state
|
||||
#(controlled-input/->fiat % conversion-rate))
|
||||
(set-input-state
|
||||
#(controlled-input/->crypto % conversion-rate)))
|
||||
(set-crypto-currency (not crypto-currency?)))]
|
||||
:as token-by-symbol} (rf/sub [:wallet/token-by-symbol
|
||||
(str token-symbol)
|
||||
enabled-from-chain-ids])
|
||||
token-balance (or default-limit-crypto total-balance)
|
||||
usd-conversion-rate (utils/token-usd-price token)
|
||||
currency (rf/sub [:profile/currency])
|
||||
conversion-rate (-> token
|
||||
:market-values-per-currency
|
||||
currency
|
||||
:price)
|
||||
token-decimals (-> token
|
||||
utils/token-usd-price
|
||||
utils/one-cent-value
|
||||
utils/calc-max-crypto-decimals)
|
||||
[input-state set-input-state] (rn/use-state controlled-input/init-state)
|
||||
clear-input! #(set-input-state controlled-input/delete-all)
|
||||
currency-symbol (rf/sub [:profile/currency-symbol])
|
||||
loading-routes? (rf/sub
|
||||
[:wallet/wallet-send-loading-suggested-routes?])
|
||||
route (rf/sub [:wallet/wallet-send-route])
|
||||
on-confirm (or default-on-confirm handle-on-confirm)
|
||||
crypto-decimals (or token-decimals default-crypto-decimals)
|
||||
max-limit (if crypto-currency?
|
||||
(utils/cut-crypto-decimals-to-fit-usd-cents
|
||||
token-balance
|
||||
usd-conversion-rate)
|
||||
(-> (money/crypto->fiat
|
||||
token-balance
|
||||
conversion-rate)
|
||||
utils/cut-fiat-balance-to-two-decimals))
|
||||
input-value (controlled-input/input-value input-state)
|
||||
valid-input? (not (or (controlled-input/empty-value? input-state)
|
||||
(controlled-input/input-error input-state)))
|
||||
confirm-disabled? (or (nil? route)
|
||||
(empty? route)
|
||||
(not valid-input?))
|
||||
amount-in-crypto (if crypto-currency?
|
||||
input-value
|
||||
(number/remove-trailing-zeroes
|
||||
(.toFixed (/ input-value conversion-rate)
|
||||
crypto-decimals)))
|
||||
total-amount-receiver (rf/sub [:wallet/total-amount true])
|
||||
amount-text (str (number/remove-trailing-zeroes
|
||||
(.toFixed total-amount-receiver
|
||||
(min token-decimals 6)))
|
||||
" "
|
||||
token-symbol)
|
||||
first-route (first route)
|
||||
native-currency-symbol (when-not confirm-disabled?
|
||||
(get-in first-route
|
||||
[:from :native-currency-symbol]))
|
||||
fee-formatted (when native-currency-symbol
|
||||
(rf/sub [:wallet/wallet-send-fee-fiat-formatted
|
||||
native-currency-symbol]))
|
||||
show-select-asset-sheet #(rf/dispatch
|
||||
[:show-bottom-sheet
|
||||
{:content (fn []
|
||||
[select-asset-bottom-sheet
|
||||
clear-input!])}])
|
||||
sender-network-values (rf/sub
|
||||
[:wallet/wallet-send-sender-network-values])
|
||||
receiver-network-values (rf/sub
|
||||
[:wallet/wallet-send-receiver-network-values])
|
||||
tx-type (rf/sub [:wallet/wallet-send-tx-type])
|
||||
token-not-supported-in-receiver-networks? (and (not= tx-type :tx/bridge)
|
||||
(->> receiver-network-values
|
||||
(remove #(= (:type %) :add))
|
||||
(every? #(= (:type %) :not-available))))
|
||||
suggested-routes (rf/sub [:wallet/wallet-send-suggested-routes])
|
||||
routes (when suggested-routes
|
||||
(or (:best suggested-routes) []))
|
||||
no-routes-found? (and
|
||||
(every-network-value-is-zero?
|
||||
sender-network-values)
|
||||
(not (nil? routes))
|
||||
(not loading-routes?)
|
||||
(not token-not-supported-in-receiver-networks?))
|
||||
receiver-networks (rf/sub [:wallet/wallet-send-receiver-networks])
|
||||
receiver-preferred-networks (rf/sub
|
||||
[:wallet/wallet-send-receiver-preferred-networks])
|
||||
receiver-preferred-networks-set (set receiver-preferred-networks)
|
||||
sending-to-unpreferred-networks? (not (every? (fn [receiver-selected-network]
|
||||
(contains?
|
||||
receiver-preferred-networks-set
|
||||
receiver-selected-network))
|
||||
receiver-networks))
|
||||
input-error (controlled-input/input-error input-state)
|
||||
limit-exceeded? (controlled-input/upper-limit-exceeded? input-state)
|
||||
should-try-again? (and (not limit-exceeded?) no-routes-found?)
|
||||
current-address (rf/sub [:wallet/current-viewing-account-address])
|
||||
owned-eth-token (rf/sub [:wallet/token-by-symbol
|
||||
(string/upper-case
|
||||
constants/mainnet-short-name)
|
||||
enabled-from-chain-ids])
|
||||
not-enough-asset? (and
|
||||
(or no-routes-found? limit-exceeded?)
|
||||
(not-empty sender-network-values)
|
||||
(if (= token-symbol
|
||||
(string/upper-case
|
||||
constants/mainnet-short-name))
|
||||
(money/equal-to
|
||||
(controlled-input/value-bn input-state)
|
||||
(controlled-input/upper-limit-bn input-state))
|
||||
(money/equal-to (:total-balance
|
||||
owned-eth-token)
|
||||
0)))
|
||||
show-no-routes? (and
|
||||
(or no-routes-found? limit-exceeded?)
|
||||
(not-empty sender-network-values)
|
||||
(not not-enough-asset?))
|
||||
request-fetch-routes (fn [bounce-duration-ms]
|
||||
(fetch-routes
|
||||
{:amount amount-in-crypto
|
||||
:valid-input? valid-input?
|
||||
:bounce-duration-ms bounce-duration-ms
|
||||
:token token
|
||||
:reset-amounts-to-zero? (and limit-exceeded?
|
||||
(some? routes))}))
|
||||
swap-between-fiat-and-crypto (fn []
|
||||
(if crypto-currency?
|
||||
(set-input-state
|
||||
#(controlled-input/->fiat % conversion-rate))
|
||||
(set-input-state
|
||||
#(controlled-input/->crypto % conversion-rate)))
|
||||
(set-crypto-currency (not crypto-currency?)))]
|
||||
(rn/use-effect
|
||||
(fn []
|
||||
(when active-screen?
|
||||
@@ -371,44 +369,38 @@
|
||||
{:token token-by-symbol
|
||||
:send-amount-in-crypto amount-in-crypto
|
||||
:valid-input? valid-input?
|
||||
:token-not-supported-in-receiver-networks? unsupported-token-in-receiver?
|
||||
:token-not-supported-in-receiver-networks? token-not-supported-in-receiver-networks?
|
||||
:current-screen-id current-screen-id
|
||||
:request-fetch-routes request-fetch-routes}]
|
||||
(when (and (not loading-routes?)
|
||||
sender-network-values
|
||||
unsupported-token-in-receiver?)
|
||||
token-not-supported-in-receiver-networks?)
|
||||
[token-not-available token-symbol receiver-networks token-networks])
|
||||
(when not-enough-asset?
|
||||
[not-enough-asset])
|
||||
(when (or (and (not no-routes-found?) (or loading-routes? route))
|
||||
not-enough-asset?)
|
||||
(when (and (not no-routes-found?) (or loading-routes? route))
|
||||
[estimated-fees
|
||||
{:loading-routes? loading-routes?
|
||||
:fees fee-formatted
|
||||
:amount amount-text}])
|
||||
(when show-no-routes?
|
||||
[no-routes-found])
|
||||
(cond
|
||||
show-no-routes? [no-routes-found]
|
||||
not-enough-asset? [not-enough-asset])
|
||||
[quo/bottom-actions
|
||||
{:actions :one-action
|
||||
:button-one-label (if should-try-again?
|
||||
(i18n/label :t/try-again)
|
||||
button-one-label)
|
||||
:button-one-props (merge (when-not should-try-again?
|
||||
button-one-props)
|
||||
{:disabled? (or not-enough-asset?
|
||||
loading-routes?
|
||||
(and (not should-try-again?)
|
||||
confirm-disabled?))
|
||||
:on-press (cond
|
||||
should-try-again?
|
||||
#(rf/dispatch [:wallet/start-get-suggested-routes
|
||||
{:amount amount-in-crypto
|
||||
:updated-token token-by-symbol}])
|
||||
sending-to-unpreferred-networks?
|
||||
#(show-unpreferred-networks-alert on-confirm)
|
||||
:else
|
||||
#(on-confirm amount-in-crypto))
|
||||
:customization-color current-color}
|
||||
:button-one-props (merge (when-not should-try-again? button-one-props)
|
||||
{:disabled? (or loading-routes?
|
||||
(and (not should-try-again?) confirm-disabled?))
|
||||
:on-press (cond
|
||||
should-try-again?
|
||||
#(rf/dispatch [:wallet/start-get-suggested-routes
|
||||
{:amount amount-in-crypto
|
||||
:updated-token token-by-symbol}])
|
||||
sending-to-unpreferred-networks?
|
||||
#(show-unpreferred-networks-alert on-confirm)
|
||||
:else
|
||||
#(on-confirm amount-in-crypto))}
|
||||
(when should-try-again?
|
||||
{:type :grey}))}]
|
||||
[quo/numbered-keyboard
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
[input-amount/view
|
||||
{:current-screen-id :screen/wallet.send-input-amount
|
||||
:button-one-label (i18n/label :t/review-send)
|
||||
:enabled-from-chain-ids (rf/sub [:wallet/wallet-send-enabled-from-chain-ids])
|
||||
:enabled-from-chain-ids (rf/sub
|
||||
[:wallet/wallet-send-enabled-from-chain-ids])
|
||||
:from-enabled-networks (rf/sub [:wallet/wallet-send-enabled-networks])
|
||||
:on-navigate-back (fn []
|
||||
(rf/dispatch-sync [:wallet/stop-and-clean-suggested-routes])
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
(ns status-im.contexts.wallet.sheets.buy-network-selection.style)
|
||||
|
||||
(defn network-list-container
|
||||
[mainnet?]
|
||||
{:margin-horizontal 8
|
||||
:padding-vertical (when mainnet? 8)})
|
||||
|
||||
(def header-container
|
||||
{:height 62
|
||||
:padding-horizontal 20})
|
||||
|
||||
(def context-tag
|
||||
{:margin-top 0})
|
||||
|
||||
(def divider-label
|
||||
{:padding-top 0
|
||||
:padding-bottom 0})
|
||||
|
||||
(def subheader-container
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:margin-top 4})
|
||||
|
||||
(def on
|
||||
{:margin-right 4})
|
||||
|
||||
(def to
|
||||
{:margin-horizontal 4})
|
||||
@@ -1,78 +0,0 @@
|
||||
(ns status-im.contexts.wallet.sheets.buy-network-selection.view
|
||||
(:require [quo.core :as quo]
|
||||
[quo.foundations.resources :as quo.resources]
|
||||
[react-native.core :as rn]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.sheets.buy-network-selection.style :as style]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- network-item
|
||||
[{:keys [network on-select-network]}]
|
||||
(let [{:keys [network-name]} network
|
||||
mainnet? (= network-name constants/mainnet-network-name)]
|
||||
[quo/network-list
|
||||
{:label (name network-name)
|
||||
:network-image (quo.resources/get-network network-name)
|
||||
:on-press #(on-select-network network)
|
||||
:container-style (style/network-list-container mainnet?)}]))
|
||||
|
||||
(defn- subheader
|
||||
[{:keys [provider account]}]
|
||||
[rn/view {:style style/subheader-container}
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:style style/on}
|
||||
(i18n/label :t/on-uppercase)]
|
||||
[quo/context-tag
|
||||
{:type :network
|
||||
:network-logo (:logo-url provider)
|
||||
:network-name (:name provider)
|
||||
:size 24
|
||||
:container-style style/context-tag}]
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:style style/to}
|
||||
(i18n/label :t/to)]
|
||||
[quo/context-tag
|
||||
{:type :account
|
||||
:account-name (:name account)
|
||||
:emoji (:emoji account)
|
||||
:size 24
|
||||
:container-style style/context-tag}]])
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [provider (rf/sub [:wallet/wallet-buy-crypto-provider])
|
||||
account (rf/sub [:wallet/wallet-buy-crypto-account])
|
||||
network-details (rf/sub [:wallet/network-details])
|
||||
mainnet-network (first network-details)
|
||||
layer-2-networks (rest network-details)
|
||||
render-fn (rn/use-callback (fn [network]
|
||||
[network-item
|
||||
{:network network
|
||||
:on-select-network
|
||||
(fn [network]
|
||||
(rf/dispatch [:wallet.buy-crypto/select-network
|
||||
network]))}]))]
|
||||
[:<>
|
||||
[rn/view {:style style/header-container}
|
||||
[quo/text
|
||||
{:size :heading-2
|
||||
:weight :semi-bold}
|
||||
(i18n/label :t/select-network-for-buying)]
|
||||
[subheader
|
||||
{:provider provider
|
||||
:account account}]]
|
||||
(when mainnet-network
|
||||
[network-item
|
||||
{:network mainnet-network
|
||||
:on-select-network #(rf/dispatch [:wallet.buy-crypto/select-network mainnet-network])}])
|
||||
[quo/divider-label {:container-style style/divider-label}
|
||||
(i18n/label :t/layer-2)]
|
||||
[rn/flat-list
|
||||
{:data (vec layer-2-networks)
|
||||
:render-fn render-fn
|
||||
:scroll-enabled false}]]))
|
||||
@@ -7,20 +7,11 @@
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- crypto-on-ramp-item
|
||||
[{:keys [name description fees logo-url site-url recurrent-site-url urls-need-parameters]
|
||||
:as provider}
|
||||
_
|
||||
_
|
||||
{:keys [account tab]}]
|
||||
(let [open-url (rn/use-callback
|
||||
(fn []
|
||||
(if urls-need-parameters
|
||||
(rf/dispatch [:wallet.buy-crypto/select-provider
|
||||
{:account account
|
||||
:provider provider
|
||||
:recurrent? (= tab :recurrent)}])
|
||||
(rn/open-url (if (= tab :recurrent) recurrent-site-url site-url))))
|
||||
[site-url recurrent-site-url tab])]
|
||||
[{:keys [name description fees logo-url site-url recurrent-site-url]} _ _ {:keys [tab]}]
|
||||
(let [open-url (rn/use-callback (fn []
|
||||
(rf/dispatch [:open-url
|
||||
(if (= tab :recurrent) recurrent-site-url site-url)]))
|
||||
[site-url recurrent-site-url tab])]
|
||||
[quo/settings-item
|
||||
{:title name
|
||||
:description :text
|
||||
@@ -48,14 +39,13 @@
|
||||
(rn/use-mount (fn []
|
||||
(rf/dispatch [:wallet/get-crypto-on-ramps])))
|
||||
(let [crypto-on-ramps (rf/sub [:wallet/crypto-on-ramps])
|
||||
account (rf/sub [:wallet/current-viewing-account-or-default])
|
||||
[selected-tab set-selected-tab] (rn/use-state initial-tab)
|
||||
[min-height set-min-height] (rn/use-state 0)
|
||||
on-layout (rn/use-callback
|
||||
#(set-min-height
|
||||
(oops/oget % :nativeEvent :layout :height)))]
|
||||
[:<>
|
||||
[quo/drawer-top {:title (or title (i18n/label :t/ways-to-buy-assets))}]
|
||||
[quo/drawer-top {:title (or title (i18n/label :t/buy-assets))}]
|
||||
[quo/segmented-control
|
||||
{:size 32
|
||||
:container-style style/tabs
|
||||
@@ -68,6 +58,5 @@
|
||||
(:one-time crypto-on-ramps))
|
||||
:on-layout on-layout
|
||||
:style (style/list-container min-height)
|
||||
:render-data {:tab selected-tab
|
||||
:account account}
|
||||
:render-data {:tab selected-tab}
|
||||
:render-fn crypto-on-ramp-item}]]))
|
||||
|
||||
@@ -2,60 +2,30 @@
|
||||
(:require [quo.core :as quo]
|
||||
quo.theme
|
||||
[react-native.gesture :as gesture]
|
||||
[status-im.contexts.wallet.common.utils :as wallet.utils]
|
||||
[status-im.contexts.wallet.sheets.select-account.style :as style]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn list-item
|
||||
[{:keys [account selected-account-address]}]
|
||||
(let [{:keys [color address]} account]
|
||||
[quo/account-item
|
||||
{:type :default
|
||||
:account-props (assoc account :customization-color color)
|
||||
:customization-color color
|
||||
:state (if (= address selected-account-address) :selected :default)
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:wallet/switch-current-viewing-account address])
|
||||
(rf/dispatch [:hide-bottom-sheet]))}]))
|
||||
|
||||
(defn list-item-with-balance
|
||||
[{:keys [account selected-account-address asset-symbol network]}]
|
||||
(let [{:keys [color address tokens]} account
|
||||
token (->> tokens
|
||||
(filter #(= (:symbol %) asset-symbol))
|
||||
first)
|
||||
token-balance (get-in token [:balances-per-chain (:chain-id network) :balance])]
|
||||
[quo/account-item
|
||||
{:type (if (= address selected-account-address) :default :tag)
|
||||
:token-props {:symbol asset-symbol
|
||||
:value (wallet.utils/cut-fiat-balance (or (js/parseFloat token-balance) 0)
|
||||
4)}
|
||||
:account-props (assoc account :customization-color color)
|
||||
:customization-color color
|
||||
:state (if (= address selected-account-address) :selected :default)
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:wallet/switch-current-viewing-account address])
|
||||
(rf/dispatch [:hide-bottom-sheet]))}]))
|
||||
(defn- render-account-item
|
||||
[{:keys [color address] :as account} _ _ {:keys [selected-account-address]}]
|
||||
[quo/account-item
|
||||
{:type :default
|
||||
:account-props (assoc account :customization-color color)
|
||||
:customization-color color
|
||||
:state (if (= address selected-account-address) :selected :default)
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:wallet/switch-current-viewing-account address])
|
||||
(rf/dispatch [:hide-bottom-sheet]))}])
|
||||
|
||||
(defn view
|
||||
[{:keys [show-account-balances? asset-symbol network]}]
|
||||
[]
|
||||
(let [selected-account-address (rf/sub [:wallet/current-viewing-account-address])
|
||||
accounts (rf/sub [:wallet/operable-accounts])]
|
||||
[:<>
|
||||
[quo/drawer-top {:title (i18n/label :t/select-account)}]
|
||||
[gesture/flat-list
|
||||
{:data accounts
|
||||
:render-fn (fn [account _ _ {:keys [selected-account-address]}]
|
||||
(if show-account-balances?
|
||||
[list-item-with-balance
|
||||
{:account account
|
||||
:selected-account-address selected-account-address
|
||||
:asset-symbol asset-symbol
|
||||
:network network}]
|
||||
[list-item
|
||||
{:account account
|
||||
:selected-account-address selected-account-address}]))
|
||||
:render-fn render-account-item
|
||||
:render-data {:selected-account-address selected-account-address}
|
||||
:content-container-style style/list-container
|
||||
:shows-vertical-scroll-indicator false}]]))
|
||||
|
||||
@@ -51,31 +51,14 @@
|
||||
:network-name full-name
|
||||
:type :network}])
|
||||
|
||||
(defn- provider-view
|
||||
[{:keys [name logo-url]}]
|
||||
[quo/context-tag
|
||||
{:size 24
|
||||
:network-logo logo-url
|
||||
:network-name name
|
||||
:type :network}])
|
||||
|
||||
(defn- subheader-view
|
||||
[{:keys [provider account network]}]
|
||||
[{:keys [account network]}]
|
||||
[rn/view {:style style/subheader-container}
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium}
|
||||
(i18n/label :t/select-asset-on)]
|
||||
(if provider
|
||||
[provider-view provider]
|
||||
[account-view account])
|
||||
(when provider
|
||||
[:<>
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium}
|
||||
(i18n/label :t/to)]
|
||||
[account-view account]])
|
||||
[account-view account]
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium}
|
||||
@@ -83,8 +66,9 @@
|
||||
[network-view network]])
|
||||
|
||||
(defn view
|
||||
[{:keys [title network provider on-select hide-token-fn disable-token-fn]}]
|
||||
(let [account (rf/sub [:wallet/current-viewing-account-or-default])
|
||||
[{:keys [title on-select hide-token-fn disable-token-fn]}]
|
||||
(let [account (rf/sub [:wallet/current-viewing-account])
|
||||
{:keys [network]} (rf/sub [:wallet/swap])
|
||||
[search-text set-search-text] (rn/use-state "")
|
||||
window-height (:height (rn/get-window))]
|
||||
[rn/safe-area-view {:style (style/container window-height)}
|
||||
@@ -97,9 +81,8 @@
|
||||
{:title title
|
||||
:title-accessibility-label :title-label}]
|
||||
[subheader-view
|
||||
{:account account
|
||||
:network network
|
||||
:provider provider}]
|
||||
{:account account
|
||||
:network network}]
|
||||
[assets-view
|
||||
{:search-text search-text
|
||||
:on-change-text #(set-search-text %)
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
[utils.number :as number]))
|
||||
|
||||
(rf/reg-event-fx :wallet.swap/start
|
||||
(fn [{:keys [db]} [{:keys [network asset-to-receive open-new-screen?] :as data}]]
|
||||
(fn [{:keys [db]} [{:keys [network open-new-screen?] :as data}]]
|
||||
(let [{:keys [wallet]} db
|
||||
test-networks-enabled? (get-in db [:profile/profile :test-networks-enabled?])
|
||||
account (swap-utils/wallet-account wallet)
|
||||
@@ -25,6 +25,12 @@
|
||||
:account account
|
||||
:test-networks-enabled? test-networks-enabled?
|
||||
:token-symbol (get-in data [:asset-to-pay :symbol])}))
|
||||
asset-to-receive (or (:asset-to-receive data)
|
||||
(swap-utils/select-default-asset-to-receive
|
||||
{:wallet wallet
|
||||
:account account
|
||||
:test-networks-enabled? test-networks-enabled?
|
||||
:asset-to-pay asset-to-pay}))
|
||||
network' (or network
|
||||
(swap-utils/select-network asset-to-pay))]
|
||||
{:db (-> db
|
||||
@@ -70,7 +76,11 @@
|
||||
|
||||
(rf/reg-event-fx :wallet.swap/select-asset-to-receive
|
||||
(fn [{:keys [db]} [{:keys [token]}]]
|
||||
{:db (assoc-in db [:wallet :ui :swap :asset-to-receive] token)}))
|
||||
{:db (update-in db
|
||||
[:wallet :ui :swap]
|
||||
#(-> %
|
||||
(assoc :asset-to-receive token)
|
||||
(assoc :loading-swap-proposal? true)))}))
|
||||
|
||||
(rf/reg-event-fx :wallet.swap/set-default-slippage
|
||||
(fn [{:keys [db]}]
|
||||
@@ -131,6 +141,8 @@
|
||||
:amount amount
|
||||
:amount-hex amount-in-hex
|
||||
:loading-swap-proposal? true)
|
||||
:always
|
||||
(dissoc :error-response)
|
||||
clean-approval-transaction?
|
||||
(dissoc :approval-transaction-id :approved-amount :swap-proposal)))
|
||||
:json-rpc/call [{:method "wallet_getSuggestedRoutesAsync"
|
||||
@@ -204,12 +216,6 @@
|
||||
(fn [{:keys [db]}]
|
||||
{:db (update-in db [:wallet :ui] dissoc :swap)}))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/on-swap-done
|
||||
(fn [_]
|
||||
{:fx [[:dispatch [:wallet/select-account-tab :activity]]
|
||||
[:dispatch [:wallet/clean-swap]]]}))
|
||||
|
||||
(rf/reg-event-fx :wallet/swap-transaction
|
||||
(fn [{:keys [db]} [sha3-pwd]]
|
||||
(let [wallet-address (get-in db
|
||||
@@ -304,6 +310,8 @@
|
||||
:screen/wallet.swap-set-spending-cap
|
||||
:screen/wallet.swap-confirmation)])
|
||||
(when-not approval-required?
|
||||
(rf/dispatch [:wallet/select-account-tab :activity])
|
||||
(rf/dispatch [:wallet/clean-swap])
|
||||
(debounce/debounce-and-dispatch
|
||||
[:toasts/upsert
|
||||
{:id :swap-transaction-pending
|
||||
|
||||
@@ -20,15 +20,10 @@
|
||||
|
||||
(defn- assets-view
|
||||
[search-text on-change-text]
|
||||
(let [snt-token (rf/sub [:wallet/token-by-symbol "SNT"])
|
||||
eth-token (rf/sub [:wallet/token-by-symbol "ETH"])
|
||||
on-token-press (fn [token]
|
||||
(let [pay-token-symbol (:symbol token)
|
||||
asset-to-receive (if (= pay-token-symbol "SNT") eth-token snt-token)]
|
||||
(rf/dispatch [:wallet.swap/start
|
||||
{:asset-to-pay token
|
||||
:asset-to-receive asset-to-receive
|
||||
:open-new-screen? false}])))]
|
||||
(let [on-token-press (fn [token]
|
||||
(rf/dispatch [:wallet.swap/start
|
||||
{:asset-to-pay token
|
||||
:open-new-screen? false}]))]
|
||||
[:<>
|
||||
[search-input search-text on-change-text]
|
||||
[asset-list/view
|
||||
|
||||
@@ -10,12 +10,8 @@
|
||||
:height 36
|
||||
:background-color :transparent})
|
||||
|
||||
(def floating-button-page-content-container
|
||||
{:margin-bottom 168})
|
||||
|
||||
(def scroll-view-container
|
||||
{:flex 1
|
||||
:padding-bottom 20})
|
||||
{:padding-bottom 150})
|
||||
|
||||
(def content-container
|
||||
{:padding-top 12
|
||||
@@ -60,5 +56,5 @@
|
||||
|
||||
(defn footer-container
|
||||
[theme]
|
||||
{:margin-bottom -12
|
||||
:background-color (colors/theme-colors colors/white colors/neutral-95 theme)})
|
||||
{:margin-bottom -10
|
||||
:background-color (colors/theme-colors colors/white colors/neutral-100 theme)})
|
||||
|
||||
@@ -254,7 +254,6 @@
|
||||
[rn/view {:style style/container}
|
||||
[floating-button-page/view
|
||||
{:footer-container-padding 0
|
||||
:content-container-style style/floating-button-page-content-container
|
||||
:header [quo/page-nav
|
||||
{:icon-name :i/close
|
||||
:on-press events-helper/navigate-back
|
||||
|
||||
@@ -1,29 +1,27 @@
|
||||
(ns status-im.contexts.wallet.swap.setup-swap.view
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[oops.core :as oops]
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[status-im.common.controlled-input.utils :as controlled-input]
|
||||
[status-im.common.events-helper :as events-helper]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.common.account-switcher.view :as account-switcher]
|
||||
[status-im.contexts.wallet.common.utils :as utils]
|
||||
[status-im.contexts.wallet.sheets.buy-token.view :as buy-token]
|
||||
[status-im.contexts.wallet.sheets.select-asset.view :as select-asset]
|
||||
[status-im.contexts.wallet.sheets.slippage-settings.view :as slippage-settings]
|
||||
[status-im.contexts.wallet.swap.setup-swap.style :as style]
|
||||
[status-im.contexts.wallet.swap.utils :as swap-utils]
|
||||
[utils.debounce :as debounce]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.money :as money]
|
||||
[utils.number :as number]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.string :as utils.string]))
|
||||
(:require [clojure.string :as string]
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[status-im.common.controlled-input.utils :as controlled-input]
|
||||
[status-im.common.events-helper :as events-helper]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.common.account-switcher.view :as account-switcher]
|
||||
[status-im.contexts.wallet.common.utils :as utils]
|
||||
[status-im.contexts.wallet.sheets.buy-token.view :as buy-token]
|
||||
[status-im.contexts.wallet.sheets.select-asset.view :as select-asset]
|
||||
[status-im.contexts.wallet.sheets.slippage-settings.view :as slippage-settings]
|
||||
[status-im.contexts.wallet.swap.setup-swap.style :as style]
|
||||
[status-im.contexts.wallet.swap.utils :as swap-utils]
|
||||
[utils.debounce :as debounce]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.money :as money]
|
||||
[utils.number :as number]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.string :as utils.string]))
|
||||
|
||||
(def ^:private default-text-for-unfocused-input "0.00")
|
||||
|
||||
@@ -87,7 +85,7 @@
|
||||
[{:keys [input-state on-max-press on-input-focus on-token-press on-approve-press input-focused?]}]
|
||||
(let [account-color (rf/sub [:wallet/current-viewing-account-color])
|
||||
network (rf/sub [:wallet/swap-network])
|
||||
pay-token-symbol (:symbol (rf/sub [:wallet/swap-asset-to-pay]))
|
||||
asset-to-pay (rf/sub [:wallet/swap-asset-to-pay])
|
||||
currency (rf/sub [:profile/currency])
|
||||
loading-swap-proposal? (rf/sub [:wallet/swap-loading-swap-proposal?])
|
||||
swap-proposal (rf/sub [:wallet/swap-proposal-without-fees])
|
||||
@@ -98,19 +96,14 @@
|
||||
approval-transaction-id (rf/sub [:wallet/swap-approval-transaction-id])
|
||||
approved-amount (rf/sub [:wallet/swap-approved-amount])
|
||||
error-response (rf/sub [:wallet/swap-error-response])
|
||||
asset-to-pay (rf/sub [:wallet/token-by-symbol pay-token-symbol])
|
||||
overlay-shown? (boolean (:sheets (rf/sub [:bottom-sheet])))
|
||||
input-ref (rn/use-ref-atom nil)
|
||||
set-input-ref (rn/use-callback (fn [ref] (reset! input-ref ref)))
|
||||
pay-input-num-value (controlled-input/value-numeric input-state)
|
||||
pay-input-amount (controlled-input/input-value input-state)
|
||||
pay-token-symbol (:symbol asset-to-pay)
|
||||
pay-token-decimals (:decimals asset-to-pay)
|
||||
pay-token-balance-selected-chain (number/convert-to-whole-number
|
||||
(get-in asset-to-pay
|
||||
[:balances-per-chain
|
||||
(:chain-id network) :raw-balance]
|
||||
0)
|
||||
pay-token-decimals)
|
||||
pay-token-balance-selected-chain (get-in asset-to-pay
|
||||
[:balances-per-chain
|
||||
(:chain-id network) :balance]
|
||||
0)
|
||||
pay-token-fiat-value (str
|
||||
(utils/calculate-token-fiat-value
|
||||
{:currency currency
|
||||
@@ -118,15 +111,10 @@
|
||||
:token asset-to-pay}))
|
||||
available-crypto-limit (money/bignumber
|
||||
pay-token-balance-selected-chain)
|
||||
display-decimals (min pay-token-decimals
|
||||
constants/min-token-decimals-to-display)
|
||||
available-crypto-limit-display (number/remove-trailing-zeroes
|
||||
(.toFixed available-crypto-limit display-decimals))
|
||||
available-crypto-limit-display (if (and (= available-crypto-limit-display "0")
|
||||
(money/greater-than available-crypto-limit
|
||||
(money/bignumber 0)))
|
||||
(number/small-number-threshold display-decimals)
|
||||
available-crypto-limit-display)
|
||||
(.toFixed available-crypto-limit
|
||||
(min pay-token-decimals
|
||||
constants/min-token-decimals-to-display)))
|
||||
approval-amount-required-num (when approval-amount-required
|
||||
(str (number/hex->whole approval-amount-required
|
||||
pay-token-decimals)))
|
||||
@@ -134,7 +122,8 @@
|
||||
(money/greater-than
|
||||
(money/bignumber pay-input-amount)
|
||||
available-crypto-limit))
|
||||
(money/equal-to available-crypto-limit
|
||||
(money/equal-to (money/bignumber
|
||||
available-crypto-limit-display)
|
||||
(money/bignumber 0)))
|
||||
valid-pay-input? (and
|
||||
(not (string/blank?
|
||||
@@ -148,20 +137,12 @@
|
||||
:valid-input? valid-pay-input?
|
||||
:clean-approval-transaction? true}))
|
||||
[pay-input-amount])]
|
||||
(rn/use-unmount #(rf/dispatch [:wallet/on-swap-done]))
|
||||
(rn/use-effect
|
||||
(fn []
|
||||
(request-fetch-swap-proposal))
|
||||
[pay-input-amount])
|
||||
(rn/use-effect
|
||||
(fn []
|
||||
(when-not overlay-shown?
|
||||
(some-> @input-ref
|
||||
(oops/ocall "focus"))))
|
||||
[overlay-shown?])
|
||||
[quo/swap-input
|
||||
{:get-ref set-input-ref
|
||||
:type :pay
|
||||
{:type :pay
|
||||
:error? pay-input-error?
|
||||
:token pay-token-symbol
|
||||
:customization-color :blue
|
||||
@@ -175,7 +156,7 @@
|
||||
:else :disabled)
|
||||
:currency-symbol currency-symbol
|
||||
:on-token-press on-token-press
|
||||
:on-max-press #(on-max-press (str pay-token-balance-selected-chain))
|
||||
:on-max-press #(on-max-press (str available-crypto-limit))
|
||||
:on-input-focus on-input-focus
|
||||
:value pay-input-amount
|
||||
:fiat-value pay-token-fiat-value
|
||||
@@ -258,15 +239,17 @@
|
||||
(merge {:action? true
|
||||
:on-button-press #(rf/dispatch [:show-bottom-sheet
|
||||
{:content buy-token/view}])
|
||||
:button-text (i18n/label :t/add-assets)})
|
||||
:button-text (i18n/label :t/buy-assets)})
|
||||
(= error-response-code
|
||||
constants/router-error-code-not-enough-native-balance)
|
||||
(merge {:action? true
|
||||
:on-button-press #(rf/dispatch
|
||||
[:show-bottom-sheet
|
||||
{:content (fn []
|
||||
[buy-token/view])}])
|
||||
:button-text (i18n/label :t/add-eth)}))]
|
||||
[buy-token/view
|
||||
{:title (i18n/label
|
||||
:t/buy-ethereum)}])}])
|
||||
:button-text (i18n/label :t/buy-eth)}))]
|
||||
(when (or pay-input-error? error-response)
|
||||
[quo/alert-banner props])))
|
||||
|
||||
@@ -291,28 +274,23 @@
|
||||
|
||||
(defn- pay-token-bottom-sheet
|
||||
[]
|
||||
(let [asset-to-receive (rf/sub [:wallet/swap-asset-to-receive])
|
||||
network (rf/sub [:wallet/swap-network])]
|
||||
(let [asset-to-receive (rf/sub [:wallet/swap-asset-to-receive])]
|
||||
[select-asset/view
|
||||
{:title (i18n/label :t/select-asset-to-pay)
|
||||
:network network
|
||||
:on-select (fn [token]
|
||||
(rf/dispatch [:wallet.swap/select-asset-to-pay {:token token}]))
|
||||
:hide-token-fn (fn [type {:keys [balances-per-chain]}]
|
||||
(let [balance (get-in balances-per-chain [(:chain-id network) :balance] "0")]
|
||||
(and (= type constants/swap-tokens-my)
|
||||
(= balance "0"))))
|
||||
:hide-token-fn (fn [type {:keys [available-balance]}]
|
||||
(and (= type constants/swap-tokens-my)
|
||||
(= available-balance 0)))
|
||||
:disable-token-fn (fn [_ token]
|
||||
(= (:symbol token)
|
||||
(:symbol asset-to-receive)))}]))
|
||||
|
||||
(defn- receive-token-bottom-sheet
|
||||
[]
|
||||
(let [asset-to-pay (rf/sub [:wallet/swap-asset-to-pay])
|
||||
network (rf/sub [:wallet/swap-network])]
|
||||
(let [asset-to-pay (rf/sub [:wallet/swap-asset-to-pay])]
|
||||
[select-asset/view
|
||||
{:title (i18n/label :t/select-asset-to-receive)
|
||||
:network network
|
||||
:on-select (fn [token]
|
||||
(rf/dispatch [:wallet.swap/select-asset-to-receive {:token token}]))
|
||||
:disable-token-fn (fn [_ token]
|
||||
@@ -332,12 +310,10 @@
|
||||
network (rf/sub [:wallet/swap-network])
|
||||
pay-input-amount (controlled-input/input-value pay-input-state)
|
||||
pay-token-decimals (:decimals asset-to-pay)
|
||||
pay-token-balance-selected-chain (number/convert-to-whole-number
|
||||
(get-in asset-to-pay
|
||||
[:balances-per-chain
|
||||
(:chain-id network) :raw-balance]
|
||||
0)
|
||||
pay-token-decimals)
|
||||
pay-token-balance-selected-chain (get-in asset-to-pay
|
||||
[:balances-per-chain
|
||||
(:chain-id network) :balance]
|
||||
0)
|
||||
pay-input-error? (and (not (string/blank? pay-input-amount))
|
||||
(money/greater-than
|
||||
(money/bignumber pay-input-amount)
|
||||
@@ -439,17 +415,13 @@
|
||||
(when (and swap-amount refetch-interval)
|
||||
(js/clearTimeout @refetch-interval)
|
||||
(reset! refetch-interval nil))
|
||||
(cond (and swap-amount (not= swap-amount pay-input-amount))
|
||||
(set-pay-input-state
|
||||
(fn [input-state]
|
||||
(controlled-input/set-input-value
|
||||
input-state
|
||||
swap-amount)))
|
||||
(and pay-input-amount
|
||||
(not (number/valid-decimal-count? pay-input-amount (:decimals asset-to-pay))))
|
||||
(set-pay-input-state controlled-input/delete-all)
|
||||
:else
|
||||
(refetch-swap-proposal)))))
|
||||
(if (and swap-amount (not= swap-amount pay-input-amount))
|
||||
(set-pay-input-state
|
||||
(fn [input-state]
|
||||
(controlled-input/set-input-value
|
||||
input-state
|
||||
swap-amount)))
|
||||
(refetch-swap-proposal)))))
|
||||
[asset-to-pay])
|
||||
(rn/use-effect
|
||||
refetch-swap-proposal
|
||||
@@ -459,10 +431,7 @@
|
||||
{:on-press on-close
|
||||
:icon-name :i/arrow-left
|
||||
:margin-top (safe-area/get-top)
|
||||
:switcher-type :select-account
|
||||
:params {:show-account-balances? true
|
||||
:asset-symbol (:symbol asset-to-pay)
|
||||
:network network}}]
|
||||
:switcher-type :select-account}]
|
||||
[rn/view {:style style/inputs-container}
|
||||
[pay-token-input
|
||||
{:input-state pay-input-state
|
||||
@@ -484,7 +453,7 @@
|
||||
:on-token-press #(rf/dispatch [:show-bottom-sheet {:content receive-token-bottom-sheet}])
|
||||
:on-input-focus #(set-pay-input-focused? false)}]]
|
||||
[rn/view {:style style/footer-container}
|
||||
(when-not loading-swap-proposal? [alert-banner {:pay-input-error? pay-input-error?}])
|
||||
[alert-banner {:pay-input-error? pay-input-error?}]
|
||||
(when (or loading-swap-proposal? swap-proposal)
|
||||
[transaction-details])
|
||||
[action-button {:on-press on-review-swap-press}]]
|
||||
|
||||
@@ -80,8 +80,7 @@
|
||||
:values (send-utils/network-values-for-ui network-values)
|
||||
:token-props {:token token-symbol
|
||||
:label (str amount " " token-symbol)
|
||||
:address (when token-address
|
||||
(address-utils/get-shortened-compressed-key token-address))
|
||||
:address (address-utils/get-shortened-compressed-key token-address)
|
||||
:size 32}}]]))
|
||||
|
||||
(defn- pay-section
|
||||
@@ -99,8 +98,7 @@
|
||||
:label (i18n/label :t/pay)
|
||||
:token-symbol pay-token-symbol
|
||||
:amount pay-amount
|
||||
:token-address (when-not (address-utils/zero-address? pay-token-address)
|
||||
pay-token-address)
|
||||
:token-address pay-token-address
|
||||
:network network-name
|
||||
:theme theme}]))
|
||||
|
||||
@@ -119,8 +117,7 @@
|
||||
:label (i18n/label :t/receive)
|
||||
:token-symbol receive-token-symbol
|
||||
:amount receive-amount
|
||||
:token-address (when-not (address-utils/zero-address? receive-token-address)
|
||||
receive-token-address)
|
||||
:token-address receive-token-address
|
||||
:network network-name
|
||||
:theme theme}]))
|
||||
|
||||
|
||||
@@ -34,8 +34,9 @@
|
||||
|
||||
(defn tokens-by-symbol
|
||||
[props]
|
||||
(tokens-by-key
|
||||
(assoc props
|
||||
:key-fn
|
||||
(fn [{:keys [chainId address] :as token}]
|
||||
(str chainId "-" (if (get-in token [:communityData :id]) address (:symbol token)))))))
|
||||
(tokens-by-key (assoc props
|
||||
:key-fn
|
||||
(fn [{:keys [address] :as token}]
|
||||
(if (get-in token [:communityData :id])
|
||||
address
|
||||
(:symbol token))))))
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
:image nil})
|
||||
:by-symbol '({:address "0x0000000000000000000000000000000000000000"
|
||||
:decimals 18
|
||||
:key "1-ETH"
|
||||
:key "ETH"
|
||||
:community-id nil
|
||||
:symbol "ETH"
|
||||
:sources ["native"]
|
||||
@@ -86,7 +86,7 @@
|
||||
:image nil}
|
||||
{:address "0x0000000000000000000000000000000000000001"
|
||||
:decimals 18
|
||||
:key "1-SNT"
|
||||
:key "SNT"
|
||||
:community-id nil
|
||||
:symbol "SNT"
|
||||
:sources ["native"]
|
||||
@@ -174,7 +174,7 @@
|
||||
:image nil})
|
||||
:by-symbol '({:address "0x0000000000000000000000000000000000000000"
|
||||
:decimals 18
|
||||
:key "1-ETH"
|
||||
:key "ETH"
|
||||
:community-id nil
|
||||
:symbol "ETH"
|
||||
:sources ["native"]
|
||||
@@ -185,7 +185,7 @@
|
||||
:image nil}
|
||||
{:address "0x0000000000000000000000000000000000000001"
|
||||
:decimals 18
|
||||
:key "1-SNT"
|
||||
:key "SNT"
|
||||
:community-id nil
|
||||
:symbol "SNT"
|
||||
:sources ["native" "second"]
|
||||
@@ -196,7 +196,7 @@
|
||||
:image nil}
|
||||
{:address "0x0000000000000000000000000000000000000002"
|
||||
:decimals 18
|
||||
:key "1-ANOTHER1"
|
||||
:key "ANOTHER1"
|
||||
:community-id nil
|
||||
:symbol "ANOTHER1"
|
||||
:sources ["second"]
|
||||
@@ -253,7 +253,7 @@
|
||||
:image nil})
|
||||
:by-symbol '({:address "0x0000000000000000000000000000000000000000"
|
||||
:decimals 18
|
||||
:key "1-ETH"
|
||||
:key "ETH"
|
||||
:community-id nil
|
||||
:symbol "ETH"
|
||||
:sources ["native"]
|
||||
@@ -264,7 +264,7 @@
|
||||
:image nil}
|
||||
{:address "0x0000000000000000000000000000000000000000"
|
||||
:decimals 18
|
||||
:key "1-ANOTHER1"
|
||||
:key "ANOTHER1"
|
||||
:community-id nil
|
||||
:symbol "ANOTHER1"
|
||||
:sources ["native" "second"]
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
(ns status-im.contexts.wallet.wallet-connect.events.effects
|
||||
(:require
|
||||
[promesa.core :as promesa]
|
||||
[re-frame.core :as rf]
|
||||
[react-native.wallet-connect :as wallet-connect]
|
||||
[status-im.config :as config]
|
||||
[status-im.constants :as constants]
|
||||
@@ -9,7 +10,6 @@
|
||||
[status-im.contexts.wallet.wallet-connect.utils.transactions :as transactions]
|
||||
[status-im.contexts.wallet.wallet-connect.utils.typed-data :as typed-data]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.security.core :as security]))
|
||||
|
||||
(rf/reg-fx
|
||||
@@ -56,8 +56,8 @@
|
||||
:proposal-request proposal-request
|
||||
:address address
|
||||
:session-networks session-networks})
|
||||
(promesa/then (partial rf/call-continuation on-success))
|
||||
(promesa/catch (partial rf/call-continuation on-fail)))))
|
||||
(promesa/then on-success)
|
||||
(promesa/catch on-fail))))
|
||||
|
||||
(rf/reg-fx
|
||||
:effects.wallet-connect/sign-message
|
||||
@@ -72,8 +72,8 @@
|
||||
(signing/eth-sign password address data)
|
||||
|
||||
(signing/personal-sign password address data))
|
||||
(promesa/then (partial rf/call-continuation on-success))
|
||||
(promesa/catch (partial rf/call-continuation on-error))))))
|
||||
(promesa/then on-success)
|
||||
(promesa/catch on-error)))))
|
||||
|
||||
(rf/reg-fx
|
||||
:effects.wallet-connect/prepare-transaction
|
||||
@@ -92,8 +92,8 @@
|
||||
tx-hash
|
||||
tx-args
|
||||
chain-id)
|
||||
(promesa/then (partial rf/call-continuation on-success))
|
||||
(promesa/catch (partial rf/call-continuation on-error)))))
|
||||
(promesa/then on-success)
|
||||
(promesa/catch on-error))))
|
||||
|
||||
(rf/reg-fx
|
||||
:effects.wallet-connect/send-transaction
|
||||
@@ -103,8 +103,8 @@
|
||||
tx-hash
|
||||
tx-args
|
||||
chain-id)
|
||||
(promesa/then (partial rf/call-continuation on-success))
|
||||
(promesa/catch (partial rf/call-continuation on-error)))))
|
||||
(promesa/then on-success)
|
||||
(promesa/catch on-error))))
|
||||
|
||||
(rf/reg-fx
|
||||
:effects.wallet-connect/sign-typed-data
|
||||
@@ -114,8 +114,8 @@
|
||||
data
|
||||
chain-id
|
||||
version)
|
||||
(promesa/then (partial rf/call-continuation on-success))
|
||||
(promesa/catch (partial rf/call-continuation on-error)))))
|
||||
(promesa/then on-success)
|
||||
(promesa/catch on-error))))
|
||||
|
||||
(rf/reg-fx
|
||||
:effects.wallet-connect/respond-session-request
|
||||
|
||||
@@ -135,21 +135,17 @@
|
||||
:proposal-request current-proposal
|
||||
:session-networks session-networks
|
||||
:address current-address
|
||||
:on-success [:wallet-connect/approve-session-success]
|
||||
:on-fail [:wallet-connect/approve-session-error]}])
|
||||
:on-success #(rf/dispatch [:wallet-connect/approve-session-success %])
|
||||
:on-fail #(rf/dispatch [:wallet-connect/approve-session-error %])}])
|
||||
[:dispatch [:dismiss-modal :screen/wallet.wallet-connect-session-proposal]]]}
|
||||
{:fx [[:dispatch [:wallet-connect/no-internet-toast]]]}))))
|
||||
|
||||
(rf/reg-event-fx :wallet-connect/approve-session-success
|
||||
(fn [{:keys [db]} [session]]
|
||||
(let [total-connected-dapps (data-store/get-total-connected-dapps db)]
|
||||
{:fx [[:dispatch [:wallet-connect/on-new-session session]]
|
||||
[:dispatch [:wallet-connect/reset-current-session-proposal]]
|
||||
[:dispatch [:wallet-connect/redirect-to-dapp (data-store/get-dapp-redirect-url session)]]
|
||||
[:dispatch
|
||||
[:centralized-metrics/track :metric/dapp-session-proposal
|
||||
{:action :approved
|
||||
:total_connected_dapps total-connected-dapps}]]]})))
|
||||
(fn [_ [session]]
|
||||
(log/info "Wallet Connect session approved")
|
||||
{:fx [[:dispatch [:wallet-connect/on-new-session session]]
|
||||
[:dispatch [:wallet-connect/reset-current-session-proposal]]
|
||||
[:dispatch [:wallet-connect/redirect-to-dapp (data-store/get-dapp-redirect-url session)]]]}))
|
||||
|
||||
(rf/reg-event-fx :wallet-connect/approve-session-error
|
||||
(fn [_ [error]]
|
||||
@@ -162,18 +158,11 @@
|
||||
:wallet-connect/reject-session-proposal
|
||||
(fn [{:keys [db]} [proposal]]
|
||||
(let [web3-wallet (get db :wallet-connect/web3-wallet)
|
||||
{:keys [request response-sent?]} (:wallet-connect/current-proposal db)
|
||||
networks (networks/get-proposal-networks (or proposal request))
|
||||
rejected? (nil? proposal)]
|
||||
{:fx (concat
|
||||
(when-not response-sent?
|
||||
[[:effects.wallet-connect/reject-session-proposal
|
||||
{:web3-wallet web3-wallet
|
||||
:proposal (or proposal request)
|
||||
:on-success #(log/info "Wallet Connect session proposal rejected")
|
||||
:on-error #(log/error "Wallet Connect unable to reject session proposal")}]
|
||||
[:dispatch
|
||||
[:centralized-metrics/track :metric/dapp-session-proposal
|
||||
{:action (if rejected? :rejected :not_supported)
|
||||
:networks networks}]]])
|
||||
[[:dispatch [:wallet-connect/reset-current-session-proposal]]])})))
|
||||
{:keys [request response-sent?]} (:wallet-connect/current-proposal db)]
|
||||
{:fx [(when-not response-sent?
|
||||
[:effects.wallet-connect/reject-session-proposal
|
||||
{:web3-wallet web3-wallet
|
||||
:proposal (or proposal request)
|
||||
:on-success #(log/info "Wallet Connect session proposal rejected")
|
||||
:on-error #(log/error "Wallet Connect unable to reject session proposal")}])
|
||||
[:dispatch [:wallet-connect/reset-current-session-proposal]]]})))
|
||||
|
||||
@@ -51,8 +51,8 @@
|
||||
:address address
|
||||
:data raw-data
|
||||
:rpc-method rpc-method
|
||||
:on-error [:wallet-connect/on-sign-error]
|
||||
:on-success [:wallet-connect/finish-session-request]}]]})))
|
||||
:on-error #(rf/dispatch [:wallet-connect/on-sign-error %])
|
||||
:on-success #(rf/dispatch [:wallet-connect/finish-session-request %])}]]})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/respond-sign-typed-data
|
||||
@@ -65,8 +65,8 @@
|
||||
:data raw-data
|
||||
:chain-id chain-id
|
||||
:version typed-data-version
|
||||
:on-error [:wallet-connect/on-sign-error]
|
||||
:on-success [:wallet-connect/finish-session-request]}]]})))
|
||||
:on-error #(rf/dispatch [:wallet-connect/on-sign-error %])
|
||||
:on-success #(rf/dispatch [:wallet-connect/finish-session-request %])}]]})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/respond-send-transaction-data
|
||||
@@ -79,8 +79,8 @@
|
||||
:chain-id chain-id
|
||||
:tx-hash tx-hash
|
||||
:tx-args tx-args
|
||||
:on-error [:wallet-connect/on-sign-error]
|
||||
:on-success [:wallet-connect/finish-session-request]}]]})))
|
||||
:on-error #(rf/dispatch [:wallet-connect/on-sign-error %])
|
||||
:on-success #(rf/dispatch [:wallet-connect/finish-session-request %])}]]})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/respond-sign-transaction-data
|
||||
@@ -93,8 +93,8 @@
|
||||
:chain-id chain-id
|
||||
:tx-hash tx-hash
|
||||
:tx-params tx-args
|
||||
:on-error [:wallet-connect/on-sign-error]
|
||||
:on-success [:wallet-connect/finish-session-request]}]]})))
|
||||
:on-error #(rf/dispatch [:wallet-connect/on-sign-error %])
|
||||
:on-success #(rf/dispatch [:wallet-connect/finish-session-request %])}]]})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/on-sign-error
|
||||
@@ -161,15 +161,9 @@
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/finish-session-request
|
||||
(fn [{:keys [db]} [result]]
|
||||
(let [event (get-in db [:wallet-connect/current-request :event])
|
||||
method (data-store/get-request-method event)]
|
||||
{:fx [[:dispatch
|
||||
[:centralized-metrics/track :metric/dapp-session-response
|
||||
{:method method
|
||||
:approved true}]]
|
||||
[:dispatch [:wallet-connect/send-response {:result result}]]
|
||||
[:dispatch [:wallet-connect/dismiss-request-modal]]]})))
|
||||
(fn [_ [result]]
|
||||
{:fx [[:dispatch [:wallet-connect/send-response {:result result}]]
|
||||
[:dispatch [:wallet-connect/dismiss-request-modal]]]}))
|
||||
|
||||
;; NOTE: Currently we only reject a session if the user dismissed a modal
|
||||
;; without accepting the session first.
|
||||
@@ -182,17 +176,9 @@
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/on-request-modal-dismissed
|
||||
(fn [{:keys [db]}]
|
||||
(let [{:keys [response-sent? event]} (get db :wallet-connect/current-request)
|
||||
method (data-store/get-request-method event)]
|
||||
{:fx (concat
|
||||
(when-not response-sent?
|
||||
[[:dispatch
|
||||
[:centralized-metrics/track :metric/dapp-session-response
|
||||
{:method method
|
||||
:approved false}]]
|
||||
[:dispatch
|
||||
[:wallet-connect/send-response
|
||||
{:request event
|
||||
:error (wallet-connect/get-sdk-error
|
||||
constants/wallet-connect-user-rejected-error-key)}]]])
|
||||
[[:dispatch [:wallet-connect/reset-current-request]]])})))
|
||||
{:fx [(when-not (get-in db [:wallet-connect/current-request :response-sent?])
|
||||
[:dispatch
|
||||
[:wallet-connect/send-response
|
||||
{:error (wallet-connect/get-sdk-error
|
||||
constants/wallet-connect-user-rejected-error-key)}]])
|
||||
[:dispatch [:wallet-connect/reset-current-request]]]}))
|
||||
|
||||
@@ -14,10 +14,7 @@
|
||||
[{:method "wallet_disconnectWalletConnectSession"
|
||||
:params [topic]
|
||||
:on-success [:wallet-connect/delete-session topic]
|
||||
:on-error #(log/info "Wallet Connect session persistence failed" %)}]]
|
||||
[:dispatch
|
||||
[:centralized-metrics/track
|
||||
:metric/dapp-session-disconnected]]]})))
|
||||
:on-error #(log/info "Wallet Connect session persistence failed" %)}]]]})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/disconnect-dapp
|
||||
@@ -29,14 +26,10 @@
|
||||
{:fx [[:effects.wallet-connect/disconnect
|
||||
{:web3-wallet web3-wallet
|
||||
:topic topic
|
||||
:on-fail (fn []
|
||||
(when on-fail
|
||||
(on-fail)))
|
||||
:on-fail on-fail
|
||||
:on-success (fn []
|
||||
(log/info "Successfully disconnected dApp session" topic)
|
||||
(rf/dispatch [:wallet-connect/delete-session topic])
|
||||
(rf/dispatch [:centralized-metrics/track
|
||||
:metric/dapp-session-disconnected])
|
||||
(when on-success
|
||||
(on-success)))}]]}
|
||||
{:fx [[:dispatch [:wallet-connect/no-internet-toast]]]}))))
|
||||
|
||||
@@ -31,12 +31,9 @@
|
||||
|
||||
:not-enough-assets
|
||||
:t/not-enough-assets-for-transaction)))
|
||||
:button-text (i18n/label :t/add-eth)
|
||||
:on-button-press (rn/use-callback (fn []
|
||||
(rf/dispatch [:centralized-metrics/track
|
||||
:metric/dapp-buy-eth])
|
||||
(rf/dispatch [:show-bottom-sheet
|
||||
{:content buy-token/view}])))}])
|
||||
:button-text (i18n/label :t/buy-eth)
|
||||
:on-button-press #(rf/dispatch [:show-bottom-sheet
|
||||
{:content buy-token/view}])}])
|
||||
[rn/view {:style style/content-container}
|
||||
(into [rn/view
|
||||
{:style style/data-items-container}]
|
||||
|
||||
@@ -73,10 +73,3 @@
|
||||
(-> db
|
||||
get-db-current-request-event
|
||||
get-request-params))
|
||||
|
||||
(defn get-total-connected-dapps
|
||||
[db]
|
||||
(-> db
|
||||
:wallet-connect/sessions
|
||||
count
|
||||
inc))
|
||||
|
||||
@@ -25,17 +25,3 @@
|
||||
(testing "returns nil if no redirect URL is found"
|
||||
(let [session {:peer {:metadata {}}}]
|
||||
(is (nil? (sut/get-dapp-redirect-url session))))))
|
||||
|
||||
(deftest get-total-connected-dapps-test
|
||||
(testing "returns the total number of connected dApps plus 1"
|
||||
(let [db {:wallet-connect/sessions [{:url "https://dapp1.com"}
|
||||
{:url "https://dapp2.com"}]}]
|
||||
(is (= 3 (sut/get-total-connected-dapps db)))))
|
||||
|
||||
(testing "returns 1 when there are no connected dApps"
|
||||
(let [db {:wallet-connect/sessions []}]
|
||||
(is (= 1 (sut/get-total-connected-dapps db)))))
|
||||
|
||||
(testing "handles nil sessions correctly"
|
||||
(let [db {:wallet-connect/sessions nil}]
|
||||
(is (= 1 (sut/get-total-connected-dapps db))))))
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
status-im.contexts.syncing.events
|
||||
status-im.contexts.wallet.add-account.add-address-to-watch.events
|
||||
status-im.contexts.wallet.add-account.create-account.events
|
||||
status-im.contexts.wallet.buy-crypto.events
|
||||
status-im.contexts.wallet.collectible.events
|
||||
status-im.contexts.wallet.common.wizard.events
|
||||
status-im.contexts.wallet.effects
|
||||
|
||||
@@ -32,8 +32,7 @@
|
||||
::wallet.long-press-watch-only-asset (enabled-in-env? :FLAG_LONG_PRESS_WATCH_ONLY_ASSET_ENABLED)
|
||||
::wallet.saved-addresses (enabled-in-env? :WALLET_SAVED_ADDRESSES)
|
||||
::wallet.wallet-connect (enabled-in-env? :FLAG_WALLET_CONNECT_ENABLED)
|
||||
::wallet.custom-network-amounts (enabled-in-env? :FLAG_WALLET_CUSTOM_NETWORK_AMOUNTS_ENABLED)
|
||||
::keycard.migrate-profile false})
|
||||
::wallet.custom-network-amounts (enabled-in-env? :FLAG_WALLET_CUSTOM_NETWORK_AMOUNTS_ENABLED)})
|
||||
|
||||
(defonce ^:private feature-flags-config
|
||||
(reagent/atom initial-flags))
|
||||
|
||||
@@ -69,12 +69,6 @@
|
||||
transitions/new-to-status-modal-animations
|
||||
transitions/push-animations-for-transparent-background)}))
|
||||
|
||||
(def keycard-modal-screen-options
|
||||
(assoc transparent-modal-screen-options
|
||||
:layout nil
|
||||
:theme :dark
|
||||
:insets {:top? true :bottom? true}))
|
||||
|
||||
(def sheet-options
|
||||
{:layout {:componentBackgroundColor :transparent
|
||||
:orientation ["portrait"]
|
||||
|
||||
@@ -26,11 +26,6 @@
|
||||
[status-im.contexts.communities.actions.share-community.view :as share-community]
|
||||
[status-im.contexts.communities.discover.view :as communities.discover]
|
||||
[status-im.contexts.communities.overview.view :as communities.overview]
|
||||
[status-im.contexts.keycard.authorise.view :as keycard.authorise]
|
||||
[status-im.contexts.keycard.check.view :as keycard.check]
|
||||
[status-im.contexts.keycard.empty.view :as keycard.empty]
|
||||
[status-im.contexts.keycard.error.view :as keycard.error]
|
||||
[status-im.contexts.keycard.not-keycard.view :as keycard.not-keycard]
|
||||
[status-im.contexts.onboarding.create-or-sync-profile.view :as create-or-sync-profile]
|
||||
[status-im.contexts.onboarding.create-password.view :as create-password]
|
||||
[status-im.contexts.onboarding.create-profile.view :as create-profile]
|
||||
@@ -47,7 +42,6 @@
|
||||
[status-im.contexts.preview.quo.component-preview.view :as component-preview]
|
||||
[status-im.contexts.preview.quo.main :as quo.preview]
|
||||
[status-im.contexts.preview.status-im.main :as status-im-preview]
|
||||
[status-im.contexts.profile.backup-recovery-phrase.view :as backup-recovery-phrase]
|
||||
[status-im.contexts.profile.contact.share.view :as share-contact]
|
||||
[status-im.contexts.profile.contact.view :as contact-profile]
|
||||
[status-im.contexts.profile.edit.accent-colour.view :as edit-accent-colour]
|
||||
@@ -64,7 +58,6 @@
|
||||
[status-im.contexts.profile.settings.screens.password.view :as settings-password]
|
||||
[status-im.contexts.profile.settings.screens.syncing.view :as settings.syncing]
|
||||
[status-im.contexts.profile.settings.view :as settings]
|
||||
[status-im.contexts.settings.keycard.view :as settings.keycard]
|
||||
[status-im.contexts.settings.language-and-currency.currency.view :as settings.currency-selection]
|
||||
[status-im.contexts.settings.language-and-currency.view :as settings.language-and-currency]
|
||||
[status-im.contexts.settings.privacy-and-security.share-usage.view :as settings.share-usage]
|
||||
@@ -108,6 +101,8 @@
|
||||
wallet-import-private-key]
|
||||
[status-im.contexts.wallet.add-account.create-account.key-pair-name.view :as
|
||||
wallet-key-pair-name]
|
||||
[status-im.contexts.wallet.add-account.create-account.new-keypair.backup-recovery-phrase.view :as
|
||||
wallet-backup-recovery-phrase]
|
||||
[status-im.contexts.wallet.add-account.create-account.new-keypair.confirm-backup.view :as
|
||||
wallet-confirm-backup]
|
||||
[status-im.contexts.wallet.add-account.create-account.select-keypair.view :as wallet-select-keypair]
|
||||
@@ -475,9 +470,9 @@
|
||||
:options {:insets {:top? true}}
|
||||
:component wallet-create-account/view}
|
||||
|
||||
{:name :screen/backup-recovery-phrase
|
||||
{:name :screen/wallet.backup-recovery-phrase
|
||||
:options {:insets {:top? true :bottom? true}}
|
||||
:component backup-recovery-phrase/view}
|
||||
:component wallet-backup-recovery-phrase/view}
|
||||
|
||||
{:name :screen/wallet.confirm-backup
|
||||
:options {:insets {:top? true :bottom? true}}
|
||||
@@ -487,7 +482,7 @@
|
||||
:options {:insets {:top? true}}
|
||||
:component wallet-key-pair-name/view}
|
||||
|
||||
{:name :screen/use-recovery-phrase
|
||||
{:name :screen/wallet.enter-seed-phrase
|
||||
:component enter-seed-phrase/view}
|
||||
|
||||
{:name :screen/wallet.share-address
|
||||
@@ -589,10 +584,6 @@
|
||||
:options options/transparent-modal-screen-options
|
||||
:component wallet-options/view}
|
||||
|
||||
{:name :screen/settings.keycard
|
||||
:options options/keycard-modal-screen-options
|
||||
:component settings.keycard/view}
|
||||
|
||||
{:name :screen/settings.rename-keypair
|
||||
:options options/transparent-screen-options
|
||||
:component keypair-rename/view}
|
||||
@@ -680,28 +671,7 @@
|
||||
:popGesture false
|
||||
:hardwareBackButton {:dismissModalOnPress false
|
||||
:popStackOnPress false})
|
||||
:component change-password-loading/view}
|
||||
|
||||
;; Keycard
|
||||
{:name :screen/keycard.check
|
||||
:options options/keycard-modal-screen-options
|
||||
:component keycard.check/view}
|
||||
|
||||
{:name :screen/keycard.empty
|
||||
:options options/keycard-modal-screen-options
|
||||
:component keycard.empty/view}
|
||||
|
||||
{:name :screen/keycard.error
|
||||
:options options/keycard-modal-screen-options
|
||||
:component keycard.error/view}
|
||||
|
||||
{:name :screen/keycard.not-keycard
|
||||
:options options/keycard-modal-screen-options
|
||||
:component keycard.not-keycard/view}
|
||||
|
||||
{:name :screen/keycard.authorise
|
||||
:options options/keycard-modal-screen-options
|
||||
:component keycard.authorise/view}]
|
||||
:component change-password-loading/view}]
|
||||
|
||||
[{:name :shell
|
||||
:options {:theme :dark}}]
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
[status-im.common.bottom-sheet-screen.view :as bottom-sheet-screen]
|
||||
[status-im.common.bottom-sheet.view :as bottom-sheet]
|
||||
[status-im.common.toasts.view :as toasts]
|
||||
[status-im.contexts.keycard.nfc-sheet.view :as keycard.sheet]
|
||||
[status-im.contexts.keycard.sheet.view :as keycard.sheet]
|
||||
[status-im.navigation.screens :as screens]
|
||||
[status-im.setup.hot-reload :as reloader]
|
||||
[utils.re-frame :as rf]))
|
||||
@@ -47,7 +47,7 @@
|
||||
(merge
|
||||
{:flex 1
|
||||
:margin-top alert-banners-top-margin
|
||||
:background-color (or background-color (colors/theme-colors colors/white colors/neutral-95 theme))}
|
||||
:background-color (or background-color (colors/theme-colors colors/white colors/neutral-100 theme))}
|
||||
(when bottom?
|
||||
{:padding-bottom (safe-area/get-bottom)})
|
||||
(when top?
|
||||
|
||||
@@ -36,8 +36,3 @@
|
||||
(fn [keycard]
|
||||
(:connection-sheet-opts keycard)))
|
||||
|
||||
(rf/reg-sub
|
||||
:keycard/application-info-error
|
||||
:<- [:keycard]
|
||||
(fn [keycard]
|
||||
(:application-info-error keycard)))
|
||||
|
||||
@@ -326,12 +326,6 @@
|
||||
(fn [profile]
|
||||
(profile.utils/photo profile)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:profile/name
|
||||
:<- [:profile/profile]
|
||||
(fn [profile]
|
||||
(profile.utils/displayed-name profile)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:profile/login-profile
|
||||
:<- [:profile/login]
|
||||
@@ -345,12 +339,6 @@
|
||||
(fn [{:keys [processing]}]
|
||||
processing))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:profile/recovery-phrase-backed-up?
|
||||
:<- [:profile/profile]
|
||||
(fn [profile]
|
||||
(not (boolean (seq (:mnemonic profile))))))
|
||||
|
||||
;; LINK PREVIEW
|
||||
;; ========================================================================================================
|
||||
|
||||
|
||||
@@ -5,28 +5,3 @@
|
||||
:wallet/crypto-on-ramps
|
||||
:<- [:wallet]
|
||||
:-> :crypto-on-ramps)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/wallet-buy-crypto
|
||||
:<- [:wallet/ui]
|
||||
:-> :buy-crypto)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/wallet-buy-crypto-account
|
||||
:<- [:wallet/wallet-buy-crypto]
|
||||
:-> :account)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/wallet-buy-crypto-provider
|
||||
:<- [:wallet/wallet-buy-crypto]
|
||||
:-> :provider)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/wallet-buy-crypto-recurrent?
|
||||
:<- [:wallet/wallet-buy-crypto]
|
||||
:-> :recurrent?)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/wallet-buy-crypto-network
|
||||
:<- [:wallet/wallet-buy-crypto]
|
||||
:-> :network)
|
||||
|
||||
@@ -126,23 +126,18 @@
|
||||
:<- [:wallet/wallet-send]
|
||||
:-> :route)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/wallet-send-enough-assets?
|
||||
:<- [:wallet/wallet-send]
|
||||
:-> :enough-assets?)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/wallet-send-token
|
||||
:<- [:wallet/wallet-send]
|
||||
:<- [:wallet/network-details]
|
||||
:<- [:wallet/wallet-send-disabled-from-chain-ids]
|
||||
(fn [[wallet-send networks disabled-from-chain-ids]]
|
||||
(let [token (:token wallet-send)
|
||||
disabled-from-chain-ids? (set disabled-from-chain-ids)
|
||||
enabled-from-chain-ids (->> networks
|
||||
(map :chain-id)
|
||||
(remove disabled-from-chain-ids?)
|
||||
set)]
|
||||
(let [token (:token wallet-send)
|
||||
enabled-from-chain-ids (->> networks
|
||||
(filter #(not (contains? (set disabled-from-chain-ids)
|
||||
(:chain-id %))))
|
||||
(map :chain-id)
|
||||
set)]
|
||||
(some-> token
|
||||
(assoc :networks (network-utils/network-list token networks)
|
||||
:available-balance (utils/calculate-total-token-balance token)
|
||||
@@ -404,22 +399,6 @@
|
||||
(assoc :balance balance
|
||||
:formatted-balance formatted-balance)))))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/current-viewing-account-or-default
|
||||
:<- [:wallet/accounts]
|
||||
:<- [:wallet/current-viewing-account-address]
|
||||
:<- [:wallet/balances-in-selected-networks]
|
||||
:<- [:profile/currency-symbol]
|
||||
(fn [[accounts current-viewing-account-address balances currency-symbol]]
|
||||
(let [account (or (utils/get-account-by-address accounts current-viewing-account-address)
|
||||
(utils/get-default-account accounts))
|
||||
address (:address account)
|
||||
balance (get balances address)
|
||||
formatted-balance (utils/prettify-balance currency-symbol balance)]
|
||||
(assoc account
|
||||
:balance balance
|
||||
:formatted-balance formatted-balance))))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/current-viewing-account-color
|
||||
:<- [:wallet/current-viewing-account]
|
||||
@@ -441,7 +420,7 @@
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/current-viewing-account-tokens-filtered
|
||||
:<- [:wallet/current-viewing-account-or-default]
|
||||
:<- [:wallet/current-viewing-account]
|
||||
:<- [:wallet/network-details]
|
||||
:<- [:wallet/wallet-send]
|
||||
(fn [[account networks send-data] [_ {:keys [query chain-ids hide-token-fn]}]]
|
||||
@@ -475,19 +454,14 @@
|
||||
(rf/reg-sub
|
||||
:wallet/tokens-filtered
|
||||
:<- [:wallet/tokens]
|
||||
:<- [:profile/currency]
|
||||
(fn [[{:keys [by-symbol market-values-per-token details-per-token prices-per-token]} currency]
|
||||
(fn [{:keys [by-symbol market-values-per-token details-per-token]}
|
||||
[_ {:keys [query chain-ids hide-token-fn]}]]
|
||||
(let [tokens (->> by-symbol
|
||||
(map (fn [token]
|
||||
(let [token-symbol (keyword (:symbol token))
|
||||
price (get-in prices-per-token [token-symbol currency])]
|
||||
(-> token
|
||||
(assoc :market-values
|
||||
(get market-values-per-token token-symbol))
|
||||
(assoc :details (get details-per-token token-symbol))
|
||||
(assoc-in [:market-values-per-currency currency :price]
|
||||
price)))))
|
||||
(-> token
|
||||
(assoc :market-values
|
||||
(get market-values-per-token (:symbol token)))
|
||||
(assoc :details (get details-per-token (:symbol token))))))
|
||||
(filter (fn [{:keys [chain-id]}]
|
||||
(some #{chain-id} chain-ids)))
|
||||
(remove #(when hide-token-fn
|
||||
@@ -502,7 +476,7 @@
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/token-by-symbol
|
||||
:<- [:wallet/current-viewing-account-or-default]
|
||||
:<- [:wallet/current-viewing-account]
|
||||
:<- [:wallet/network-details]
|
||||
(fn [[{:keys [tokens]} networks] [_ token-symbol chain-ids]]
|
||||
(->> (utils/tokens-with-balance tokens networks chain-ids)
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
(def regx-eip-3770-address #"^(?:(?:eth:|arb1:|oeth:)(?=:|))*0x[0-9a-fA-F]{40}$")
|
||||
(def regx-metamask-address #"^ethereum:(0x[0-9a-fA-F]{40})(?:@(0x1|0xa|0xa4b1))?$")
|
||||
(def regx-address-contains #"(?i)0x[a-fA-F0-9]{40}")
|
||||
(def zero-address "0x0000000000000000000000000000000000000000")
|
||||
|
||||
(defn normalized-hex
|
||||
[hex]
|
||||
@@ -138,6 +137,3 @@
|
||||
(metamask-address? address)
|
||||
(metamask-address->eth-address address)))
|
||||
|
||||
(defn zero-address?
|
||||
[address]
|
||||
(= address zero-address))
|
||||
|
||||
+8
-10
@@ -47,10 +47,11 @@
|
||||
(if (bignumber? n) n (bignumber n)))
|
||||
|
||||
(defn ->bignumbers
|
||||
[& numbers]
|
||||
(let [transformed-numbers (map ->bignumber numbers)]
|
||||
(when (every? bignumber? transformed-numbers)
|
||||
transformed-numbers)))
|
||||
[n1 n2]
|
||||
(when-let [bn1 (->bignumber n1)]
|
||||
(when-let [bn2 (->bignumber n2)]
|
||||
(when (and (bignumber? bn1) (bignumber? bn2))
|
||||
[bn1 bn2]))))
|
||||
|
||||
(defn greater-than-or-equals
|
||||
[^js n1 ^js n2]
|
||||
@@ -238,12 +239,9 @@
|
||||
|
||||
(defn crypto->fiat
|
||||
[crypto fiat-price]
|
||||
(let [^js crypto-bn (bignumber crypto)
|
||||
^js fiat-price-bn (bignumber fiat-price)]
|
||||
(when (and crypto-bn fiat-price-bn)
|
||||
(-> crypto-bn
|
||||
(.times fiat-price-bn)
|
||||
(with-precision 2)))))
|
||||
(when-let [^js bn (bignumber crypto)]
|
||||
(-> (.times bn ^js (bignumber fiat-price))
|
||||
(with-precision 2))))
|
||||
|
||||
(defn sufficient-funds?
|
||||
[^js amount ^js balance]
|
||||
|
||||
+13
-32
@@ -2,8 +2,7 @@
|
||||
(:require [clojure.string :as string]
|
||||
[native-module.core :as native-module]
|
||||
[utils.hex :as utils.hex]
|
||||
[utils.money :as utils.money]
|
||||
[utils.money :as money]))
|
||||
[utils.money :as utils.money]))
|
||||
|
||||
(defn naive-round
|
||||
"Quickly and naively round number `n` up to `decimal-places`.
|
||||
@@ -19,6 +18,17 @@
|
||||
(/ (Math/round (* n scale))
|
||||
scale)))
|
||||
|
||||
(defn convert-to-whole-number
|
||||
"Converts a fractional `amount` to its corresponding whole number representation
|
||||
by dividing it by 10 raised to the power of `decimals`. This is often used in financial
|
||||
calculations where amounts are stored in their smallest units (e.g., cents) and need
|
||||
to be converted to their whole number equivalents (e.g., dollars).
|
||||
|
||||
Example usage:
|
||||
(convert-to-whole-number 12345 2) ; => 123.45"
|
||||
[amount decimals]
|
||||
(/ amount (Math/pow 10 decimals)))
|
||||
|
||||
(defn parse-int
|
||||
"Parses `n` as an integer. Defaults to zero or `default` instead of NaN."
|
||||
([n]
|
||||
@@ -55,44 +65,15 @@
|
||||
"")
|
||||
""))))
|
||||
|
||||
(defn convert-to-whole-number
|
||||
"Converts a fractional `amount` to its corresponding whole number representation
|
||||
by dividing it by 10 raised to the power of `decimals`. This is often used in financial
|
||||
calculations where amounts are stored in their smallest units (e.g., cents) and need
|
||||
to be converted to their whole number equivalents (e.g., dollars).
|
||||
|
||||
Example usage:
|
||||
(convert-to-whole-number 12345 2) ; => 123.45"
|
||||
[amount decimals]
|
||||
(-> amount
|
||||
(/ (Math/pow 10 decimals))
|
||||
(.toFixed decimals)
|
||||
remove-trailing-zeroes))
|
||||
|
||||
(defn hex->whole
|
||||
[num decimals]
|
||||
(-> num
|
||||
utils.hex/normalize-hex
|
||||
native-module/hex-to-number
|
||||
(convert-to-whole-number decimals)
|
||||
money/bignumber))
|
||||
(convert-to-whole-number decimals)))
|
||||
|
||||
(defn to-fixed
|
||||
[num decimals]
|
||||
(-> num
|
||||
(utils.money/to-fixed decimals)
|
||||
remove-trailing-zeroes))
|
||||
|
||||
(defn small-number-threshold
|
||||
"Receives a decimal count and returns a string like '<0.001' if the decimal count is 3,
|
||||
'<0.000001' if the decimal count is 6, etc."
|
||||
[decimal-count]
|
||||
(if (> decimal-count 0)
|
||||
(str "<0." (apply str (repeat (dec decimal-count) "0")) "1")
|
||||
"0"))
|
||||
|
||||
(defn valid-decimal-count?
|
||||
"Returns false if the number has more decimals than the decimal count, otherwise true."
|
||||
[num decimal-count]
|
||||
(let [decimal-part (second (string/split (str num) #"\."))]
|
||||
(or (nil? decimal-part) (<= (count decimal-part) decimal-count))))
|
||||
|
||||
+11
-44
@@ -5,23 +5,23 @@
|
||||
|
||||
(deftest convert-to-whole-number-test
|
||||
(testing "correctly converts fractional amounts to whole numbers"
|
||||
(is (= "123.45" (utils.number/convert-to-whole-number 12345 2)))
|
||||
(is (= "1.2345" (utils.number/convert-to-whole-number 12345 4)))
|
||||
(is (= "12345" (utils.number/convert-to-whole-number 1234500 2)))
|
||||
(is (= "0.123" (utils.number/convert-to-whole-number 123 3)))
|
||||
(is (= "1000" (utils.number/convert-to-whole-number 1000000 3))))
|
||||
(is (= 123.45 (utils.number/convert-to-whole-number 12345 2)))
|
||||
(is (= 1.2345 (utils.number/convert-to-whole-number 12345 4)))
|
||||
(is (= 12345.0 (utils.number/convert-to-whole-number 1234500 2)))
|
||||
(is (= 0.123 (utils.number/convert-to-whole-number 123 3)))
|
||||
(is (= 1000.0 (utils.number/convert-to-whole-number 1000000 3))))
|
||||
|
||||
(testing "handles zero decimals"
|
||||
(is (= "12345" (utils.number/convert-to-whole-number 12345 0))))
|
||||
(is (= 12345 (utils.number/convert-to-whole-number 12345 0))))
|
||||
|
||||
(testing "handles negative amounts"
|
||||
(is (= "-123.45" (utils.number/convert-to-whole-number -12345 2)))
|
||||
(is (= "-1.2345" (utils.number/convert-to-whole-number -12345 4)))
|
||||
(is (= "-0.123" (utils.number/convert-to-whole-number -123 3))))
|
||||
(is (= -123.45 (utils.number/convert-to-whole-number -12345 2)))
|
||||
(is (= -1.2345 (utils.number/convert-to-whole-number -12345 4)))
|
||||
(is (= -0.123 (utils.number/convert-to-whole-number -123 3))))
|
||||
|
||||
(testing "handles zero amount"
|
||||
(is (= "0" (utils.number/convert-to-whole-number 0 2)))
|
||||
(is (= "0" (utils.number/convert-to-whole-number 0 0)))))
|
||||
(is (= 0 (utils.number/convert-to-whole-number 0 2)))
|
||||
(is (= 0 (utils.number/convert-to-whole-number 0 0)))))
|
||||
|
||||
(deftest parse-int-test
|
||||
(testing "defaults to zero"
|
||||
@@ -50,36 +50,3 @@
|
||||
(is (= 6 (utils.number/parse-float "6")))
|
||||
(is (= 6.99 (utils.number/parse-float "6.99" 0)))
|
||||
(is (= -6.9 (utils.number/parse-float "-6.9" 0)))))
|
||||
|
||||
(deftest small-number-threshold-test
|
||||
(testing "correctly generates threshold strings based on decimal count"
|
||||
(is (= "<0.1" (utils.number/small-number-threshold 1)))
|
||||
(is (= "<0.01" (utils.number/small-number-threshold 2)))
|
||||
(is (= "<0.001" (utils.number/small-number-threshold 3)))
|
||||
(is (= "<0.000001" (utils.number/small-number-threshold 6)))
|
||||
(is (= "<0.0000000001" (utils.number/small-number-threshold 10)))
|
||||
(is (= "<0.000000000000000001" (utils.number/small-number-threshold 18)))
|
||||
(is (= "<0.000000000000000000001" (utils.number/small-number-threshold 21))))
|
||||
|
||||
(testing "handles edge cases for decimal count"
|
||||
(is (= "0" (utils.number/small-number-threshold 0)))
|
||||
(is (= "0" (utils.number/small-number-threshold -1)))))
|
||||
|
||||
(deftest valid-decimal-count?-test
|
||||
(testing "valid decimal count check for numbers with varying decimals"
|
||||
(is (true? (utils.number/valid-decimal-count? 123 2)))
|
||||
(is (true? (utils.number/valid-decimal-count? 123 0)))
|
||||
|
||||
(is (true? (utils.number/valid-decimal-count? 123.45 2)))
|
||||
(is (true? (utils.number/valid-decimal-count? 123.4 2)))
|
||||
(is (true? (utils.number/valid-decimal-count? 123.456 3)))
|
||||
|
||||
(is (false? (utils.number/valid-decimal-count? 123.456 2)))
|
||||
(is (false? (utils.number/valid-decimal-count? 123.456789 4)))
|
||||
|
||||
(is (true? (utils.number/valid-decimal-count? 123.0 1)))
|
||||
(is (true? (utils.number/valid-decimal-count? -123.45 2)))
|
||||
(is (false? (utils.number/valid-decimal-count? -123.4567 3)))
|
||||
|
||||
(is (true? (utils.number/valid-decimal-count? 1234567890.12 2)))
|
||||
(is (false? (utils.number/valid-decimal-count? 1234567890.12345 3)))))
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
|
||||
"owner": "status-im",
|
||||
"repo": "status-go",
|
||||
"version": "v3.3.0",
|
||||
"commit-sha1": "43659f0c7e1a64102e7f8e38bd532b72714c5819",
|
||||
"src-sha256": "01fpviw1g22f4ni3li2wnhyz0l517jfipvnyfysckds6yi94l0hf"
|
||||
"version": "hop-path-processor-update",
|
||||
"commit-sha1": "0af7eec514bbcd105461f779d8d794b037c37279",
|
||||
"src-sha256": "1wfm28afb1mqn8vd1w426xvkg0nj9cycwc35swqdcqj6ga40cm1b"
|
||||
}
|
||||
|
||||
@@ -125,7 +125,6 @@ class TestrailReport(BaseTestReport):
|
||||
test_cases['nightly']['activity_centre_contact_request'] = 50984
|
||||
test_cases['nightly']['activity_centre_other'] = 51005
|
||||
test_cases['nightly']['wallet'] = 59443
|
||||
test_cases['nightly']['fallback'] = 63472
|
||||
|
||||
## Upgrade e2e
|
||||
# test_cases['upgrade']['general'] = 881
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user