diff --git a/resources/images/dapps/WalletConnect@2x.png b/resources/images/dapps/WalletConnect@2x.png new file mode 100644 index 0000000000..6ae713eb62 Binary files /dev/null and b/resources/images/dapps/WalletConnect@2x.png differ diff --git a/resources/images/dapps/WalletConnect@3x.png b/resources/images/dapps/WalletConnect@3x.png new file mode 100644 index 0000000000..c69ecf6f2d Binary files /dev/null and b/resources/images/dapps/WalletConnect@3x.png differ diff --git a/src/quo/components/tags/context_tag/schema.cljs b/src/quo/components/tags/context_tag/schema.cljs index 32adacaf4a..4e7345737c 100644 --- a/src/quo/components/tags/context_tag/schema.cljs +++ b/src/quo/components/tags/context_tag/schema.cljs @@ -6,7 +6,7 @@ [:type {:optional true} [:maybe [:enum :default :multiuser :group :channel :community :token :network :multinetwork :account - :collectible :address :icon :audio :wallet-user]]] + :collectible :address :icon :audio :wallet-user :dapp]]] [:customization-color {:optional true} [:maybe :schema.common/customization-color]] [:container-style {:optional true} [:maybe :map]] [:blur? {:optional true} [:maybe :boolean]] diff --git a/src/quo/components/tags/context_tag/view.cljs b/src/quo/components/tags/context_tag/view.cljs index 74d8e87a75..78ad97ae90 100644 --- a/src/quo/components/tags/context_tag/view.cljs +++ b/src/quo/components/tags/context_tag/view.cljs @@ -17,16 +17,18 @@ [schema.core :as schema])) (defn- tag-skeleton - [{:keys [size text] :or {size 24}} logo-component] - (let [theme (quo.theme/use-theme)] - [rn/view {:style (style/tag-container size)} - logo-component - [rn/view {:style (style/tag-spacing size)} - [text/text - {:style (style/text theme) - :weight :medium - :size (if (= size 24) :paragraph-2 :paragraph-1)} - text]]])) + [{:keys [size text theme] + :or {size 24 + theme (quo.theme/use-theme)}} + logo-component] + [rn/view {:style (style/tag-container size)} + logo-component + [rn/view {:style (style/tag-spacing size)} + [text/text + {:style (style/text theme) + :weight :medium + :size (if (= size 24) :paragraph-2 :paragraph-1)} + text]]]) (defn- communities-tag [{:keys [size community-logo community-name blur? channel? channel-name]}] @@ -81,95 +83,100 @@ context]]])) (defn- view-internal - [{:keys [type size state blur? customization-color profile-picture full-name users + [{:keys [type theme size state blur? customization-color profile-picture full-name users group-name amount token network-logo network-name networks - account-name emoji collectible collectible-name collectible-number duration container-style] + account-name emoji collectible collectible-name collectible-number + dapp-name dapp-logo duration container-style] :or {customization-color :blue type :default - state :default} + state :default + theme (quo.theme/use-theme)} :as props}] - (let [theme (quo.theme/use-theme)] - [rn/view {:style (merge {:align-items :flex-start} container-style)} - [rn/view - {:style (style/container {:theme theme - :type type - :size size - :state state - :blur? blur? - :customization-color customization-color}) - :accessibility-label :context-tag} - (case type - :default - [tag-skeleton {:theme theme :size size :text full-name} - [user-avatar/user-avatar - {:full-name full-name - :profile-picture profile-picture - :size (if (= size 24) :xxs 28) - :status-indicator? false - :ring? false - :customization-color customization-color}]] + [rn/view {:style (merge {:align-items :flex-start} container-style)} + [rn/view + {:style (style/container {:theme theme + :type type + :size size + :state state + :blur? blur? + :customization-color customization-color}) + :accessibility-label :context-tag} + (case type + :default + [tag-skeleton {:theme theme :size size :text full-name} + [user-avatar/user-avatar + {:full-name full-name + :profile-picture profile-picture + :size (if (= size 24) :xxs 28) + :status-indicator? false + :ring? false + :customization-color customization-color}]] - :multiuser - [preview-list/view {:type :user :size :size-20} - users] + :multiuser + [preview-list/view {:type :user :size :size-20} + users] - :multinetwork - [preview-list/view {:type :network :size :size-20} - networks] + :multinetwork + [preview-list/view {:type :network :size :size-20} + networks] - :audio - [tag-skeleton {:theme theme :text (str duration)} - [rn/view {:style (style/audio-tag-icon-container customization-color theme)} - [icons/icon :i/play {:color style/audio-tag-icon-color :size 12}]]] + :audio + [tag-skeleton {:theme theme :text (str duration)} + [rn/view {:style (style/audio-tag-icon-container customization-color theme)} + [icons/icon :i/play {:color style/audio-tag-icon-color :size 12}]]] - :group - [tag-skeleton {:theme theme :size size :text group-name} - [group-avatar/view - {:icon-name :i/members - :size (if (= size 24) :size-20 :size-28) - :customization-color (colors/custom-color customization-color 50)}]] + :group + [tag-skeleton {:theme theme :size size :text group-name} + [group-avatar/view + {:icon-name :i/members + :size (if (= size 24) :size-20 :size-28) + :customization-color (colors/custom-color customization-color 50)}]] - (:channel :community) - [communities-tag (assoc props :channel? (= type :channel))] + (:channel :community) + [communities-tag (assoc props :channel? (= type :channel))] - :token - [tag-skeleton {:theme theme :size size :text (str amount " " token)} - [token/view - {:style (style/token-logo size) - :token token - :size (if (= size 24) :size-20 :size-28)}]] + :token + [tag-skeleton {:theme theme :size size :text (str amount " " token)} + [token/view + {:style (style/token-logo size) + :token token + :size (if (= size 24) :size-20 :size-28)}]] - :network - [tag-skeleton {:theme theme :size size :text network-name} - [rn/image {:style (style/circle-logo size) :source network-logo}]] + :network + [tag-skeleton {:theme theme :size size :text network-name} + [rn/image {:style (style/circle-logo size) :source network-logo}]] - :collectible - [tag-skeleton - {:theme theme - :size size - :text (str collectible-name " #" collectible-number)} - [rn/image {:style (style/rounded-logo size) :source collectible}]] + :collectible + [tag-skeleton + {:theme theme + :size size + :text (str collectible-name " #" collectible-number)} + [rn/image {:style (style/rounded-logo size) :source collectible}]] - :account - [tag-skeleton {:theme theme :size size :text account-name} - [account-avatar/view - {:customization-color customization-color - :emoji emoji - :size (if (= size 24) 20 28)}]] + :account + [tag-skeleton {:theme theme :size size :text account-name} + [account-avatar/view + {:customization-color customization-color + :emoji emoji + :size (if (= size 24) 20 28)}]] - :address - [address-tag props] + :address + [address-tag props] - :icon - [icon-tag props] + :icon + [icon-tag props] - :wallet-user - [tag-skeleton {:theme theme :size size :text full-name} - [wallet-user-avatar/wallet-user-avatar - {:full-name full-name - :size (if (= size 24) :size-20 :size-24) - :customization-color customization-color}]] + :wallet-user + [tag-skeleton {:theme theme :size size :text full-name} + [wallet-user-avatar/wallet-user-avatar + {:full-name full-name + :size (if (= size 24) :size-20 :size-24) + :customization-color customization-color}]] - nil)]])) + :dapp + [tag-skeleton {:theme theme :size size :text dapp-name} + [rn/image {:style (style/circle-logo size) :source dapp-logo}]] + + nil)]]) (def view (schema/instrument #'view-internal component-schema/?schema)) diff --git a/src/quo/foundations/resources.cljs b/src/quo/foundations/resources.cljs index e94320bdef..63f37c79ae 100644 --- a/src/quo/foundations/resources.cljs +++ b/src/quo/foundations/resources.cljs @@ -24,12 +24,13 @@ (get ui k)) (def dapps - {:coingecko (js/require "../resources/images/dapps/CoinGecko.png") - :1inch (js/require "../resources/images/dapps/1inch.png") - :aave (js/require "../resources/images/dapps/Aave.png") - :uniswap (js/require "../resources/images/dapps/Uniswap.png") - :zapper (js/require "../resources/images/dapps/Zapper.png") - :zerion (js/require "../resources/images/dapps/Zerion.png")}) + {:coingecko (js/require "../resources/images/dapps/CoinGecko.png") + :1inch (js/require "../resources/images/dapps/1inch.png") + :aave (js/require "../resources/images/dapps/Aave.png") + :uniswap (js/require "../resources/images/dapps/Uniswap.png") + :zapper (js/require "../resources/images/dapps/Zapper.png") + :zerion (js/require "../resources/images/dapps/Zerion.png") + :wallet-connect (js/require "../resources/images/dapps/WalletConnect.png")}) (defn get-dapp [k] diff --git a/src/status_im/contexts/wallet/common/account_switcher/view.cljs b/src/status_im/contexts/wallet/common/account_switcher/view.cljs index b1607f0a86..17ab23c194 100644 --- a/src/status_im/contexts/wallet/common/account_switcher/view.cljs +++ b/src/status_im/contexts/wallet/common/account_switcher/view.cljs @@ -37,7 +37,7 @@ :networks networks :align-center? true :networks-on-press #(rf/dispatch [:show-bottom-sheet {:content network-filter/view}]) - :right-side [(when (and (ff/enabled? ::wallet.wallet-connect) + :right-side [(when (and (ff/enabled? ::ff/wallet.wallet-connect) (not watch-only?)) {:icon-name :i/dapps :on-press #(rf/dispatch [:navigate-to :screen/wallet.connected-dapps])}) diff --git a/src/status_im/contexts/wallet/connected_dapps/scan_dapp/style.cljs b/src/status_im/contexts/wallet/connected_dapps/scan_dapp/style.cljs new file mode 100644 index 0000000000..05e325f8ce --- /dev/null +++ b/src/status_im/contexts/wallet/connected_dapps/scan_dapp/style.cljs @@ -0,0 +1,11 @@ +(ns status-im.contexts.wallet.connected-dapps.scan-dapp.style + (:require [quo.foundations.colors :as colors])) + +(def subtitle-container + {:flex-direction :row + :align-items :center + :padding-horizontal 20 + :gap 4}) + +(def subtitle-text + {:color colors/white}) diff --git a/src/status_im/contexts/wallet/connected_dapps/scan_dapp/view.cljs b/src/status_im/contexts/wallet/connected_dapps/scan_dapp/view.cljs new file mode 100644 index 0000000000..6608cd396d --- /dev/null +++ b/src/status_im/contexts/wallet/connected_dapps/scan_dapp/view.cljs @@ -0,0 +1,44 @@ +(ns status-im.contexts.wallet.connected-dapps.scan-dapp.view + (:require [quo.core :as quo] + [quo.foundations.resources :as quo.resources] + [quo.theme] + [react-native.core :as rn] + [react-native.hooks :as hooks] + [status-im.common.scan-qr-code.view :as scan-qr-code] + [status-im.contexts.wallet.connected-dapps.scan-dapp.style :as style] + [utils.debounce :as debounce] + [utils.i18n :as i18n] + [utils.re-frame :as rf])) + +(defn view + [] + (let [{:keys [keyboard-shown]} (hooks/use-keyboard) + {:keys [name emoji color]} (rf/sub [:wallet/current-viewing-account])] + (rn/use-mount + (fn [] + (when keyboard-shown + (rn/dismiss-keyboard!)))) + [scan-qr-code/view + {:title (i18n/label :t/scan-qr) + :subtitle [rn/view style/subtitle-container + [quo/context-tag + {:theme :dark + :type :account + :size 24 + :account-name name + :emoji emoji + :customization-color color}] + [quo/text + {:style style/subtitle-text + :size :paragraph-1} + (i18n/label :t/wallet-connect-via)] + [quo/context-tag + {:theme :dark + :type :dapp + :size 24 + :dapp-name (i18n/label :t/wallet-connect-label) + :dapp-logo (quo.resources/get-dapp :wallet-connect)}]] + :on-success-scan (fn [scanned-text] + (debounce/debounce-and-dispatch + [:wallet-connect/on-scan-connection scanned-text] + 300))}])) diff --git a/src/status_im/contexts/wallet/connected_dapps/view.cljs b/src/status_im/contexts/wallet/connected_dapps/view.cljs index be7d079e4b..b8408f95f7 100644 --- a/src/status_im/contexts/wallet/connected_dapps/view.cljs +++ b/src/status_im/contexts/wallet/connected_dapps/view.cljs @@ -90,7 +90,7 @@ {:title (i18n/label :t/connected-dapps) :wallet-account wallet-account :on-close #(rf/dispatch [:navigate-back]) - :on-add #(js/alert "Feature not implemented")}] + :on-add #(rf/dispatch [:navigate-to :screen/wallet.scan-dapp])}] (if (empty? pairings) [quo/empty-state {:title (i18n/label :t/no-dapps) diff --git a/src/status_im/contexts/wallet/wallet_connect/events.cljs b/src/status_im/contexts/wallet/wallet_connect/events.cljs index d50838ba5d..e0697c97bc 100644 --- a/src/status_im/contexts/wallet/wallet_connect/events.cljs +++ b/src/status_im/contexts/wallet/wallet_connect/events.cljs @@ -67,8 +67,7 @@ :session-networks session-networks :address (-> without-watched first - :address) - ) + :address)) :fx [[:dispatch [:open-modal :screen/wallet.wallet-connect-session-proposal]]]} {:fx [[:dispatch @@ -190,27 +189,25 @@ (fn [_ [scanned-text]] (let [parsed-uri (wallet-connect/parse-uri scanned-text) version (:version parsed-uri) + valid-wc-uri? (wc-utils/valid-uri? parsed-uri) expired? (-> parsed-uri :expiryTimestamp wc-utils/timestamp-expired?) version-supported? (wc-utils/version-supported? version)] - (cond - expired? + (if (or (not valid-wc-uri?) expired? (not version-supported?)) {:fx [[:dispatch [:toasts/upsert {:type :negative :theme :dark - :text (i18n/label :t/wallet-connect-qr-expired)}]]]} + :text (cond (not valid-wc-uri?) + (i18n/label :t/wallet-connect-wrong-qr) - (not version-supported?) - {:fx [[:dispatch - [:toasts/upsert - {:type :negative - :theme :dark - :text (i18n/label :t/wallet-connect-version-not-supported - {:version version})}]]]} + expired? + (i18n/label :t/wallet-connect-qr-expired) - :else + (not version-supported?) + (i18n/label :t/wallet-connect-version-not-supported + {:version version}))}]]]} {:fx [[:dispatch [:wallet-connect/pair scanned-text]]]})))) (rf/reg-event-fx diff --git a/src/status_im/navigation/screens.cljs b/src/status_im/navigation/screens.cljs index 812f5f4930..d7b72a78f5 100644 --- a/src/status_im/navigation/screens.cljs +++ b/src/status_im/navigation/screens.cljs @@ -108,6 +108,7 @@ [status-im.contexts.wallet.bridge.select-asset.view :as wallet-bridge-select-asset] [status-im.contexts.wallet.collectible.view :as wallet-collectible] [status-im.contexts.wallet.common.scan-account.view :as wallet-scan-address] + [status-im.contexts.wallet.connected-dapps.scan-dapp.view :as wallet-scan-dapp] [status-im.contexts.wallet.connected-dapps.view :as wallet-connected-dapps] [status-im.contexts.wallet.send.from.view :as wallet-select-from] [status-im.contexts.wallet.send.select-address.view :as wallet-select-address] @@ -411,10 +412,6 @@ :options {:insets {:top? true}} :component wallet-accounts/view} - {:name :screen/wallet.connected-dapps - :options {:insets {:top? true}} - :component wallet-connected-dapps/view} - {:name :screen/wallet.wallet-connect-session-proposal :options {:sheet? true} :component wallet-connect-session-proposal/view} @@ -549,6 +546,16 @@ :options {:sheet? true} :component wallet-connect-send-transaction/view} + {:name :screen/wallet.connected-dapps + :options {:insets {:top? true}} + :component wallet-connected-dapps/view} + + {:name :screen/wallet.scan-dapp + :options (merge + options/dark-screen + {:modalPresentationStyle :overCurrentContext}) + :component wallet-scan-dapp/view} + ;; Settings {:name :screen/settings-password diff --git a/translations/en.json b/translations/en.json index cc12be4486..dea6d1742e 100644 --- a/translations/en.json +++ b/translations/en.json @@ -2733,8 +2733,11 @@ "dapp-will-be-able-to": "{{dapp-name}} will be able to:", "check-your-account-balance-and-activity": "Check your account balance and activity", "request-txns-and-message-signing": "Request transactions and message signing", + "wallet-connect-label": "WalletConnect", + "wallet-connect-via": "via", "wallet-connect-qr-expired": "WalletConnect QR has expired", "wallet-connect-version-not-supported": "WalletConnect version {{version}} is not supported", + "wallet-connect-wrong-qr": "It’s not a WalletConnect QR", "add-network-preferences": "Add network preferences", "saved-address-network-preference-selection-description": "Only change if you know which networks the address owner is happy to to receive funds on", "add-preferences": "Add preferences",