Compare commits

..
122 changed files with 3924 additions and 5304 deletions
+9 -14
View File
@@ -1,15 +1,10 @@
/*
# Format top-level js files.
*
!*.js
# Ignore all except src/js/**/*.js
!/src/
/src/*
!/src/js
!/src/js/**/*.js
# Ignore all except translations/en.json
!/translations/
/translations/*
!/translations/en.json
!*/
*.clj-kondo
*.shadow-cljs
modules
result
target
component-spec
/app
-4
View File
@@ -6,8 +6,4 @@ module.exports = {
tabWidth: 2,
trailingComma: 'all',
useTabs: false,
// JSON sorting
jsonSortOrder: '{ "/.*/": "caseInsensitiveLexical" } ',
plugins: ['prettier-plugin-sort-json'],
};
+1 -1
View File
@@ -317,7 +317,7 @@ lint: ##@test Run code style checks
scripts/lint/translations.clj && \
zprint '{:search-config? true}' -sfc $$ALL_CLOJURE_FILES && \
sh scripts/lint/trailing-newline.sh && \
node_modules/.bin/prettier --check .
node_modules/.bin/prettier --write .
# NOTE: We run the linter twice because of https://github.com/kkinnear/zprint/issues/271
lint-fix: export TARGET := clojure
+1 -1
View File
@@ -1 +1 @@
2.29.0
2.29.20538
+1 -2
View File
@@ -97,8 +97,7 @@
"jest-silent-reporter": "^0.5.0",
"nodemon": "^2.0.16",
"nyc": "^14.1.1",
"prettier": "^3.3.3",
"prettier-plugin-sort-json": "^4.0.0",
"prettier": "^2.8.8",
"process": "0.11.10",
"react-test-renderer": "18.1.0",
"shadow-cljs": "2.26.2",
Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

@@ -1,6 +1,5 @@
(ns quo.components.avatars.token-avatar.view
(:require [quo.components.avatars.token-avatar.style :as style]
[quo.components.utilities.token.view :as token]
[react-native.core :as rn]
[react-native.hole-view :as hole-view]
[react-native.platform :as platform]
@@ -13,14 +12,13 @@
[:map {:closed true}
[:type {:optional true} [:enum :asset :collectible]]
[:context? {:optional true} [:maybe :boolean]]
[:image {:optional true} [:maybe :schema.common/image-source]]
[:token {:optional true} [:maybe [:or :keyword :string]]]
[:image :schema.common/image-source]
[:network-image {:optional true} [:maybe :schema.common/image-source]]
[:container-style {:optional true} [:maybe :map]]]]]
:any])
(defn- view-internal
[{:keys [type context? image token network-image container-style]}]
[{:keys [type context? image network-image container-style]}]
[rn/view
{:style (merge style/container container-style)
:accessibility-label :token-avatar}
@@ -34,11 +32,9 @@
[])
:style style/hole-view}
platform/android? (assoc :key context?))
[token/view
{:size :size-32
:token token
:style (style/image type)
:image-source image}]]
[rn/image
{:source image
:style (style/image type)}]]
(when context?
[rn/image
{:source network-image
@@ -21,17 +21,15 @@
(colors/theme-colors colors/white colors/neutral-95 theme))})
(defn buttons-container
[actions container-style]
(merge
{:flex-direction (if (= actions :two-vertical-actions) :column :row)
:justify-content :space-around
:padding-vertical 12
:gap 12
:padding-horizontal 20}
container-style))
[actions]
{:flex-direction (if (= actions :two-vertical-actions) :column :row)
:justify-content :space-around
:padding-vertical 12
:gap 12
:padding-horizontal 20})
(def button-container
{:flex-grow 1})
{:flex 1})
(def description-top
{:flex-direction :row
@@ -30,8 +30,7 @@
[:button-two-props {:optional true} [:maybe :map]]
[:scroll? {:optional true} [:maybe :boolean]]
[:blur? {:optional true} [:maybe :boolean]]
[:container-style {:optional true} [:maybe :map]]
[:buttons-container-style {:optional true} [:maybe :map]]]]]
[:container-style {:optional true} [:maybe :map]]]]]
:any])
(def ^:private role-icon
@@ -43,7 +42,7 @@
(defn- view-internal
[{:keys [actions description description-text description-top-text error-message role button-one-label
button-two-label blur? button-one-props button-two-props scroll? container-style
buttons-container-style context-tag-props]}]
context-tag-props]}]
(let [theme (quo.theme/use-theme)]
[rn/view
{:style (merge (style/container scroll? blur? theme) container-style)}
@@ -73,14 +72,14 @@
:context (i18n/label (keyword "t" role))}
context-tag-props)]])
[rn/view {:style (style/buttons-container actions buttons-container-style)}
[rn/view {:style (style/buttons-container actions)}
(when (or (= actions :two-actions)
(= actions :two-vertical-actions))
[button/button
(merge
{:size 40
:container-style style/button-container
:background (when (or blur? scroll?) :blur)
:container-style style/button-container
:theme theme
:accessibility-label :button-two}
button-two-props)
@@ -28,7 +28,6 @@
{:type :spending-cap
:label "Spending Cap"
:button-label "Edit"
:button-icon :i/options
:on-button-press on-button-press
:avatar-props {:image "image"}}])
(h/fire-event :press (h/get-by-text "Edit"))
@@ -107,7 +107,7 @@
:style (style/description blur? theme)}
description])]
(when (= type :account) [tiny-tag/view {:label tag-label}])
(when (and (= type :spending-cap) button-icon)
(when (= type :spending-cap)
[button/button
{:type :outline
:size 24
@@ -121,7 +121,6 @@
[:card? {:optional true} [:maybe :boolean]]
[:right-icon {:optional true} [:maybe :keyword]]
[:right-content {:optional true} [:maybe :map]]
[:icon-color {:optional true} [:maybe :schema.common/customization-color]]
[:status {:optional true} [:maybe [:enum :default :loading]]]
[:subtitle-type {:optional true} [:maybe [:enum :default :icon :network :account :editable]]]
[:size {:optional true} [:maybe [:enum :default :small :large]]]
@@ -53,7 +53,7 @@
(def ^:private ?network
[:map
[:network-logo {:optional true} [:maybe :schema.common/image-source]]
[:network-name {:optional true} [:maybe [:or :string :keyword]]]])
[:network-name {:optional true} [:maybe :string]]])
(def ^:private ?multinetwork
[:map
@@ -41,8 +41,7 @@
:align-items :center
:height size
:background-color background-color
:border-radius border-radius
:flex-shrink 1}
:border-radius border-radius}
(= state :selected) (assoc :height (+ size 2)
:border-color border-color
:border-width 1))))
@@ -51,13 +50,11 @@
[size]
{:margin-right (if (= size 24) 6 10)
:flex-direction :row
:flex-shrink 1
:align-items :center})
(defn tag-spacing
[size shrinkable?]
(cond-> {:margin-left (if (= size 24) 4 8)}
shrinkable? (assoc :flex-shrink 1)))
[size]
{:margin-left (if (= size 24) 4 8)})
(defn text
[theme]
+9 -12
View File
@@ -17,19 +17,17 @@
[schema.core :as schema]))
(defn- tag-skeleton
[{:keys [size text theme shrinkable?]
[{:keys [size text theme]
:or {size 24
theme (quo.theme/use-theme)}}
logo-component]
[rn/view {:style (style/tag-container size)}
logo-component
[rn/view {:style (style/tag-spacing size shrinkable?)}
[rn/view {:style (style/tag-spacing size)}
[text/text
{:style (style/text theme)
:weight :medium
:size (if (= size 24) :paragraph-2 :paragraph-1)
:number-of-lines 1
:ellipsize-mode :middle}
{:style (style/text theme)
:weight :medium
:size (if (= size 24) :paragraph-2 :paragraph-1)}
text]]])
(defn- communities-tag
@@ -39,7 +37,7 @@
icon-size (if (= size 24) 16 20)]
[rn/view {:style (style/tag-container size)}
[fast-image/fast-image {:style (style/circle-logo size) :source community-logo}]
[rn/view {:style (style/tag-spacing size false)}
[rn/view {:style (style/tag-spacing size)}
[text/text
{:style (style/text theme)
:weight :medium
@@ -150,10 +148,9 @@
:collectible
[tag-skeleton
{:theme theme
:size size
:text (str collectible-name " #" collectible-number)
:shrinkable? true}
{:theme theme
:size size
:text (str collectible-name " #" collectible-number)}
[rn/image {:style (style/rounded-logo size) :source collectible}]]
:account
@@ -4,7 +4,8 @@
(defn main
[{:keys [type customization-color]} theme]
{:align-items :center
{:justify-content :center
:align-items :center
:height 32
:padding-left 4
:padding-right 10
@@ -67,9 +67,7 @@
:style (style/main (assoc props :customization-color customization-color) theme)}
[left-view props]
[text/text
{:style (style/label type theme)
:weight :semi-bold
:ellipsize-mode :tail
:number-of-lines 1
:size :heading-1}
{:style (style/label type theme)
:weight :semi-bold
:size :heading-1}
label]]))
@@ -1,31 +0,0 @@
(ns quo.components.wallet.swap-input.component-spec
(:require [quo.components.wallet.swap-input.view :as swap-input]
[test-helpers.component :as h]))
(h/describe "Wallet: Swap Input"
(h/test "should render correctly with props"
(h/render-with-theme-provider
[swap-input/view
{:type :pay
:error? false
:token "SNT"
:status :default
:currency-symbol "€"
:value "5"
:fiat-value "1.50"
:network-tag-props {:title "Max: 200 SNT"}}])
(h/is-truthy (h/get-by-label-text :swap-input))
(h/is-truthy (h/get-by-text "SNT"))
(h/is-truthy (h/get-by-text "€1.50"))
(h/is-truthy (h/get-by-text "Max: 200 SNT")))
(h/test "should render correctly with approval label"
(h/render-with-theme-provider
[swap-input/view
{:type :pay
:show-approval-label? true
:approval-label-props
{:status :approve
:token-value "10"
:token-symbol "SNT"}}])
(h/is-truthy (h/get-by-text "Approve 10 SNT"))))
@@ -1,74 +0,0 @@
(ns quo.components.wallet.swap-input.style
(:require [quo.foundations.colors :as colors]
[quo.foundations.typography :as typography]))
(defn- border-color
[theme]
(colors/theme-colors colors/neutral-10 colors/neutral-80 theme))
(defn- loader-color
[theme]
(colors/theme-colors colors/neutral-5 colors/neutral-90 theme))
(defn content
[theme]
{:border-width 1
:border-radius 16
:border-color (border-color theme)
:background-color (colors/theme-colors colors/white colors/neutral-95 theme)})
(defn row-1
[loading?]
{:padding 12
:gap 8
:align-items (if loading? :center :flex-end)
:flex-direction :row})
(defn row-1-loader
[theme]
{:width 74
:height 14
:border-radius 6
:background-color (loader-color theme)})
(def input-container
{:flex 1
:flex-direction :row
:gap 5
:height 32
:align-items :flex-end})
(defn input
[disabled? error? theme]
(assoc typography/font-semi-bold
:font-size 27
:flex-shrink 1
:padding 0
:color (cond
error? (colors/resolve-color :danger theme)
disabled? (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)
:else (colors/theme-colors colors/neutral-100 colors/white theme))
:line-height 32))
(defn token-symbol
[theme]
{:padding-bottom 3
:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)})
(defn row-2
[align-right?]
{:flex-direction :row
:justify-content (if align-right? :flex-end :space-between)
:align-items :center
:padding 12})
(defn row-2-loader
[theme]
{:width 80
:height 10
:margin-vertical 7
:border-radius 6
:background-color (loader-color theme)})
(def fiat-amount
{:color colors/neutral-50})
@@ -1,121 +0,0 @@
(ns quo.components.wallet.swap-input.view
(:require [oops.core :as oops]
[quo.components.avatars.token-avatar.view :as token-avatar]
[quo.components.buttons.button.view :as buttons]
[quo.components.dividers.divider-line.view :as divider-line]
[quo.components.markdown.text :as text]
[quo.components.tags.network-tags.view :as network-tag]
[quo.components.wallet.approval-label.schema :as approval-label.schema]
[quo.components.wallet.approval-label.view :as approval-label]
[quo.components.wallet.swap-input.style :as style]
[quo.foundations.colors :as colors]
quo.theme
[react-native.core :as rn]
[schema.core :as schema]))
(def ?schema
[:=>
[:catn
[:props
[:map {:closed true}
[:type {:optional true} [:maybe [:enum :pay :receive]]]
[:status {:optional true} [:maybe [:enum :default :disabled :loading]]]
[:token {:optional true} [:maybe :string]]
[:value {:optional true} [:maybe :string]]
[:default-value {:optional true} [:maybe :string]]
[:currency-symbol {:optional true} [:maybe :string]]
[:fiat-value {:optional true} [:maybe :string]]
[:show-approval-label? {:optional true} [:maybe :boolean]]
[:error? {:optional true} [:maybe :boolean]]
[:show-keyboard? {:optional true} [:maybe :boolean]]
[:approval-label-props {:optional true} [:maybe approval-label.schema/?schema]]
[:network-tag-props {:optional true} [:maybe :map]]
[:on-change-text {:optional true} [:maybe fn?]]
[:enable-swap? {:optional true} [:maybe :boolean]]
[:on-swap-press {:optional true} [:maybe fn?]]
[:on-token-press {:optional true} [:maybe fn?]]
[:on-max-press {:optional true} [:maybe fn?]]
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
[:container-style {:optional true} [:maybe :map]]]]]
:any])
(defn view-internal
[{:keys [type status token value fiat-value show-approval-label? error? network-tag-props
approval-label-props default-value enable-swap?
currency-symbol on-change-text show-keyboard?
container-style on-swap-press on-token-press on-max-press]}]
(let [theme (quo.theme/use-theme)
pay? (= type :pay)
disabled? (= status :disabled)
loading? (= status :loading)
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}
[rn/view {:style (style/content theme)}
[rn/view
{:style (style/row-1 loading?)}
[rn/pressable {:on-press on-token-press}
[token-avatar/view
{:type :asset
:token token}]]
(if loading?
[rn/view {:style (style/row-1-loader theme)}]
[:<>
[rn/pressable
{:style style/input-container
:on-press focus-input}
[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
:auto-focus true
: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)}
token]]
(when (and pay? enable-swap?)
[buttons/button
{:type :outline
:size 32
:on-press on-swap-press
:icon-only? true}
:i/reorder])])]
[divider-line/view]
[rn/view
{:style (style/row-2 (or (not pay?) loading?))}
(when-not loading?
[:<>
(when pay?
[rn/pressable {:on-press on-max-press}
[network-tag/view
(assoc network-tag-props
:status
(if error? :error :default))]])
[text/text
{:size :paragraph-2
:style style/fiat-amount
:weight :medium}
(str currency-symbol fiat-value)]])
(when loading?
[rn/view {:style (style/row-2-loader theme)}])]]
(when (and (not= status :loading) (= type :pay) show-approval-label?)
[approval-label/view
approval-label-props])]))
(def view (schema/instrument #'view-internal ?schema))
@@ -51,7 +51,8 @@
(defn prop-text
[theme]
{:color (colors/theme-colors colors/neutral-100 colors/white theme)})
{:margin-right 4
:color (colors/theme-colors colors/neutral-100 colors/white theme)})
(def icon-container
{:width 32
@@ -60,15 +61,12 @@
(def container
{:flex-direction :row
:flex 1
:column-gap 8})
(def content-line
{:flex-direction :row
:margin-top 2
:align-items :center
:column-gap 4
:justify-content :flex-start})
{:flex-direction :row
:margin-top 2
:align-items :center})
(def icon-hole-view
{:width 32
@@ -98,11 +98,8 @@
(defn prop-tag
[props blur?]
[context-tag/view
(assoc props
:size 24
:blur? blur?
:container-style {:flex-shrink 1})])
[rn/view {:style {:margin-right 4}}
[context-tag/view (merge props {:size 24 :blur? blur?})]])
(defn- view-internal
[{:keys [state blur? first-tag second-tag third-tag fourth-tag on-press
@@ -124,7 +121,7 @@
:on-press-out on-press-out}
[rn/view {:style style/container}
[transaction-icon-view props theme]
[rn/view {:style {:flex 1}}
[rn/view
[transaction-header props theme]
[rn/view {:style style/content-line}
(when first-tag [prop-tag first-tag blur?])
-2
View File
@@ -186,7 +186,6 @@
quo.components.wallet.progress-bar.view
quo.components.wallet.required-tokens.view
quo.components.wallet.summary-info.view
quo.components.wallet.swap-input.view
quo.components.wallet.token-input.view
quo.components.wallet.transaction-progress.view
quo.components.wallet.transaction-summary.view
@@ -473,7 +472,6 @@
(def progress-bar quo.components.wallet.progress-bar.view/view)
(def required-tokens quo.components.wallet.required-tokens.view/view)
(def summary-info quo.components.wallet.summary-info.view/view)
(def swap-input quo.components.wallet.swap-input.view/view)
(def network-link quo.components.wallet.network-link.view/view)
(def token-input quo.components.wallet.token-input.view/view)
(def wallet-overview quo.components.wallet.wallet-overview.view/view)
-1
View File
@@ -112,7 +112,6 @@
quo.components.wallet.progress-bar.component-spec
quo.components.wallet.required-tokens.component-spec
quo.components.wallet.summary-info.component-spec
quo.components.wallet.swap-input.component-spec
quo.components.wallet.token-input.component-spec
quo.components.wallet.transaction-progress.component-spec
quo.components.wallet.transaction-summary.component-spec
-1
View File
@@ -43,7 +43,6 @@
:gnosis (js/require "../resources/images/networks/Gnosis.png")
:hermez (js/require "../resources/images/networks/Hermez.png")
:optimism (js/require "../resources/images/networks/Optimism.png")
:paraswap (js/require "../resources/images/networks/Paraswap.png")
:polygon (js/require "../resources/images/networks/Polygon.png")
:scroll (js/require "../resources/images/networks/Scroll.png")
:taiko (js/require "../resources/images/networks/Taiko.png")
+6 -7
View File
@@ -62,17 +62,16 @@
(bean/->js {:id id
:namespaces approved-namespaces})))
(defn disconnect-session
[{:keys [web3-wallet reason topic]}]
(oops/ocall web3-wallet
"disconnectSession"
(bean/->js {:topic topic
:reason reason})))
(defn get-active-sessions
[web3-wallet]
(oops/ocall web3-wallet "getActiveSessions"))
(defn core-pairing-disconnnect
[web3-wallet topic]
(oops/ocall web3-wallet
"core.pairing.disconnect"
(bean/->js {:topic topic})))
(defn core-pairing-pair
[web3-wallet url]
(oops/ocall web3-wallet
@@ -1,6 +1,5 @@
(ns status-im.common.floating-button-page.floating-container.style
(:require [quo.foundations.colors :as colors]
[react-native.safe-area :as safe-area]))
(:require [react-native.safe-area :as safe-area]))
(defn content-container
[blur? keyboard-shown?]
@@ -12,12 +11,7 @@
:padding-horizontal 20}
blur? (dissoc :padding-vertical :padding-horizontal))))
(defn blur-inner-container
[theme shell-overlay?]
{:background-color (colors/theme-colors colors/white-70-blur
(if shell-overlay?
colors/neutral-80-opa-80-blur
colors/neutral-95-opa-70-blur)
theme)
(def blur-inner-container
{:background-color :transparent ; required, otherwise blur-view will shrink
:padding-vertical 12
:padding-horizontal 20})
@@ -1,25 +1,27 @@
(ns status-im.common.floating-button-page.floating-container.view
(:require
[quo.core :as quo]
[quo.foundations.colors :as colors]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[status-im.common.floating-button-page.floating-container.style :as style]))
(defn- blur-container
[child shell-overlay?]
[child]
(let [theme (quo.theme/use-theme)]
[quo/blur
{:blur-amount 20
:blur-type :transparent
:overlay-color :transparent}
[rn/view {:style (style/blur-inner-container theme shell-overlay?)}
{:blur-amount 52
:blur-radius 20
:blur-type :transparent
:blur-overlay-color (colors/theme-colors colors/white-70-blur colors/neutral-95-opa-70-blur theme)}
[rn/view {:style style/blur-inner-container}
child]]))
(defn view
[{:keys [on-layout keyboard-shown? blur? shell-overlay?]} child]
[{:keys [on-layout keyboard-shown? blur?]} child]
[rn/view
{:style (style/content-container blur? keyboard-shown?)
:on-layout on-layout}
(if blur?
[blur-container child shell-overlay?]
[blur-container child]
child)])
@@ -58,7 +58,7 @@
(defn view
[{:keys [header footer customization-color footer-container-padding header-container-style
content-container-style gradient-cover? keyboard-should-persist-taps shell-overlay?]
content-container-style gradient-cover? keyboard-should-persist-taps]
:or {footer-container-padding (safe-area/get-top)}}
& children]
(reagent/with-let [scroll-view-ref (atom nil)
@@ -121,8 +121,7 @@
[floating-container/view
{:on-layout set-footer-container-height
:keyboard-shown? keyboard-shown?
:blur? show-background?
:shell-overlay? shell-overlay?}
:blur? show-background?}
footer]]]])
(finally
(remove-listeners))))
@@ -1,14 +0,0 @@
(ns status-im.common.metrics-confirmation-modal.style)
(def points-wrapper
{:margin-top 11
:margin-horizontal 20
:gap 21
:margin-bottom 15})
(def item-text
{:margin-top 10
:margin-left -4})
(def info-text
{:margin-top -5})
@@ -1,79 +0,0 @@
(ns status-im.common.metrics-confirmation-modal.view
(:require
[quo.core :as quo]
[react-native.core :as rn]
[status-im.common.metrics-confirmation-modal.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- dismiss-keyboard
[]
(rf/dispatch [:dismiss-keyboard]))
(defn- hide-bottom-sheet
[]
(rf/dispatch [:hide-bottom-sheet]))
(defn- toggle-metrics
[enabled?]
(rf/dispatch [:centralized-metrics/toggle-centralized-metrics enabled?]))
(def ^:private will-receive-points
[:t/ip-address
:t/universally-unique-identifiers-of-device
:t/logs-of-actions-withing-the-app])
(def ^:private not-receive-points
[:t/your-profile-information
:t/your-addresses
:t/information-you-input-and-send])
(defn- bullet-points
[{:keys [title points]}]
[rn/view
[quo/text {:weight :semi-bold}
title]
(for [label points]
^{:key label}
[quo/markdown-list
{:description (i18n/label label)
:blur? true
:container-style style/item-text}])])
(defn- on-share-usage
[]
(toggle-metrics true)
(hide-bottom-sheet))
(defn- on-do-not-share
[]
(toggle-metrics false)
(hide-bottom-sheet))
(defn view
[{:keys [settings?]}]
(rn/use-mount #(dismiss-keyboard))
[:<>
[quo/drawer-top
{:title (i18n/label :t/help-us-improve-status)
:description (i18n/label :t/collecting-usage-data)}]
[rn/view {:style style/points-wrapper}
[bullet-points
{:title (i18n/label :t/what-we-will-receive)
:points will-receive-points}]
[bullet-points
{:title (i18n/label :t/what-we-wont-receive)
:points not-receive-points}]
(when-not settings?
[quo/text
{:size :paragraph-2
:style style/info-text}
(i18n/label :t/sharing-usage-data-can-be-turned-off)])]
[quo/bottom-actions
{:actions :two-actions
:blur? true
:button-one-label (i18n/label :t/share-usage-data)
:button-one-props {:on-press on-share-usage}
:button-two-label (i18n/label (if settings? :t/do-not-share :t/not-now))
:button-two-props {:type :grey
:on-press on-do-not-share}}]])
+2 -18
View File
@@ -45,11 +45,6 @@
(def ^:const activity-center-membership-status-accepted 2)
(def ^:const activity-center-membership-status-declined 3)
;; Choose the maximum number of notifications that *usually/safely* fit on
;; most screens, so that the UI doesn't have to needlessly render
;; notifications.
(def ^:const notifications-per-page 7)
(def ^:const mute-for-15-mins-type 1)
(def ^:const mute-for-1-hour-type 2)
(def ^:const mute-for-8-hours-type 3)
@@ -281,21 +276,16 @@
#{wallet-connect-personal-sign-method
wallet-connect-eth-sign-method
wallet-connect-eth-send-transaction-method
;; NOTE: disabled, as we have no clear use cases for it and other wallets don't support it
;; wallet-connect-eth-sign-transaction-method
wallet-connect-eth-sign-transaction-method
wallet-connect-eth-sign-typed-method
wallet-connect-eth-sign-typed-v4-method})
(def ^:const wallet-connect-supported-events #{"accountsChanged" "chainChanged"})
(def ^:const wallet-connect-session-proposal-event "session_proposal")
(def ^:const wallet-connect-session-request-event "session_request")
(def ^:const wallet-connect-session-delete-event "session_delete")
(def ^:const wallet-connect-user-rejected-error-key "USER_REJECTED")
(def ^:const wallet-connect-user-disconnected-reason-key "USER_DISCONNECTED")
(def ^:const transaction-pending-type-wallet-connect-transfer "WalletConnectTransfer")
(def ^:const token-sort-priority {"SNT" 1 "STT" 1 "ETH" 2 "DAI" 3})
(def ^:const dapp-permission-contact-code "contact-code")
(def ^:const dapp-permission-web3 "web3")
(def ^:const dapp-permission-qr-code "qr-code")
@@ -516,9 +506,6 @@
(def ^:const optimism-full-name "Optimism")
(def ^:const arbitrum-full-name "Arbitrum")
(def ^:const sepolia-full-name "Sepolia")
(def ^:const goerli-full-name "Goerli")
(def ^:const mainnet-network-name :mainnet)
(def ^:const ethereum-network-name :ethereum)
(def ^:const optimism-network-name :optimism)
@@ -580,8 +567,5 @@
(def ^:const max-recommended-slippage 5)
(def ^:const max-slippage-decimal-places 2)
(def ^:const swap-default-provider
{:name :paraswap
:full-name "Paraswap"
:color :blue
:contract-address "0xdef171fe48cf0115b1d80b88dc8eab59176fee57"
{:name "Paraswap"
:terms-and-conditions-url "https://files.paraswap.io/tos_v4.pdf"})
@@ -7,17 +7,10 @@
[taoensso.timbre :as log]
[utils.re-frame :as rf]))
(def ^:const user-confirmed-key :centralized-metrics/user-confirmed?)
(def ^:const enabled-key :centralized-metrics/enabled?)
(defn show-confirmation-modal?
[db]
(not (user-confirmed-key db)))
(defn push-event?
[db]
(or (not (user-confirmed-key db))
(enabled-key db)))
(or (not (:centralized-metrics/user-confirmed? db))
(:centralized-metrics/enabled? db)))
(defn centralized-metrics-interceptor
[context]
@@ -36,16 +29,5 @@
(fn [{:keys [db]} [enabled?]]
{:fx [[:effects.centralized-metrics/toggle-metrics enabled?]]
:db (assoc db
user-confirmed-key
true
enabled-key
enabled?)}))
(rf/reg-event-fx :centralized-metrics/check-modal
(fn [{:keys [db]} [modal-view]]
(when (show-confirmation-modal? db)
{:fx [[:dispatch
[:show-bottom-sheet
{:content (fn [] [modal-view])
:shell? true}]]]})))
:centralized-metrics/user-confirmed? true
:centralized-metrics/enabled? enabled?)}))
@@ -6,11 +6,6 @@
[status-im.contexts.centralized-metrics.tracking :as tracking]
[test-helpers.unit :as h]))
(deftest show-confirmation-modal-test
(testing "returns true if the user confirmed"
(is (false? (events/show-confirmation-modal? {events/user-confirmed-key true})))
(is (true? (events/show-confirmation-modal? {})))))
(deftest push-event-test
(testing "returns correct boolean value"
(is (true? (events/push-event? {:centralized-metrics/user-confirmed? false})))
@@ -27,7 +27,7 @@
:on-error #(p-reject (str "failed to sign data\n" %))}))))
(defn- edit-shared-addresses-for-community
[community-id signatures addresses-to-reveal airdrop-address _share-future-addresses?]
[community-id signatures addresses-to-reveal airdrop-address]
(promesa/create
(fn [p-resolve p-reject]
(rpc/call
@@ -41,16 +41,15 @@
:on-error p-reject}))))
(defn- request-to-join
[community-id signatures addresses-to-reveal airdrop-address share-future-addresses?]
[community-id signatures addresses-to-reveal airdrop-address]
(promesa/create
(fn [p-resolve p-reject]
(rpc/call
{:method :wakuext_requestToJoinCommunity
:params [{:communityId community-id
:signatures signatures
:addressesToReveal addresses-to-reveal
:airdropAddress airdrop-address
:shareFutureAddresses share-future-addresses?}]
:params [{:communityId community-id
:signatures signatures
:addressesToReveal addresses-to-reveal
:airdropAddress airdrop-address}]
:js-response true
:on-success p-resolve
:on-error p-reject}))))
@@ -65,18 +64,15 @@
(defn- sign-and-call-endpoint
[{:keys [community-id password pub-key
addresses-to-reveal airdrop-address share-future-addresses?
addresses-to-reveal airdrop-address
on-success on-error
callback]}]
(-> (promesa/let [sign-params (generate-requests-for-signing pub-key
community-id
addresses-to-reveal)
(-> (promesa/let [sign-params (generate-requests-for-signing pub-key community-id addresses-to-reveal)
signatures (sign-data sign-params password)
result (callback community-id
signatures
addresses-to-reveal
airdrop-address
share-future-addresses?)]
airdrop-address)]
(run-callback-or-event on-success result))
(promesa/catch #(run-callback-or-event on-error %))))
@@ -91,7 +87,6 @@
[:or [:set string?]
[:sequential string?]]]
[:airdrop-address string?]
[:share-future-addresses? boolean?]
[:on-success [:or fn? :schema.re-frame/event]]
[:on-error [:or fn? :schema.re-frame/event]]
[:callback fn?]]]
@@ -17,12 +17,13 @@
(rf/reg-event-fx :communities/initialize-permission-addresses initialize-permission-addresses)
(defn do-init-permission-addresses
[{:keys [db]} [community-id revealed-accounts share-future-addresses?]]
[{:keys [db]} [community-id revealed-accounts]]
(let [wallet-accounts (utils/sorted-operable-non-watch-only-accounts db)
addresses-to-reveal (if (seq revealed-accounts)
(set (keys revealed-accounts))
;; Reveal all addresses as fallback.
(set (map :address wallet-accounts)))
;; When there are no revealed addresses, such as when joining a
;; community, use first address for airdrops.
airdrop-address (or (->> revealed-accounts
@@ -34,7 +35,10 @@
first
:address))]
{:db (-> db
(assoc-in [:communities/selected-share-all-addresses community-id] share-future-addresses?)
;; Set to false by default while we don't persist the user's choice
;; in status-go, otherwise whenever the view is mounted, the choice
;; of selected addresses won't be respected.
(assoc-in [:communities/selected-share-all-addresses community-id] false)
(assoc-in [:communities/all-addresses-to-reveal community-id] addresses-to-reveal)
(assoc-in [:communities/all-airdrop-addresses community-id] airdrop-address))
:fx [[:dispatch
@@ -56,44 +60,36 @@
is selecting an airdrop address, we must submit to status-go the current
choice of addresses to share, and vice-versa. If we omit addresses to share,
status-go will default to all available."
[{:keys [db]}
[{:keys [community-id password on-success addresses airdrop-address share-future-addresses?]}]]
(let [pub-key (get-in db [:profile/profile :public-key])
wallet-accounts (utils/sorted-operable-non-watch-only-accounts db)
addresses-to-reveal (if (seq addresses)
(set addresses)
(get-in db [:communities/all-addresses-to-reveal community-id]))
new-airdrop-address (if (contains? addresses-to-reveal airdrop-address)
airdrop-address
(->> wallet-accounts
(filter #(contains? addresses-to-reveal (:address %)))
first
:address))
share-future-addresses? (if (nil? share-future-addresses?)
(get-in db [:communities/selected-share-all-addresses community-id])
share-future-addresses?)]
[{:keys [db]} [{:keys [community-id password on-success addresses airdrop-address]}]]
(let [pub-key (get-in db [:profile/profile :public-key])
wallet-accounts (utils/sorted-operable-non-watch-only-accounts db)
addresses-to-reveal (if (seq addresses)
(set addresses)
(get-in db [:communities/all-addresses-to-reveal community-id]))
new-airdrop-address (if (contains? addresses-to-reveal airdrop-address)
airdrop-address
(->> wallet-accounts
(filter #(contains? addresses-to-reveal (:address %)))
first
:address))]
{:fx [[:effects.community/edit-shared-addresses
{:community-id community-id
:password password
:pub-key pub-key
:addresses-to-reveal addresses-to-reveal
:share-future-addresses? share-future-addresses?
:airdrop-address new-airdrop-address
:on-success (fn []
(when (fn? on-success)
(on-success addresses-to-reveal
new-airdrop-address
share-future-addresses?))
(rf/dispatch [:communities/edit-shared-addresses-success
community-id addresses-to-reveal airdrop-address]))
:on-error [:communities/edit-shared-addresses-failure community-id]}]]}))
{:community-id community-id
:password password
:pub-key pub-key
:addresses-to-reveal addresses-to-reveal
:airdrop-address new-airdrop-address
:on-success (fn []
(when (fn? on-success)
(on-success addresses-to-reveal new-airdrop-address))
(rf/dispatch [:communities/edit-shared-addresses-success
community-id addresses-to-reveal airdrop-address]))
:on-error [:communities/edit-shared-addresses-failure community-id]}]]}))
(rf/reg-event-fx :communities/edit-shared-addresses edit-shared-addresses)
(rf/reg-event-fx :communities/edit-shared-addresses-success
(fn [_ [community-id addresses-to-reveal airdrop-address share-future-addresses?]]
(fn [_ [community-id addresses-to-reveal airdrop-address]]
{:fx [[:dispatch [:communities/set-airdrop-address community-id airdrop-address]]
[:dispatch [:communities/set-share-all-addresses community-id share-future-addresses?]]
[:dispatch [:communities/set-addresses-to-reveal community-id addresses-to-reveal]]]}))
(rf/reg-event-fx :communities/edit-shared-addresses-failure
@@ -70,7 +70,7 @@
(is
(match?
{:db (-> (:db cofx)
(assoc-in [:communities/selected-share-all-addresses community-id] true)
(assoc-in [:communities/selected-share-all-addresses community-id] false)
(assoc-in [:communities/all-addresses-to-reveal community-id] addresses-to-reveal)
(assoc-in [:communities/all-airdrop-addresses community-id] airdrop-address))
:fx [[:dispatch
@@ -82,7 +82,7 @@
[:dispatch
[:communities/check-permissions-to-join-during-selection community-id
addresses-to-reveal]]]}
(sut/do-init-permission-addresses cofx [community-id revealed-accounts true])))))
(sut/do-init-permission-addresses cofx [community-id revealed-accounts])))))
;; Expect to mark all addresses to be revealed and first one to receive
;; airdrops when no addresses were previously revealed.
@@ -93,7 +93,7 @@
(is
(match?
{:db (-> (:db cofx)
(assoc-in [:communities/selected-share-all-addresses community-id] true)
(assoc-in [:communities/selected-share-all-addresses community-id] false)
(assoc-in [:communities/all-addresses-to-reveal community-id] addresses-to-reveal))
:fx [[:dispatch
[:communities/check-permissions-to-join-community
@@ -101,7 +101,7 @@
[:dispatch
[:communities/check-permissions-to-join-during-selection community-id
addresses-to-reveal]]]}
(sut/do-init-permission-addresses cofx [community-id revealed-accounts true]))))))
(sut/do-init-permission-addresses cofx [community-id revealed-accounts]))))))
(deftest edit-shared-addresses-test
(testing
@@ -109,7 +109,6 @@
fallback to all wallet addresses"
(let [pub-key "abcdef"
revealed-addresses #{"0xB" "0xC"}
share-future-addresses? true
cofx {:db {:profile/profile {:public-key pub-key}
:communities/all-addresses-to-reveal {community-id revealed-addresses}}}
airdrop-address "0xB"
@@ -117,24 +116,22 @@
actual
(sut/edit-shared-addresses
cofx
[{:community-id community-id
:password password
:airdrop-address airdrop-address
:share-future-addresses? share-future-addresses?
:on-success (fn [new-addresses-to-reveal]
(is (match? revealed-addresses new-addresses-to-reveal)))}])
[{:community-id community-id
:password password
:airdrop-address airdrop-address
:on-success (fn [new-addresses-to-reveal]
(is (match? revealed-addresses new-addresses-to-reveal)))}])
on-success-wrapper (-> actual :fx first second :on-success)]
(is (match?
{:fx [[:effects.community/edit-shared-addresses
{:community-id community-id
:password password
:pub-key pub-key
:addresses-to-reveal revealed-addresses
:share-future-addresses? share-future-addresses?
:airdrop-address airdrop-address
:on-success fn?
:on-error [:communities/edit-shared-addresses-failure community-id]}]]}
{:community-id community-id
:password password
:pub-key pub-key
:addresses-to-reveal revealed-addresses
:airdrop-address airdrop-address
:on-success fn?
:on-error [:communities/edit-shared-addresses-failure community-id]}]]}
actual))
(on-success-wrapper)))
@@ -203,9 +203,7 @@
:addresses-for-permissions])
(rf/dispatch [:hide-bottom-sheet]))}]))}])
(rf/dispatch [:communities/set-share-all-addresses id flag-share-all-addresses]))
(do
(rf/dispatch [:communities/set-share-all-addresses id flag-share-all-addresses])
(rf/dispatch [:communities/set-addresses-to-reveal id addresses-to-reveal]))))
(rf/dispatch [:communities/set-addresses-to-reveal id addresses-to-reveal])))
highest-role (rf/sub [:communities/highest-role-for-selection id])
[unmodified-role _] (rn/use-state highest-role)]
@@ -263,7 +261,6 @@
can-edit-addresses? (rf/sub [:communities/can-edit-shared-addresses? id])
wallet-accounts (rf/sub [:wallet/operable-accounts-without-watched-accounts])
joined (rf/sub [:communities/community-joined id])
unmodified-addresses-to-reveal (rf/sub [:communities/addresses-to-reveal id])
[addresses-to-reveal set-addresses-to-reveal] (rn/use-state unmodified-addresses-to-reveal)
@@ -288,6 +285,7 @@
(set-flag-share-all-addresses new-value)
(when new-value
(set-addresses-to-reveal (set (map :address wallet-accounts))))))]
(rn/use-mount
(fn []
(when-not flag-share-all-addresses
@@ -312,7 +310,6 @@
flag-share-all-addresses]
:header [quo/page-setting
{:checked? flag-share-all-addresses
:disabled? joined
:customization-color color
:on-change toggle-flag-share-all-addresses
:setting-text (i18n/label
@@ -47,11 +47,12 @@
:label (i18n/label :t/view-token-gating)}))
(defn- action-mark-as-read
[chat-id]
{:icon :i/mark-as-read
:accessibility-label :chat-mark-as-read
:on-press #(hide-sheet-and-dispatch [:chat.ui/mark-all-read-pressed chat-id])
:label (i18n/label :t/mark-as-read)})
[]
(when config/show-not-implemented-features?
{:icon :i/mark-as-read
:accessibility-label :chat-mark-as-read
:on-press not-implemented/alert
:label (i18n/label :t/mark-as-read)}))
(defn- action-toggle-muted
[id muted? muted-till chat-type]
@@ -129,7 +130,7 @@
(and (not inside-chat?) (not locked?))
[quo/action-drawer
[[(when-not hide-view-members? (action-view-members-and-details community-id chat-id))
(action-mark-as-read chat-id)
(action-mark-as-read)
(action-toggle-muted chat-id muted muted-till chat-type)
(action-notification-settings)
(action-pinned-messages chat-id)
@@ -142,7 +143,7 @@
[[(action-view-members-and-details community-id chat-id)
(when token-gated?
(action-token-requirements))
(action-mark-as-read chat-id)
(action-mark-as-read)
(action-toggle-muted chat-id muted muted-till chat-type)
(action-notification-settings)
(when config/fetch-messages-enabled?
+18 -14
View File
@@ -16,7 +16,6 @@
[status-im.navigation.events :as navigation]
[status-im.navigation.transitions :as transitions]
[taoensso.timbre :as log]
[utils.collection :as collection-utils]
[utils.re-frame :as rf]))
(defn handle-community
@@ -373,14 +372,15 @@
(when (and community joined (not fetching-revealed-accounts))
{:db (assoc-in db [:communities community-id :fetching-revealed-accounts] true)
:json-rpc/call
[{:method "wakuext_latestRequestToJoinForCommunity"
:params [community-id]
:on-success [:communities/get-revealed-accounts-success community-id on-success]
:on-error (fn [err]
(log/error {:message "failed to fetch revealed accounts"
:community-id community-id
:err err})
(rf/dispatch [:communities/get-revealed-accounts-failed community-id]))}]})))
[{:method "wakuext_getRevealedAccounts"
:params [community-id (get-in db [:profile/profile :public-key])]
:js-response true
:on-success [:communities/get-revealed-accounts-success community-id on-success]
:on-error (fn [err]
(log/error {:message "failed to fetch revealed accounts"
:community-id community-id
:err err})
(rf/dispatch [:communities/get-revealed-accounts-failed community-id]))}]})))
(rf/reg-event-fx :communities/get-revealed-accounts get-revealed-accounts)
@@ -399,18 +399,22 @@
[:json-rpc/call :schema.common/rpc-call]]]])
(rf/reg-event-fx :communities/get-revealed-accounts-success
(fn [{:keys [db]} [community-id on-success request-to-join]]
(fn [{:keys [db]} [community-id on-success revealed-accounts-js]]
(when-let [community (get-in db [:communities community-id])]
(let [revealed-accounts (collection-utils/index-by :address (:revealedAccounts request-to-join))
share-future-addresses? (:shareFutureAddresses request-to-join)
(let [revealed-accounts
(reduce
(fn [acc {:keys [address] :as revealed-account}]
(assoc acc address revealed-account))
{}
(data-store.communities/<-revealed-accounts-rpc revealed-accounts-js))
community-with-revealed-accounts
(-> community
(assoc :revealed-accounts revealed-accounts)
(assoc :share-future-addresses? share-future-addresses?)
(dissoc :fetching-revealed-accounts))]
{:db (assoc-in db [:communities community-id] community-with-revealed-accounts)
:fx [(when (vector? on-success)
[:dispatch (conj on-success revealed-accounts share-future-addresses?)])]}))))
[:dispatch (conj on-success revealed-accounts)])]}))))
(rf/reg-event-fx :communities/get-revealed-accounts-failed
(fn [{:keys [db]} [community-id]]
@@ -146,8 +146,8 @@
effects (events/get-revealed-accounts {:db db} [community-id])]
(is (match? (assoc-in db [:communities community-id :fetching-revealed-accounts] true)
(:db effects)))
(is (match? {:method "wakuext_latestRequestToJoinForCommunity"
:params [community-id]}
(is (match? {:method "wakuext_getRevealedAccounts"
:params [community-id "profile-public-key"]}
(-> effects :json-rpc/call first (select-keys [:method :params]))))))))
(deftest handle-community-test
@@ -117,14 +117,13 @@
{:community community-name})}]]]})))
(defn request-to-join-with-signatures
[_ [community-id addresses-to-reveal signatures share-future-addresses?]]
[_ [community-id addresses-to-reveal signatures]]
{:fx [[:json-rpc/call
[{:method "wakuext_requestToJoinCommunity"
:params [{:communityId community-id
:signatures signatures
:addressesToReveal addresses-to-reveal
:shareFutureAddresses share-future-addresses?
:airdropAddress (first addresses-to-reveal)}]
:params [{:communityId community-id
:signatures signatures
:addressesToReveal addresses-to-reveal
:airdropAddress (first addresses-to-reveal)}]
:js-response true
:on-success [:communities/requested-to-join]
:on-error [:communities/requested-to-join-error community-id]}]]]})
@@ -154,18 +153,16 @@
(defn request-to-join-with-addresses
[{:keys [db]}
[{:keys [community-id password]}]]
(let [pub-key (get-in db [:profile/profile :public-key])
addresses-to-reveal (get-in db [:communities/all-addresses-to-reveal community-id])
share-future-addresses? (get-in db [:communities/selected-share-all-addresses community-id])
airdrop-address (get-in db [:communities/all-airdrop-addresses community-id])]
(let [pub-key (get-in db [:profile/profile :public-key])
addresses-to-reveal (get-in db [:communities/all-addresses-to-reveal community-id])
airdrop-address (get-in db [:communities/all-airdrop-addresses community-id])]
{:fx [[:effects.community/request-to-join
{:community-id community-id
:password password
:pub-key pub-key
:addresses-to-reveal addresses-to-reveal
:airdrop-address airdrop-address
:share-future-addresses? share-future-addresses?
:on-success [:communities/requested-to-join]
:on-error [:communities/requested-to-join-error community-id]}]]}))
{:community-id community-id
:password password
:pub-key pub-key
:addresses-to-reveal addresses-to-reveal
:airdrop-address airdrop-address
:on-success [:communities/requested-to-join]
:on-error [:communities/requested-to-join-error community-id]}]]}))
(rf/reg-event-fx :communities/request-to-join-with-addresses request-to-join-with-addresses)
@@ -37,22 +37,19 @@
(sut/sign-data cofx [community-id password sign-params])))))
(deftest request-to-join-with-signatures-test
(let [cofx {:db {}}
addresses-to-reveal [account-pub-key "0x2"]
share-future-addresses? true
signatures ["11111" "222222"]
expected {:fx [[:json-rpc/call
[{:method "wakuext_requestToJoinCommunity"
:params [{:communityId community-id
:signatures signatures
:addressesToReveal addresses-to-reveal
:shareFutureAddresses share-future-addresses?
:airdropAddress "0x1"}]
:js-response true
:on-success [:communities/requested-to-join]
:on-error [:communities/requested-to-join-error
community-id]}]]]}]
(let [cofx {:db {}}
addresses-to-reveal [account-pub-key "0x2"]
signatures ["11111" "222222"]
expected {:fx [[:json-rpc/call
[{:method "wakuext_requestToJoinCommunity"
:params [{:communityId community-id
:signatures signatures
:addressesToReveal addresses-to-reveal
:airdropAddress "0x1"}]
:js-response true
:on-success [:communities/requested-to-join]
:on-error [:communities/requested-to-join-error
community-id]}]]]}]
(is (match? expected
(sut/request-to-join-with-signatures cofx
[community-id addresses-to-reveal signatures
share-future-addresses?])))))
[community-id addresses-to-reveal signatures])))))
@@ -5,8 +5,13 @@
(def background-container
{:background-color colors/neutral-100
:flex 1
:overflow :hidden})
:flex-direction :row
:position :absolute
:overflow :hidden
:top 0
:bottom 0
:left 0
:right 0})
(def background-blur-overlay
{:position :absolute
@@ -25,12 +25,13 @@
:sub-text (i18n/label :t/explore-the-decentralized-web)}])
(defn background-image
[image-view-width]
[content-width]
[rn/image
{:resize-mode :stretch
:style {:flex 1
:width image-view-width}
:source (resources/get-image :onboarding-illustration)}])
{:resize-mode :stretch
:resize-method :scale
:style {:top 138
:width content-width}
:source (resources/get-image :onboarding-illustration)}])
(defonce progress (atom nil))
(defonce paused? (atom nil))
@@ -5,9 +5,12 @@
(defn header-container
[status-bar-height content-width index header-background]
{:margin-left (* content-width index)
{:position :absolute
:top 0
:left (* content-width index)
:padding-top (+ 30 status-bar-height)
:width content-width
:height (+ 96 status-bar-height)
:flex-direction :row
:background-color (when header-background colors/onboarding-header-black)})
@@ -59,9 +62,9 @@
:top (+ 12 status-bar-height)})
(defn carousel-container
[left animate? width]
(cond->> {:flex-direction :row
:flex 1
:width width
:margin-left left}
animate? (reanimated/apply-animations-to-style {:margin-left left})))
[left animate?]
(cond->> {:position :absolute
:top 0
:flex-direction :row
:left left}
animate? (reanimated/apply-animations-to-style {:left left})))
@@ -18,18 +18,19 @@
:size :heading-2}
(get-in header-text [index :text])]
[quo/text
{:style style/carousel-sub-text}
{:style style/carousel-sub-text
:size :paragraph-1}
(get-in header-text [index :sub-text])]])
(defn content-view
[{:keys [window-width status-bar-height index header-text header-background]} content]
(let [content-width (* 4 window-width)]
[rn/view {:style {:flex 1}}
[:<>
(when content content)
[rn/view {:style (style/header-container status-bar-height content-width index header-background)}
(for [index (range 4)]
^{:key index}
[header-text-view index window-width header-text])]
(when content content)]))
[header-text-view index window-width header-text])]]))
(defn progress-bar
[{:keys [static? progress-bar-width]}]
@@ -63,10 +64,10 @@
:swipeable (animation/composed-gestures progress paused? is-dragging? drag-amount)
:tappable (animation/tap-gesture progress paused?)
nil)]
[rn/view {:style {:flex 1}}
[:<>
[gesture/gesture-detector {:gesture identified-gesture}
[container-view {:style (style/carousel-container carousel-left animate? (* 4 window-width))}
(for [index (range 1)]
[container-view {:style (style/carousel-container carousel-left animate?)}
(for [index (range 2)]
^{:key index}
[content-view
{:window-width window-width
@@ -5,7 +5,6 @@
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[status-im.common.check-before-syncing.view :as check-before-syncing]
[status-im.common.metrics-confirmation-modal.view :as metrics-modal]
[status-im.common.not-implemented :as not-implemented]
[status-im.common.resources :as resources]
[status-im.config :as config]
@@ -127,7 +126,6 @@
(defn- internal-view
[sign-in-type]
(rn/use-mount #(rf/dispatch [:centralized-metrics/check-modal metrics-modal/view]))
(let [{:keys [top]} (safe-area/get-insets)]
[rn/view {:style style/content-container}
[quo/page-nav
@@ -4,20 +4,20 @@
(def title-container
{:margin-horizontal 20
:padding-bottom 20
:padding-top 12})
:padding-vertical 12})
(defn page-container
[insets]
{:flex 1
:padding-top (+ (:top insets) 56)})
{:flex 1
:justify-content :space-between
:padding-top (+ (:top insets) 56)})
(defn page-illustration
[width]
{:flex 1
:margin-top 12
:margin-bottom 10
:width width})
{:flex 1
:padding-top 12
:padding-bottom 10
:width width})
(defn buttons
[insets]
@@ -2,16 +2,11 @@
(defn page-container
[insets]
{:flex 1
:padding-top (:top insets)})
{:flex 1
:justify-content :space-between
:padding-top (:top insets)})
(defn page-illustration
[width]
{:flex 1
:width width})
(def title-style
{:position :absolute
:left 0
:right 0
:top 0})
@@ -17,22 +17,19 @@
(defn generate-keys-title
[]
[quo/text-combinations
{:container-style {:margin-horizontal 20
:margin-vertical 12}
{:container-style {:margin-horizontal 20}
:title (i18n/label :t/generating-keys)}])
(defn saving-keys-title
[]
[quo/text-combinations
{:container-style {:margin-horizontal 20
:margin-vertical 12}
{:container-style {:margin-horizontal 20}
:title (i18n/label :t/saving-keys-to-device)}])
(defn keys-saved-title
[]
[quo/text-combinations
{:container-style {:margin-horizontal 20
:margin-vertical 12}
{:container-style {:margin-horizontal 20}
:title (i18n/label :t/keys-saved)}])
(defn sequence-animation
@@ -64,42 +61,46 @@
reanimated/easings))))))
(defn title
[]
(let [generate-keys-opacity (reanimated/use-shared-value 1)
[insets]
(let [top-insets (+ (if rn/small-screen? 62 112) (:insets insets))
generate-keys-opacity (reanimated/use-shared-value 1)
saving-keys-opacity (reanimated/use-shared-value 0)
keys-saved-opacity (reanimated/use-shared-value 0)]
(sequence-animation generate-keys-opacity saving-keys-opacity keys-saved-opacity)
[rn/view
{:style {:margin-top 56
:height 56}}
{:position :absolute
:top top-insets}
[reanimated/view
{:style (reanimated/apply-animations-to-style
{:opacity generate-keys-opacity}
style/title-style)}
{:position :absolute})}
[generate-keys-title]]
[reanimated/view
{:style (reanimated/apply-animations-to-style
{:opacity saving-keys-opacity}
style/title-style)}
{:position :absolute})}
[saving-keys-title]]
[reanimated/view
{:style (reanimated/apply-animations-to-style
{:opacity keys-saved-opacity}
style/title-style)}
{:position :absolute})}
[keys-saved-title]]]))
(defn content
[]
(let [width (:width (rn/get-window))]
[rn/image
{:resize-mode :contain
:style (style/page-illustration width)
:source (resources/get-image :generate-keys1)}]))
[rn/view
{:top 156
:position :absolute}
[rn/image
{:resize-mode :contain
:style (style/page-illustration width)
:source (resources/get-image :generate-keys1)}]]))
(defn view
[]
(let [insets (safe-area/get-insets)]
[rn/view {:style (style/page-container insets)}
[:<>
[title]
[title insets]
[content]]]))
@@ -7,8 +7,9 @@
:justify-content :flex-end})
(def text-container
{:text-align :center
:margin-top 4
{:flex 1
:text-align :center
:margin-top 16
:flex-wrap :wrap})
(def plain-text
@@ -18,8 +19,9 @@
{:flex 1
:color colors/white})
(defn bottom-actions-container
[bottom-insets]
{:background-color colors/onboarding-header-black
:flex-shrink 1
:padding-bottom (+ 20 bottom-insets)})
(def bottom-actions-container
{:position :absolute
:background-color colors/onboarding-header-black
:left 0
:right 0
:padding-bottom 40})
@@ -2,7 +2,6 @@
(:require
[quo.core :as quo]
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[status-im.contexts.onboarding.common.background.view :as background]
[status-im.contexts.onboarding.common.overlay.view :as overlay]
[status-im.contexts.onboarding.intro.style :as style]
@@ -15,7 +14,7 @@
[rn/view {:style style/page-container}
[background/view false]
[quo/bottom-actions
{:container-style (style/bottom-actions-container (safe-area/get-bottom))
{:container-style style/bottom-actions-container
:actions :two-vertical-actions
:description :bottom
:description-text [quo/text
@@ -212,7 +212,6 @@
[status-im.contexts.preview.quo.wallet.progress-bar :as progress-bar]
[status-im.contexts.preview.quo.wallet.required-tokens :as required-tokens]
[status-im.contexts.preview.quo.wallet.summary-info :as summary-info]
[status-im.contexts.preview.quo.wallet.swap-input :as swap-input]
[status-im.contexts.preview.quo.wallet.token-input :as token-input]
[status-im.contexts.preview.quo.wallet.transaction-progress :as transaction-progress]
[status-im.contexts.preview.quo.wallet.transaction-summary :as
@@ -571,7 +570,6 @@
{:name :required-tokens
:component required-tokens/view}
{:name :summary-info :component summary-info/view}
{:name :swap-input :component swap-input/view}
{:name :token-input :component token-input/view}
{:name :wallet-activity :component wallet-activity/view}
{:name :transaction-progress :component transaction-progress/view}
@@ -1,68 +0,0 @@
(ns status-im.contexts.preview.quo.wallet.swap-input
(:require
[quo.core :as quo]
[quo.foundations.resources :as resources]
[react-native.core :as rn]
[status-im.contexts.preview.quo.preview :as preview]))
(def descriptor
[{:type :select
:key :type
:options [{:key :pay}
{:key :receive}]}
{:type :select
:key :status
:options [{:key :default}
{:key :disabled}
{:key :loading}]}
{:type :select
:key :value
:options [{:key :token}
{:key :fiat}]}
{:type :boolean
:key :error?}
{:type :boolean
:key :enable-swap?}
{:type :boolean
:key :show-approval-label?}
(preview/customization-color-option)])
(defn view
[]
(let [[state set-state] (rn/use-state {:type :pay
:error? false
:token "SNT"
:customization-color :blue
:show-approval-label? false
:enable-swap? true
:status :default
:currency-symbol "€"})
[value set-value] (rn/use-state "")
on-press (fn [v] (set-value (str value v)))
delete (fn [] (set-value #(subs % 0 (dec (count %)))))]
[preview/preview-container
{:state state
:set-state set-state
:descriptor descriptor}
[quo/swap-input
(assoc state
:on-swap-press #(js/alert "Swap Pressed")
:on-token-press #(js/alert "Token Pressed")
:on-max-press #(js/alert "Max Pressed")
:value value
:fiat-value (str (.toFixed (* value 0.3) 2))
:container-style {:margin-bottom 20}
:network-tag-props {:title "Max: 200 SNT"
:networks [{:source (resources/get-network :ethereum)}]}
:approval-label-props
{:status :approve
:token-value "10"
:button-props {:on-press
#(js/alert "Approve Pressed")}
:customization-color (:customization-color state)
:token-symbol "SNT"})]
[quo/numbered-keyboard
{:left-action :dot
:delete-key? true
:on-press on-press
:on-delete delete}]]))
@@ -7,7 +7,6 @@
[react-native.safe-area :as safe-area]
[status-im.common.check-before-syncing.view :as check-before-syncing]
[status-im.common.confirmation-drawer.view :as confirmation-drawer]
[status-im.common.metrics-confirmation-modal.view :as metrics-modal]
[status-im.common.standard-authentication.core :as standard-authentication]
[status-im.config :as config]
[status-im.constants :as constants]
@@ -255,7 +254,6 @@
(defn view
[]
(rn/use-mount #(rf/dispatch [:centralized-metrics/check-modal metrics-modal/view]))
(let [[show-profiles? set-show-profiles] (rn/use-state false)
show-profiles (rn/use-callback #(set-show-profiles true))
hide-profiles (rn/use-callback #(set-show-profiles false))]
@@ -113,8 +113,7 @@
(defn view
[]
(let [view-id (rf/sub [:view-id])
profile-color (rf/sub [:profile/customization-color])
(let [profile-color (rf/sub [:profile/customization-color])
accounts-addresses (rf/sub [:wallet/addresses])
saved-addresses-addresses (rf/sub [:wallet/saved-addresses-addresses])
[address-or-ens set-address-or-ens] (rn/use-state "")
@@ -176,12 +175,11 @@
:on-press navigate-back
:margin-top (safe-area/get-top)
:accessibility-label :add-address-to-save-page-nav}]
:footer (when (= view-id :screen/settings.add-address-to-save)
[quo/button
{:customization-color profile-color
:disabled? button-disabled?
:on-press on-press-continue}
(i18n/label :t/continue)])}
:footer [quo/button
{:customization-color profile-color
:disabled? button-disabled?
:on-press on-press-continue}
(i18n/label :t/continue)]}
[quo/page-top
{:container-style style/header-container
:blur? true
@@ -121,8 +121,7 @@
:on-press on-press-save}
(i18n/label :t/save-address)]
:customization-color address-color
:gradient-cover? true
:shell-overlay? true}
:gradient-cover? true}
[quo/wallet-user-avatar
{:full-name (if (string/blank? address-label)
placeholder
@@ -1,18 +0,0 @@
(ns status-im.contexts.shell.activity-center.context
(:require
["react" :as react]
[oops.core :as oops]
[react-native.core :as rn]))
(defonce ^:private context
(react/createContext {}))
(defn provider
[state & children]
(into [:> (oops/oget context :Provider) {:value state}]
children))
(defn use-context
[]
(let [ctx (rn/use-context context)]
{:active-swipeable (oops/oget ctx :activeSwipeable)}))
@@ -15,7 +15,10 @@
(def defaults
{:filter-status :unread
:filter-type types/no-type
:notifications-per-page constants/notifications-per-page})
;; Choose the maximum number of notifications that *usually/safely* fit on
;; most screens, so that the UI doesn't have to needlessly render
;; notifications.
:notifications-per-page 8})
;;;; Navigation
@@ -1,7 +1,6 @@
(ns status-im.contexts.shell.activity-center.notification.admin.view
(:require
[quo.core :as quo]
[react-native.core :as rn]
[status-im.constants :as constants]
[status-im.contexts.shell.activity-center.notification.common.style :as common-style]
[status-im.contexts.shell.activity-center.notification.common.view :as common]
@@ -24,50 +23,42 @@
:text (i18n/label :t/decline)}])
(defn- swipeable
[{:keys [notification extra-fn]} child]
(let [{:keys [community-id id
membership-status]} notification
accept (rn/use-callback
(fn []
(rf/dispatch [:communities/accept-request-to-join-pressed
community-id id]))
[community-id id])
decline (rn/use-callback
(fn []
(rf/dispatch [:communities/decline-request-to-join-pressed
community-id id]))
[community-id id])]
[{:keys [active-swipeable notification extra-fn]} child]
(let [{:keys [community-id id membership-status]} notification]
(cond
(#{constants/activity-center-membership-status-accepted
constants/activity-center-membership-status-declined}
membership-status)
[common/swipeable
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:extra-fn extra-fn}
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:active-swipeable active-swipeable
:extra-fn extra-fn}
child]
(= membership-status constants/activity-center-membership-status-pending)
[common/swipeable
{:left-button swipe-button-accept
:left-on-press accept
:right-button swipe-button-decline
:right-on-press decline
:extra-fn extra-fn}
{:left-button swipe-button-accept
:left-on-press #(rf/dispatch [:communities/accept-request-to-join-pressed community-id id])
:right-button swipe-button-decline
:right-on-press #(rf/dispatch [:communities/decline-request-to-join-pressed community-id
id])
:active-swipeable active-swipeable
:extra-fn extra-fn}
child]
:else
child)))
(defn view
[{:keys [notification] :as props}]
[{:keys [notification set-swipeable-height customization-color] :as props}]
(let [{:keys [author community-id id membership-status
read timestamp]} notification
community-name (rf/sub [:communities/name community-id])
community-logo (rf/sub [:communities/logo community-id])
customization-color (rf/sub [:profile/customization-color])]
community (rf/sub [:communities/community community-id])
community-name (:name community)
community-image (get-in community [:images :thumbnail :uri])]
[swipeable props
[quo/activity-log
{:title (i18n/label :t/join-request)
@@ -75,13 +66,14 @@
:icon :i/add-user
:timestamp (datetime/timestamp->relative timestamp)
:unread? (not read)
:on-layout set-swipeable-height
:context [[common/user-avatar-tag author]
(i18n/label :t/wants-to-join)
[quo/context-tag
{:type :community
:size 24
:blur? true
:community-logo community-logo
:community-logo community-image
:community-name community-name}]]
:items (condp = membership-status
constants/activity-center-membership-status-accepted
@@ -4,7 +4,6 @@
(def swipe-action-width 80)
(def swipe-button-border-radius 16)
(def swipe-button-margin 8)
(def user-avatar-tag
{:background-color colors/white-opa-10})
@@ -1,12 +1,10 @@
(ns status-im.contexts.shell.activity-center.notification.common.view
(:require
[oops.core :as oops]
[quo.core :as quo]
[quo.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.gesture :as gesture]
[status-im.contexts.profile.utils :as profile.utils]
[status-im.contexts.shell.activity-center.context :as ac.context]
[status-im.contexts.shell.activity-center.notification.common.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -16,7 +14,7 @@
(let [profile (rf/sub [:contacts/contact-by-identity user-id])]
[rn/view
{:on-start-should-set-responder
(fn []
(fn [_event]
(rf/dispatch [:navigate-back])
(rf/dispatch [:chat.ui/show-profile user-id])
true)}
@@ -35,27 +33,35 @@
swipe-button
swipeable-ref
style]}]
(fn [_ drag-x]
(let [extra (extra-fn)
opacity (oops/ocall drag-x :interpolate interpolation-opacity)
translate-x (oops/ocall drag-x :interpolate interpolation-translate-x)]
(fn [_ ^js drag-x]
(let [{:keys [height] :as extra} (extra-fn)
opacity (.interpolate drag-x interpolation-opacity)
translate-x (.interpolate drag-x interpolation-translate-x)]
[gesture/rect-button
{:style (merge {:border-radius style/swipe-button-border-radius} style)
:accessibility-label :notification-swipe-action-button
:on-press (fn []
(when @swipeable-ref
(oops/ocall @swipeable-ref :close)
(.close ^js @swipeable-ref)
(reset! active-swipeable nil))
(on-press extra))}
[swipe-button
{:style {:opacity opacity
:transform [{:translateX translate-x}]
:flex 1
:height height
:width style/swipe-action-width}}
extra]])))
(defn- close-active-swipeable
[active-swipeable swipeable]
(fn [_]
(when (and @active-swipeable
(not= @active-swipeable @swipeable))
(.close ^js @active-swipeable))
(reset! active-swipeable @swipeable)))
(defn swipe-button-container
[{:keys [style icon text]}]
[{:keys [style icon text]} _]
[rn/animated-view
{:accessibility-label :notification-swipe
:style style}
@@ -97,54 +103,47 @@
(rf/dispatch [:activity-center.notifications/delete (:id notification)]))
(defn swipeable
[{:keys [extra-fn
left-button
left-on-press
right-button
right-on-press]}
child]
(let [{:keys [active-swipeable]} (ac.context/use-context)
this-swipeable (rn/use-ref-atom nil)
set-this-swipeable (rn/use-callback #(reset! this-swipeable %)
[this-swipeable])
on-swipeable-will-open (rn/use-callback
(fn []
(when (and @active-swipeable
(not= @active-swipeable @this-swipeable))
(oops/ocall @active-swipeable :close))
(reset! active-swipeable @this-swipeable))
[@active-swipeable @this-swipeable])]
[gesture/swipeable
(cond-> {:ref set-this-swipeable
:accessibility-label :notification-swipeable
:friction 2
:on-swipeable-will-open on-swipeable-will-open
:children-container-style {:padding-horizontal 20}}
left-button
(assoc :overshoot-left false
:left-threshold style/swipe-action-width
:render-left-actions (render-swipe-action
{:active-swipeable active-swipeable
:extra-fn extra-fn
:interpolation-opacity style/left-swipe-opacity-interpolation-js
:interpolation-translate-x
style/left-swipe-translate-x-interpolation-js
:on-press left-on-press
:swipe-button left-button
:swipeable-ref this-swipeable
:style {:left style/swipe-button-margin}}))
right-button
(assoc :overshoot-right false
:right-threshold style/swipe-action-width
:render-right-actions (render-swipe-action
{:active-swipeable active-swipeable
:extra-fn extra-fn
:interpolation-opacity style/right-swipe-opacity-interpolation-js
:interpolation-translate-x
style/right-swipe-translate-x-interpolation-js
:on-press right-on-press
:swipe-button right-button
:swipeable-ref this-swipeable
:style {:right (- style/swipe-button-margin)}})))
child]))
[_]
(let [swipeable-ref (atom nil)]
(fn [{:keys [active-swipeable
extra-fn
left-button
left-on-press
right-button
right-on-press]}
& children]
(into
[gesture/swipeable
(merge
{:ref #(reset! swipeable-ref %)
:accessibility-label :notification-swipeable
:friction 2
:on-swipeable-will-open (close-active-swipeable active-swipeable swipeable-ref)
:children-container-style {:padding-horizontal 20}}
(when left-button
{:overshoot-left false
:left-threshold style/swipe-action-width
:render-left-actions (render-swipe-action
{:active-swipeable active-swipeable
:extra-fn extra-fn
:interpolation-opacity style/left-swipe-opacity-interpolation-js
:interpolation-translate-x
style/left-swipe-translate-x-interpolation-js
:on-press left-on-press
:swipe-button left-button
:swipeable-ref swipeable-ref
:style {:left 8}})})
(when right-button
{:overshoot-right false
:right-threshold style/swipe-action-width
:render-right-actions (render-swipe-action
{:active-swipeable active-swipeable
:extra-fn extra-fn
:interpolation-opacity style/right-swipe-opacity-interpolation-js
:interpolation-translate-x
style/right-swipe-translate-x-interpolation-js
:on-press right-on-press
:swipe-button right-button
:swipeable-ref swipeable-ref
:style {:right -8}})}))]
children))))
@@ -1,7 +1,6 @@
(ns status-im.contexts.shell.activity-center.notification.community-kicked.view
(:require
[quo.core :as quo]
[react-native.core :as rn]
[react-native.gesture :as gesture]
[status-im.contexts.shell.activity-center.notification.common.style :as common-style]
[status-im.contexts.shell.activity-center.notification.common.view :as common]
@@ -10,34 +9,33 @@
[utils.re-frame :as rf]))
(defn- swipeable
[{:keys [extra-fn]} child]
[{:keys [active-swipeable extra-fn]} child]
[common/swipeable
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:extra-fn extra-fn}
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:active-swipeable active-swipeable
:extra-fn extra-fn}
child])
(defn view
[{:keys [notification extra-fn]}]
(let [{:keys [id community-id read
[{:keys [notification set-swipeable-height customization-color] :as props}]
(let [{:keys [community-id read
timestamp]} notification
community (rf/sub [:communities/community community-id])
community-name (:name community)
community-image (get-in community [:images :thumbnail :uri])
customization-color (rf/sub [:profile/customization-color])
on-press (rn/use-callback
(fn []
(rf/dispatch [:navigate-back])
(rf/dispatch [:activity-center.notifications/mark-as-read id]))
[id])]
[swipeable {:extra-fn extra-fn}
[gesture/touchable-without-feedback {:on-press on-press}
community-image (get-in community [:images :thumbnail :uri])]
[swipeable props
[gesture/touchable-without-feedback
{:on-press (fn []
(rf/dispatch [:navigate-back])
(rf/dispatch [:activity-center.notifications/mark-as-read (:id notification)]))}
[quo/activity-log
{:title (i18n/label :t/community-kicked-heading)
:customization-color customization-color
:icon :i/placeholder
:on-layout set-swipeable-height
:timestamp (datetime/timestamp->relative timestamp)
:unread? (not read)
:context [[quo/text {:style common-style/user-avatar-tag-text}
@@ -1,7 +1,6 @@
(ns status-im.contexts.shell.activity-center.notification.community-request.view
(:require
[quo.core :as quo]
[react-native.core :as rn]
[react-native.gesture :as gesture]
[status-im.constants :as constants]
[status-im.contexts.shell.activity-center.notification.common.style :as common-style]
@@ -11,23 +10,27 @@
[utils.re-frame :as rf]))
(defn- swipeable
[{:keys [extra-fn]} child]
[{:keys [active-swipeable extra-fn]} child]
[common/swipeable
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:extra-fn extra-fn}
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:active-swipeable active-swipeable
:extra-fn extra-fn}
child])
(defn- get-header-text-and-context
[community-logo community-name community-permissions membership-status]
(let [open? (not= 3 (:access community-permissions))
[community membership-status]
(let [community-name (:name community)
permissions (:permissions community)
open? (not= 3 (:access permissions))
community-image (get-in community [:images :thumbnail :uri])
community-context-tag [quo/context-tag
{:type :community
:size 24
:blur? true
:community-logo community-logo
:community-logo community-image
:community-name community-name}]]
(cond
(= membership-status constants/activity-center-membership-status-idle)
@@ -53,33 +56,27 @@
:t/joined-community
:t/community-request-accepted-body-text)
(when open? {:community community-name}))]
community-context-tag]})))
community-context-tag]}
:else nil)))
(defn view
[{:keys [notification extra-fn]}]
[{:keys [notification set-swipeable-height customization-color] :as props}]
(let [{:keys [community-id membership-status read
timestamp]} notification
community-name (rf/sub [:communities/name community-id])
community-logo (rf/sub [:communities/logo community-id])
community-permissions (rf/sub [:communities/permissions community-id])
customization-color (rf/sub [:profile/customization-color])
{:keys [header-text
context]} (get-header-text-and-context community-logo
community-name
community-permissions
membership-status)
on-press (rn/use-callback
(fn []
(rf/dispatch [:navigate-back])
(rf/dispatch [:communities/navigate-to-community-overview
community-id]))
[community-id])]
[swipeable {:extra-fn extra-fn}
[gesture/touchable-without-feedback {:on-press on-press}
timestamp]} notification
community (rf/sub [:communities/community community-id])
{:keys [header-text context]} (get-header-text-and-context community
membership-status)]
[swipeable props
[gesture/touchable-without-feedback
{:on-press (fn []
(rf/dispatch [:navigate-back])
(rf/dispatch [:communities/navigate-to-community-overview community-id]))}
[quo/activity-log
{:title header-text
:customization-color customization-color
:icon :i/communities
:on-layout set-swipeable-height
:timestamp (datetime/timestamp->relative timestamp)
:unread? (not read)
:context context}]]]))
@@ -1,7 +1,6 @@
(ns status-im.contexts.shell.activity-center.notification.contact-requests.view
(:require
[quo.core :as quo]
quo.theme
[react-native.core :as rn]
[status-im.constants :as constants]
[status-im.contexts.shell.activity-center.notification.common.style :as common-style]
@@ -25,52 +24,48 @@
:text (i18n/label :t/decline)}])
(defn- swipeable
[{:keys [extra-fn notification]} child]
[{:keys [active-swipeable extra-fn notification]} child]
(let [{:keys [id author message]} notification
{:keys [contact-request-state]} message
{:keys [public-key]} (rf/sub [:multiaccount/contact])
outgoing? (= public-key author)
accept (rn/use-callback
#(rf/dispatch [:activity-center.contact-requests/accept id])
[id])
decline (rn/use-callback
#(rf/dispatch [:activity-center.contact-requests/decline id])
[id])]
outgoing? (= public-key author)]
(cond
(or (#{constants/contact-request-message-state-accepted
constants/contact-request-message-state-declined}
contact-request-state)
(and outgoing? (= contact-request-state constants/contact-request-message-state-pending)))
[common/swipeable
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:extra-fn extra-fn}
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:active-swipeable active-swipeable
:extra-fn extra-fn}
child]
(and (= contact-request-state constants/contact-request-message-state-pending)
(not outgoing?))
[common/swipeable
{:left-button swipe-button-accept
:left-on-press accept
:right-button swipe-button-decline
:right-on-press decline
:extra-fn extra-fn}
{:left-button swipe-button-accept
:left-on-press #(rf/dispatch [:activity-center.contact-requests/accept id])
:right-button swipe-button-decline
:right-on-press #(rf/dispatch [:activity-center.contact-requests/decline id])
:active-swipeable active-swipeable
:extra-fn extra-fn}
child]
:else
child)))
(defn- outgoing-contact-request-view
[{:keys [notification]} theme]
[{:keys [notification set-swipeable-height customization-color]} theme]
(let [{:keys [chat-id message last-message accepted]} notification
{:keys [contact-request-state] :as message} (or message last-message)
customization-color (rf/sub [:profile/customization-color])]
{:keys [contact-request-state] :as message} (or message last-message)]
(if accepted
[quo/activity-log
{:title (i18n/label :t/contact-request-was-accepted)
:customization-color customization-color
:on-layout set-swipeable-height
:icon :i/add-user
:timestamp (datetime/timestamp->relative (:timestamp notification))
:unread? (not (:read notification))
@@ -81,6 +76,7 @@
[quo/activity-log
{:title (i18n/label :t/contact-request)
:customization-color customization-color
:on-layout set-swipeable-height
:icon :i/add-user
:timestamp (datetime/timestamp->relative (:timestamp notification))
:unread? (not (:read notification))
@@ -106,22 +102,13 @@
nil)}])))
(defn- incoming-contact-request-view
[{:keys [notification]} theme]
(let [{:keys [id author message
last-message]} notification
customization-color (rf/sub [:profile/customization-color])
message (or message last-message)
accept (rn/use-callback
(fn []
(rf/dispatch [:activity-center.contact-requests/accept id]))
[id])
decline (rn/use-callback
(fn []
(rf/dispatch [:activity-center.contact-requests/decline id]))
[id])]
[{:keys [notification set-swipeable-height customization-color]} theme]
(let [{:keys [id author message last-message]} notification
message (or message last-message)]
[quo/activity-log
{:title (i18n/label :t/contact-request)
:customization-color customization-color
:on-layout set-swipeable-height
:icon :i/add-user
:timestamp (datetime/timestamp->relative (:timestamp notification))
:unread? (not (:read notification))
@@ -153,13 +140,13 @@
:key :button-decline
:label (i18n/label :t/decline)
:accessibility-label :decline-contact-request
:on-press decline}
:on-press #(rf/dispatch [:activity-center.contact-requests/decline id])}
{:type :button
:subtype :positive
:key :button-accept
:label (i18n/label :t/accept)
:accessibility-label :accept-contact-request
:on-press accept}]
:on-press #(rf/dispatch [:activity-center.contact-requests/accept id])}]
nil)}]))
@@ -168,16 +155,16 @@
(let [{:keys [author message last-message]} notification
{:keys [public-key]} (rf/sub [:multiaccount/contact])
{:keys [contact-request-state]} (or message last-message)
theme (quo.theme/use-theme)]
app-theme (rf/sub [:theme])]
[swipeable props
(cond
(= public-key author)
[outgoing-contact-request-view props theme]
[outgoing-contact-request-view props app-theme]
(= contact-request-state constants/contact-request-message-state-accepted)
[rn/pressable
{:on-press #(rf/dispatch [:chat.ui/start-chat author])}
[incoming-contact-request-view props theme]]
[incoming-contact-request-view props app-theme]]
:else
[incoming-contact-request-view props theme])]))
[incoming-contact-request-view props app-theme])]))
@@ -105,7 +105,7 @@
(rf/dispatch [:activity-center.notifications/mark-as-read id]))
(defn- swipeable
[{:keys [extra-fn notification replying?] :as props} child]
[{:keys [active-swipeable extra-fn notification replying?] :as props} child]
(let [{:keys [id message
contact-verification-status]} notification
challenger? (:outgoing message)]
@@ -116,21 +116,23 @@
(and (not challenger?)
(= contact-verification-status constants/contact-verification-status-pending))
[common/swipeable
{:left-button swipe-button-reply
:left-on-press #(prepare-challenge-reply props)
:right-button swipe-button-decline
:right-on-press #(decline-challenge id)
:extra-fn extra-fn}
{:left-button swipe-button-reply
:left-on-press #(prepare-challenge-reply props)
:right-button swipe-button-decline
:right-on-press #(decline-challenge id)
:active-swipeable active-swipeable
:extra-fn extra-fn}
child]
(and challenger?
(= contact-verification-status constants/contact-verification-status-accepted))
[common/swipeable
{:left-button swipe-button-trust
:left-on-press #(mark-challenge-trusted id)
:right-button swipe-button-untrustworthy
:right-on-press #(mark-challenge-untrustworthy id)
:extra-fn extra-fn}
{:left-button swipe-button-trust
:left-on-press #(mark-challenge-trusted id)
:right-button swipe-button-untrustworthy
:right-on-press #(mark-challenge-untrustworthy id)
:active-swipeable active-swipeable
:extra-fn extra-fn}
child]
(#{constants/contact-verification-status-accepted
@@ -138,11 +140,12 @@
constants/contact-verification-status-trusted}
contact-verification-status)
[common/swipeable
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:extra-fn extra-fn}
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:active-swipeable active-swipeable
:extra-fn extra-fn}
child]
:else
@@ -151,9 +154,8 @@
(defn view
[_]
(let [reply (atom "")]
(fn [{:keys [notification replying?] :as props}]
(let [customization-color (rf/sub [:profile/customization-color])
{:keys [id message
(fn [{:keys [notification set-swipeable-height replying? customization-color] :as props}]
(let [{:keys [id message
contact-verification-status]} notification
challenger? (:outgoing message)]
;; TODO(@ilmotta): Declined challenges should only be displayed for the challengee, not the
@@ -163,84 +165,86 @@
(= contact-verification-status constants/contact-verification-status-declined))
[swipeable props
[quo/activity-log
{:title (i18n/label :t/identity-verification-request)
:customization-color customization-color
:icon :i/friend
:timestamp (datetime/timestamp->relative (:timestamp notification))
:unread? (not (:read notification))
:on-update-reply #(reset! reply %)
:replying? replying?
:max-reply-length max-reply-length
:valid-reply? valid-reply?
:context (context-tags challenger? notification)
:message (activity-message challenger? notification)
:items
(cond-> []
(and challenger?
(= contact-verification-status constants/contact-verification-status-accepted))
(concat
[{:type :button
:subtype :danger
:key :button-mark-as-untrustworthy
:label (i18n/label :t/untrustworthy)
:accessibility-label :mark-contact-verification-as-untrustworthy
:on-press #(mark-challenge-untrustworthy id)}
{:type :button
:subtype :positive
:key :button-accept
:label (i18n/label :t/accept)
:accessibility-label :mark-contact-verification-as-trusted
:on-press #(mark-challenge-trusted id)}])
(merge
(when-not replying?
{:on-layout set-swipeable-height})
{:title (i18n/label :t/identity-verification-request)
:customization-color customization-color
:icon :i/friend
:timestamp (datetime/timestamp->relative (:timestamp notification))
:unread? (not (:read notification))
:on-update-reply #(reset! reply %)
:replying? replying?
:max-reply-length max-reply-length
:valid-reply? valid-reply?
:context (context-tags challenger? notification)
:message (activity-message challenger? notification)
:items
(cond-> []
(and challenger?
(= contact-verification-status constants/contact-verification-status-accepted))
(concat
[{:type :button
:subtype :danger
:key :button-mark-as-untrustworthy
:label (i18n/label :t/untrustworthy)
:accessibility-label :mark-contact-verification-as-untrustworthy
:on-press #(mark-challenge-untrustworthy id)}
{:type :button
:subtype :positive
:key :button-accept
:label (i18n/label :t/accept)
:accessibility-label :mark-contact-verification-as-trusted
:on-press #(mark-challenge-trusted id)}])
(and challenger?
(= contact-verification-status constants/contact-verification-status-trusted))
(concat [{:type :status
:subtype :positive
:key :status-trusted
:label (i18n/label :t/status-confirmed)}])
(and challenger?
(= contact-verification-status constants/contact-verification-status-trusted))
(concat [{:type :status
:subtype :positive
:key :status-trusted
:label (i18n/label :t/status-confirmed)}])
(and challenger?
(= contact-verification-status
constants/contact-verification-status-untrustworthy))
(concat [{:type :status
:subtype :negative
:key :status-untrustworthy
:label (i18n/label :t/untrustworthy)}])
(and challenger?
(= contact-verification-status constants/contact-verification-status-untrustworthy))
(concat [{:type :status
:subtype :negative
:key :status-untrustworthy
:label (i18n/label :t/untrustworthy)}])
(and (not challenger?)
(= contact-verification-status constants/contact-verification-status-accepted))
(concat [{:type :status
:subtype :positive
:key :status-accepted
:label (i18n/label :t/replied)}])
(and (not challenger?)
(= contact-verification-status constants/contact-verification-status-accepted))
(concat [{:type :status
:subtype :positive
:key :status-accepted
:label (i18n/label :t/replied)}])
(and (not challenger?)
(= contact-verification-status constants/contact-verification-status-declined))
(concat [{:type :status
:subtype :negative
:key :status-declined
:label (i18n/label :t/declined)}])
(and (not challenger?)
(= contact-verification-status constants/contact-verification-status-declined))
(concat [{:type :status
:subtype :negative
:key :status-declined
:label (i18n/label :t/declined)}])
(and (not challenger?)
(= contact-verification-status constants/contact-verification-status-pending))
(concat
[{:type :button
:subtype :danger
:key :button-decline
:label (i18n/label :t/decline)
:accessibility-label :decline-contact-verification
:on-press #(decline-challenge id)}
(if replying?
{:type :button
:subtype :primary
:key :button-reply
:label (i18n/label :t/send-reply)
:accessibility-label :reply-to-contact-verification
:disable-when invalid-reply?
:on-press #(send-challenge-reply id @reply)}
{:type :button
:subtype :primary
:key :button-send-reply
:label (i18n/label :t/message-reply)
:accessibility-label :send-reply-to-contact-verification
:on-press #(prepare-challenge-reply props)})]))}]])))))
(and (not challenger?)
(= contact-verification-status constants/contact-verification-status-pending))
(concat
[{:type :button
:subtype :danger
:key :button-decline
:label (i18n/label :t/decline)
:accessibility-label :decline-contact-verification
:on-press #(decline-challenge id)}
(if replying?
{:type :button
:subtype :primary
:key :button-reply
:label (i18n/label :t/send-reply)
:accessibility-label :reply-to-contact-verification
:disable-when invalid-reply?
:on-press #(send-challenge-reply id @reply)}
{:type :button
:subtype :primary
:key :button-send-reply
:label (i18n/label :t/message-reply)
:accessibility-label :send-reply-to-contact-verification
:on-press #(prepare-challenge-reply props)})]))})]])))))
@@ -1,7 +1,6 @@
(ns status-im.contexts.shell.activity-center.notification.membership.view
(:require
[quo.core :as quo]
[react-native.core :as rn]
[react-native.gesture :as gesture]
[status-im.contexts.shell.activity-center.notification.common.style :as common-style]
[status-im.contexts.shell.activity-center.notification.common.view :as common]
@@ -34,50 +33,35 @@
:text (i18n/label :t/decline)}])
(defn- swipeable
[{:keys [notification extra-fn]} child]
(let [{:keys [accepted dismissed
id]} notification
accept (rn/use-callback
(fn [] (rf/dispatch [:activity-center.notifications/accept id]))
[id])
dismiss (rn/use-callback
(fn [] (rf/dispatch [:activity-center.notifications/dismiss id]))
[id])]
[{:keys [active-swipeable notification extra-fn]} child]
(let [{:keys [accepted dismissed id]} notification]
(if (or accepted dismissed)
[common/swipeable
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:extra-fn extra-fn}
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:active-swipeable active-swipeable
:extra-fn extra-fn}
child]
[common/swipeable
{:left-button swipe-button-accept
:left-on-press accept
:right-button swipe-button-decline
:right-on-press dismiss
:extra-fn extra-fn}
{:left-button swipe-button-accept
:left-on-press #(rf/dispatch [:activity-center.notifications/accept id])
:right-button swipe-button-decline
:right-on-press #(rf/dispatch [:activity-center.notifications/dismiss id])
:active-swipeable active-swipeable
:extra-fn extra-fn}
child])))
(defn view
[{:keys [notification] :as props}]
(let [{:keys [id accepted dismissed author read
timestamp chat-name
chat-id]} notification
customization-color (rf/sub [:profile/customization-color])
accept (rn/use-callback
(fn []
(rf/dispatch [:activity-center.notifications/accept id]))
[id])
dismiss (rn/use-callback
(fn []
(rf/dispatch [:activity-center.notifications/dismiss id]))
[id])]
[{:keys [notification set-swipeable-height customization-color] :as props}]
(let [{:keys [id accepted dismissed author read timestamp chat-name chat-id]} notification]
[swipeable props
[pressable {:accepted accepted :chat-id chat-id}
[quo/activity-log
{:title (i18n/label :t/added-to-group-chat)
:customization-color customization-color
:on-layout set-swipeable-height
:icon :i/add-user
:timestamp (datetime/timestamp->relative timestamp)
:unread? (not read)
@@ -94,10 +78,13 @@
:key :button-accept
:label (i18n/label :t/accept)
:accessibility-label :accept-group-chat-invitation
:on-press accept}
:on-press #(rf/dispatch
[:activity-center.notifications/accept id])}
{:type :button
:subtype :danger
:key :button-decline
:label (i18n/label :t/decline)
:accessibility-label :decline-group-chat-invitation
:on-press dismiss}])}]]]))
:on-press #(rf/dispatch
[:activity-center.notifications/dismiss
id])}])}]]]))
@@ -30,24 +30,25 @@
parsed-text-children))))
(defn- swipeable
[{:keys [extra-fn]} child]
[{:keys [active-swipeable extra-fn]} child]
[common/swipeable
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:extra-fn extra-fn}
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:active-swipeable active-swipeable
:extra-fn extra-fn}
child])
(defn view
[{:keys [notification extra-fn]}]
[{:keys [notification set-swipeable-height customization-color] :as props}]
(let [{:keys [author chat-name community-id chat-id
message read timestamp]} notification
community-chat? (not (string/blank? community-id))
community-name (rf/sub [:communities/name community-id])
community-logo (rf/sub [:communities/logo community-id])
customization-color (rf/sub [:profile/customization-color])]
[swipeable {:extra-fn extra-fn}
community (rf/sub [:communities/community community-id])
community-name (:name community)
community-image (get-in community [:images :thumbnail :uri])]
[swipeable props
[gesture/touchable-without-feedback
{:on-press (fn []
(rf/dispatch [:hide-popover])
@@ -55,6 +56,7 @@
[quo/activity-log
{:title (i18n/label :t/mention)
:customization-color customization-color
:on-layout set-swipeable-height
:icon :i/mention
:timestamp (datetime/timestamp->relative timestamp)
:unread? (not read)
@@ -66,7 +68,7 @@
{:type :channel
:blur? true
:size 24
:community-logo community-logo
:community-logo community-image
:community-name community-name
:channel-name chat-name}]
[quo/context-tag
@@ -51,26 +51,26 @@
nil))
(defn- swipeable
[{:keys [extra-fn]} child]
[{:keys [active-swipeable extra-fn]} child]
[common/swipeable
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:extra-fn extra-fn}
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:active-swipeable active-swipeable
:extra-fn extra-fn}
child])
(defn view
[{:keys [notification extra-fn]}]
[{:keys [notification set-swipeable-height customization-color] :as props}]
(let [{:keys [author chat-name community-id chat-id
message read timestamp
album-messages]} notification
community-chat? (not (string/blank? community-id))
community-name (rf/sub [:communities/name community-id])
community-logo (rf/sub [:communities/logo community-id])
customization-color (rf/sub [:profile/customization-color])
media-server-port (rf/sub [:mediaserver/port])]
[swipeable {:extra-fn extra-fn}
message read timestamp album-messages]} notification
community-chat? (not (string/blank? community-id))
community (rf/sub [:communities/community community-id])
community-name (:name community)
community-image (get-in community [:images :thumbnail :uri])
media-server-port (rf/sub [:mediaserver/port])]
[swipeable props
[gesture/touchable-without-feedback
{:on-press (fn []
(rf/dispatch [:hide-popover])
@@ -78,6 +78,7 @@
[quo/activity-log
{:title (i18n/label :t/message-reply)
:customization-color customization-color
:on-layout set-swipeable-height
:icon :i/reply
:timestamp (datetime/timestamp->relative timestamp)
:unread? (not read)
@@ -88,7 +89,7 @@
{:type :channel
:blur? true
:size 24
:community-logo community-logo
:community-logo community-image
:community-name community-name
:channel-name chat-name}]
[quo/context-tag
@@ -112,7 +113,10 @@
(= (:content-type message)
constants/content-type-gif)
:gif)
:gif
:else
nil)
:body (get-message-content message
album-messages
media-server-port)}}]]]))
@@ -1,10 +1,9 @@
(ns status-im.contexts.shell.activity-center.view
(:require
[oops.core :as oops]
[quo.core :as quo]
[react-native.core :as rn]
[react-native.navigation :as navigation]
[status-im.constants :as constants]
[status-im.contexts.shell.activity-center.context :as ac.context]
[status-im.contexts.shell.activity-center.header.view :as header]
[status-im.contexts.shell.activity-center.notification-types :as types]
[status-im.contexts.shell.activity-center.notification.admin.view :as admin]
@@ -24,68 +23,61 @@
[utils.re-frame :as rf]))
(defn notification-component
[{:keys [type] :as notification} index]
(let [extra-fn (rn/use-callback
(fn []
{:notification notification})
[notification])
props {:notification notification
:extra-fn extra-fn}]
;; Notifications are expensive to render. Without `delay-render` the opening
;; animation of the Activity Center can be clunky and the time to open the
;; AC after pressing the bell icon can be high.
[rn/view {:style (style/notification-container index)}
(cond
(= type types/contact-verification)
[contact-verification/view props]
(= type types/contact-request)
[contact-requests/view props]
(= type types/mention)
[mentions/view props]
(= type types/reply)
[reply/view props]
(= type types/admin)
[admin/view props]
(some types/membership [type])
(condp = type
types/private-group-chat [membership/view props]
types/community-request [community-request/view props]
types/community-kicked [community-kicked/view props]
nil))]))
(defn- fetch-next-page
[]
(rf/dispatch [:activity-center.notifications/fetch-next-page]))
(let [height (atom 0)
set-swipeable-height #(reset! height (oops/oget % "nativeEvent.layout.height"))]
(fn [{:keys [type] :as notification} index _ {:keys [active-swipeable customization-color]}]
(let [props {:height height
:customization-color customization-color
:active-swipeable active-swipeable
:set-swipeable-height set-swipeable-height
:notification notification
:extra-fn (fn [] {:height @height :notification notification})}]
[rn/view {:style (style/notification-container index)}
(cond
(= type types/contact-verification)
[contact-verification/view props]
(= type types/contact-request)
[contact-requests/view props]
(= type types/mention)
[mentions/view props]
(= type types/reply)
[reply/view props]
(= type types/admin)
[admin/view props]
(some types/membership [type])
(condp = type
types/private-group-chat [membership/view props]
types/community-request [community-request/view props]
types/community-kicked [community-kicked/view props]
nil)
:else
nil)]))))
(defn view
[]
(let [notifications (rf/sub [:activity-center/notifications])
;; We globally control the active swipeable for all notifications
;; because when a swipe left/right gesture initiates, the previously
;; active swiped notification (if any) must be removed & closed with
;; animation.
active-swipeable (rn/use-ref-atom nil)]
(rn/use-mount
(fn []
(rf/dispatch [:activity-center.notifications/fetch-first-page])))
[ac.context/provider {:active-swipeable active-swipeable}
[quo/overlay {:type :shell}
[rn/view {:style {:flex 1 :padding-top (navigation/status-bar-height)}}
[header/header]
(rn/delay-render
[rn/flat-list
{:data notifications
:initial-num-to-render constants/notifications-per-page
:content-container-style {:flex-grow 1}
:empty-component [empty-tab/empty-tab]
:key-fn :id
:on-scroll-to-index-failed identity
:on-end-reached fetch-next-page
:render-fn notification-component}])]]]))
(let [active-swipeable (atom nil)]
(rf/dispatch [:activity-center.notifications/fetch-first-page])
(fn []
(let [notifications (rf/sub [:activity-center/notifications])
customization-color (rf/sub [:profile/customization-color])]
[quo/overlay {:type :shell}
[rn/view {:flex 1 :padding-top (navigation/status-bar-height)}
[header/header]
[rn/flat-list
{:data notifications
:render-data {:active-swipeable active-swipeable
:customization-color customization-color}
:content-container-style {:flex-grow 1}
:empty-component [empty-tab/empty-tab]
:key-fn :id
:on-scroll-to-index-failed identity
:on-end-reached #(rf/dispatch [:activity-center.notifications/fetch-next-page])
:render-fn notification-component}]]
]))))
@@ -117,14 +117,13 @@
(defn- f-internal-view
[]
(let [{:keys [keyboard-shown]} (hooks/use-keyboard)]
(rn/use-mount
(fn []
(when keyboard-shown
(rn/dismiss-keyboard!))))
[scan-qr-code/view
{:title (i18n/label :t/scan-qr)
:share-button? true
:on-success-scan on-qr-code-scanned}]))
[:<>
(when keyboard-shown
(rn/dismiss-keyboard!))
[scan-qr-code/view
{:title (i18n/label :t/scan-qr)
:share-button? true
:on-success-scan on-qr-code-scanned}]]))
(defn view
[]
@@ -4,19 +4,12 @@
[utils.re-frame :as rf]
[utils.transforms :as transforms]))
(defonce ^:private request-id-atom (atom 0))
(defn- get-unique-request-id
[]
(swap! request-id-atom inc)
@request-id-atom)
(rf/reg-event-fx
:wallet/fetch-activities-for-current-account
(fn [{:keys [db]}]
(let [address (-> db :wallet :current-viewing-account-address)
chain-ids (chain/chain-ids db)
request-id (get-unique-request-id)
request-id 0
filters {:period {:startTimestamp 0
:endTimestamp 0}
:types []
@@ -27,10 +20,9 @@
:filterOutAssets false
:filterOutCollectibles false}
offset 0
limit 50
limit 35
request-params [request-id [address] chain-ids filters offset limit]]
{:db (assoc-in db [:wallet :ui :activity-tab :request request-id] address)
:fx [[:json-rpc/call
{:fx [[:json-rpc/call
[{;; This method is deprecated and will be replaced by
;; "wallet_startActivityFilterSession"
;; https://github.com/status-im/status-mobile/issues/19864
@@ -40,31 +32,13 @@
{:event :wallet/fetch-activities-for-current-account
:params request-params}]}]]]})))
(def ^:private activity-transaction-id (comp hash :transaction))
(rf/reg-event-fx
:wallet/activity-filtering-for-current-account-done
(fn [{:keys [db]} [{:keys [message requestId]}]]
(let [address (get-in db [:wallet :ui :activity-tab :request requestId])
activities (->> message
(transforms/json->clj)
(:activities)
(cske/transform-keys transforms/->kebab-case-keyword))
activities-indexed (zipmap (map activity-transaction-id activities)
activities)]
{:db (assoc-in db [:wallet :activities address] activities-indexed)})))
(def ^:private nested-merge (partial merge-with merge))
(rf/reg-event-fx
:wallet/activities-filtering-entries-updated
(fn [{:keys [db]} [{:keys [message requestId]}]]
(let [address (get-in db [:wallet :ui :activity-tab :request requestId])
activities (->> message
(transforms/json->clj)
(cske/transform-keys transforms/->kebab-case-keyword))
activities-indexed (zipmap (map activity-transaction-id activities)
activities)]
{:db (-> db
(update-in [:wallet :ui :activity-tab :request] dissoc requestId)
(update-in [:wallet :activities address] nested-merge activities-indexed))})))
(fn [{:keys [db]} [{:keys [message]}]]
(let [address (-> db :wallet :current-viewing-account-address)
activities (->> message
(transforms/json->clj)
(:activities)
(cske/transform-keys transforms/->kebab-case-keyword))
sorted-activities (sort :timestamp activities)]
{:db (assoc-in db [:wallet :activities address] sorted-activities)})))
@@ -11,81 +11,31 @@
(defn send-and-receive-activity
[{:keys [transaction relative-date status sender recipient token amount network-name
network-logo token-id nft-url nft-name]}]
(if token-id
[quo/wallet-activity
{:transaction transaction
:timestamp relative-date
:status status
:counter 1
:first-tag {:size 24
:type :collectible
:collectible nft-url
:collectible-name (if (> amount 1)
(str amount " " nft-name)
nft-name)
:collectible-number token-id}
:second-tag-prefix :t/from
:second-tag {:type :address :address sender}
:third-tag-prefix :t/to
:third-tag {:type :address :address recipient}
:fourth-tag-prefix :t/via
:fourth-tag {:size 24
:type :network
:network-name network-name
:network-logo network-logo}
:blur? false}]
[quo/wallet-activity
{:transaction transaction
:timestamp relative-date
:status status
:counter 1
:first-tag {:size 24
:type :token
:token token
:amount amount}
:second-tag-prefix :t/from
:second-tag {:type :address :address sender}
:third-tag-prefix :t/to
:third-tag {:type :address :address recipient}
:fourth-tag-prefix :t/via
:fourth-tag {:size 24
:type :network
:network-name network-name
:network-logo network-logo}
:blur? false}]))
;; WIP to add the mint activity.
;(defn mint-activity
; [{:keys [transaction relative-date status recipient network-name
; network-logo nft-name nft-url token-id]}]
; [quo/wallet-activity
; {:transaction transaction
; :timestamp relative-date
; :status status
; :counter 1
; :first-tag {:size 24
; :type :collectible
; :collectible nft-url
; :collectible-name nft-name
; :collectible-number token-id}
; :second-tag-prefix :t/at
; :second-tag {:type :address :address recipient}
; :third-tag-prefix :t/to
; :third-tag {:type :address :address recipient}
; :fourth-tag-prefix :t/via
; :fourth-tag {:size 24
; :type :network
; :network-name network-name
; :network-logo network-logo}
; :blur? false}])
network-logo]}]
[quo/wallet-activity
{:transaction transaction
:timestamp relative-date
:status status
:counter 1
:first-tag {:size 24
:type :token
:token token
:amount amount}
:second-tag-prefix :t/from
:second-tag {:type :address :address sender}
:third-tag-prefix :t/to
:third-tag {:type :address :address recipient}
:fourth-tag-prefix :t/via
:fourth-tag {:size 24
:type :network
:network-name network-name
:network-logo network-logo}
:blur? false}])
(defn activity-item
[{:keys [transaction] :as activity}]
(case transaction
(:send :receive) [send-and-receive-activity activity]
;; WIP to add the mint activity.
;; :mint [mint-activity activity]
nil))
(defn view
@@ -307,14 +307,10 @@
:color color
:currency currency
:currency-symbol currency-symbol}))
calculated-tokens (map calculate-token tokens)]
calculated-tokens (map calculate-token tokens)
token-priority {"SNT" 1 "STT" 1 "ETH" 2 "DAI" 3}]
(sort-by (fn [token]
(let [fiat-value (get-in token [:values :fiat-unformatted-value])
priority (get constants/token-sort-priority (:token token) ##Inf)]
priority (get token-priority (:token token) 999)]
[(- fiat-value) priority]))
calculated-tokens)))
(defn sort-tokens
[tokens]
(let [priority #(get constants/token-sort-priority (:symbol %) ##Inf)]
(sort-by (juxt (comp - :balance) priority) tokens)))
@@ -172,20 +172,17 @@
(defn get-network-details
[chain-id]
(as-> chain-id $
(condp contains? $
#{constants/ethereum-mainnet-chain-id constants/ethereum-goerli-chain-id
constants/ethereum-sepolia-chain-id}
mainnet-network-details
(condp contains? chain-id
#{constants/ethereum-mainnet-chain-id constants/ethereum-goerli-chain-id
constants/ethereum-sepolia-chain-id}
mainnet-network-details
#{constants/arbitrum-mainnet-chain-id constants/arbitrum-goerli-chain-id
constants/arbitrum-sepolia-chain-id}
arbitrum-network-details
#{constants/arbitrum-mainnet-chain-id constants/arbitrum-goerli-chain-id
constants/arbitrum-sepolia-chain-id}
arbitrum-network-details
#{constants/optimism-mainnet-chain-id constants/optimism-goerli-chain-id
constants/optimism-sepolia-chain-id}
optimism-network-details
#{constants/optimism-mainnet-chain-id constants/optimism-goerli-chain-id
constants/optimism-sepolia-chain-id}
optimism-network-details
nil)
(when $
(assoc $ :chain-id chain-id))))
nil))
@@ -149,14 +149,5 @@
expected-order ["DAI" "ETH" "SNT"]]
(is (= expected-order sorted-tokens))))))))
(deftest sort-tokens-test
(testing "sort-tokens function"
(let [mock-tokens [{:symbol "ETH" :balance 5}
{:symbol "DAI" :balance 10}
{:symbol "SNT" :balance 1}]
sorted-tokens (map :symbol (utils/sort-tokens mock-tokens))
expected-order ["DAI" "ETH" "SNT"]]
(is (= expected-order sorted-tokens)))))
@@ -1,16 +1,16 @@
(ns status-im.contexts.wallet.connected-dapps.view
(:require
[quo.core :as quo]
[quo.foundations.colors :as colors]
[quo.theme]
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[status-im.common.plus-button.view :as plus-button]
[status-im.common.resources :as resources]
[status-im.contexts.wallet.connected-dapps.disconnect-dapp.view :as disconnect-dapp]
[status-im.contexts.wallet.connected-dapps.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
[quo.core :as quo]
[quo.foundations.colors :as colors]
[quo.theme]
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[status-im.common.plus-button.view :as plus-button]
[status-im.common.resources :as resources]
[status-im.contexts.wallet.connected-dapps.disconnect-dapp.view :as disconnect-dapp]
[status-im.contexts.wallet.connected-dapps.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- on-disconnect
[wallet-account {:keys [name topic]}]
@@ -19,6 +19,7 @@
[:wallet-connect/disconnect-dapp
{:topic topic
:on-success (fn []
(rf/dispatch [:wallet-connect/remove-pairing-by-topic topic])
(rf/dispatch [:toasts/upsert
{:id :dapp-disconnect-success
:type :positive
@@ -82,8 +83,7 @@
[]
(let [{:keys [bottom]} (safe-area/get-insets)
{:keys [color] :as wallet-account} (rf/sub [:wallet/current-viewing-account])
sessions (rf/sub
[:wallet-connect/sessions-for-current-account])
pairings (rf/sub [:wallet-connect/pairings])
theme (quo.theme/use-theme)]
[rn/view {:flex 1}
[header
@@ -91,7 +91,7 @@
:wallet-account wallet-account
:on-close #(rf/dispatch [:navigate-back])
:on-add #(rf/dispatch [:navigate-to :screen/wallet.scan-dapp])}]
(if (empty? sessions)
(if (empty? pairings)
[quo/empty-state
{:title (i18n/label :t/no-dapps)
:description (i18n/label :t/no-dapps-description)
@@ -99,16 +99,16 @@
:container-style style/empty-container-style}]
[rn/view (style/dapps-container bottom)
[rn/flat-list
{:data sessions
{:data pairings
:always-bounce-vertical false
:content-container-style (style/dapps-list theme)
:render-fn (fn [{:keys [topic pairingTopic name url iconUrl]}]
:render-fn (fn [{:keys [topic]
{:keys [icons name url]} :peerMetadata}]
[quo/dapp
{:dapp {:avatar iconUrl
:name name
:value url
:topic topic
:pairing-topic pairingTopic}
{:dapp {:avatar (get icons 0)
:name name
:value url
:topic topic}
:accessibility-label (str "dapp-" topic)
:state :default
:action :icon
@@ -187,8 +187,15 @@
(rf/reg-event-fx
:wallet/update-receiver-networks
(fn [{:keys [db]} [selected-networks]]
(let [amount (get-in db [:wallet :ui :send :amount])]
{:db (assoc-in db [:wallet :ui :send :receiver-networks] selected-networks)
(let [amount (get-in db [:wallet :ui :send :amount])
disabled-from-chain-ids (get-in db [:wallet :ui :send :disabled-from-chain-ids])
filtered-disabled-from-chain-ids (filter (fn [chain-id]
(some #(= chain-id %)
selected-networks))
disabled-from-chain-ids)]
{:db (-> db
(assoc-in [:wallet :ui :send :receiver-networks] selected-networks)
(assoc-in [:wallet :ui :send :disabled-from-chain-ids] filtered-disabled-from-chain-ids))
:fx [[:dispatch [:wallet/get-suggested-routes {:amount amount}]]]})))
(rf/reg-event-fx
@@ -23,6 +23,19 @@
selected-networks-after [:ethereum :optimism]
expected-db {:wallet {:ui {:send {:receiver-networks selected-networks-after}}}}]
(reset! rf-db/app-db {:wallet {:ui {:send {:receiver-networks selected-networks-before}}}})
(is (match? expected-db (:db (dispatch [event-id selected-networks-after]))))))
(testing "if receiver network removed, it is also removed from disabled ones"
(let [selected-networks-before [:ethereum :optimism :arbitrum]
selected-networks-after [:ethereum :optimism]
disabled-from-chain-ids-before [:optimism :arbitrum]
disabled-from-chain-ids-after [:optimism]
expected-db {:wallet {:ui {:send {:receiver-networks selected-networks-after
:disabled-from-chain-ids
disabled-from-chain-ids-after}}}}]
(reset! rf-db/app-db {:wallet {:ui {:send {:receiver-networks selected-networks-before
:disabled-from-chain-ids
disabled-from-chain-ids-before}}}})
(is (match? expected-db (:db (dispatch [event-id selected-networks-after])))))))
(h/deftest-event :wallet/set-token-to-send
@@ -120,7 +120,7 @@
[]
[quo/alert-banner
{:action? true
:text (i18n/label :t/not-enough-assets-to-pay-gas-fees)
:text (i18n/label :t/not-enough-assets)
:button-text (i18n/label :t/buy-eth)
:on-button-press #(rf/dispatch [:show-bottom-sheet
{:content buy-token/view}])}])
@@ -154,9 +154,11 @@
[input-state set-input-state] (rn/use-state controlled-input/init-state)
[just-toggled-mode? set-just-toggled-mode?] (rn/use-state false)
clear-input! #(set-input-state controlled-input/delete-all)
handle-on-confirm (fn [amount]
handle-on-confirm (fn []
(rf/dispatch [:wallet/set-token-amount-to-send
{:amount amount
{:amount
(controlled-input/input-value
input-state)
:stack-id current-screen-id}]))
{fiat-currency :currency} (rf/sub [:profile/profile])
{token-symbol :symbol
@@ -157,6 +157,7 @@
[quo/data-item
{:container-style style/detail-item
:blur? false
:description :default
:card? false
:status :default
:size :small
+18 -35
View File
@@ -23,39 +23,22 @@
:block-number blockNumber
:accounts accounts})
(case event-type
"pending-transaction-status-changed"
{:fx
[[:dispatch
[:wallet/pending-transaction-status-changed-received
(transforms/js->clj event-js)]]]}
"wallet-owned-collectibles-filtering-done"
{:fx [[:dispatch
[:wallet/owned-collectibles-filtering-done
(transforms/js->clj event-js)]]]}
"wallet-get-collectibles-details-done"
{:fx [[:dispatch
[:wallet/get-collectible-details-done
(transforms/js->clj event-js)]]]}
"wallet-tick-reload"
{:fx [[:dispatch [:wallet/reload]]]}
"wallet-blockchain-status-changed"
{:fx [[:dispatch
[:wallet/blockchain-status-changed
(transforms/js->clj event-js)]]]}
"wallet-activity-filtering-done"
{:fx
[[:dispatch
[:wallet/activity-filtering-for-current-account-done
(transforms/js->clj event-js)]]]}
"wallet-activity-filtering-entries-updated"
{:fx [[:dispatch
[:wallet/activities-filtering-entries-updated
(transforms/js->clj event-js)]]]}
"pending-transaction-status-changed" {:fx
[[:dispatch
[:wallet/pending-transaction-status-changed-received
(transforms/js->clj event-js)]]]}
"wallet-owned-collectibles-filtering-done" {:fx [[:dispatch
[:wallet/owned-collectibles-filtering-done
(transforms/js->clj event-js)]]]}
"wallet-get-collectibles-details-done" {:fx [[:dispatch
[:wallet/get-collectible-details-done
(transforms/js->clj event-js)]]]}
"wallet-tick-reload" {:fx [[:dispatch [:wallet/reload]]]}
"wallet-blockchain-status-changed" {:fx [[:dispatch
[:wallet/blockchain-status-changed
(transforms/js->clj event-js)]]]}
"wallet-activity-filtering-done" {:fx
[[:dispatch
[:wallet/activity-filtering-for-current-account-done
(transforms/js->clj event-js)]]]}
(log/debug ::unknown-wallet-event :type event-type)))))
@@ -1,40 +0,0 @@
(ns status-im.contexts.wallet.swap.set-spending-cap.style
(:require [quo.foundations.colors :as colors]))
(def container
{:flex 1
:margin-top -20})
(def detail-item
{:flex 1
:height 36
:background-color :transparent})
(def content-container
{:padding-top 12
:padding-horizontal 20
:padding-bottom 32})
(def title-container
{:margin-horizontal 4})
(def title-line-with-margin-top
{:flex-direction :row
:margin-top 4})
(def details-container
{:flex-direction :row
:justify-content :space-between
:height 52
:padding-top 7
:padding-horizontal 1
:margin-bottom 8})
(def summary-section-container
{:padding-horizontal 20
:padding-bottom 16})
(defn section-label
[theme]
{:margin-bottom 8
:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)})
@@ -1,253 +0,0 @@
(ns status-im.contexts.wallet.swap.set-spending-cap.view
(:require
[quo.core :as quo]
[quo.foundations.resources :as resources]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[status-im.common.floating-button-page.view :as floating-button-page]
[status-im.common.standard-authentication.core :as standard-auth]
[status-im.contexts.wallet.common.utils.external-links :as external-links]
[status-im.contexts.wallet.swap.set-spending-cap.style :as style]
[utils.address :as address-utils]
[utils.i18n :as i18n]
[utils.navigation :as navigation]
[utils.re-frame :as rf]))
(defn- swap-title
[{:keys [pay-token-symbol pay-amount account provider]}]
[rn/view {:style style/content-container}
[rn/view {:style {:flex-direction :row}}
[quo/text
{:size :heading-1
:weight :semi-bold
:style style/title-container
:accessibility-label :set-spending-cap-of}
(i18n/label :t/set-spending-cap-of)]]
[rn/view {:style style/title-line-with-margin-top}
[quo/summary-tag
{:token pay-token-symbol
:label (str pay-amount " " pay-token-symbol)
:type :token}]
[quo/text
{:size :heading-1
:weight :semi-bold
:style style/title-container
:accessibility-label :for}
(i18n/label :t/for)]]
[rn/view {:style style/title-line-with-margin-top}
[quo/summary-tag
{:label (:full-name provider)
:type :network
:image-source (resources/get-network (:name provider))
:customization-color (:color provider)}]
[quo/text
{:size :heading-1
:weight :semi-bold
:style style/title-container
:accessibility-label :on}
(i18n/label :t/on)]]
[rn/view {:style style/title-line-with-margin-top}
[quo/summary-tag
{:label (:name account)
:type :account
:emoji (:emoji account)
:customization-color (:color account)}]]])
(defn- spending-cap-section
[{:keys [theme amount token-symbol]}]
[rn/view {:style style/summary-section-container}
[quo/text
{:size :paragraph-2
:weight :medium
:style (style/section-label theme)
:accessibility-label :spending-cap-label}
(i18n/label :t/spending-cap)]
[quo/approval-info
{:type :spending-cap
:unlimited-icon? false
:label (str amount " " token-symbol)
:avatar-props {:token token-symbol}}]])
(defn- account-section
[{:keys [theme account pay-token-symbol pay-token-amount]}]
[rn/view {:style style/summary-section-container}
[quo/text
{:size :paragraph-2
:weight :medium
:style (style/section-label theme)
:accessibility-label :account-label}
(i18n/label :t/account)]
[quo/approval-info
{:type :account
:unlimited-icon? false
:label (:name account)
:description (address-utils/get-short-wallet-address (:address account))
:tag-label (str pay-token-amount " " pay-token-symbol)
:avatar-props {:emoji (:emoji account)
:customization-color (:color account)}}]])
(defn- on-option-press
[{:keys [chain-id contract-address]}]
(rf/dispatch
[:show-bottom-sheet
{:content (fn []
[quo/action-drawer
[[{:icon :i/link
:accessibility-label :view-on-etherscan
:on-press (fn []
(rf/dispatch
[:wallet/navigate-to-chain-explorer-from-bottom-sheet
(external-links/get-explorer-url-by-chain-id chain-id)
contract-address]))
:label (i18n/label :t/view-on-eth)
:right-icon :i/external}]]])}]))
(defn- token-section
[{:keys [theme token-address token-symbol network-chain-id]}]
[rn/view {:style style/summary-section-container}
[quo/text
{:size :paragraph-2
:weight :medium
:style (style/section-label theme)
:accessibility-label :token-label}
(i18n/label :t/token)]
[quo/approval-info
{:type :token-contract
:option-icon :i/options
:on-option-press #(on-option-press {:chain-id network-chain-id
:contract-address token-address})
:unlimited-icon? false
:label token-symbol
:description (address-utils/get-short-wallet-address token-address)
:avatar-props {:token token-symbol}}]])
(defn- spender-contract-section
[{:keys [theme provider network-chain-id]}]
[rn/view {:style style/summary-section-container}
[quo/text
{:size :paragraph-2
:weight :medium
:style (style/section-label theme)
:accessibility-label :spender-contract-label}
(i18n/label :t/spender-contract)]
[quo/approval-info
{:type :token-contract
:option-icon :i/options
:on-option-press #(on-option-press {:chain-id network-chain-id
:contract-address (:contract-address provider)})
:unlimited-icon? false
:label (:full-name provider)
:description (address-utils/get-short-wallet-address (:contract-address provider))
:avatar-props {:image (resources/get-network (:name provider))}}]])
(defn- data-item
[{:keys [network-image title subtitle size loading?]}]
[quo/data-item
{:container-style style/detail-item
:blur? false
:card? false
:network-image network-image
:subtitle-type (if network-image :network :default)
:status (if loading? :loading :default)
:title title
:subtitle subtitle
:size size}])
(defn- transaction-details
[{:keys [estimated-time-min max-fees network loading-fees?]}]
[rn/view {:style style/details-container}
[:<>
[data-item
{:title (i18n/label :t/network)
:subtitle (:full-name network)
:network-image (:source network)}]
[data-item
{:title (i18n/label :t/est-time)
:subtitle (i18n/label :t/time-in-mins {:minutes (str estimated-time-min)})}]
[data-item
{:title (i18n/label :t/max-fees)
:subtitle max-fees
:loading? loading-fees?
:size :small}]]])
(defn footer
[{:keys [estimated-time-min native-currency-symbol network theme account-color loading-fees?]}]
(let [native-token (when native-currency-symbol
(rf/sub [:wallet/token-by-symbol
native-currency-symbol]))
fee-formatted (rf/sub [:wallet/wallet-send-fee-fiat-formatted
native-token])
on-auth-success (rn/use-callback #(js/alert "Not implemented yet"))]
[rn/view {:style {:margin-bottom -10}}
[transaction-details
{:estimated-time-min estimated-time-min
:max-fees fee-formatted
:network network
:loading-fees? loading-fees?
:theme theme}]
[standard-auth/slide-button
{:size :size-48
:track-text (i18n/label :t/slide-to-swap)
:container-style {:z-index 2}
:customization-color account-color
:disabled? loading-fees?
:on-auth-success on-auth-success
:auth-button-label (i18n/label :t/confirm)}]]))
(defn view
[]
(let [theme (quo.theme/use-theme)
swap-transaction-data (rf/sub [:wallet/swap])
{:keys [asset-to-pay network pay-amount
providers swap-proposal
loading-fees?]} swap-transaction-data
estimated-time-min (:estimated-time swap-proposal)
pay-token-symbol (:symbol asset-to-pay)
pay-token-address (:address asset-to-pay)
native-currency-symbol (get-in swap-proposal [:from :native-currency-symbol])
account (rf/sub [:wallet/current-viewing-account])
account-color (:color account)
provider (first providers)]
[rn/view {:style style/container}
[floating-button-page/view
{:footer-container-padding 0
:header [quo/page-nav
{:icon-name :i/close
:on-press navigation/navigate-back
:margin-top 8
:background :blur
:accessibility-label :top-bar}]
:footer [footer
{:estimated-time-min estimated-time-min
:native-currency-symbol native-currency-symbol
:network network
:account-color account-color
:provider provider
:loading-fees? loading-fees?
:theme theme}]
:gradient-cover? true
:customization-color account-color}
[:<>
[swap-title
{:pay-token-symbol pay-token-symbol
:pay-amount pay-amount
:account account
:provider provider}]
[spending-cap-section
{:token-symbol pay-token-symbol
:amount pay-amount
:theme theme}]
[account-section
{:account account
:pay-token-symbol pay-token-symbol
:pay-token-amount pay-amount
:theme theme}]
[token-section
{:token-symbol pay-token-symbol
:token-address pay-token-address
:network-chain-id (:chain-id network)
:theme theme}]
[spender-contract-section
{:provider provider
:network-chain-id (:chain-id network)
:theme theme}]]]]))
@@ -16,7 +16,4 @@
[quo/button
{:on-press #(rf/dispatch [:navigate-to-within-stack
[:screen/wallet.swap-confirmation :screen/wallet.swap-propasal]])}
"Swap confirmation"]
[quo/button
{:on-press #(rf/dispatch [:open-modal :screen/wallet.swap-set-spending-cap])}
"Set spending cap"]]))
"Swap confirmation"]]))
@@ -85,61 +85,12 @@
(defn required-networks-supported?
[proposal supported-networks]
(let [supported-namespaces #{:eip155}
required-namespaces (get-in proposal [:params :requiredNamespaces])]
(when (every? #(contains? supported-namespaces %)
(keys required-namespaces))
(let [required-networks (get-in required-namespaces [:eip155 :chains])
supported-eip155 (set (map chain-id->eip155 supported-networks))]
(every? #(contains? supported-eip155 %)
required-networks)))))
(let [required-networks (get-in proposal [:params :requiredNamespaces :eip155 :chains])
supported-eip155 (set (map chain-id->eip155 supported-networks))]
(every? #(contains? supported-eip155 %) required-networks)))
(defn get-networks-by-mode
[db]
(let [test-mode? (get-in db [:profile/profile :test-networks-enabled?])
networks (get-in db [:wallet :networks (if test-mode? :test :prod)])]
(mapv #(-> % :chain-id) networks)))
(defn add-full-testnet-name
"Updates the `:full-name` key with the full testnet name if using testnet `:chain-id`.\n
e.g. `{:full-name \"Mainnet\"}` -> `{:full-name \"Mainnet Sepolia\"`}`"
[network]
(let [add-testnet-name (fn [testnet-name]
(update network :full-name #(str % " " testnet-name)))]
(condp #(contains? %1 %2) (:chain-id network)
constants/sepolia-chain-ids (add-testnet-name constants/sepolia-full-name)
constants/goerli-chain-ids (add-testnet-name constants/goerli-full-name)
network)))
(defn event-should-be-handled?
[db {:keys [topic]}]
(some #(= topic %)
(map :topic (:wallet-connect/sessions db))))
(defn sdk-session->db-session
[{:keys [topic expiry pairingTopic] :as session}]
{:topic topic
:expiry expiry
:sessionJson (transforms/clj->json session)
:pairingTopic pairingTopic
:name (get-in session [:peer :metadata :name])
:iconUrl (get-in session [:peer :metadata :icons 0])
:url (get-in session [:peer :metadata :url])
:accounts (get-in session [:namespaces :eip155 :accounts])
:disconnected false})
(defn filter-operable-accounts
[accounts]
(filter #(and (:operable? %)
(not (:watch-only? %)))
accounts))
(defn filter-sessions-for-account-addresses
[account-addresses sessions]
(filter (fn [{:keys [accounts]}]
(some (fn [account]
(some (fn [account-address]
(clojure.string/includes? account account-address))
account-addresses))
accounts))
sessions))
@@ -31,6 +31,13 @@
:event wc-event
:handler handler})))
(rf/reg-fx
:effects.wallet-connect/fetch-pairings
(fn [{:keys [web3-wallet on-success on-fail]}]
(-> (wallet-connect/get-pairings web3-wallet)
(promesa/then on-success)
(promesa/catch on-fail))))
(rf/reg-fx
:effects.wallet-connect/pair
(fn [{:keys [web3-wallet url on-success on-fail]}]
@@ -41,10 +48,15 @@
(rf/reg-fx
:effects.wallet-connect/disconnect
(fn [{:keys [web3-wallet topic reason on-success on-fail]}]
(-> (wallet-connect/disconnect-session {:web3-wallet web3-wallet
:topic topic
:reason reason})
(fn [{:keys [web3-wallet topic on-success on-fail]}]
(-> (wallet-connect/core-pairing-disconnnect web3-wallet topic)
(promesa/then on-success)
(promesa/catch on-fail))))
(rf/reg-fx
:effects.wallet-connect/fetch-active-sessions
(fn [{:keys [web3-wallet on-success on-fail]}]
(-> (wallet-connect/get-active-sessions web3-wallet)
(promesa/then on-success)
(promesa/catch on-fail))))
@@ -62,13 +74,6 @@
(promesa/then on-success)
(promesa/catch on-fail)))))
(rf/reg-fx
:effects.wallet-connect/fetch-active-sessions
(fn [{:keys [web3-wallet on-success on-fail]}]
(-> (wallet-connect/get-active-sessions web3-wallet)
(promesa/then on-success)
(promesa/catch on-fail))))
(rf/reg-fx
:effects.wallet-connect/sign-message
(fn [{:keys [password address data rpc-method on-success on-error]}]
@@ -85,33 +90,22 @@
(promesa/then on-success)
(promesa/catch on-error)))))
(rf/reg-fx
:effects.wallet-connect/prepare-transaction
(fn [{:keys [tx chain-id on-success on-error]}]
(-> (transactions/prepare-transaction tx
chain-id
transactions/default-tx-priority)
(promesa/then on-success)
(promesa/catch on-error))))
(rf/reg-fx
:effects.wallet-connect/sign-transaction
(fn [{:keys [password address chain-id tx-hash tx-args on-success on-error]}]
(fn [{:keys [password address chain-id tx on-success on-error]}]
(-> (transactions/sign-transaction (security/safe-unmask-data password)
address
tx-hash
tx-args
tx
chain-id)
(promesa/then on-success)
(promesa/catch on-error))))
(rf/reg-fx
:effects.wallet-connect/send-transaction
(fn [{:keys [password address chain-id tx-hash tx-args on-success on-error]}]
(fn [{:keys [password address chain-id tx on-success on-error]}]
(-> (transactions/send-transaction (security/safe-unmask-data password)
address
tx-hash
tx-args
tx
chain-id)
(promesa/then on-success)
(promesa/catch on-error))))
@@ -8,8 +8,7 @@
status-im.contexts.wallet.wallet-connect.responding-events
[status-im.contexts.wallet.wallet-connect.utils :as wc-utils]
[taoensso.timbre :as log]
[utils.i18n :as i18n]
[utils.transforms :as types]))
[utils.i18n :as i18n]))
(rf/reg-event-fx
:wallet-connect/init
@@ -23,7 +22,12 @@
(fn [{:keys [db]} [web3-wallet]]
{:db (assoc db :wallet-connect/web3-wallet web3-wallet)
:fx [[:dispatch [:wallet-connect/register-event-listeners]]
[:dispatch [:wallet-connect/fetch-persisted-sessions]]]}))
[:effects.wallet-connect/fetch-pairings
{:web3-wallet web3-wallet
:on-fail #(log/error "Failed to get dApp pairings" {:error %})
:on-success (fn [data]
(rf/dispatch [:wallet-connect/set-pairings
(js->clj data :keywordize-keys true)]))}]]}))
(rf/reg-event-fx
:wallet-connect/register-event-listeners
@@ -36,11 +40,7 @@
[:effects.wallet-connect/register-event-listener
[web3-wallet
constants/wallet-connect-session-request-event
#(rf/dispatch [:wallet-connect/on-session-request %])]]
[:effects.wallet-connect/register-event-listener
[web3-wallet
constants/wallet-connect-session-delete-event
#(rf/dispatch [:wallet-connect/on-session-delete %])]]]})))
#(rf/dispatch [:wallet-connect/on-session-request %])]]]})))
(rf/reg-event-fx
:wallet-connect/on-init-fail
@@ -54,22 +54,20 @@
(fn [{:keys [db]} [proposal]]
(log/info "Received Wallet Connect session proposal: " {:id (:id proposal)})
(let [accounts (get-in db [:wallet :accounts])
current-viewing-address (get-in db [:wallet :current-viewing-account-address])
available-accounts (wallet-connect-core/filter-operable-accounts (vals accounts))
without-watched (remove :watch-only? (vals accounts))
networks (wallet-connect-core/get-networks-by-mode db)
session-networks (wallet-connect-core/proposal-networks-intersection proposal
networks)
required-networks-supported? (wallet-connect-core/required-networks-supported? proposal
networks)]
(if (and (not-empty session-networks) required-networks-supported?)
(if required-networks-supported?
{:db (update db
:wallet-connect/current-proposal assoc
:request proposal
:session-networks session-networks
:address (or current-viewing-address
(-> available-accounts
first
:address)))
:address (-> without-watched
first
:address))
:fx [[:dispatch
[:open-modal :screen/wallet.wallet-connect-session-proposal]]]}
{:fx [[:dispatch
@@ -87,16 +85,9 @@
(rf/reg-event-fx
:wallet-connect/on-session-request
(fn [{:keys [db]} [event]]
(when (wallet-connect-core/event-should-be-handled? db event)
{:fx [[:dispatch [:wallet-connect/process-session-request event]]]})))
(rf/reg-event-fx
:wallet-connect/on-session-delete
(fn [{:keys [db]} [{:keys [topic] :as event}]]
(when (wallet-connect-core/event-should-be-handled? db event)
(log/info "Received Wallet Connect session delete: " event)
{:fx [[:dispatch [:wallet-connect/disconnect-session topic]]]})))
(fn [_ [event]]
(log/info "Received Wallet Connect session request: " event)
{:fx [[:dispatch [:wallet-connect/process-session-request event]]]}))
(rf/reg-event-fx
:wallet-connect/reset-current-session-proposal
@@ -113,6 +104,19 @@
(fn [{:keys [db]}]
{:db (dissoc db :wallet-connect/current-request)}))
(rf/reg-event-fx
:wallet-connect/set-pairings
(fn [{:keys [db]} [pairings]]
{:db (assoc db :wallet-connect/pairings pairings)}))
(rf/reg-event-fx
:wallet-connect/remove-pairing-by-topic
(fn [{:keys [db]} [topic]]
{:db (update db
:wallet-connect/pairings
(fn [pairings]
(remove #(= (:topic %) topic) pairings)))}))
(rf/reg-event-fx
:wallet-connect/disconnect-dapp
(fn [{:keys [db]} [{:keys [topic on-success on-fail]}]]
@@ -120,13 +124,8 @@
{:fx [[:effects.wallet-connect/disconnect
{:web3-wallet web3-wallet
:topic topic
:reason (wallet-connect/get-sdk-error
constants/wallet-connect-user-disconnected-reason-key)
:on-fail on-fail
:on-success (fn []
(rf/dispatch [:wallet-connect/disconnect-session topic])
(when on-success
(on-success)))}]]})))
:on-success on-success}]]})))
(rf/reg-event-fx
:wallet-connect/pair
@@ -138,6 +137,15 @@
:on-fail #(log/error "Failed to pair with dApp" {:error %})
:on-success #(log/info "dApp paired successfully")}]]})))
(rf/reg-event-fx
:wallet-connect/fetch-active-sessions
(fn [{:keys [db]}]
(let [web3-wallet (get db :wallet-connect/web3-wallet)]
{:fx [[:effects.wallet-connect/fetch-active-sessions
{:web3-wallet web3-wallet
:on-fail #(log/error "Failed to get active sessions" {:error %})
:on-success #(log/info "Got active sessions successfully" {:sessions %})}]]})))
(rf/reg-event-fx
:wallet-connect/approve-session
(fn [{:keys [db]}]
@@ -196,63 +204,10 @@
{:version version}))}]]]}
{:fx [[:dispatch [:wallet-connect/pair scanned-text]]]}))))
;; We first load sessions from database, then we initiate a call to Wallet Connect SDK and
;; then replace the list we have stored in the database with the one that came from the SDK.
;; In addition to that, we also update the backend state by marking sessions that are not
;; active anymore by calling `:wallet-connect/disconnect-session`.
(rf/reg-event-fx
:wallet-connect/fetch-active-sessions-success
(fn [{:keys [db now]} [sessions]]
(let [persisted-sessions (:wallet-connect/sessions db)
account-addresses (->> (get-in db [:wallet :accounts])
vals
wallet-connect-core/filter-operable-accounts
(map :address))
sessions (->> (js->clj sessions :keywordize-keys true)
vals
(map wallet-connect-core/sdk-session->db-session)
(wallet-connect-core/filter-sessions-for-account-addresses
account-addresses))
session-topics (set (map :topic sessions))
expired-sessions (filter
(fn [{:keys [expiry topic]}]
(or (< expiry (/ now 1000))
(not (contains? session-topics topic))))
persisted-sessions)]
{:fx (mapv (fn [{:keys [topic]}]
[:dispatch [:wallet-connect/disconnect-session topic]])
expired-sessions)
:db (assoc db :wallet-connect/sessions sessions)})))
(rf/reg-event-fx
:wallet-connect/fetch-active-sessions
(fn [{:keys [db]}]
(let [web3-wallet (get db :wallet-connect/web3-wallet)]
{:fx [[:effects.wallet-connect/fetch-active-sessions
{:web3-wallet web3-wallet
:on-fail #(log/error "Failed to get active sessions" {:error %})
:on-success #(rf/dispatch [:wallet-connect/fetch-active-sessions-success %])}]]})))
(rf/reg-event-fx
:wallet-connect/fetch-persisted-sessions-success
(fn [{:keys [db]} [sessions]]
(let [sessions' (mapv (fn [{:keys [sessionJson] :as session}]
(assoc session
:accounts
(-> sessionJson
types/json->clj
:namespaces
:eip155
:accounts)))
sessions)]
{:fx [[:dispatch [:wallet-connect/fetch-active-sessions]]]
:db (assoc db :wallet-connect/sessions sessions')})))
(rf/reg-event-fx
:wallet-connect/fetch-persisted-sessions-fail
(fn [_ [error]]
(log/info "Wallet Connect fetch persisted sessions failed" error)
{:fx [[:dispatch [:wallet-connect/fetch-active-sessions]]]}))
{:db (assoc db :wallet-connect/persisted-sessions sessions)}))
(rf/reg-event-fx
:wallet-connect/fetch-persisted-sessions
@@ -263,7 +218,7 @@
;; 0 means, return everything
:params [0]
:on-success [:wallet-connect/fetch-persisted-sessions-success]
:on-error [:wallet-connect/fetch-persisted-sessions-fail]}]]]}))
:on-error #(log/info "Wallet Connect fetch persisted sessions failed" %)}]]]}))
(rf/reg-event-fx
:wallet-connect/persist-session
@@ -271,22 +226,5 @@
{:fx [[:json-rpc/call
[{:method "wallet_addWalletConnectSession"
:params [(js/JSON.stringify session-info)]
:on-success (fn []
(log/info "Wallet Connect session persisted")
(rf/dispatch [:wallet-connect/fetch-persisted-sessions]))
:on-error #(log/info "Wallet Connect session persistence failed" %)}]]]}))
(rf/reg-event-fx
:wallet-connect/disconnect-session
(fn [{:keys [db]} [topic]]
{:db (update db
:wallet-connect/sessions
(fn [sessions]
(->> sessions
(remove #(= (:topic %) topic))
(into []))))
:fx [[:json-rpc/call
[{:method "wallet_disconnectWalletConnectSession"
:params [topic]
:on-success #(log/info "Wallet Connect session disconnected")
:on-success #(log/info "Wallet Connect session persisted")
:on-error #(log/info "Wallet Connect session persistence failed" %)}]]]}))
@@ -1,31 +0,0 @@
(ns status-im.contexts.wallet.wallet-connect.modals.common.fees-data-item.view
(:require [quo.core :as quo]
[quo.foundations.colors :as colors]
[quo.theme]
[status-im.contexts.wallet.wallet-connect.modals.common.style :as style]
[utils.i18n :as i18n]))
(defn- fees-subtitle
[{:keys [text error?]}]
(let [theme (quo.theme/use-theme)]
[quo/text
{:weight :medium
:size :paragraph-2
:style {:color (if error?
(colors/resolve-color :danger theme)
(colors/theme-colors colors/neutral-100
colors/white
theme))}}
text]))
(defn view
[{:keys [fees fees-error]}]
[quo/data-item
{:size :small
:status :default
:card? false
:container-style style/data-item
:title (i18n/label :t/max-fees)
:custom-subtitle (fn [] [fees-subtitle
{:text (or fees (i18n/label :t/no-fees))
:error? (= fees-error :not-enough-assets-to-pay-gas-fees)}])}])
@@ -13,7 +13,7 @@
(rf/dispatch [:wallet-connect/respond-current-session password]))
(defn view
[{:keys [warning-label slide-button-text disabled?]} & children]
[{:keys [warning-label slide-button-text disabed?]} & children]
(let [{:keys [customization-color]} (rf/sub [:wallet-connect/current-request-account-details])]
[rn/view {:style style/content-container}
(into [rn/view
@@ -23,7 +23,7 @@
[standard-authentication/slide-button
{:size :size-48
:track-text slide-button-text
:disabled? disabled?
:disabled? disabed?
:customization-color customization-color
:on-auth-success on-auth-success
:auth-button-label (i18n/label :t/confirm)}]]
@@ -1,15 +1,10 @@
(ns status-im.contexts.wallet.wallet-connect.modals.common.header.style)
(def header-container
{:padding-vertical 12
:flex-direction :column
:align-items :stretch})
{:padding-vertical 12})
(def header-dapp-name
{:flex-direction :row})
(def header-text
{:margin-vertical 4})
{:margin-top -4})
(def header-account-name
{:align-items :flex-start})
{:padding-top 4})
@@ -5,23 +5,22 @@
(defn view
[{:keys [label dapp account]}]
[rn/view {:style style/header-container}
(let [{:keys [name iconUrl]} dapp]
[rn/view {:style style/header-dapp-name}
[rn/view {:flex 1}
[rn/view
{:style style/header-container}
[quo/text
{:size :heading-1
:weight :semi-bold}
(let [{:keys [name icons]} (:peerMetadata dapp)]
[rn/view {:style style/header-dapp-name}
[quo/summary-tag
{:type :dapp
:label name
:image-source iconUrl}]]])
[quo/text
{:size :heading-1
:weight :semi-bold
:style style/header-text}
label]
(let [{:keys [emoji customization-color name]} account]
[rn/view {:style style/header-account-name}
[quo/summary-tag
{:type :account
:emoji emoji
:label name
:customization-color customization-color}]])])
:image-source (first icons)}]])
(str " " label " ")
(let [{:keys [emoji customization-color name]} account]
[rn/view {:style style/header-account-name}
[quo/summary-tag
{:type :account
:emoji emoji
:label name
:customization-color customization-color}]])]])
@@ -1,11 +1,8 @@
(ns status-im.contexts.wallet.wallet-connect.modals.send-transaction.view
(:require [quo.core :as quo]
[quo.theme]
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[status-im.contexts.wallet.wallet-connect.modals.common.data-block.view :as data-block]
[status-im.contexts.wallet.wallet-connect.modals.common.fees-data-item.view :as
fees-data-item]
[status-im.contexts.wallet.wallet-connect.modals.common.footer.view :as footer]
[status-im.contexts.wallet.wallet-connect.modals.common.header.view :as header]
[status-im.contexts.wallet.wallet-connect.modals.common.page-nav.view :as page-nav]
@@ -43,7 +40,7 @@
:not-enough-assets
:t/not-enough-assets))}])
[footer/view
{:warning-label (i18n/label :t/wallet-connect-sign-warning)
{:warning-label (i18n/label :t/wallet-connect-send-transaction-warning)
:slide-button-text (i18n/label :t/slide-to-send)
:disabled? error-state}
[quo/data-item
@@ -54,7 +51,11 @@
:subtitle-type :network
:network-image (:source network)
:subtitle (:full-name network)}]
[fees-data-item/view
{:fees max-fees-fiat-formatted
:fees-error error-state}]]]]))
[quo/data-item
{:size :small
:status :default
:card? false
:container-style style/data-item
:title (i18n/label :t/max-fees)
:subtitle (or max-fees-fiat-formatted (i18n/label :t/no-fees))}]]]]))
@@ -3,8 +3,6 @@
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[status-im.contexts.wallet.wallet-connect.modals.common.data-block.view :as data-block]
[status-im.contexts.wallet.wallet-connect.modals.common.fees-data-item.view :as
fees-data-item]
[status-im.contexts.wallet.wallet-connect.modals.common.footer.view :as footer]
[status-im.contexts.wallet.wallet-connect.modals.common.header.view :as header]
[status-im.contexts.wallet.wallet-connect.modals.common.page-nav.view :as page-nav]
@@ -30,7 +28,13 @@
:account account}]
[data-block/view]]
[footer/view
{:warning-label (i18n/label :t/wallet-connect-sign-warning)
{:warning-label (i18n/label :t/wallet-connect-sign-message-warning)
:slide-button-text (i18n/label :t/slide-to-sign)}
[fees-data-item/view]]]]))
[quo/data-item
{:size :small
:status :default
:card? false
:container-style style/data-item
:title (i18n/label :t/max-fees)
:subtitle (i18n/label :t/no-fees)}]]]]))
@@ -3,8 +3,6 @@
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[status-im.contexts.wallet.wallet-connect.modals.common.data-block.view :as data-block]
[status-im.contexts.wallet.wallet-connect.modals.common.fees-data-item.view :as
fees-data-item]
[status-im.contexts.wallet.wallet-connect.modals.common.footer.view :as footer]
[status-im.contexts.wallet.wallet-connect.modals.common.header.view :as header]
[status-im.contexts.wallet.wallet-connect.modals.common.page-nav.view :as page-nav]
@@ -42,7 +40,7 @@
:not-enough-assets
:t/not-enough-assets))}])
[footer/view
{:warning-label (i18n/label :t/wallet-connect-sign-warning)
{:warning-label (i18n/label :t/wallet-connect-sign-transaction-warning)
:slide-button-text (i18n/label :t/slide-to-sign)
:disabled? error-state}
[quo/data-item
@@ -53,7 +51,11 @@
:subtitle-type :network
:network-image (:source network)
:subtitle (:full-name network)}]
[fees-data-item/view
{:fees max-fees-fiat-formatted
:fees-error error-state}]]]]))
[quo/data-item
{:size :small
:status :default
:card? false
:container-style style/data-item
:title (i18n/label :t/max-fees)
:subtitle (or max-fees-fiat-formatted (i18n/label :t/no-fees))}]]]]))
@@ -1,32 +1,18 @@
(ns status-im.contexts.wallet.wallet-connect.processing-events
(:require [cljs-bean.core :as bean]
[clojure.string :as string]
(:require [clojure.string :as string]
[native-module.core :as native-module]
[re-frame.core :as rf]
[status-im.constants :as constants]
[status-im.contexts.wallet.wallet-connect.core :as wallet-connect-core]
[status-im.contexts.wallet.wallet-connect.transactions :as transactions]
[taoensso.timbre :as log]
[utils.transforms :as transforms]))
(rf/reg-event-fx
:wallet-connect/show-request-modal
(fn [{:keys [db]}]
(let [event (get-in db [:wallet-connect/current-request :event])
method (wallet-connect-core/get-request-method event)
screen (wallet-connect-core/method-to-screen method)]
(if screen
{:fx [[:dispatch [:open-modal screen]]]}
(log/error "Didn't find screen for Wallet Connect method"
{:method method
:event :wallet-connect/process-session-request})))))
(rf/reg-event-fx
:wallet-connect/process-session-request
(fn [{:keys [db]} [event]]
(let [method (wallet-connect-core/get-request-method event)
existing-event (get-in db [:wallet-connect/current-request :event])]
;; NOTE: make sure we don't show two requests at the same time
(when-not existing-event
(let [method (wallet-connect-core/get-request-method event)
screen (wallet-connect-core/method-to-screen method)]
(if screen
{:db (assoc-in db [:wallet-connect/current-request :event] event)
:fx [(condp = method
constants/wallet-connect-eth-send-transaction-method
@@ -45,7 +31,12 @@
[:dispatch [:wallet-connect/process-sign-typed]]
constants/wallet-connect-personal-sign-method
[:dispatch [:wallet-connect/process-personal-sign]])]}))))
[:dispatch [:wallet-connect/process-personal-sign]])
[:dispatch [:open-modal screen]]]}
(log/error "Didn't find screen for Wallet Connect method"
{:method method
:event :wallet-connect/process-session-request})))))
(rf/reg-event-fx
:wallet-connect/process-personal-sign
@@ -57,8 +48,7 @@
assoc
:address (string/lower-case address)
:raw-data raw-data
:display-data (or parsed-data raw-data))
:fx [[:dispatch [:wallet-connect/show-request-modal]]]})))
:display-data (or parsed-data raw-data))})))
(rf/reg-event-fx
:wallet-connect/process-eth-sign
@@ -70,53 +60,44 @@
assoc
:address (string/lower-case address)
:raw-data raw-data
:display-data (or parsed-data raw-data))
:fx [[:dispatch [:wallet-connect/show-request-modal]]]})))
(rf/reg-event-fx
:wallet-connect/prepare-transaction-success
(fn [{:keys [db]} [prepared-tx chain-id]]
(let [{:keys [tx-args]} prepared-tx
tx (bean/->clj tx-args)
address (-> tx :from string/lower-case)
display-data (transactions/beautify-transaction tx)]
{:db (update-in db
[:wallet-connect/current-request]
assoc
:address address
:raw-data prepared-tx
:transaction tx
:chain-id chain-id
:display-data display-data)
:fx [[:dispatch [:wallet-connect/show-request-modal]]]})))
:display-data (or parsed-data raw-data))})))
(rf/reg-event-fx
:wallet-connect/process-eth-send-transaction
(fn [{:keys [db]}]
(let [event (wallet-connect-core/get-db-current-request-event db)
tx (-> event wallet-connect-core/get-request-params first)
chain-id (-> event
(get-in [:params :chainId])
wallet-connect-core/eip155->chain-id)]
{:fx [[:effects.wallet-connect/prepare-transaction
{:tx tx
:chain-id chain-id
:on-success #(rf/dispatch [:wallet-connect/prepare-transaction-success % chain-id])
:on-error #(rf/dispatch [:wallet-connect/on-processing-error %])}]]})))
(let [event (wallet-connect-core/get-db-current-request-event db)
display-data (-> event
clj->js
(js/JSON.stringify nil 2))
{:keys [from] :as tx} (-> event wallet-connect-core/get-request-params first)
chain-id (-> event
(get-in [:params :chainId])
wallet-connect-core/eip155->chain-id)]
{:db (update-in db
[:wallet-connect/current-request]
assoc
:address (string/lower-case from)
:raw-data tx
:chain-id chain-id
:display-data display-data)})))
(rf/reg-event-fx
:wallet-connect/process-eth-sign-transaction
(fn [{:keys [db]}]
(let [event (wallet-connect-core/get-db-current-request-event db)
tx (-> event wallet-connect-core/get-request-params first)
chain-id (-> event
(get-in [:params :chainId])
wallet-connect-core/eip155->chain-id)]
{:fx [[:effects.wallet-connect/prepare-transaction
{:tx tx
:chain-id chain-id
:on-success #(rf/dispatch [:wallet-connect/prepare-transaction-success % chain-id])
:on-error #(rf/dispatch [:wallet-connect/on-processing-error %])}]]})))
(let [event (wallet-connect-core/get-db-current-request-event db)
display-data (.stringify js/JSON (clj->js event) nil 2)
{:keys [from] :as tx} (-> event wallet-connect-core/get-request-params first)
chain-id (-> event
(get-in [:params :chainId])
wallet-connect-core/eip155->chain-id)]
{:db (update-in db
[:wallet-connect/current-request]
assoc
:address (string/lower-case from)
:raw-data tx
:chain-id chain-id
:display-data display-data)})))
(rf/reg-event-fx
:wallet-connect/process-sign-typed
@@ -127,31 +108,11 @@
(transforms/js-dissoc :types :primaryType)
(transforms/js-stringify 2))
(catch js/Error _ nil))]
(if (nil? parsed-data)
{:fx [[:dispatch
[:wallet-connect/on-processing-error
(ex-info "Failed to parse JSON typed data" {:data raw-data})]]]}
{:db (update-in db
[:wallet-connect/current-request]
assoc
:address (string/lower-case address)
:display-data (or parsed-data raw-data)
:raw-data raw-data)
:fx [[:dispatch [:wallet-connect/show-request-modal]]]}))))
;; TODO: we should reject a request if processing fails
(rf/reg-event-fx
:wallet-connect/on-processing-error
(fn [{:keys [db]} [error]]
(let [{:keys [address event]} (get db :wallet-connect/current-request)
method (wallet-connect-core/get-request-method event)
screen (wallet-connect-core/method-to-screen method)]
(log/error "Failed to process Wallet Connect request"
{:error error
:address address
:method method
:wallet-connect-event event
:event :wallet-connect/on-processing-error})
{:fx [[:dispatch [:dismiss-modal screen]]
[:dispatch [:wallet-connect/reset-current-request]]]})))
;; TODO: decide if we should proceed if the typed-data is invalid JSON or fail ahead of time
(when (nil? parsed-data) (log/error "Invalid typed data"))
{:db (update-in db
[:wallet-connect/current-request]
assoc
:address (string/lower-case address)
:display-data (or parsed-data raw-data)
:raw-data raw-data)})))
@@ -58,38 +58,34 @@
(rf/reg-event-fx
:wallet-connect/respond-send-transaction-data
(fn [{:keys [db]} [password]]
(let [{:keys [chain-id raw-data address]} (get db :wallet-connect/current-request)
{:keys [tx-hash tx-args]} raw-data]
(let [{:keys [chain-id raw-data address]} (get db :wallet-connect/current-request)]
{:fx [[:effects.wallet-connect/send-transaction
{:password password
:address address
:chain-id chain-id
:tx-hash tx-hash
:tx-args tx-args
:tx raw-data
:on-error #(rf/dispatch [:wallet-connect/on-sign-error %])
:on-success #(rf/dispatch [:wallet-connect/send-response {:result %}])}]]})))
(rf/reg-event-fx
:wallet-connect/respond-sign-transaction-data
(fn [{:keys [db]} [password]]
(let [{:keys [chain-id raw-data address]} (get db :wallet-connect/current-request)
{:keys [tx-hash tx-args]} raw-data]
(let [{:keys [chain-id raw-data address]} (get db :wallet-connect/current-request)]
{:fx [[:effects.wallet-connect/sign-transaction
{:password password
:address address
:chain-id chain-id
:tx-hash tx-hash
:tx-params tx-args
:tx raw-data
:on-error #(rf/dispatch [:wallet-connect/on-sign-error %])
:on-success #(rf/dispatch [:wallet-connect/send-response {:result %}])}]]})))
;; TODO: should reject if "signing" fails
(rf/reg-event-fx
:wallet-connect/on-sign-error
(fn [{:keys [db]} [error]]
(let [{:keys [raw-data address event]} (get db :wallet-connect/current-request)
method (wallet-connect-core/get-request-method event)
screen (wallet-connect-core/method-to-screen method)]
(let [event (get-in db [:wallet-connect/current-request :event])
{:keys [raw-data address]} (get db :wallet-connect/current-request)
method (wallet-connect-core/get-request-method event)
screen (wallet-connect-core/method-to-screen method)]
(log/error "Failed to sign Wallet Connect request"
{:error error
:address address
@@ -136,7 +132,7 @@
:proposal current-proposal
: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]]]})))
[:dispatch [:wallet-connect/reset-current-session]]]})))
;; NOTE: Currently we only reject a session if the user rejected it
;; But this needs to be solidified to ensure other cases:
@@ -59,8 +59,3 @@
password
chain-id
legacy?))
(defn wallet-get-suggested-fees
[chain-id]
(-> (call-rpc "wallet_getSuggestedFees" chain-id)
(promesa/then transforms/js->clj)))

Some files were not shown because too many files have changed in this diff Show More