Merge remote-tracking branch 'origin/develop' into status-go/relay-lightclient-peerExchange

This commit is contained in:
Prem Chaitanya Prathi 2024-06-27 15:18:34 +05:30
commit 95a1ee1623
98 changed files with 1382 additions and 606 deletions

View File

@ -2,7 +2,7 @@
name: MVPBug Report
about: MVPBug Report
title: ''
labels: 'E:Mobile Bug MVP'
labels: ['E:Mobile Bug MVP', ':1234: low prio']
assignees: ''
---

View File

@ -14,9 +14,7 @@
[react-native.reanimated :as reanimated]))
(defn drag-gesture
[x-pos disabled? track-width sliding-complete?
set-sliding-complete
on-complete reset-fn]
[x-pos disabled? track-width sliding-complete? set-sliding-complete on-complete reset-fn]
(-> (gesture/gesture-pan)
(gesture/with-test-ID :slide-button-gestures)
(gesture/enabled (not disabled?))
@ -71,14 +69,16 @@
(dimensions :thumb))
[dimensions])
custom-color (if (= type :danger) :danger customization-color)
gesture (rn/use-memo #(drag-gesture x-pos
disabled?
(dimensions :usable-track)
sliding-complete?
set-sliding-complete
on-complete
reset-fn)
[sliding-complete? disabled?])]
gesture (rn/use-memo
(fn []
(drag-gesture x-pos
disabled?
(dimensions :usable-track)
sliding-complete?
set-sliding-complete
on-complete
reset-fn))
[sliding-complete? disabled? on-complete])]
[gesture/gesture-detector
{:gesture gesture}
[reanimated/view

View File

@ -8,10 +8,11 @@
[react-native.core :as rn]))
(defn- get-icon-color
[danger? theme]
(if danger?
(colors/theme-colors colors/danger-50 colors/danger-60 theme)
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme)))
[blur? danger? theme]
(cond
danger? (colors/theme-colors colors/danger-50 colors/danger-60 theme)
blur? colors/white-opa-70
:else (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)))
(defn- divider
[theme blur?]
@ -51,7 +52,7 @@
:accessible true
:style (style/left-icon sub-label)}
[icon/icon icon
{:color (or icon-color (get-icon-color danger? theme))
{:color (or icon-color (get-icon-color blur? danger? theme))
:no-color no-icon-color?
:size 20}]])
[rn/view
@ -84,7 +85,7 @@
:accessible true
:accessibility-label :right-icon-for-action}
[icon/icon right-icon
{:color (get-icon-color danger? theme)
{:color (get-icon-color blur? danger? theme)
:size 20}]])
(when (= state :selected)
[rn/view {:style style/right-icon}

View File

@ -18,7 +18,7 @@
(defn- left-image
[{:keys [type customization-color account-avatar-emoji account-avatar-type icon-avatar
profile-picture]}]
profile-picture blur?]}]
(case type
:account [account-avatar/view
{:customization-color customization-color
@ -28,6 +28,7 @@
:keypair [icon-avatar/icon-avatar
{:icon icon-avatar
:border? true
:blur? blur?
:color :neutral}]
:default-keypair [user-avatar/user-avatar
@ -213,6 +214,7 @@
[rn/view {:style style/left-container}
[left-image
{:type type
:blur? blur?
:customization-color customization-color
:account-avatar-emoji account-avatar-emoji
:account-avatar-type account-avatar-type

View File

@ -31,7 +31,8 @@
:size :paragraph-2}
(:name account-props)]
[address-text/view
{:networks networks
{:blur? blur?
:networks networks
:address (:address account-props)
:format :short}]]]
(when (= action :icon)

View File

@ -34,7 +34,8 @@
(def container-info
{:flex-direction :row
:align-items :center})
:align-items :center
:flex 1})
(def user-info
{:margin-left 8})

View File

@ -25,14 +25,16 @@
:style {:width 32 :height 32}}]
[rn/view {:style style/user-info}
[text/text
{:weight :semi-bold
:size :paragraph-1
:style (style/style-text-name theme)}
{:weight :semi-bold
:size :paragraph-1
:number-of-lines 1
:style (style/style-text-name theme)}
(:name dapp)]
[text/text
{:weight :regular
:size :paragraph-2
:style (style/style-text-value theme)}
{:weight :regular
:size :paragraph-2
:number-of-lines 1
:style (style/style-text-value theme)}
(:value dapp)]]]
(when right-component
[right-component dapp])]))

View File

@ -31,7 +31,7 @@
(defn- checkbox-border-unchecked-color
[theme]
{:normal (colors/theme-colors colors/neutral-30 colors/neutral-70 theme)
:blur (colors/theme-colors colors/neutral-80-opa-20 colors/white-opa-40 theme)})
:blur (colors/theme-colors colors/neutral-80-opa-20 colors/white-opa-20 theme)})
(defn- filled-checkbox-background-color
[theme]

View File

@ -51,3 +51,24 @@
:right-icon :i/globe
:chevron? true}]}])
(h/is-truthy (h/get-by-text "subtitle"))))
(h/describe "Data Item Category tests"
(h/test "category renders"
(h/render [category/category
{:list-type :data-item
:label "Label"
:data [{:title "Item 1"
:subtitle "subtitle"
:right-icon :i/globe}]}])
(h/is-truthy (h/get-by-text "Label"))
(h/is-truthy (h/get-by-text "Item 1"))
(h/is-truthy (h/get-by-text "subtitle")))
(h/test "category renders without label"
(h/render [category/category
{:list-type :data-item
:data [{:title "Item 1"
:subtitle "subtitle"
:right-icon :i/globe}]}])
(h/is-falsy (h/query-by-label-text "Label"))
(h/is-truthy (h/get-by-text "Item 1"))))

View File

@ -0,0 +1,32 @@
(ns quo.components.settings.category.data-item.view
(:require
[quo.components.markdown.text :as text]
[quo.components.settings.category.style :as style]
[quo.components.settings.data-item.view :as data-item]
[quo.theme :as quo.theme]
[react-native.core :as rn]))
(defn view
[{:keys [label data container-style blur?]}]
(let [theme (quo.theme/use-theme)
last-item (rn/use-memo #(last data) [data])]
[rn/view {:style (merge (style/container label) container-style)}
(when label
[text/text
{:weight :medium
:size :paragraph-2
:style (style/label blur? theme)}
label])
[rn/view {:style (style/settings-items blur? theme)}
(for [item data
;; NOTE: overwriting the background of the data-item in favor of the category bg
:let [data-item-container-style (-> item :container-style (assoc :background-color nil))
data-item-props (assoc item
:blur? blur?
:container-style data-item-container-style)]]
^{:key item}
[:<>
[data-item/view data-item-props]
(when-not (= item last-item)
[rn/view {:style (style/settings-separator blur? theme)}])])]]))

View File

@ -1,10 +1,13 @@
(ns quo.components.settings.category.view
(:require
[quo.components.settings.category.data-item.view :as data-item]
[quo.components.settings.category.reorder.view :as reorder]
[quo.components.settings.category.settings.view :as settings]))
(defn category
[{:keys [list-type] :as props}]
(if (= list-type :settings)
[settings/settings-category props]
[reorder/reorder-category props]))
(condp = list-type
:settings [settings/settings-category props]
:data-item [data-item/view props]
:reorder [reorder/reorder-category props]
nil))

View File

@ -39,6 +39,12 @@
(def avatar-container-rounded
(assoc avatar-container-common :border-radius 16))
(def big-avatar-container-rounded
(assoc avatar-container-common
:width 84
:height 84
:border-radius 42))
(def community-logo-image
{:width 64
:height 64

View File

@ -13,8 +13,9 @@
:as props}]
[rn/view {:style style/avatar-overlay}
[rn/view
{:style (if (= avatar-type :wallet-account)
style/avatar-container-rounded
{:style (case avatar-type
:wallet-account style/avatar-container-rounded
:saved-address style/big-avatar-container-rounded
style/avatar-container-circular)}
(case avatar-type
:profile
@ -37,7 +38,7 @@
[channel-avatar/view (assoc props :locked? nil :size :size-64)]
:saved-address
[wallet-avatar/wallet-user-avatar (assoc props :size :size-64)]
[wallet-avatar/wallet-user-avatar (assoc props :size :size-80)]
nil)]])

View File

@ -28,5 +28,10 @@
:height 24
:border-radius 12})
(def dapp
{:width 24
:height 24
:border-radius 12})
(def token-image
{:border-radius 12})

View File

@ -23,6 +23,10 @@
[rn/image
{:source image-source
:style style/network}]
:dapp
[rn/image
{:source image-source
:style style/dapp}]
:saved-address
[wallet-user-avatar/wallet-user-avatar
{:full-name label
@ -50,7 +54,7 @@
- :label - string - tag label
- :customization-color - color - It will be passed down to components that
should vary based on a custom color.
- :type - :token / :user / :collectible / :saved-address / :network / :account
- :type - :token / :user / :collectible / :saved-address / :network / :account / :dapp
- :emoji - string - emoji used for displaying account avatar
- :image-source - resource - image to display on :network, :collectible and :user
- :theme - :light / :dark"

View File

@ -7,14 +7,14 @@
[{:keys [blur? customization-color theme selected? container-style]}]
(merge {:border-radius 16
:border-width 1
:border-color (if selected?
(if blur?
colors/white
(colors/resolve-color customization-color theme))
(if blur?
colors/white-opa-5
(colors/theme-colors colors/neutral-10 colors/neutral-80 theme)))
:padding-bottom 8}
:padding-bottom 8
:border-color (cond
(and selected? blur?) colors/white
selected? (colors/resolve-color customization-color theme)
blur? colors/white-opa-5
:else (colors/theme-colors colors/neutral-10
colors/neutral-80
theme))}
container-style))
(def header-container

View File

@ -47,12 +47,13 @@
:accessibility-label :title}
[text/text {:weight :semi-bold}
(if (= type :default-keypair) (keypair-string full-name) full-name)]
(if (= action :selector)
[selectors/view
{:type :radio
:checked? selected?
:blur? blur?
:customization-color customization-color}]
(case action
:none nil
:selector [selectors/view
{:type :radio
:checked? selected?
:blur? blur?
:customization-color customization-color}]
[rn/pressable {:on-press on-options-press}
[icon/icon :i/options
{:color (if blur?
@ -94,20 +95,23 @@
(defn view
[{:keys [accounts action container-style selected? on-press] :as props}]
[rn/pressable
{:style (style/container (merge props
{:selected? selected?
:container-style container-style}))
:on-press #(when (= action :selector) (on-press))}
[rn/view {:style style/header-container}
[avatar props]
[rn/view
{:style {:margin-left 8
:flex 1}}
[title-view (assoc props :selected? selected?)]
[details-view props]]]
[rn/flat-list
{:data accounts
:render-fn acc-list-card
:separator [rn/view {:style {:height 8}}]
:style {:padding-horizontal 8}}]])
(let [theme (quo.theme/use-theme)]
[rn/pressable
{:style (style/container (assoc props
:selected? selected?
:container-style container-style
:theme theme))
:on-press #(when (= action :selector) (on-press))
:pointer-events :box-only}
[rn/view {:style style/header-container}
[avatar props]
[rn/view
{:style {:margin-left 8
:flex 1}}
[title-view (assoc props :selected? selected?)]
[details-view props]]]
[rn/flat-list
{:data accounts
:render-fn acc-list-card
:separator [rn/view {:style {:height 8}}]
:style {:padding-horizontal 8}}]]))

View File

@ -11,7 +11,7 @@
[utils.i18n :as i18n]))
(defn title-view
[{:keys [keypairs blur? on-import-press]}]
[{:keys [keypairs blur? on-import-press show-import-all?]}]
(let [theme (quo.theme/use-theme)]
[rn/view
{:accessibility-label :title
@ -29,12 +29,13 @@
:style {:color colors/warning-60}}
(i18n/label :t/amount-missing-keypairs
{:amount (str (count keypairs))})]
[button/button
{:type :outline
:background :blur
:size 24
:on-press on-import-press}
(i18n/label :t/import)]]
(when show-import-all?
[button/button
{:type :outline
:background :blur
:size 24
:on-press on-import-press}
(i18n/label :t/import)])]
[text/text
{:size :paragraph-2
:style (style/subtitle blur? theme)}

View File

@ -1,7 +1,6 @@
(ns status-im.common.bottom-sheet.style
(:require
[quo.foundations.colors :as colors]
[react-native.platform :as platform]))
[quo.foundations.colors :as colors]))
(def ^:private sheet-border-radius 20)
@ -22,11 +21,8 @@
:left 0
:right 0})
(defn shell-bg
[blur-background]
{:background-color (if blur-background
blur-background
(if platform/ios? colors/white-opa-5 colors/neutral-100-opa-90))
(def shell-bg
{:background-color colors/bottom-sheet-background-blur
:flex 1})
(def shell-bg-container

View File

@ -63,7 +63,7 @@
(defn view
[{:keys [hide? insets]}
{:keys [content selected-item padding-bottom-override border-radius on-close shell?
gradient-cover? customization-color hide-handle? blur-radius blur-background]
gradient-cover? customization-color hide-handle? blur-radius]
:or {border-radius 12}}]
(let [theme (quo.theme/use-theme)
{window-height :height} (rn/get-window)
@ -134,7 +134,7 @@
(when shell?
[rn/view {:style style/shell-bg-container}
[quo/blur
{:style (style/shell-bg blur-background)
{:style style/shell-bg
:blur-radius (or blur-radius 20)
:blur-amount 32
:blur-type :transparent

View File

@ -1,6 +1,5 @@
(ns status-im.common.enter-seed-phrase.style
(:require
[react-native.safe-area :as safe-area]))
(:require [react-native.platform :as platform]))
(def full-layout {:flex 1})
@ -11,6 +10,13 @@
:left 0
:right 0})
(defn recovery-phrase-container
[{:keys [banner-offset insets keyboard-shown?]}]
{:flex 1
:padding-bottom (if keyboard-shown?
(when platform/ios? banner-offset)
(:bottom insets))})
(def form-container
{:flex 1
:padding-horizontal 20
@ -29,9 +35,7 @@
:margin-top 12
:margin-horizontal -20})
(defn continue-button
[keyboard-shown?]
{:margin-top :auto
:margin-bottom (when-not keyboard-shown? (safe-area/get-bottom))})
(def continue-button
{:margin-top :auto})
(def keyboard-container {:margin-top :auto})

View File

@ -96,7 +96,7 @@
(take 7)))
(defn recovery-phrase-screen
[{:keys [keypair title recovering-keypair? render-controls]}]
[{:keys [banner-offset initial-insets keypair title recovering-keypair? render-controls]}]
(reagent/with-let [keyboard-shown? (reagent/atom false)
keyboard-show-listener (.addListener rn/keyboard
"keyboardDidShow"
@ -114,7 +114,8 @@
seed-phrase (reagent/atom "")
on-change-seed-phrase (fn [new-phrase]
(when @invalid-seed-phrase?
(reset! invalid-seed-phrase? false)
(reset! invalid-seed-phrase? false))
(when @incorrect-seed-phrase?
(reset! incorrect-seed-phrase? false))
(reset! seed-phrase new-phrase))
on-submit (fn []
@ -161,7 +162,10 @@
button-disabled? (or error-state?
(not (constants/seed-phrase-valid-length word-count))
(not all-words-valid?))]
[:<>
[rn/view
{:style (style/recovery-phrase-container {:insets initial-insets
:banner-offset banner-offset
:keyboard-shown? @keyboard-shown?})}
[recovery-phrase-form
{:title title
:keypair keypair
@ -172,18 +176,18 @@
(if (fn? render-controls)
(render-controls {:submit-disabled? button-disabled?
:keyboard-shown? @keyboard-shown?
:container-style (style/continue-button @keyboard-shown?)
:container-style style/continue-button
:prepare-seed-phrase secure-clean-seed-phrase
:focus-input focus-input
:seed-phrase (security/mask-data @seed-phrase)
:set-incorrect-seed-phrase set-incorrect-seed-phrase})
[quo/button
{:container-style (style/continue-button @keyboard-shown?)
{:container-style style/continue-button
:type :primary
:disabled? button-disabled?
:on-press on-submit}
(i18n/label :t/continue)])]
(when @keyboard-shown?
(when (or @keyboard-shown? error-state?)
[rn/view {:style style/keyboard-container}
[quo/predictive-keyboard
{:type suggestions-state
@ -197,7 +201,8 @@
(defn screen
[{:keys [initial-insets title keypair navigation-icon recovering-keypair? render-controls]}]
(let [{navigation-bar-top :top} initial-insets]
(let [{navigation-bar-top :top} initial-insets
banner-offset (rf/sub [:alert-banners/top-margin])]
[rn/view {:style style/full-layout}
[rn/keyboard-avoiding-view {:style style/page-container}
[quo/page-nav
@ -210,6 +215,8 @@
{:title title
:keypair keypair
:render-controls render-controls
:banner-offset banner-offset
:initial-insets initial-insets
:recovering-keypair? recovering-keypair?}]]]))
(defn view

View File

@ -58,7 +58,7 @@
(defn view
[{:keys [header footer customization-color footer-container-padding header-container-style
gradient-cover? keyboard-should-persist-taps]
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)
@ -110,7 +110,9 @@
:always-bounce-vertical @keyboard-did-show?
:shows-vertical-scroll-indicator false
:keyboard-should-persist-taps keyboard-should-persist-taps}
(into [rn/view {:on-layout set-content-container-height}]
(into [rn/view
{:style content-container-style
:on-layout set-content-container-height}]
children)]
[rn/keyboard-avoiding-view
{:style style/keyboard-avoiding-view

View File

@ -2,12 +2,13 @@
(:require [quo.foundations.colors :as colors]))
(def container
{:flex 1
:padding 10
:margin-vertical 10.5
:border-width 1
:border-color colors/neutral-10
:border-radius 16})
{:flex 1
:padding 10
:margin-top 10.5
:margin-bottom 0
:border-width 1
:border-color colors/neutral-10
:border-radius 16})
(def content
{:padding-bottom 20})

View File

@ -4,7 +4,7 @@
[status-im.common.raw-data-block.style :as style]))
(defn view
[{:keys [data]}]
[data]
[rn/scroll-view
{:style style/container
:content-container-style style/content}

View File

@ -195,7 +195,7 @@
true)
(defn view
[{:keys [title subtitle validate-fn on-success-scan error-message share-button?]}]
[{:keys [title subtitle validate-fn on-success-scan error-message share-button? import-keypair?]}]
(let [insets (safe-area/get-insets)
qr-code-succeed? (reagent/atom false)
qr-view-finder (reagent/atom {})
@ -233,7 +233,9 @@
:set-qr-code-succeeded (fn [value]
(when on-success-scan
(on-success-scan value))
(rf/dispatch [:navigate-back]))
(if import-keypair?
(set-rescan-timeout)
(rf/dispatch [:navigate-back])))
:set-rescan-timeout set-rescan-timeout}])
[rn/view {:style (style/root-container (:top insets))}
[header

View File

@ -33,6 +33,7 @@
:size 24}]]
[password-input/view
{:on-press-biometrics on-press-biometrics
:blur? true
:processing processing
:error error
:default-password password

View File

@ -20,7 +20,7 @@
(rf/reg-event-fx :standard-auth/authorize authorize)
(defn authorize-with-biometric
[_ [{:keys [on-auth-success on-auth-fail] :as args}]]
[_ [{:keys [on-auth-success on-auth-fail on-close] :as args}]]
(let [args-with-biometric-btn
(assoc args
:on-press-biometric
@ -31,7 +31,10 @@
{:prompt-message (i18n/label :t/biometric-auth-confirm-message)
:on-cancel #(rf/dispatch [:standard-auth/authorize-with-password
args-with-biometric-btn])
:on-success #(rf/dispatch [:standard-auth/on-biometric-success on-auth-success])
:on-success (fn []
(when (fn? on-close)
(on-close))
(rf/dispatch [:standard-auth/on-biometric-success on-auth-success]))
:on-fail (fn [err]
(rf/dispatch [:standard-auth/authorize-with-password
args-with-biometric-btn])

View File

@ -14,10 +14,12 @@
(> (-> s str string/trim count) constants/key-pair-name-max-length))
(defn validation-keypair-name
[s]
[s existing-keypair-names]
(cond
(string/blank? s) nil
(validators/has-emojis? s) (i18n/label :t/key-name-error-emoji)
(validators/has-special-characters? s) (i18n/label :t/key-name-error-special-char)
(keypair-too-short? s) (i18n/label :t/your-key-pair-name-is-too-short)
(keypair-too-long? s) (i18n/label :t/your-key-pair-name-is-too-long)))
(keypair-too-short? s) (i18n/label :t/key-name-error-too-short
{:count constants/key-pair-name-min-length})
(keypair-too-long? s) (i18n/label :t/your-key-pair-name-is-too-long)
(contains? existing-keypair-names s) (i18n/label :t/key-name-error-taken)))

View File

@ -2,6 +2,7 @@
(:require
[cljs.test :refer-macros [deftest are]]
[status-im.common.validation.keypair :as keypair-validator]
[status-im.constants :as constants]
[utils.i18n :as i18n]))
(deftest keypair-name-too-short-test
@ -18,10 +19,12 @@
(deftest validation-keypair-name-test
(are [arg expected]
(= (keypair-validator/validation-keypair-name arg) expected)
(= (keypair-validator/validation-keypair-name arg #{"Collection"}) expected)
nil nil
"" nil
"name !" (i18n/label :t/key-name-error-special-char)
"Hello 😊" (i18n/label :t/key-name-error-emoji)
"abc" (i18n/label :t/your-key-pair-name-is-too-short)
"abc" (i18n/label :t/key-name-error-too-short
{:count constants/key-pair-name-min-length})
"Collection" (i18n/label :t/key-name-error-taken)
(apply str (repeat 25 "a")) (i18n/label :t/your-key-pair-name-is-too-long)))

View File

@ -268,12 +268,14 @@
(def ^:const wallet-connect-personal-sign-method "personal_sign")
(def ^:const wallet-connect-eth-sign-method "eth_sign")
(def ^:const wallet-connect-eth-send-transaction-method "eth_sendTransaction")
(def ^:const wallet-connect-eth-sign-transaction-method "eth_signTransaction")
(def ^:const wallet-connect-eth-sign-typed-method "eth_signTypedData")
(def ^:const wallet-connect-eth-sign-typed-v4-method "eth_signTypedData_v4")
(def ^:const wallet-connect-supported-methods
#{wallet-connect-personal-sign-method
wallet-connect-eth-sign-method
wallet-connect-eth-send-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"})
@ -492,6 +494,10 @@
(def ^:const optimism-abbreviated-name "Oeth.")
(def ^:const arbitrum-abbreviated-name "Arb1.")
(def ^:const mainnet-full-name "Mainnet")
(def ^:const optimism-full-name "Optimism")
(def ^:const arbitrum-full-name "Arbitrum")
(def ^:const mainnet-network-name :mainnet)
(def ^:const ethereum-network-name :ethereum)
(def ^:const optimism-network-name :optimism)

View File

@ -1,6 +1,7 @@
(ns status-im.contexts.preview.quo.settings.category
(:require
[quo.core :as quo]
[quo.foundations.colors :as colors]
[reagent.core :as reagent]
[status-im.common.resources :as resources]
[status-im.contexts.preview.quo.preview :as preview]))
@ -17,6 +18,24 @@
:image-props :i/browser
:image-size 32})))
(defn create-data-item-array
[n]
(vec
(for [i (range n)]
{:blur? false
:description :default
:icon-right? true
:right-icon :i/chevron-right
:icon-color colors/neutral-10
:card? false
:label :preview
:status :default
:size :default
:right-content {:type :accounts
:data [{:emoji "🔥" :customization-color :yellow}]}
:title (str "Item title " i)
:subtitle "Item subtitle"})))
(def descriptor
[{:key :blur? :type :boolean}
{:key :list-type
@ -24,7 +43,11 @@
:options [{:key :settings
:value :settings}
{:key :reorder
:value :reorder}]}])
:value :reorder}
{:key :data-item
:value :data-item}]}])
(def ^:constant n-items 5)
(defn view
[]
@ -32,7 +55,10 @@
:blur? false
:list-type :settings})]
(fn []
(let [data (create-item-array 5)]
(let [list-type (:list-type @state)
data (if (= list-type :data-item)
(create-data-item-array n-items)
(create-item-array n-items))]
[preview/preview-container
{:state state
:descriptor descriptor

View File

@ -51,7 +51,9 @@
{:value "Saved address"
:key :saved-address}
{:value "Account"
:key :account}]}])
:key :account}
{:value "Dapp"
:key :dapp}]}])
(defn view
[]

View File

@ -92,23 +92,28 @@
(rf/reg-event-fx :wallet/make-keypairs-accounts-fully-operable make-keypairs-accounts-fully-operable)
(defn connection-string-for-import-keypair
[{:keys [db]} [{:keys [sha3-pwd keypairs-key-uids connection-string]}]]
[{:keys [db]} [{:keys [sha3-pwd keypairs-key-uids connection-string on-success]}]]
(let [key-uid (get-in db [:profile/profile :key-uid])]
{:fx [[:effects.syncing/import-keypairs-keystores
{:key-uid key-uid
:sha3-pwd sha3-pwd
:keypairs-key-uids keypairs-key-uids
:connection-string connection-string
:on-success #(rf/dispatch [:wallet/make-keypairs-accounts-fully-operable %])
:on-fail #(rf/dispatch [:toasts/upsert
{:type :negative
:theme :dark
:text %}])}]]}))
:on-success (fn [key-uids]
(rf/call-continuation on-success)
(rf/dispatch [:wallet/make-keypairs-accounts-fully-operable key-uids]))
:on-fail (fn [error]
(log/error "failed to import missing key pairs with connection string"
{:error error})
(rf/dispatch [:toasts/upsert
{:type :negative
:theme :dark
:text (i18n/label :t/incorrect-qr-code)}]))}]]}))
(rf/reg-event-fx :wallet/connection-string-for-import-keypair connection-string-for-import-keypair)
(defn success-keypair-qr-scan
[_ [connection-string keypairs-key-uids]]
[_ [connection-string keypairs-key-uids on-import-success]]
{:fx [[:dispatch
[:standard-auth/authorize-with-password
{:blur? true
@ -120,7 +125,8 @@
[:wallet/connection-string-for-import-keypair
{:connection-string connection-string
:keypairs-key-uids keypairs-key-uids
:sha3-pwd password}]))}]]]})
:sha3-pwd password
:on-success on-import-success}]))}]]]})
(rf/reg-event-fx :wallet/success-keypair-qr-scan success-keypair-qr-scan)
@ -146,7 +152,7 @@
{:fx [[:json-rpc/call
[{:method "accounts_makePrivateKeyKeypairFullyOperable"
:params [(security/safe-unmask-data private-key)
(-> password security/safe-unmask-data native-module/sha3)]
(security/safe-unmask-data password)]
:on-success on-success
:on-error on-error}]]]})

View File

@ -41,31 +41,37 @@
[quo/action-drawer
[(when has-paired-device
(if-not missing-keypair?
[{:icon :i/qr-code
[{:blur? true
:icon :i/qr-code
:accessibility-label :show-key-pr-qr
:label (i18n/label :t/show-encrypted-qr-of-key-pairs)
:on-press on-show-qr}]
[{:icon :i/scan
[{:blur? true
:icon :i/scan
:accessibility-label :import-by-scan-qr
:label (i18n/label :t/import-by-scanning-encrypted-qr)
:on-press on-scan-qr}]))
(when (= (:type drawer-props) :keypair)
[(when missing-keypair?
(case (:type keypair)
:seed {:icon :i/seed
:seed {:blur? true
:icon :i/seed
:accessibility-label :import-seed-phrase
:label (i18n/label :t/import-by-entering-recovery-phrase)
:on-press on-import-seed-phrase}
:key {:icon :i/key
:key {:blur? true
:icon :i/key
:accessibility-label :import-private-key
:label (i18n/label :t/import-by-entering-private-key)
:on-press on-import-private-key}
nil))
{:icon :i/edit
{:blur? true
:icon :i/edit
:accessibility-label :rename-key-pair
:label (i18n/label :t/rename-key-pair)
:on-press on-rename-keypair}
{:icon :i/delete
{:blur? true
:icon :i/delete
:accessibility-label :remove-key-pair
:add-divider? true
:danger? true

View File

@ -11,13 +11,16 @@
[]
(let [keypairs-key-uids (rf/sub [:get-screen-params])
on-success-scan (rn/use-callback (fn [scanned-text]
(rf/dispatch [:wallet/success-keypair-qr-scan scanned-text
keypairs-key-uids])
(rf/dispatch [:wallet/success-keypair-qr-scan
scanned-text
keypairs-key-uids
[:navigate-back]])
[keypairs-key-uids]))]
[scan-qr-code/view
{:title (i18n/label :t/scan-key-pairs-qr-code)
:subtitle (i18n/label :t/find-it-in-setting)
:share-button? false
:import-keypair? true
:validate-fn sync-utils/valid-connection-string?
:error-message (i18n/label :t/invalid-qr)
:error-message (i18n/label :t/invalid-key-pair-qr)
:on-success-scan on-success-scan}]))

View File

@ -4,7 +4,8 @@
{:margin-bottom 8})
(def bottom-action
{:margin-horizontal -20})
{:margin-horizontal -20
:margin-vertical -12})
(def error-container
{:margin-left 20

View File

@ -2,6 +2,7 @@
(:require [clojure.string :as string]
[quo.core :as quo]
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[status-im.common.floating-button-page.view :as floating-button-page]
[status-im.common.validation.keypair :as keypair-validator]
[status-im.constants :as constants]
@ -14,19 +15,24 @@
(defn view
[]
(let [{:keys [name key-uid]} (rf/sub [:get-screen-params])
(let [insets (safe-area/get-insets)
{existing-keypair-name :name
:keys [key-uid]} (rf/sub [:get-screen-params])
existing-keypair-names (rf/sub [:wallet/keypair-names])
customization-color (rf/sub [:profile/customization-color])
[unsaved-keypair-name set-unsaved-keypair-name] (rn/use-state name)
[unsaved-keypair-name set-unsaved-keypair-name] (rn/use-state existing-keypair-name)
[error-msg set-error-msg] (rn/use-state nil)
[typing? set-typing?] (rn/use-state false)
validate-keypair-name (rn/use-callback
(debounce/debounce
(fn [name]
(fn [input-name]
(set-error-msg
(keypair-validator/validation-keypair-name
name))
input-name
existing-keypair-names))
(set-typing? false))
300))
300)
[existing-keypair-names])
on-change-text (rn/use-callback (fn [text]
(set-typing? true)
(set-unsaved-keypair-name
@ -40,45 +46,57 @@
:keypair-name
unsaved-keypair-name}])
[unsaved-keypair-name key-uid])]
[floating-button-page/view
{:header [quo/page-nav
{:icon-name :i/close
:on-press navigate-back
:accessibility-label :top-bar}]
:footer [quo/bottom-actions
{:actions :one-action
:button-one-label (i18n/label :t/save)
:button-one-props {:disabled? (or typing?
(string/blank? unsaved-keypair-name)
(not (string/blank? error-msg)))
:customization-color customization-color
:on-press on-save}
:container-style style/bottom-action}]}
[quo/page-top
{:container-style style/header-container
:title (i18n/label :t/rename-key-pair)
:description :context-tag
:context-tag {:type :icon
:size 24
:context name
:icon :i/seed-phrase}}]
[quo/input
{:container-style {:margin-horizontal 20}
:placeholder (i18n/label :t/keypair-name-input-placeholder)
:label (i18n/label :t/keypair-name)
:default-value unsaved-keypair-name
:char-limit constants/key-pair-name-max-length
:max-length constants/key-pair-name-max-length
:auto-focus true
:clearable? (not (string/blank? unsaved-keypair-name))
:on-clear on-clear
:on-change-text on-change-text
:error? (not (string/blank? error-msg))}]
(when-not (string/blank? error-msg)
[quo/info-message
{:type :error
:size :default
:icon :i/info
:container-style style/error-container}
error-msg])]))
[quo/overlay {:type :shell}
[floating-button-page/view
{:footer-container-padding 0
:blur? true
:header [quo/page-nav
{:margin-top (:top insets)
:icon-name :i/close
:background :blur
:on-press navigate-back
:accessibility-label :top-bar}]
:footer [quo/bottom-actions
{:actions :one-action
:blur? true
:button-one-label (i18n/label :t/save)
:button-one-props {:blur? true
:disabled? (or typing?
(= existing-keypair-name
unsaved-keypair-name)
(string/blank?
unsaved-keypair-name)
(not (string/blank?
error-msg)))
:customization-color customization-color
:on-press on-save}
:container-style style/bottom-action}]}
[quo/page-top
{:container-style style/header-container
:title (i18n/label :t/rename-key-pair)
:description :context-tag
:blur? true
:context-tag {:type :icon
:size 24
:context existing-keypair-name
:icon :i/seed-phrase}}]
[quo/input
{:blur? true
:container-style {:margin-horizontal 20}
:placeholder (i18n/label :t/keypair-name-input-placeholder)
:label (i18n/label :t/keypair-name)
:default-value unsaved-keypair-name
:char-limit constants/key-pair-name-max-length
:auto-focus true
:clearable? (not (string/blank? unsaved-keypair-name))
:on-clear on-clear
:on-change-text on-change-text
:error? (not (string/blank? error-msg))}]
(when-not (string/blank? error-msg)
[quo/info-message
{:type :error
:size :default
:icon :i/info
:container-style style/error-container}
error-msg])]]))

View File

@ -1,11 +1,11 @@
(ns status-im.contexts.settings.wallet.keypairs-and-accounts.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.contexts.settings.wallet.keypairs-and-accounts.actions.view :as actions]
[status-im.contexts.settings.wallet.keypairs-and-accounts.style :as style]
[status-im.feature-flags :as ff]
[utils.address :as utils]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@ -17,13 +17,12 @@
(defn on-options-press
[{:keys [drawer-props keypair]}]
(rf/dispatch [:show-bottom-sheet
{:content (fn [] [actions/view
{:drawer-props drawer-props
:keypair keypair}])
{:content (fn [] [actions/view
{:drawer-props drawer-props
:keypair keypair}])
:blur-background colors/bottom-sheet-background-blur
:theme (:theme drawer-props)
:shell? true}]))
:theme (:theme drawer-props)
:shell? true}]))
(defn options-drawer-props
[{{:keys [name]} :keypair
@ -70,7 +69,7 @@
{:blur? true
:status-indicator false
:stored :on-device
:action :options
:action (if default-keypair? :none :options)
:accounts accounts
:customization-color customization-color
:container-style style/keypair-container-style
@ -83,17 +82,16 @@
(defn on-missing-keypair-options-press
[_event keypair-data]
(rf/dispatch [:show-bottom-sheet
{:theme :dark
:shell? true
:blur-background colors/bottom-sheet-background-blur
:content (fn [] [actions/view
{:keypair keypair-data
:drawer-props (options-drawer-props
{:theme :dark
:type :keypair
:stored :missing
:blur? true
:keypair keypair-data})}])}]))
{:theme :dark
:shell? true
:content (fn [] [actions/view
{:keypair keypair-data
:drawer-props (options-drawer-props
{:theme :dark
:type :keypair
:stored :missing
:blur? true
:keypair keypair-data})}])}]))
(defn view
[]
@ -127,6 +125,7 @@
:header (when (seq missing-keypairs)
[quo/missing-keypairs
{:blur? true
:show-import-all? (ff/enabled? ::ff/settings.import-all-keypairs)
:keypairs missing-keypairs
:on-import-press on-import-press
:container-style style/missing-keypairs-container-style

View File

@ -1,6 +1,5 @@
(ns status-im.contexts.settings.wallet.network-settings.view
(:require [quo.core :as quo]
[quo.foundations.colors :as colors]
[quo.foundations.resources :as resources]
[quo.theme]
[react-native.core :as rn]
@ -80,12 +79,11 @@
(defn on-change-testnet
[{:keys [enable? blur? theme]}]
(rf/dispatch [:show-bottom-sheet
{:content (fn [] [testnet/view
{:enable? enable?
:blur? blur?}])
:theme theme
:shell? blur?
:blur-background colors/bottom-sheet-background-blur}]))
{:content (fn [] [testnet/view
{:enable? enable?
:blur? blur?}])
:theme theme
:shell? blur?}]))
(defn view
[]

View File

@ -27,4 +27,5 @@
{:color colors/white-opa-40})
(def saved-address-item
{:margin-top 4})
{:margin-top 4
:background-color colors/white-opa-5})

View File

@ -49,6 +49,7 @@
:multiline? true
:on-clear clear-input
:return-key-type :done
:auto-focus true
:clearable? (not empty-input?)
:on-change-text on-change-text
:button (when empty-input?
@ -83,7 +84,7 @@
[quo/info-message
{:accessibility-label :error-message
:size :default
:icon :i/info
:icon :i/alert
:type :error
:style style/info-message}
error-msg])))
@ -91,8 +92,7 @@
(defn- existing-saved-address
[{:keys [address]}]
(let [{:keys [name customization-color chain-short-names ens ens?]}
(rf/sub [:wallet/saved-address-by-address
address])]
(rf/sub [:wallet/saved-address-by-address address])]
[rn/view {:style style/existing-saved-address-container}
[quo/text
{:size :paragraph-1

View File

@ -93,20 +93,19 @@
:subtitle-type :default
:label :none
:blur? true
:icon-right? (not ens?)
:right-icon :i/advanced
:right-icon (when-not ens? :i/advanced)
:card? true
:title (i18n/label :t/address)
:subtitle ens
:custom-subtitle address-text
:on-press open-network-preferences
:on-press (when-not ens? open-network-preferences)
:container-style style/data-item}
ens?
(dissoc :custom-subtitle))
[ens ens? open-network-preferences address-text])]
[quo/overlay {:type :shell}
[floating-button-page/view
{:footer-container-padding 0
{:footer-container-padding (if edit? (+ (safe-area/get-bottom) 12) 0)
:header [quo/page-nav
{:type :no-title
:background :blur
@ -133,7 +132,7 @@
:container-style style/avatar}]
[quo/title-input
{:blur? true
:auto-focus true
:auto-focus (not edit?)
:max-length 24
:size :heading-1
:placeholder placeholder

View File

@ -2,7 +2,6 @@
(:require
[clojure.string :as string]
[quo.core :as quo]
[quo.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.platform :as platform]
[status-im.constants :as constants]
@ -52,11 +51,10 @@
open-remove-confirmation-sheet (rn/use-callback
#(rf/dispatch
[:show-bottom-sheet
{:theme :dark
:shell? true
:blur-background colors/bottom-sheet-background-blur
:content (fn []
[remove-address/view opts])}])
{:theme :dark
:shell? true
:content (fn []
[remove-address/view opts])}])
[opts])
open-show-address-qr (rn/use-callback
#(rf/dispatch [:open-modal

View File

@ -73,27 +73,34 @@
(defn- filtered-list
[{:keys [search-text]}]
[rn/flat-list
{:key-fn :address
:data (rf/sub [:wallet/filtered-saved-addresses search-text])
:render-fn saved-address
:shows-vertical-scroll-indicator false
:keyboard-should-persist-taps :always
:content-container-style {:flex-grow 1}
:empty-component [empty-result]}])
(let [search-result (rf/sub [:wallet/filtered-saved-addresses search-text])]
(if (empty? search-result)
[empty-result]
[rn/flat-list
{:key-fn :address
:data search-result
:render-fn saved-address
:shows-vertical-scroll-indicator false
:keyboard-should-persist-taps :always
:content-container-style {:flex-grow 1}
:bounces false
:over-scroll-mode :never}])))
(defn- unfiltered-list
[{:keys [grouped-saved-addresses]}]
[rn/section-list
{:key-fn :title
:shows-vertical-scroll-indicator false
:sticky-section-headers-enabled false
:keyboard-should-persist-taps :always
:render-section-header-fn header
:sections grouped-saved-addresses
:render-fn saved-address
:content-container-style {:flex-grow 1}
:empty-component [empty-list]}])
(if (empty? grouped-saved-addresses)
[empty-list]
[rn/section-list
{:key-fn :title
:shows-vertical-scroll-indicator false
:sticky-section-headers-enabled false
:keyboard-should-persist-taps :always
:render-section-header-fn header
:sections grouped-saved-addresses
:render-fn saved-address
:bounces false
:over-scroll-mode :never
:content-container-style {:flex-grow 1}}]))
(defn- navigate-back
[]

View File

@ -2,7 +2,6 @@
(:require [quo.core :as quo]
[react-native.safe-area :as safe-area]
[status-im.contexts.settings.wallet.wallet-options.style :as style]
[status-im.feature-flags :as ff]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@ -16,16 +15,14 @@
(defn basic-settings-options
[]
[(when (ff/enabled? ::ff/settings.keypairs-and-accounts)
{:title (i18n/label :t/keypairs-and-accounts)
:blur? true
:on-press open-keypairs-and-accounts-settings-modal
:action :arrow})
(when (ff/enabled? ::ff/settings.saved-addresses)
{:title (i18n/label :t/saved-addresses)
:blur? true
:on-press open-saved-addresses-settings-modal
:action :arrow})])
[{:title (i18n/label :t/keypairs-and-accounts)
:blur? true
:on-press open-keypairs-and-accounts-settings-modal
:action :arrow}
{:title (i18n/label :t/saved-addresses)
:blur? true
:on-press open-saved-addresses-settings-modal
:action :arrow}])
(defn basic-settings
[]
@ -74,7 +71,5 @@
[quo/page-top
{:title (i18n/label :t/wallet)
:title-accessibility-label :wallet-settings-header}]
(when (or (ff/enabled? ::ff/settings.keypairs-and-accounts)
(ff/enabled? ::ff/settings.saved-addresses))
[basic-settings])
[basic-settings]
[advanced-settings]]))

View File

@ -1,6 +1,7 @@
(ns status-im.contexts.shell.qr-reader.sheets.scanned-wallet-address
(:require
[quo.core :as quo]
[status-im.feature-flags :as ff]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@ -20,7 +21,8 @@
:recipient address
:stack-id :wallet-select-address
:start-flow? true}]))}
{:icon :i/save
:accessibility-label :save-address
:label (i18n/label :t/save-address)
:on-press #(js/alert "feature not implemented")}]]]])
(when (ff/enabled? :ff/wallet.saved-addresses)
{:icon :i/save
:accessibility-label :save-address
:label (i18n/label :t/save-address)
:on-press #(js/alert "feature not implemented")})]]]])

View File

@ -16,12 +16,13 @@
(rf/dispatch [:wallet/get-collectible-details id]))
(defn- on-collectible-long-press
[{:keys [preview-url collectible-details]}]
[{:keys [preview-url collectible-details id]}]
(rf/dispatch [:show-bottom-sheet
{:content (fn []
[options-drawer/view
{:name (:name collectible-details)
:image (:uri preview-url)}])}]))
:image (:uri preview-url)
:id id}])}]))
(defn- on-end-reached
[]

View File

@ -124,7 +124,7 @@
:on-success on-success
:on-error (fn [error]
(log/error
"Failed to resolve next path derivation path"
"Failed to resolve next derivation path"
{:event :wallet/next-derivation-path
:method "accounts_resolveSuggestedPathForKeypair"
:error error
@ -191,7 +191,7 @@
(rf/reg-event-fx
:wallet/derive-address-and-add-account
(fn [_ [{:keys [password derived-from-address derivation-path account-preferences]}]]
(fn [_ [{:keys [password derived-from-address derivation-path account-preferences key-uid]}]]
{:fx [[:json-rpc/call
[{:method "wallet_getDerivedAddresses"
:params [(security/safe-unmask-data password)
@ -199,9 +199,10 @@
[derivation-path]]
:on-success (fn [[derived-account]]
(rf/dispatch [:wallet/add-account
(assoc account-preferences :password password)
(assoc account-preferences
:key-uid key-uid
:password password)
derived-account]))
:on-error #(log/info "Failed to get derived addresses"
derived-from-address
%)}]]]}))
:on-error [:wallet/log-rpc-error
{:event :wallet/derive-address-and-add-account
:params [derived-from-address [derivation-path]]}]}]]]}))

View File

@ -105,8 +105,7 @@
[quo/bottom-actions
{:actions :one-action
:button-one-label (i18n/label :t/confirm-account-origin)
:button-one-props {:disabled? (= selected-keypair selected-key-uid)
:customization-color customization-color
:button-one-props {:customization-color customization-color
:on-press #(rf/dispatch [:wallet/confirm-account-origin
selected-key-uid])}
:container-style style/bottom-action-container}]]))

View File

@ -48,7 +48,6 @@
:action-props {:on-press #(rf/dispatch [:standard-auth/authorize
{:on-auth-success on-auth-success
:auth-button-label (i18n/label :t/continue)}])
:button-text (i18n/label :t/edit)
:icon-left :i/face-id
:alignment :flex-start}
@ -70,7 +69,7 @@
:icon-only? true
:on-press #(rf/dispatch [:emoji-picker/open {:on-select on-select-emoji}])
:container-style style/reaction-button-container}
:i/reaction]])
:i/edit]])
(defn- input
[_]
@ -217,6 +216,7 @@
[:wallet/derive-address-and-add-account
{:password password
:derived-from-address derived-from
:key-uid key-uid
:derivation-path @derivation-path
:account-preferences preferences}])))
[derived-from])]
@ -231,7 +231,7 @@
{:account-color @account-color
:slide-button-props {:on-auth-success on-auth-success
:disabled? (or (empty? @account-name)
(= "" @derivation-path)
(string/blank? @derivation-path)
(some? error))}}
[avatar
{:account-color @account-color

View File

@ -1,5 +1,6 @@
(ns status-im.contexts.wallet.collectible.events
(:require [camel-snake-kebab.extras :as cske]
[react-native.platform :as platform]
[status-im.contexts.wallet.collectible.utils :as collectible-utils]
[taoensso.timbre :as log]
[utils.ethereum.chain :as chain]
@ -200,25 +201,35 @@
(rf/reg-event-fx :wallet/trigger-share-collectible
(fn [_ [{:keys [title uri]}]]
{:fx [[:effects.share/open
{:title title
:message title
:url uri}]]}))
{:fx [[:dispatch
[:open-share
{:options (if platform/ios?
{:activityItemSources
[{:placeholderItem {:type :text
:content uri}
:item {:default {:type :url
:content uri}}
:linkMetadata {:title title}}]}
{:title title
:subject title
:url uri
:isNewTask true})}]]]}))
(rf/reg-event-fx :wallet/share-collectible
(fn [_ [{:keys [title uri in-sheet?]}]]
(if in-sheet?
(fn [{:keys [db]} [{:keys [title token-id contract-address chain-id]}]]
(let [uri (collectible-utils/get-opensea-collectible-url
{:chain-id chain-id
:token-id token-id
:contract-address contract-address
:test-networks-enabled? (get-in db [:profile/profile :test-networks-enabled?])
:is-goerli-enabled? (get-in db [:profile/profile :is-goerli-enabled?])})]
{:fx [[:dispatch
[:hide-bottom-sheet]]
[:dispatch-later
{:ms 600
:dispatch [:wallet/trigger-share-collectible
{:title title
:uri uri}]}]]}
{:fx [[:dispatch
[:wallet/trigger-share-collectible
{:title title
:uri uri}]]]})))
:uri uri}]}]]})))
(rf/reg-event-fx
:wallet/navigate-to-opensea

View File

@ -7,15 +7,18 @@
[utils.url :as url]))
(defn view
[{:keys [image name chain-id address]}]
(let [uri (url/replace-port image (rf/sub [:mediaserver/port]))]
[{:keys [image name id]}]
(let [chain-id (get-in id [:contract-id :chain-id])
token-id (:token-id id)
contract-address (get-in id [:contract-id :address])
uri (url/replace-port image (rf/sub [:mediaserver/port]))]
[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)
address]))
contract-address]))
:label (i18n/label :t/view-on-eth)
:right-icon :i/external}]
[{:icon :i/save
@ -34,6 +37,14 @@
:accessibility-label :share-collectible
:label (i18n/label :t/share-collectible)
:on-press #(rf/dispatch [:wallet/share-collectible
{:in-sheet? true
:title name
:uri uri}])}]]]))
{:token-id token-id
:contract-address contract-address
:chain-id chain-id
:title name}])}]]]))
"222"
"https://nft-cdn.alchemy.com/eth-mainnet/219530f9b3a7901f02169334d593823e"
"Tengria #913"
{:contract-id {:chain-id 1 :address "0x1a4ceef5d575c2228d142ef862a9b60be8161e7f"} :token-id "913"}
{:contract-id {:chain-id 1 :address "0x1a4ceef5d575c2228d142ef862a9b60be8161e7f"} :token-id "913"}

View File

@ -79,7 +79,8 @@
(js/setTimeout #(rf/dispatch [:wallet/clear-last-collectible-details]) 700))
(defn animated-header
[{:keys [scroll-amount title-opacity page-nav-type picture title description theme]}]
[{:keys [scroll-amount title-opacity page-nav-type picture title description theme
id]}]
(let [blur-amount (header-animations/use-blur-amount scroll-amount)
layer-opacity (header-animations/use-layer-opacity
scroll-amount
@ -110,7 +111,8 @@
{:content (fn []
[options-drawer/view
{:name title
:image picture}])
:image picture
:id id}])
:theme theme}])}]
:center-opacity title-opacity}]]]]))
@ -197,7 +199,8 @@
[options-drawer/view
{:name collectible-name
:image
preview-uri}])}])}])))
preview-uri
:id id}])}])}])))
:on-collectible-load (fn []
;; We need to delay the measurement because the
;; navigation has an animation
@ -246,7 +249,8 @@
{collection-name :name} collection-data]
[rn/view {:style (style/background-color theme)}
[animated-header
{:scroll-amount scroll-amount
{:id (:id collectible)
:scroll-amount scroll-amount
:title-opacity title-opacity
:page-nav-type :title-description
:picture preview-uri

View File

@ -4,7 +4,6 @@
[status-im.contexts.wallet.sheets.account-options.view :as account-options]
[status-im.contexts.wallet.sheets.network-filter.view :as network-filter]
[status-im.contexts.wallet.sheets.select-account.view :as select-account]
[status-im.feature-flags :as ff]
[utils.re-frame :as rf]))
(defn get-bottom-sheet-args
@ -37,7 +36,7 @@
:networks networks
:align-center? true
:networks-on-press #(rf/dispatch [:show-bottom-sheet {:content network-filter/view}])
:right-side [(when (and (ff/enabled? ::ff/wallet.wallet-connect)
:right-side [(when (and true
(not watch-only?))
{:icon-name :i/dapps
:on-press #(rf/dispatch [:navigate-to :screen/wallet.connected-dapps])})

View File

@ -28,7 +28,7 @@
(let [{:keys [on-result]} (rf/sub [:get-screen-params])]
[scan-qr-code/view
{:title (i18n/label :t/scan-qr)
:subtitle (i18n/label :t/scan-an-account-qr-code)
:subtitle (i18n/label :t/scan-an-address-qr-code)
:error-message (i18n/label :t/oops-this-qr-does-not-contain-an-address)
:validate-fn #(contains-supported-address? %)
:on-success-scan (fn [result]

View File

@ -49,7 +49,7 @@
:icon-only? true
:on-press #(rf/dispatch [:emoji-picker/open {:on-select on-change-emoji}])
:container-style style/reaction-button-container}
:i/reaction]]
:i/edit]]
[rn/view
[quo/title-input

View File

@ -220,7 +220,7 @@
(defn make-network-item
"This function generates props for quo/category component item"
[{:keys [network-name color on-change networks state label-props type]}]
[{:keys [network-name color on-change networks state label-props type blur?]}]
(cond-> {:title (string/capitalize (name network-name))
:image :icon-avatar
:image-props {:icon (resources/get-network network-name)
@ -230,6 +230,7 @@
(if (= :default state)
:filled-checkbox
:checkbox))
:blur? blur?
:customization-color color
:checked? (contains? networks network-name)
:on-change on-change}}

View File

@ -1,5 +1,6 @@
(ns status-im.contexts.wallet.common.utils.networks
(:require [clojure.string :as string]
[quo.foundations.resources :as resources]
[status-im.constants :as constants]
[utils.number]))
@ -141,3 +142,41 @@
(let [token-networks-ids (mapv #(:chain-id %) token-networks)
token-networks-ids-set (set token-networks-ids)]
(contains? token-networks-ids-set chain-id)))
(def mainnet-network-details
{:source (resources/get-network constants/mainnet-network-name)
:short-name constants/mainnet-short-name
:full-name constants/mainnet-full-name
:network-name constants/mainnet-network-name
:abbreviated-name constants/mainnet-abbreviated-name})
(def arbitrum-network-details
{:source (resources/get-network constants/arbitrum-network-name)
:short-name constants/arbitrum-short-name
:full-name constants/arbitrum-full-name
:network-name constants/arbitrum-network-name
:abbreviated-name constants/arbitrum-abbreviated-name})
(def optimism-network-details
{:source (resources/get-network constants/optimism-network-name)
:short-name constants/optimism-short-name
:full-name constants/optimism-full-name
:network-name constants/optimism-network-name
:abbreviated-name constants/optimism-abbreviated-name})
(defn get-network-details
[chain-id]
(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/optimism-mainnet-chain-id constants/optimism-goerli-chain-id
constants/optimism-sepolia-chain-id}
optimism-network-details
nil))

View File

@ -73,7 +73,7 @@
(fn [resolver rejecter]
(json-rpc/call {:method "accounts_makeSeedPhraseKeypairFullyOperable"
:params [(security/safe-unmask-data mnemonic)
(-> password security/safe-unmask-data native-module/sha3)]
(security/safe-unmask-data password)]
:on-error (fn [error]
(rejecter (ex-info (str error) {:error error})))
:on-success (fn [value]

View File

@ -215,13 +215,12 @@
[:dispatch [:wallet/clear-create-account]]]}))
(rf/reg-event-fx :wallet/add-account
(fn [{:keys [db]}
[{:keys [password account-name emoji color type]
(fn [_
[{:keys [key-uid password account-name emoji color type]
:or {type :generated}}
{:keys [public-key address path] :as _derived-account}]]
(let [lowercase-address (some-> address
(string/lower-case))
key-uid (get-in db [:wallet :ui :create-account :selected-keypair-uid])
string/lower-case)
account-config {:key-uid (when (= type :generated) key-uid)
:wallet false
:chat false
@ -529,18 +528,17 @@
:wallet/process-keypair-from-backup
(fn [{:keys [db]} [{:keys [backedUpKeypair]}]]
(let [{:keys [key-uid accounts]} backedUpKeypair
updated-keypairs (assoc-in db
[:wallet :keypairs key-uid]
(data-store/rpc->keypair backedUpKeypair))
accounts-fx (mapv (fn [{:keys [chat] :as account}]
;; We exclude the chat account from the profile keypair
;; for fetching the assets
(when-not chat
[:dispatch
[:wallet/process-account-from-signal
account]]))
accounts)]
{:db (assoc-in db [:wallet :keypairs] updated-keypairs)
accounts-fx
(mapv (fn [{:keys [chat] :as account}]
;; We exclude the chat account from the profile keypair for fetching the assets
(when-not chat
[:dispatch
[:wallet/process-account-from-signal
account]]))
accounts)]
{:db (assoc-in db
[:wallet :keypairs key-uid]
(data-store/rpc->keypair backedUpKeypair))
:fx accounts-fx})))
(rf/reg-event-fx

View File

@ -9,16 +9,13 @@
[utils.re-frame :as rf]))
(defn- on-collectible-long-press
[{:keys [preview-url collectible-details id]}]
(let [chain-id (get-in id [:contract-id :chain-id])
address (get-in id [:contract-id :address])]
(rf/dispatch [:show-bottom-sheet
{:content (fn []
[options-drawer/view
{:chain-id chain-id
:address address
:name (:name collectible-details)
:image (:uri preview-url)}])}])))
[{:keys [preview-url :collectible-data id]}]
(rf/dispatch [:show-bottom-sheet
{:content (fn []
[options-drawer/view
{:id id
:name (:name collectible-data)
:image (:uri preview-url)}])}]))
(defn- on-collectible-press
[{:keys [id]}]

View File

@ -205,21 +205,22 @@
token-networks-ids (mapv #(:chain-id %) token-networks)
token-not-supported-in-receiver-networks? (not-any? (set receiver-networks)
token-networks-ids)]
{:db (cond-> db
:always (update-in [:wallet :ui :send] dissoc :collectible)
:always (assoc-in [:wallet :ui :send :token-display-name]
(:symbol token))
:always (assoc-in
[:wallet :ui :send :token-not-supported-in-receiver-networks?]
token-not-supported-in-receiver-networks?)
token (assoc-in [:wallet :ui :send :token] token)
token-symbol (assoc-in [:wallet :ui :send :token-symbol] token-symbol))
:fx [[:dispatch [:wallet/clean-suggested-routes]]
[:dispatch
[:wallet/wizard-navigate-forward
{:current-screen stack-id
:start-flow? start-flow?
:flow-id :wallet-send-flow}]]]})))
(when (or token token-symbol)
{:db (cond-> db
:always (update-in [:wallet :ui :send] dissoc :collectible)
:always (assoc-in
[:wallet :ui :send :token-not-supported-in-receiver-networks?]
token-not-supported-in-receiver-networks?)
token (assoc-in [:wallet :ui :send :token] token)
token (assoc-in [:wallet :ui :send :token-display-name]
(:symbol token))
token-symbol (assoc-in [:wallet :ui :send :token-symbol] token-symbol))
:fx [[:dispatch [:wallet/clean-suggested-routes]]
[:dispatch
[:wallet/wizard-navigate-forward
{:current-screen stack-id
:start-flow? start-flow?
:flow-id :wallet-send-flow}]]]}))))
(rf/reg-event-fx
:wallet/edit-token-to-send

View File

@ -0,0 +1,165 @@
(ns status-im.contexts.wallet.send.events-test
(:require
[cljs.test :refer-macros [is testing]]
[re-frame.db :as rf-db]
status-im.contexts.wallet.send.events
[test-helpers.unit :as h]))
(h/deftest-event :wallet/update-receiver-networks
[event-id dispatch]
(testing "reciever networks changed"
(let [selected-networks-before [:ethereum :optimism :arbitrum]
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
[event-id dispatch]
(let [token-symbol "ETH"
token {:symbol "ETH"
:name "Ether"
:networks #{{:chain-id 421614}
{:chain-id 11155420}
{:chain-id 11155111}}}
receiver-networks [421614 11155420]]
(testing "can be called with :token"
(let [initial-db {:wallet {:ui {:send {:receiver-networks receiver-networks}}}}
expected-db {:wallet {:ui {:send {:token-display-name token-symbol
:token-not-supported-in-receiver-networks? false}}}}
_ (reset! rf-db/app-db initial-db)
result (dispatch [event-id {:token token}])]
(is (match? expected-db (:db result)))))
(testing "can be called with :token-symbol"
(testing "can be called with :token"
(let [initial-db {:wallet {:ui {:send {:receiver-networks receiver-networks}}}}
expected-db {:wallet {:ui {:send {:token-symbol token-symbol
:token-not-supported-in-receiver-networks? true}}}}
_ (reset! rf-db/app-db initial-db)
result (dispatch [event-id {:token-symbol token-symbol}])]
(is (match? expected-db (:db result))))))
(testing "shouldn't have changes if called without :token or :token-symbol")
(let [initial-db {:wallet {:ui {:send {:receiver-networks receiver-networks}}}}
expected-db nil
_ (reset! rf-db/app-db initial-db)
result (dispatch [event-id {}])]
(is (match? expected-db (:db result))))
(testing "should clean :collectible set"
(let [initial-db {:wallet {:ui {:send {:receiver-networks receiver-networks
:collectible "some-collectible"}}}}
expected-db {:wallet {:ui {:send {:token-display-name token-symbol
:token-not-supported-in-receiver-networks? false}}}}
_ (reset! rf-db/app-db initial-db)
result (dispatch [event-id {:token token}])]
(is (match? expected-db (:db result)))
(is (match? nil (get-in result [:db :wallet :ui :send :collectible])))))
(testing "should set :token-not-supported-in-receiver-networks?"
(let [initial-db {:wallet {:ui {:send {:receiver-networks []}}}}
expected-db {:wallet {:ui {:send {:token-display-name token-symbol
:token-not-supported-in-receiver-networks? true}}}}
_ (reset! rf-db/app-db initial-db)
result (dispatch [event-id {:token token}])]
(is (match? expected-db (:db result)))))))
(h/deftest-event :wallet/edit-token-to-send
[event-id dispatch]
(let [token-symbol "ETH"
token {:symbol "ETH"
:name "Ether"
:networks #{{:chain-id 421614}
{:chain-id 11155420}
{:chain-id 11155111}}}
receiver-networks [421614 11155420]]
(testing "can be called with :token"
(let [initial-db {:wallet {:ui {:send {:receiver-networks receiver-networks
:token-display-name "DAI"
:token-not-supported-in-receiver-networks? true}}}}
expected-db {:wallet {:ui {:send {:token-display-name token-symbol
:token-not-supported-in-receiver-networks? false}}}}
_ (reset! rf-db/app-db initial-db)
result (dispatch [event-id token])]
(is (match? expected-db (:db result)))))
(testing "should set :token-not-supported-in-receiver-networks?"
(let [initial-db {:wallet {:ui {:send {:receiver-networks []
:token-display-name "DAI"
:token-not-supported-in-receiver-networks? false}}}}
expected-db {:wallet {:ui {:send {:token-display-name token-symbol
:token-not-supported-in-receiver-networks? true}}}}
_ (reset! rf-db/app-db initial-db)
result (dispatch [event-id token])]
(is (match? expected-db (:db result)))))))
(h/deftest-event :wallet/set-collectible-to-send
[event-id dispatch]
(let
[collectible
{:data-type 2
:id
{:contract-id
{:chain-id 11155111
:address "0x1ed60fedff775d500dde21a974cd4e92e0047cc8"}
:token-id "15"}
:contract-type 3
:collectible-data
{:name "DOG #1"
:description
"dogs are cute and this one is the cutestdogs are cute and this one is the cutest"}
:collection-data
{:name "ERC-1155 Faucet"}
:ownership
[{:address "0xf90014b2027e584fc96e6f6c8078998fe46c5ccb"
:balance "1"
:tx-timestamp 1710331776}]
:preview-url
{:uri
"https://ipfs.io/ipfs/bafybeie7b7g7iibpac4k6ydw4m5ivgqw5vov7oyzlf4v5zoor57wokmsxy/isolated-happy-smiling-dog-white-background-portrait-4_1562-693.avif"}}
initial-db {:wallet {:ui {:send {:token {:symbol "ETH"}}}}}
_ (reset! rf-db/app-db initial-db)
result (dispatch [event-id {:collectible collectible}])]
(testing ":collectible field assigned"
(is (match? collectible (get-in result [:db :wallet :ui :send :collectible]))))
(testing ":token should be removed"
(is (match? nil (get-in result [:db :wallet :ui :send :token]))))
(testing ":token-display-name assigned"
(is (match? "DOG #1" (get-in result [:db :wallet :ui :send :token-display-name]))))
(testing ":tx-type assigned"
(is (match? :tx/collectible-erc-1155 (get-in result [:db :wallet :ui :send :tx-type]))))
(testing "amount set if collectible was single"
(is (match? 1 (get-in result [:db :wallet :ui :send :amount]))))))
(h/deftest-event :wallet/set-collectible-amount-to-send
[event-id dispatch]
(let [initial-db {:wallet {:ui {:send nil}}}
expected-fx [[:dispatch [:wallet/get-suggested-routes {:amount 10}]]
[:dispatch
[:wallet/wizard-navigate-forward
{:current-screen nil :flow-id :wallet-send-flow}]]]
amount 10
_ (reset! rf-db/app-db initial-db)
result (dispatch [event-id {:amount amount}])]
(testing "amount set"
(is (match? amount (get-in result [:db :wallet :ui :send :amount]))))
(testing "effects match"
(is (match? expected-fx (:fx result))))))
(h/deftest-event :wallet/set-token-amount-to-send
[event-id dispatch]
(let [initial-db {:wallet {:ui {:send {:token {:symbol "ETH"}}}}}
amount 10
_ (reset! rf-db/app-db initial-db)
result (dispatch [event-id {:amount amount}])]
(testing "amount set"
(is (match? amount (get-in result [:db :wallet :ui :send :amount]))))))

View File

@ -47,6 +47,7 @@
:network-name :mainnet
:abbreviated-name
"Eth."
:full-name "Mainnet"
:chain-id 1
:related-chain-id 1
:layer 1}]
@ -92,6 +93,7 @@
:short-name "eth"
:network-name :mainnet
:abbreviated-name "Eth."
:full-name "Mainnet"
:chain-id 1
:related-chain-id 1
:layer 1}]

View File

@ -15,6 +15,7 @@
[status-im.contexts.wallet.send.routes.view :as routes]
[status-im.contexts.wallet.sheets.buy-token.view :as buy-token]
[status-im.contexts.wallet.sheets.unpreferred-networks-alert.view :as unpreferred-networks-alert]
[status-im.feature-flags :as ff]
[utils.debounce :as debounce]
[utils.i18n :as i18n]
[utils.money :as money]
@ -24,16 +25,17 @@
(defn- estimated-fees
[{:keys [loading-routes? fees amount]}]
[rn/view {:style style/estimated-fees-container}
[rn/view {:style style/estimated-fees-content-container}
[quo/button
{:icon-only? true
:type :outline
:size 32
:inner-style {:opacity 1}
:accessibility-label :advanced-button
:disabled? loading-routes?
:on-press #(js/alert "Not implemented yet")}
:i/advanced]]
(when (ff/enabled? ::ff/wallet.advanced-sending)
[rn/view {:style style/estimated-fees-content-container}
[quo/button
{:icon-only? true
:type :outline
:size 32
:inner-style {:opacity 1}
:accessibility-label :advanced-button
:disabled? loading-routes?
:on-press #(js/alert "Not implemented yet")}
:i/advanced]])
[quo/data-item
{:container-style style/fees-data-item
:status (if loading-routes? :loading :default)
@ -376,7 +378,7 @@
sender-network-values
token-not-supported-in-receiver-networks?)
[token-not-available token-symbol receiver-networks token-networks])
(when (or loading-routes? route)
(when (and (not no-routes-found?) (or loading-routes? route))
[estimated-fees
{:loading-routes? loading-routes?
:fees fee-formatted

View File

@ -82,11 +82,12 @@
empty-state-component (rn/use-memo
(fn []
[quo/empty-state
{:title (i18n/label :t/no-saved-addresses)
:description (i18n/label
:t/you-like-to-type-43-characters)
:image (resources/get-themed-image :sweating-man
theme)}])
{:title (i18n/label :t/no-saved-addresses)
:description (i18n/label
:t/you-like-to-type-43-characters)
:container-style style/empty-container-style
:image (resources/get-themed-image :sweating-man
theme)}])
[theme])]
[rn/section-list
{:key-fn :title
@ -94,6 +95,7 @@
:render-section-header-fn section-header
:sections group-saved-addresses
:render-fn saved-address
:content-container-style {:flex 1}
:empty-component empty-state-component}]))
(defn view

View File

@ -136,7 +136,7 @@
:keyboard-should-persist-taps :handled
:render-fn suggestion-component}]]))
(defn- f-view
(defn view
[]
(let [on-close (fn []
(rf/dispatch [:wallet/clean-scanned-address])
@ -155,7 +155,8 @@
local-suggestion-address (rf/sub [:wallet/local-suggestions->full-address])
color (rf/sub [:wallet/current-viewing-account-color])]
[floating-button-page/view
{:footer-container-padding 0
{:content-container-style {:flex 1}
:footer-container-padding 0
:keyboard-should-persist-taps true
:header [account-switcher/view
{:on-press on-close
@ -205,7 +206,3 @@
:scrollable? true
:on-change on-change-tab}]
[tabs/view {:selected-tab selected-tab}]])]))))
(defn view
[]
[:f> f-view])

View File

@ -90,10 +90,7 @@
:address address
:blur? blur?
:format :long}])
:container-style (merge style/data-item
{:background-color (colors/theme-colors colors/neutral-2_5
colors/neutral-90
theme)})}])
:container-style style/data-item}])
[quo/category
{:list-type :settings
:blur? blur?
@ -106,6 +103,7 @@
:normal-checkbox? receiver?
:networks (get-current-preferences-names)
:type :checkbox
:blur? blur?
:on-change (fn []
(toggle-network (:network-name
network))
@ -137,6 +135,7 @@
:normal-checkbox? receiver?
:networks (get-current-preferences-names)
:type :checkbox
:blur? blur?
:on-change (fn []
(toggle-network (:network-name
network))

View File

@ -1,8 +1,19 @@
(ns status-im.contexts.wallet.wallet-connect.core
(:require [native-module.core :as native-module]
(:require [clojure.edn :as edn]
[clojure.string :as string]
[native-module.core :as native-module]
[status-im.constants :as constants]
[utils.security.core :as security]
[utils.transforms :as transforms]))
(def method-to-screen
{constants/wallet-connect-personal-sign-method :screen/wallet-connect.sign-message
constants/wallet-connect-eth-sign-typed-method :screen/wallet-connect.sign-message
constants/wallet-connect-eth-sign-method :screen/wallet-connect.sign-message
constants/wallet-connect-eth-sign-typed-v4-method :screen/wallet-connect.sign-message
constants/wallet-connect-eth-send-transaction-method :screen/wallet-connect.send-transaction
constants/wallet-connect-eth-sign-transaction-method :screen/wallet-connect.sign-transaction})
(defn extract-native-call-signature
[data]
(-> data transforms/json->clj :result))
@ -11,6 +22,13 @@
[chain-id]
(str "eip155:" chain-id))
(defn eip155->chain-id
[chain-id-str]
(-> chain-id-str
(string/split #":")
last
edn/read-string))
(defn format-eip155-address
[address chain-id]
(str chain-id ":" address))
@ -23,9 +41,14 @@
[event]
(get-in event [:params :request :params]))
(defn get-db-current-request-event
[db]
(get-in db [:wallet-connect/current-request :event]))
(defn get-db-current-request-params
[db]
(-> (get-in db [:wallet-connect/current-request :event])
(-> db
get-db-current-request-event
get-request-params))
(def ^:private sign-typed-data-by-version

View File

@ -70,7 +70,7 @@
{:db (dissoc db :wallet-connect/current-proposal)}))
(rf/reg-event-fx
:wallet-connect/reset-current-session-request
:wallet-connect/reset-current-request
(fn [{:keys [db]}]
{:db (dissoc db :wallet-connect/current-request)}))
@ -107,12 +107,6 @@
:on-fail #(log/error "Failed to pair with dApp" {:error %})
:on-success #(log/info "dApp paired successfully")}]]})))
(rf/reg-event-fx
:wallet-connect/close-session-request
(fn [_ _]
{:fx [[:dispatch [:dismiss-modal :screen/wallet.wallet-connect-session-proposal]]
[:dispatch [:wallet-connect/reset-current-session-request]]]}))
(rf/reg-event-fx
:wallet-connect/fetch-active-sessions
(fn [{:keys [db]}]

View File

@ -0,0 +1,8 @@
(ns status-im.contexts.wallet.wallet-connect.modals.common.data-block.view
(:require [status-im.common.raw-data-block.view :as raw-data-block]
[utils.re-frame :as rf]))
(defn view
[]
(let [display-data (rf/sub [:wallet-connect/current-request-display-data])]
[raw-data-block/view display-data]))

View File

@ -0,0 +1,18 @@
(ns status-im.contexts.wallet.wallet-connect.modals.common.footer.style)
(def content-container
{:padding-horizontal 20})
(def data-items-container
{:flex-direction :row
:padding-top 12
:padding-bottom 4
:gap 16})
(def auth-container
{:height 48
:margin-vertical 12})
(def warning-container
{:align-items :center
:margin-bottom 12})

View File

@ -0,0 +1,35 @@
(ns status-im.contexts.wallet.wallet-connect.modals.common.footer.view
(:require [quo.core :as quo]
[quo.foundations.colors :as colors]
[react-native.core :as rn]
[status-im.common.standard-authentication.core :as standard-authentication]
[status-im.contexts.wallet.wallet-connect.modals.common.footer.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- on-auth-success
[password]
(rf/dispatch [:hide-bottom-sheet])
(rf/dispatch [:wallet-connect/respond-current-session password]))
(defn view
[{: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
{:style style/data-items-container}]
children)
[rn/view {:style style/auth-container}
[standard-authentication/slide-button
{:size :size-48
:track-text slide-button-text
:disabled? disabed?
:customization-color customization-color
:on-auth-success on-auth-success
:auth-button-label (i18n/label :t/confirm)}]]
[rn/view {:style style/warning-container}
[quo/text
{:size :paragraph-2
:style {:color colors/neutral-80-opa-70}
:weight :medium}
warning-label]]]))

View File

@ -0,0 +1,10 @@
(ns status-im.contexts.wallet.wallet-connect.modals.common.header.style)
(def header-container
{:padding-vertical 12})
(def header-dapp-name
{:margin-top -4})
(def header-account-name
{:padding-top 4})

View File

@ -0,0 +1,26 @@
(ns status-im.contexts.wallet.wallet-connect.modals.common.header.view
(:require [quo.core :as quo]
[react-native.core :as rn]
[status-im.contexts.wallet.wallet-connect.modals.common.header.style :as style]))
(defn view
[{:keys [label dapp account]}]
[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 (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}]])]])

View File

@ -0,0 +1,23 @@
(ns status-im.contexts.wallet.wallet-connect.modals.common.style
(:require [status-im.constants :as constants]))
(defn container
[bottom]
{:position :absolute
:bottom bottom
:top 0
:left 0
:right 0
:padding-top constants/sheet-screen-handle-height})
(def data-content-container
{:flex 1
:padding-horizontal 20})
(def sign-message-content-container
(merge data-content-container
{:margin-bottom 10.5}))
(def data-item
{:flex 1
:background-color :transparent})

View File

@ -0,0 +1,63 @@
(ns status-im.contexts.wallet.wallet-connect.modals.send-transaction.view
(:require [quo.core :as quo]
[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.footer.view :as footer]
[status-im.contexts.wallet.wallet-connect.modals.common.header.view :as header]
[status-im.contexts.wallet.wallet-connect.modals.common.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn view
[]
(let [bottom (safe-area/get-bottom)
{:keys [customization-color]
:as account} (rf/sub [:wallet-connect/current-request-account-details])
dapp (rf/sub [:wallet-connect/current-request-dapp])
network (rf/sub [:wallet-connect/current-request-network])
{:keys [max-fees-fiat-formatted
error-state]} (rf/sub [:wallet-connect/current-request-transaction-information])]
[rn/view {:style (style/container bottom)}
[quo/gradient-cover {:customization-color customization-color}]
[quo/page-nav
{:icon-name :i/close
:background :blur
:on-press #(rf/dispatch [:navigate-back])
:accessibility-label :wallet-connect-sign-message-close}]
[rn/view {:flex 1}
[rn/view {:style style/data-content-container}
[header/view
{:label (i18n/label :t/wallet-connect-send-transaction-header)
:dapp dapp
:account account}]
[data-block/view]]
(when error-state
[quo/alert-banner
{:action? false
:text (i18n/label (condp = error-state
:not-enough-assets-to-pay-gas-fees
:t/not-enough-assets-to-pay-gas-fees
:not-enough-assets
:t/not-enough-assets))}])
[footer/view
{: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
{:status :default
:card? false
:container-style style/data-item
:title (i18n/label :t/network)
:subtitle-type :network
:network-image (:source network)
:subtitle (:full-name network)}]
[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))}]]]]))

View File

@ -0,0 +1,42 @@
(ns status-im.contexts.wallet.wallet-connect.modals.sign-message.view
(:require [quo.core :as quo]
[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.footer.view :as footer]
[status-im.contexts.wallet.wallet-connect.modals.common.header.view :as header]
[status-im.contexts.wallet.wallet-connect.modals.common.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn view
[]
(let [bottom (safe-area/get-bottom)
{:keys [customization-color]
:as account} (rf/sub [:wallet-connect/current-request-account-details])
dapp (rf/sub [:wallet-connect/current-request-dapp])]
[rn/view {:style (style/container bottom)}
[quo/gradient-cover {:customization-color customization-color}]
[quo/page-nav
{:icon-name :i/close
:background :blur
:on-press #(rf/dispatch [:navigate-back])
:accessibility-label :wallet-connect-sign-message-close}]
[rn/view {:flex 1}
[rn/view {:style style/sign-message-content-container}
[header/view
{:label (i18n/label :t/wallet-connect-sign-message-header)
:dapp dapp
:account account}]
[data-block/view]]
[footer/view
{:warning-label (i18n/label :t/wallet-connect-sign-message-warning)
:slide-button-text (i18n/label :t/slide-to-sign)}
[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)}]]]]))

View File

@ -0,0 +1,63 @@
(ns status-im.contexts.wallet.wallet-connect.modals.sign-transaction.view
(:require [quo.core :as quo]
[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.footer.view :as footer]
[status-im.contexts.wallet.wallet-connect.modals.common.header.view :as header]
[status-im.contexts.wallet.wallet-connect.modals.common.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn view
[]
(let [bottom (safe-area/get-bottom)
{:keys [customization-color]
:as account} (rf/sub [:wallet-connect/current-request-account-details])
dapp (rf/sub [:wallet-connect/current-request-dapp])
network (rf/sub [:wallet-connect/current-request-network])
{:keys [max-fees-fiat-formatted
error-state]} (rf/sub [:wallet-connect/current-request-transaction-information])]
[rn/view {:style (style/container bottom)}
[quo/gradient-cover {:customization-color customization-color}]
[quo/page-nav
{:icon-name :i/close
:background :blur
:on-press #(rf/dispatch [:navigate-back])
:accessibility-label :wallet-connect-sign-message-close}]
[rn/view {:flex 1}
[rn/view {:style style/data-content-container}
[header/view
{:label (i18n/label :t/wallet-connect-sign-transaction-header)
:dapp dapp
:account account}]
[data-block/view]]
(when error-state
[quo/alert-banner
{:action? false
:text (i18n/label (condp = error-state
:not-enough-assets-to-pay-gas-fees
:t/not-enough-assets-to-pay-gas-fees
:not-enough-assets
:t/not-enough-assets))}])
[footer/view
{: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
{:status :default
:card? false
:container-style style/data-item
:title (i18n/label :t/network)
:subtitle-type :network
:network-image (:source network)
:subtitle (:full-name network)}]
[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))}]]]]))

View File

@ -6,31 +6,32 @@
[taoensso.timbre :as log]
[utils.transforms :as transforms]))
(def ^:private method-to-screen
{constants/wallet-connect-personal-sign-method :screen/wallet-connect.sign-message
constants/wallet-connect-eth-sign-typed-method :screen/wallet-connect.sign-message
constants/wallet-connect-eth-sign-method :screen/wallet-connect.sign-message
constants/wallet-connect-eth-sign-typed-v4-method :screen/wallet-connect.sign-message})
(rf/reg-event-fx
:wallet-connect/process-session-request
(fn [{:keys [db]} [event]]
(let [method (wallet-connect-core/get-request-method event)
screen (method-to-screen method)]
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-personal-sign-method
[:dispatch [:wallet-connect/process-personal-sign]]
constants/wallet-connect-eth-send-transaction-method
[:dispatch [:wallet-connect/process-eth-send-transaction]]
constants/wallet-connect-eth-sign-method
[:dispatch [:wallet-connect/process-eth-sign]]
constants/wallet-connect-eth-sign-transaction-method
[:dispatch [:wallet-connect/process-eth-sign-transaction]]
constants/wallet-connect-eth-sign-typed-method
[:dispatch [:wallet-connect/process-sign-typed]]
constants/wallet-connect-eth-sign-typed-v4-method
[:dispatch [:wallet-connect/process-sign-typed]])
[:dispatch [:wallet-connect/process-sign-typed]]
constants/wallet-connect-personal-sign-method
[:dispatch [:wallet-connect/process-personal-sign]])
[:dispatch [:open-modal screen]]]}
(log/error "Didn't find screen for Wallet Connect method"
{:method method
@ -60,6 +61,34 @@
:raw-data raw-data
: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)
display-data (-> event
clj->js
(js/JSON.stringify nil 2))
{:keys [to]} (-> event wallet-connect-core/get-request-params first)]
{:db (update-in db
[:wallet-connect/current-request]
assoc
:address to
:raw-data event
: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)
display-data (.stringify js/JSON (clj->js event) nil 2)
{:keys [to]} (-> event wallet-connect-core/get-request-params first)]
{:db (update-in db
[:wallet-connect/current-request]
assoc
:address to
:raw-data event
:display-data display-data)})))
(rf/reg-event-fx
:wallet-connect/process-sign-typed
(fn [{:keys [db]}]

View File

@ -13,9 +13,19 @@
constants/wallet-connect-personal-sign-method
[:dispatch [:wallet-connect/respond-personal-sign password]]
constants/wallet-connect-eth-send-transaction-method
[:dispatch
[:wallet-connect/respond-build-transaction
#(rf/dispatch [:wallet-connect/respond-send-transaction-data password %])]]
constants/wallet-connect-eth-sign-method
[:dispatch [:wallet-connect/respond-eth-sign password]]
constants/wallet-connect-eth-sign-transaction-method
[:dispatch
[:wallet-connect/respond-build-transaction
#(rf/dispatch [:wallet-connect/respond-sign-transaction-data password %])]]
constants/wallet-connect-eth-sign-typed-method
[:dispatch [:wallet-connect/respond-sign-typed-data password :v1]]
@ -57,12 +67,50 @@
:on-error #(rf/dispatch [:wallet-connect/on-sign-error %])
:on-success #(rf/dispatch [:wallet-connect/send-response %])}]]})))
(rf/reg-event-fx
:wallet-connect/respond-build-transaction
(fn [{:keys [db]} [on-success]]
(let [{:keys [raw-data]} (get db :wallet-connect/current-request)
chain-id (-> raw-data
(get-in [:params :chainId])
wallet-connect-core/eip155->chain-id)]
{:fx [[:json-rpc/call
[{:method "wallet_buildTransaction"
:params [chain-id (js/JSON.stringify raw-data)]
:on-success on-success
:on-error [:wallet-connect/on-sign-error]}]]]})))
(rf/reg-event-fx
:wallet-connect/respond-send-transaction-data
(fn [_ [password data]]
(let [{:keys [address]
message-to-sign :messageToSign} data]
{:fx [[:effects.wallet-connect/sign-message
{:password password
:address address
:data message-to-sign
:on-error #(rf/dispatch [:wallet-connect/on-sign-error %])
:on-success #(rf/dispatch [:wallet-connect/send-response %])}]]})))
(rf/reg-event-fx
:wallet-connect/respond-sign-transaction-data
(fn [_ [password data]]
(let [{:keys [address]
message-to-sign :messageToSign} data]
{:fx [[:effects.wallet-connect/sign-message
{:password password
:address address
:data message-to-sign
:on-error #(rf/dispatch [:wallet-connect/on-sign-error %])
:on-success #(rf/dispatch [:wallet-connect/send-response %])}]]})))
(rf/reg-event-fx
:wallet-connect/on-sign-error
(fn [{:keys [db]} [error]]
(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)]
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
@ -70,7 +118,8 @@
:method method
:wallet-connect-event event
:event :wallet-connect/on-sign-error})
{:fx [[:dispatch [:wallet-connect/close-session-request]]]})))
{:fx [[:dispatch [:dismiss-modal screen]]
[:dispatch [:wallet-connect/reset-current-request]]]})))
(rf/reg-event-fx
@ -78,6 +127,7 @@
(fn [{:keys [db]} [result]]
(let [{:keys [id topic] :as 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)
web3-wallet (get db :wallet-connect/web3-wallet)]
{:fx [[:effects.wallet-connect/respond-session-request
{:web3-wallet web3-wallet
@ -90,7 +140,9 @@
:method method
:event :wallet-connect/send-response
:wallet-connect-event event})
(rf/dispatch [:wallet-connect/close-session-request]))
(rf/dispatch [:dismiss-modal screen])
(rf/dispatch [:wallet-connect/reset-current-request]))
:on-success (fn []
(log/info "Successfully sent Wallet Connect response to dApp")
(rf/dispatch [:wallet-connect/close-session-request]))}]]})))
(rf/dispatch [:dismiss-modal screen])
(rf/dispatch [:wallet-connect/reset-current-request]))}]]})))

View File

@ -24,8 +24,3 @@
(def approval-li-spacer
{:width 8})
(def detail-item
{:margin-bottom 20
:margin-horizontal 20
:padding 12})

View File

@ -2,6 +2,7 @@
(:require
[quo.core :as quo]
[quo.foundations.colors :as colors]
[quo.foundations.resources :as quo.resources]
[quo.theme]
[react-native.core :as rn]
[status-im.common.floating-button-page.view :as floating-button-page]
@ -44,41 +45,47 @@
[quo/text label]])
labels)]))
(defn- accounts-data-item
(defn- get-placeholder-networks
[]
;; TODO. This account is currently hard coded in
;; `status-im.contexts.wallet.wallet-connect.events`. Should be selectable and changeable
(let [accounts (rf/sub [:wallet/accounts-without-watched-accounts])
name (-> accounts first :name)]
[quo/data-item
{:container-style style/detail-item
:blur? false
:description :default
:icon-right? true
:right-icon :i/chevron-right
:icon-color colors/neutral-10
:card? false
:label :preview
;; TODO. The quo component for data item doesn't support showing accounts yet
:status :default
:size :small
:title (i18n/label :t/account-title)
:subtitle name}]))
[{:source (quo.resources/get-network :ethereum)}
{:source (quo.resources/get-network :optimism)}
{:source (quo.resources/get-network :arbitrum)}])
(defn- networks-data-item
(defn- connection-category
[]
[quo/data-item
{:container-style style/detail-item
:blur? false
:description :default
:icon-right? true
:card? true
:label :none
:status :default
:size :small
:title (i18n/label :t/networks)
;; TODO. The quo component for data-item does not support showing networks yet
:subtitle "Networks will show up here"}])
(let [{:keys [name emoji customization-color]} (first (rf/sub
[:wallet/accounts-without-watched-accounts]))
data-item-common-props {:blur? false
:description :default
:card? false
:label :preview
:status :default
:size :default}
account-data-item-props (assoc data-item-common-props
:right-content {:type :accounts
:size :size-32
:data [{:emoji emoji
:customization-color
customization-color}]}
:on-press #(js/alert "Not yet implemented")
:title (i18n/label :t/account-title)
:subtitle name
:icon-right? true
:right-icon :i/chevron-right
:icon-color colors/neutral-10)
networks-data-item-props (assoc data-item-common-props
:right-content {:type :network
:data
(get-placeholder-networks)}
:title (i18n/label :t/networks)
;; TODO. The quo component for data-item
;; does not support showing networks yet
:subtitle "Networks placeholder")]
[quo/category
{:blur? false
:list-type :data-item
:data [account-data-item-props
networks-data-item-props]}]))
(defn- footer
[]
@ -114,6 +121,5 @@
:footer [footer]}
[rn/view
[dapp-metadata]
[accounts-data-item]
[networks-data-item]
[connection-category]
[approval-note]]])

View File

@ -1,29 +0,0 @@
(ns status-im.contexts.wallet.wallet-connect.sign-message.style
(:require [quo.foundations.colors :as colors]
[status-im.constants :as constants]))
(defn container
[bottom]
{:position :absolute
:bottom bottom
:top 0
:left 0
:right 0
:padding-top constants/sheet-screen-handle-height})
(def content-container
{:flex 1
:padding-horizontal 20})
(def fees-container
{:padding-top 12
:padding-bottom 4
:background-color colors/white})
(def auth-container
{:height 48
:margin-vertical 12})
(def warning-container
{:align-items :center
:margin-bottom 12})

View File

@ -1,82 +0,0 @@
(ns status-im.contexts.wallet.wallet-connect.sign-message.view
(:require [quo.core :as quo]
[quo.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[status-im.common.raw-data-block.view :as raw-data-block]
[status-im.common.standard-authentication.core :as standard-authentication]
[status-im.contexts.wallet.wallet-connect.sign-message.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- close-sheet
[]
(rf/dispatch [:navigate-back]))
(defn- on-auth-success
[password]
(rf/dispatch [:hide-bottom-sheet])
(rf/dispatch [:wallet-connect/respond-current-session password]))
;; NOTE: this will be a reusable component
(defn- header
[{:keys [emoji customization-color name]}]
[rn/view
{:style {:padding-vertical 12}}
[quo/text
{:size :heading-1
:weight :semi-bold}
[rn/view {:style {:margin-top -4}}
[quo/summary-tag
{:label "dapp placeholder"}]]
(i18n/label :t/wallet-connect-sign-header)
[rn/view {:style {:padding-top 4}}
[quo/summary-tag
{:type :account
:emoji emoji
:label name
:customization-color customization-color}]]]])
(defn data-block
[]
(let [display-data (rf/sub [:wallet-connect/current-request-display-data])]
[raw-data-block/view {:data display-data}]))
(defn view
[]
(let [bottom (safe-area/get-bottom)
{:keys [name emoji customization-color]} (rf/sub
[:wallet-connect/current-request-account-details])]
[rn/view {:style (style/container bottom)}
[quo/gradient-cover {:customization-color customization-color}]
[quo/page-nav
{:icon-name :i/close
:background :blur
:on-press close-sheet
:accessibility-label :wallet-connect-sign-message-close}]
[rn/view {:style style/content-container}
[header
{:emoji emoji
:customization-color customization-color
:name name}]
[data-block]
[quo/data-item
{:size :small
:status :default
:card? false
:container-style style/fees-container
:title (i18n/label :t/max-fees)
:subtitle (i18n/label :t/no-fees)}]
[rn/view {:style style/auth-container}
[standard-authentication/slide-button
{:size :size-48
:track-text (i18n/label :t/slide-to-sign)
:customization-color customization-color
:on-auth-success on-auth-success
:auth-button-label (i18n/label :t/confirm)}]]
[rn/view {:style style/warning-container}
[quo/text
{:size :paragraph-2
:style {:color colors/neutral-80-opa-70}
:weight :medium}
(i18n/label :t/wallet-connect-sign-warning)]]]]))

View File

@ -11,11 +11,10 @@
(def ^:private initial-flags
{::community.edit-account-selection (enabled-in-env? :FLAG_EDIT_ACCOUNT_SELECTION_ENABLED)
::settings.keypairs-and-accounts (enabled-in-env?
:FLAG_WALLET_SETTINGS_KEYPAIRS_AND_ACCOUNTS_ENABLED)
::settings.saved-addresses (enabled-in-env?
:FLAG_WALLET_SETTINGS_SAVED_ADDRESSES_ENABLED)
::settings.import-all-keypairs (enabled-in-env?
:FLAG_WALLET_SETTINGS_IMPORT_ALL_KEYPAIRS)
::shell.jump-to (enabled-in-env? :ENABLE_JUMP_TO)
::wallet.advanced-sending (enabled-in-env? :FLAG_ADVANCED_SENDING)
::wallet.assets-modal-hide (enabled-in-env? :FLAG_ASSETS_MODAL_HIDE)
::wallet.assets-modal-manage-tokens (enabled-in-env? :FLAG_ASSETS_MODAL_MANAGE_TOKENS)
::wallet.bridge-token (enabled-in-env? :FLAG_BRIDGE_TOKEN_ENABLED)
@ -24,6 +23,7 @@
::wallet.graph (enabled-in-env? :FLAG_GRAPH_ENABLED)
::wallet.import-private-key (enabled-in-env? :FLAG_IMPORT_PRIVATE_KEY_ENABLED)
::wallet.long-press-watch-only-asset (enabled-in-env? :FLAG_LONG_PRESS_WATCH_ONLY_ASSET_ENABLED)
::wallet.saved-addresses (enabled-in-env? :WALLET_SAVED_ADDRESSES)
::wallet.swap (enabled-in-env? :FLAG_SWAP_ENABLED)
::wallet.wallet-connect (enabled-in-env? :FLAG_WALLET_CONNECT_ENABLED)})

View File

@ -116,8 +116,12 @@
[status-im.contexts.wallet.send.transaction-confirmation.view :as wallet-transaction-confirmation]
[status-im.contexts.wallet.send.transaction-progress.view :as wallet-transaction-progress]
[status-im.contexts.wallet.swap.select-asset-to-pay.view :as wallet-swap-select-asset-to-pay]
[status-im.contexts.wallet.wallet-connect.modals.send-transaction.view :as
wallet-connect-send-transaction]
[status-im.contexts.wallet.wallet-connect.modals.sign-message.view :as wallet-connect-sign-message]
[status-im.contexts.wallet.wallet-connect.modals.sign-transaction.view :as
wallet-connect-sign-transaction]
[status-im.contexts.wallet.wallet-connect.session-proposal.view :as wallet-connect-session-proposal]
[status-im.contexts.wallet.wallet-connect.sign-message.view :as wallet-connect-sign-message]
[status-im.navigation.options :as options]
[status-im.navigation.transitions :as transitions]))
@ -531,6 +535,14 @@
:options {:sheet? true}
:component wallet-connect-sign-message/view}
{:name :screen/wallet-connect.sign-transaction
:options {:sheet? true}
:component wallet-connect-sign-transaction/view}
{:name :screen/wallet-connect.send-transaction
:options {:sheet? true}
:component wallet-connect-send-transaction/view}
;; Settings
{:name :screen/settings-password
@ -542,7 +554,7 @@
:component wallet-options/view}
{:name :screen/settings.rename-keypair
:options (assoc options/dark-screen :sheet? true)
:options options/transparent-screen-options
:component keypair-rename/view}
{:name :screen/settings.encrypted-keypair-qr
@ -558,7 +570,7 @@
:component keypairs-and-accounts/view}
{:name :screen/settings.scan-keypair-qr
:options options/transparent-modal-screen-options
:options options/transparent-screen-options
:component scan-keypair-qr/view}
{:name :screen/settings.missing-keypair.import-seed-phrase

View File

@ -1,7 +1,5 @@
(ns status-im.subs.wallet.networks
(:require [quo.foundations.resources :as resources]
[re-frame.core :as re-frame]
[status-im.constants :as constants]
(:require [re-frame.core :as re-frame]
[status-im.contexts.wallet.common.utils.networks :as network-utils]))
(def max-network-prefixes 2)
@ -18,41 +16,6 @@
(fn [[networks test-networks-enabled?]]
(get networks (if test-networks-enabled? :test :prod))))
(def mainnet-network-details
{:source (resources/get-network constants/mainnet-network-name)
:short-name constants/mainnet-short-name
:network-name constants/mainnet-network-name
:abbreviated-name constants/mainnet-abbreviated-name})
(def arbitrum-network-details
{:source (resources/get-network constants/arbitrum-network-name)
:short-name constants/arbitrum-short-name
:network-name constants/arbitrum-network-name
:abbreviated-name constants/arbitrum-abbreviated-name})
(def optimism-network-details
{:source (resources/get-network constants/optimism-network-name)
:short-name constants/optimism-short-name
:network-name constants/optimism-network-name
:abbreviated-name constants/optimism-abbreviated-name})
(defn get-network-details
[chain-id]
(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/optimism-mainnet-chain-id constants/optimism-goerli-chain-id
constants/optimism-sepolia-chain-id}
optimism-network-details
nil))
(re-frame/reg-sub
:wallet/network-details
:<- [:wallet/networks-by-mode]
@ -60,7 +23,7 @@
(->> networks
(map
(fn [{:keys [chain-id related-chain-id layer]}]
(assoc (get-network-details chain-id)
(assoc (network-utils/get-network-details chain-id)
:chain-id chain-id
:related-chain-id related-chain-id
:layer layer)))

View File

@ -12,6 +12,7 @@
:short-name "eth"
:network-name :mainnet
:abbreviated-name "Eth."
:full-name "Mainnet"
:related-chain-id 1
:chain-id 3
:layer 1}
@ -47,15 +48,18 @@
:short-name "eth"
:chain-id 1
:abbreviated-name "Eth."
:full-name "Mainnet"
:layer 1}
{:network-name :arbitrum
:short-name "arb1"
:abbreviated-name "Arb1."
:full-name "Arbitrum"
:chain-id 42161
:layer 2}
{:network-name :optimism
:short-name "oeth"
:abbreviated-name "Oeth."
:full-name "Optimism"
:chain-id 10
:layer 2}]
(map #(dissoc % :source :related-chain-id) (rf/sub [sub-name]))))))
@ -70,15 +74,18 @@
:short-name "eth"
:chain-id 1
:abbreviated-name "Eth."
:full-name "Mainnet"
:layer 1}
:arbitrum {:network-name :arbitrum
:short-name "arb1"
:abbreviated-name "Arb1."
:full-name "Arbitrum"
:chain-id 42161
:layer 2}
:optimism {:network-name :optimism
:short-name "oeth"
:abbreviated-name "Oeth."
:full-name "Optimism"
:chain-id 10
:layer 2}}
(rf/sub [sub-name])))))

View File

@ -54,7 +54,7 @@
:wallet/saved-address-by-address
:<- [:wallet/saved-addresses-by-network-mode]
(fn [saved-addresses [_ address]]
(get saved-addresses address)))
(get saved-addresses (string/lower-case address))))
(rf/reg-sub
:wallet/filtered-saved-addresses
@ -65,7 +65,7 @@
(sort-by :name)
(filter
(fn [{:keys [name address ens chain-short-names]}]
(let [lowercase-query (string/lower-case query)]
(let [lowercase-query (string/lower-case (string/trim query))]
(or
(string/includes? (string/lower-case name) lowercase-query)
(string/includes? address lowercase-query)

View File

@ -205,6 +205,12 @@
(fn [{:keys [keypairs]}]
(vals keypairs)))
(rf/reg-sub
:wallet/keypair-names
:<- [:wallet/keypairs-list]
(fn [keypairs]
(set (map :name keypairs))))
(rf/reg-sub
:wallet/selected-keypair-uid
:<- [:wallet/create-account]
@ -244,7 +250,7 @@
size 32}}]
(->> accounts
(keep (fn [{:keys [path color emoji name address]}]
(when-not (string/starts-with? path constants/path-eip1581)
(when-not (string/starts-with? (str path) constants/path-eip1581)
{:account-props {:customization-color color
:size size
:emoji emoji

View File

@ -1,6 +1,9 @@
(ns status-im.subs.wallet.wallet-connect
(:require [re-frame.core :as rf]
[status-im.contexts.wallet.common.utils :as wallet-utils]))
[status-im.contexts.wallet.common.utils :as wallet-utils]
[status-im.contexts.wallet.common.utils.networks :as networks]
[status-im.contexts.wallet.wallet-connect.core :as wallet-connect-core]
[utils.money :as money]))
(rf/reg-sub
:wallet-connect/current-request-address
@ -31,6 +34,79 @@
:name name
:emoji emoji})))
(rf/reg-sub
:wallet-connect/current-request-dapp
:<- [:wallet-connect/current-request]
:<- [:wallet-connect/pairings]
(fn [[request pairings]]
(let [dapp-url (get-in request [:raw-data :verifyContext :verified :origin])]
(->> pairings
(filter (fn [pairing]
(= dapp-url (get-in pairing [:peerMetadata :url]))))
(first)))))
(rf/reg-sub
:wallet-connect/current-request-network
:<- [:wallet-connect/current-request]
(fn [request]
(-> request
(get-in [:raw-data :params :chainId])
(wallet-connect-core/eip155->chain-id)
(networks/get-network-details))))
(rf/reg-sub
:wallet-connect/current-request-transaction-information
:<- [:wallet-connect/current-request]
:<- [:wallet/accounts]
:<- [:profile/currency]
:<- [:profile/currency-symbol]
(fn [[request accounts currency currency-symbol]]
(let [chain-id (-> request
(get-in [:raw-data :params :chainId])
(wallet-connect-core/eip155->chain-id))
all-tokens (->> accounts
(filter #(= (:address %)
(:address request)))
(first)
:tokens)
eth-token (->> all-tokens
(filter #(= (:symbol %) "ETH"))
(first))
{:keys [gasPrice gasLimit value]} (-> request
:raw-data
wallet-connect-core/get-request-params
first)
max-fees-wei (money/bignumber (* gasPrice gasLimit))]
(when (and gasPrice gasLimit)
(let [max-fees-ether (money/wei->ether max-fees-wei)
token-fiat-value (wallet-utils/calculate-token-fiat-value {:currency currency
:balance max-fees-ether
:token eth-token})
crypto-formatted (wallet-utils/get-standard-crypto-format eth-token max-fees-ether)
fiat-formatted (wallet-utils/get-standard-fiat-format crypto-formatted
currency-symbol
token-fiat-value)
balance (-> eth-token
(get-in [:balances-per-chain chain-id :raw-balance])
(money/bignumber))
value (money/bignumber value)
total-transaction-value (money/add max-fees-wei value)]
{:total-transaction-value total-transaction-value
:balance balance
:max-fees max-fees-wei
:max-fees-fiat-value token-fiat-value
:max-fees-fiat-formatted fiat-formatted
:error-state (cond
(and
(money/sufficient-funds? value balance)
(not (money/sufficient-funds? total-transaction-value balance)))
:not-enough-assets-to-pay-gas-fees
(not (money/sufficient-funds? value balance))
:not-enough-assets
:else nil)})))))
(rf/reg-sub
:wallet-connect/session-proposer
:<- [:wallet-connect/current-proposal]

View File

@ -526,18 +526,21 @@
(match? [{:short-name "eth"
:network-name :mainnet
:abbreviated-name "Eth."
:full-name "Mainnet"
:chain-id 1
:related-chain-id nil
:layer 1}
{:short-name "arb1"
:network-name :arbitrum
:abbreviated-name "Arb1."
:full-name "Arbitrum"
:chain-id 42161
:related-chain-id nil
:layer 2}
{:short-name "oeth"
:network-name :optimism
:abbreviated-name "Oeth."
:full-name "Optimism"
:chain-id 10
:related-chain-id nil
:layer 2}]
@ -643,18 +646,20 @@
:removed false})
(def profile-key-pair-key-uid "abc")
(def profile-key-pair-name "My Profile")
(def seed-phrase-key-pair-key-uid "def")
(def seed-phrase-key-pair-name "My Key Pair")
(def profile-keypair
{:key-uid profile-key-pair-key-uid
:name "My Profile"
:name profile-key-pair-name
:type :profile
:lowest-operability :fully
:accounts []})
(def seed-phrase-keypair
{:key-uid seed-phrase-key-pair-key-uid
:name "My Key Pair"
:name seed-phrase-key-pair-name
:type :seed
:lowest-operability :no
:accounts []})
@ -676,6 +681,14 @@
(is (= 2 (count result)))
(is (match? expected result))))
(h/deftest-sub :wallet/keypair-names
[sub-name]
(swap! rf-db/app-db assoc-in
[:wallet :keypairs]
{profile-key-pair-key-uid profile-keypair
seed-phrase-key-pair-key-uid seed-phrase-keypair})
(is (match? #{seed-phrase-key-pair-name profile-key-pair-name} (rf/sub [sub-name]))))
(h/deftest-sub :wallet/settings-keypairs-accounts
[sub-name]
(testing "returns formatted key-pairs and accounts"

View File

@ -160,10 +160,13 @@ class GithubHtmlReport(BaseTestReport):
html += "Device %d:" % i
html += "<ul>"
if test_run.first_commands:
html += "<li><a href=\"%s\">Steps, video, logs</a></li>" % \
self.get_sauce_job_url(job_id, test_run.first_commands[job_id])
try:
first_command = test_run.first_commands[job_id]
except KeyError:
first_command = 0
else:
html += "<li><a href=\"%s\">Steps, video, logs</a></li>" % self.get_sauce_job_url(job_id)
first_command = 0
html += "<li><a href=\"%s\">Steps, video, logs</a></li>" % self.get_sauce_job_url(job_id, first_command)
# if test_run.error:
# html += "<li><a href=\"%s\">Failure screenshot</a></li>" % self.get_sauce_final_screenshot_url(job_id)
html += "</ul></p>"

View File

@ -190,7 +190,10 @@ class TestrailReport(BaseTestReport):
test_steps += step + "\n"
for i, device in enumerate(last_testrun.jobs):
if last_testrun.first_commands:
first_command = last_testrun.first_commands[device]
try:
first_command = last_testrun.first_commands[device]
except KeyError:
first_command = 0
else:
first_command = 0
try:
@ -233,7 +236,10 @@ class TestrailReport(BaseTestReport):
continue
for res in results:
if last_testrun.first_commands:
pattern = r"%s\?auth=.*#%s" % (device, str(last_testrun.first_commands[device]))
try:
pattern = r"%s\?auth=.*#%s" % (device, str(last_testrun.first_commands[device]))
except KeyError:
pattern = device
else:
pattern = device
if re.findall(pattern, res['comment']):
@ -285,10 +291,13 @@ class TestrailReport(BaseTestReport):
error = "```%s```\n **%s** \n" % (code_error, no_code_error_str)
for job_id, f in last_testrun.jobs.items():
if last_testrun.first_commands:
job_url = self.get_sauce_job_url(job_id=job_id,
first_command=last_testrun.first_commands[job_id])
try:
first_command = last_testrun.first_commands[job_id]
except KeyError:
first_command = 0
else:
job_url = self.get_sauce_job_url(job_id=job_id)
first_command = 0
job_url = self.get_sauce_job_url(job_id=job_id, first_command=first_command)
case_info = "Logs for device %d: [steps](%s), [failure screenshot](%s)" \
% (f, job_url, self.get_sauce_final_screenshot_url(job_id))

View File

@ -2,7 +2,7 @@ import time
import pytest
from tests import marks, common_password, used_fleet
from tests import marks, common_password
from tests.base_test_case import create_shared_drivers, MultipleSharedDeviceTestCase
from views.sign_in_view import SignInView
from tests.users import basic_user, ens_user, ens_user_message_sender, transaction_senders, chat_users
@ -415,8 +415,8 @@ class TestBrowserProfileOneDevice(MultipleSharedDeviceTestCase):
profile = self.home.profile_button.click()
profile.advanced_button.click()
if not profile.element_by_text(used_fleet).is_element_displayed():
self.errors.append('%s is not selected by default' % used_fleet)
# if not profile.element_by_text(used_fleet).is_element_displayed():
# self.errors.append('%s is not selected by default' % used_fleet)
self.home.just_fyi('Set another fleet and check that changes are applied')
profile.fleet_setting_button.click()

View File

@ -1302,6 +1302,8 @@
"scan-with-status-app": "Scan with the Status app on another device",
"scan-key-pairs-qr-code": "Scan key pairs QR code",
"invalid-qr": "Oops! This QR doesnt work with Status",
"invalid-key-pair-qr": "This does not look like a key pair QR code",
"incorrect-qr-code": "This is not the QR code you are looking for",
"search": "Search",
"search-discover-communities": "Search communities or categories",
"secret-keys-confirmation-text": "You will need them to continue to use your Keycard in case you ever lose your phone.",
@ -1928,6 +1930,8 @@
"pinned-by": "Pinned by",
"pin-limit-reached": "Pin limit reached. Unpin a previous message first.",
"no-fees": "No fees",
"not-enough-assets-to-pay-gas-fees": "Not enough assets to pay gas fees.",
"not-enough-assets": "Not enough assets to complete transaction.",
"max-fee": "Max fee",
"max-fees": "Max fees",
"max-priority-fee": "Max priority fee",
@ -2027,8 +2031,12 @@
"wallet-connect-go-back": "Go back to your browser or dapp",
"wallet-connect-2.0": "Wallet Connect 2.0",
"wallet-connect": "Wallet Connect",
"wallet-connect-sign-header": "wants you to sign a message with",
"wallet-connect-sign-warning": "Sign messages only if you trust the dApp",
"wallet-connect-sign-message-header": "wants you to sign the message with",
"wallet-connect-send-transaction-header": "wants you to send this transaction with",
"wallet-connect-sign-transaction-header": "wants you to sign this transaction with",
"wallet-connect-sign-message-warning": "Sign messages only if you trust the dApp",
"wallet-connect-send-transaction-warning": "Send transactions only if you trust the dApp",
"wallet-connect-sign-transaction-warning": "Sign transactions only if you trust the dApp",
"reject": "Reject",
"manage-connections": "Manage connections from within Application Connections",
"contact-request-was-ignored": "Contact request ignored",
@ -2467,7 +2475,7 @@
"make-one-it-is-easy-we-promise": "Make one, its easy, we promise!",
"saved-addresses": "Saved addresses",
"no-saved-addresses": "No saved addresses",
"you-like-to-type-43-characters": "You like to type 43 characters?",
"you-like-to-type-43-characters": "Do you like to type 43 characters?",
"no-other-accounts": "No other accounts",
"here-is-a-cat-in-a-box-instead": "Heres a cat in a box instead",
"accounts-count": "{{count}} accounts",
@ -2498,6 +2506,7 @@
"select-another-account": "Select another account",
"oops-this-qr-does-not-contain-an-address": "Oops! This QR does not contain an address",
"scan-an-account-qr-code": "Scan an account QR code",
"scan-an-address-qr-code": "Scan an address QR code",
"buy-assets": "Buy assets",
"one-time": "One time",
"recurrent": "Recurrent",
@ -2612,7 +2621,7 @@
"generating-keypair": "Generating key pair...",
"keypair-name": "Key pair name",
"keypair-name-description": "Name key pair for your own personal reference",
"keypair-name-input-placeholder": "Collectibles account, Old vault....",
"keypair-name-input-placeholder": "Collectibles key pair, Old vault....",
"key-pair-name-updated": "Key pair name updated",
"key-pair-removed": "Key pair and derived accounts has been removed",
"goerli-testnet-toggle-confirmation": "Are you sure you want to toggle Goerli? This will log you out and you will have to login again.",
@ -2639,6 +2648,7 @@
"max": "Max: {{number}}",
"your-key-pair-name-is-too-long": "Your key pair name is too long",
"your-key-pair-name-is-too-short": "Your key pair name is too short",
"key-name-error-taken": "Key pair name already in use",
"key-name-error-length": "Key name too long",
"key-name-error-emoji": "Emojis are not allowed",
"key-name-error-special-char": "Special characters are not allowed",