diff --git a/src/native_module/core.cljs b/src/native_module/core.cljs index ea9497723d..89b70351ad 100644 --- a/src/native_module/core.cljs +++ b/src/native_module/core.cljs @@ -359,9 +359,11 @@ (defn sign-message "NOTE: beware, the password in rpcParams has to be sha3 hashed" - [rpcParams callback] - (log/debug "[native-module] sign-message") - (.signMessage ^js (encryption) rpcParams callback)) + ([rpcParams] + (native-utils/promisify-native-module-call sign-message rpcParams)) + ([rpcParams callback] + (log/debug "[native-module] sign-message") + (.signMessage ^js (encryption) rpcParams callback))) (defn recover-message [rpcParams callback] @@ -376,15 +378,19 @@ (defn sign-typed-data "NOTE: beware, the password has to be sha3 hashed" - [data account hashed-password callback] - (log/debug "[native-module] sign-typed-data") - (.signTypedData ^js (encryption) data account hashed-password callback)) + ([data account hashed-password] + (native-utils/promisify-native-module-call sign-typed-data data account hashed-password)) + ([data account hashed-password callback] + (log/debug "[native-module] sign-typed-data") + (.signTypedData ^js (encryption) data account hashed-password callback))) (defn sign-typed-data-v4 "NOTE: beware, the password has to be sha3 hashed" - [data account hashed-password callback] - (log/debug "[native-module] sign-typed-data-v4") - (.signTypedDataV4 ^js (encryption) data account hashed-password callback)) + ([data account hashed-password] + (native-utils/promisify-native-module-call sign-typed-data-v4 data account hashed-password)) + ([data account hashed-password callback] + (log/debug "[native-module] sign-typed-data-v4") + (.signTypedDataV4 ^js (encryption) data account hashed-password callback))) (defn send-logs [dbJson js-logs callback] diff --git a/src/react_native/wallet_connect.cljs b/src/react_native/wallet_connect.cljs index bf971cf083..ee1e6ff68b 100644 --- a/src/react_native/wallet_connect.cljs +++ b/src/react_native/wallet_connect.cljs @@ -1,7 +1,7 @@ (ns react-native.wallet-connect (:require ["@walletconnect/core" :refer [Core]] - ["@walletconnect/utils" :refer [buildApprovedNamespaces]] + ["@walletconnect/utils" :refer [buildApprovedNamespaces getSdkError]] ["@walletconnect/web3wallet" :refer [Web3Wallet]])) (defn- wallet-connect-core @@ -20,3 +20,7 @@ (buildApprovedNamespaces (clj->js {:proposal proposal :supportedNamespaces supported-namespaces}))) + +(defn get-sdk-error + [error-key] + (getSdkError error-key)) diff --git a/src/status_im/common/bottom_sheet_screen/style.cljs b/src/status_im/common/bottom_sheet_screen/style.cljs index bc0e074f18..782e4cfafb 100644 --- a/src/status_im/common/bottom_sheet_screen/style.cljs +++ b/src/status_im/common/bottom_sheet_screen/style.cljs @@ -2,7 +2,8 @@ (:require [quo.foundations.colors :as colors] [quo.theme] - [react-native.reanimated :as reanimated])) + [react-native.reanimated :as reanimated] + [status-im.constants :as constants])) (defn container [padding-top] @@ -35,7 +36,7 @@ {:left 0 :right 0 :top 0 - :height 20 + :height constants/sheet-screen-handle-height :z-index 2 :position :absolute :justify-content :center diff --git a/src/status_im/common/raw_data_block/style.cljs b/src/status_im/common/raw_data_block/style.cljs new file mode 100644 index 0000000000..d3ef6279f3 --- /dev/null +++ b/src/status_im/common/raw_data_block/style.cljs @@ -0,0 +1,13 @@ +(ns status-im.common.raw-data-block.style + (: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}) + +(def content + {:padding-bottom 20}) diff --git a/src/status_im/common/raw_data_block/view.cljs b/src/status_im/common/raw_data_block/view.cljs new file mode 100644 index 0000000000..64fc506815 --- /dev/null +++ b/src/status_im/common/raw_data_block/view.cljs @@ -0,0 +1,14 @@ +(ns status-im.common.raw-data-block.view + (:require [quo.core :as quo] + [react-native.core :as rn] + [status-im.common.raw-data-block.style :as style])) + +(defn view + [{:keys [data]}] + [rn/scroll-view + {:style style/container + :content-container-style style/content} + [quo/text + {:size :paragraph-2 + :weight :code} + data]]) diff --git a/src/status_im/constants.cljs b/src/status_im/constants.cljs index 810c9a01d0..974a40964f 100644 --- a/src/status_im/constants.cljs +++ b/src/status_im/constants.cljs @@ -263,10 +263,21 @@ (def ^:const wallet-connect-metadata-icon "https://res.cloudinary.com/dhgck7ebz/image/upload/f_auto,c_limit,w_1080,q_auto/Brand/Logo%20Section/Mark/Mark_01") (def ^:const wallet-connect-metadata-url "https://status.app") -(def ^:const optimism-crosschain-id "eip155:10") -(def ^:const wallet-connect-supported-methods ["eth_sendTransaction" "personal_sign"]) -(def ^:const wallet-connect-supported-events ["accountsChanged" "chainChanged"]) + +(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-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-typed-method + wallet-connect-eth-sign-typed-v4-method}) +(def ^:const wallet-connect-supported-events #{"accountsChanged" "chainChanged"}) (def ^:const wallet-connect-session-proposal-event "session_proposal") +(def ^:const wallet-connect-session-request-event "session_request") (def ^:const dapp-permission-contact-code "contact-code") (def ^:const dapp-permission-web3 "web3") @@ -522,6 +533,8 @@ (def ^:const alert-banner-height 40) +(def ^:const sheet-screen-handle-height 20) + (def ^:const status-hostname "status.app") (def ^:const community-joined-notification-type "communityJoined") diff --git a/src/status_im/contexts/wallet/wallet_connect/core.cljs b/src/status_im/contexts/wallet/wallet_connect/core.cljs new file mode 100644 index 0000000000..4de3f399c9 --- /dev/null +++ b/src/status_im/contexts/wallet/wallet_connect/core.cljs @@ -0,0 +1,40 @@ +(ns status-im.contexts.wallet.wallet-connect.core + (:require [native-module.core :as native-module] + [utils.security.core :as security] + [utils.transforms :as transforms])) + +(defn extract-native-call-signature + [data] + (-> data transforms/json->clj :result)) + +(defn chain-id->eip155 + [chain-id] + (str "eip155:" chain-id)) + +(defn format-eip155-address + [address chain-id] + (str chain-id ":" address)) + +(defn get-request-method + [event] + (get-in event [:params :request :method])) + +(defn get-request-params + [event] + (get-in event [:params :request :params])) + +(defn get-db-current-request-params + [db] + (-> (get-in db [:wallet-connect/current-request :event]) + get-request-params)) + +(def ^:private sign-typed-data-by-version + {:v1 native-module/sign-typed-data + :v4 native-module/sign-typed-data-v4}) + +(defn sign-typed-data + [version data address password] + (let [f (get sign-typed-data-by-version version)] + (->> password + security/safe-unmask-data + (f data address)))) diff --git a/src/status_im/contexts/wallet/wallet_connect/effects.cljs b/src/status_im/contexts/wallet/wallet_connect/effects.cljs index 89cbf1f99e..699131aaed 100644 --- a/src/status_im/contexts/wallet/wallet_connect/effects.cljs +++ b/src/status_im/contexts/wallet/wallet_connect/effects.cljs @@ -1,10 +1,15 @@ (ns status-im.contexts.wallet.wallet-connect.effects - (:require [promesa.core :as promesa] + (:require [cljs-bean.core :as bean] + [native-module.core :as native-module] + [promesa.core :as promesa] [re-frame.core :as rf] [react-native.wallet-connect :as wallet-connect] [status-im.config :as config] [status-im.constants :as constants] - [utils.i18n :as i18n])) + [status-im.contexts.wallet.wallet-connect.core :as wallet-connect-core] + [utils.i18n :as i18n] + [utils.security.core :as security] + [utils.transforms :as transforms])) (rf/reg-fx :effects.wallet-connect/init @@ -64,10 +69,44 @@ :effects.wallet-connect/approve-session (fn [{:keys [web3-wallet proposal supported-namespaces on-success on-fail]}] (let [{:keys [params id]} proposal - approved-namespaces (wallet-connect/build-approved-namespaces params - supported-namespaces)] + approved-namespaces (wallet-connect/build-approved-namespaces + params + supported-namespaces)] (-> (.approveSession web3-wallet (clj->js {:id id :namespaces approved-namespaces})) (promesa/then on-success) (promesa/catch on-fail))))) + +(rf/reg-fx + :effects.wallet-connect/sign-message + (fn [{:keys [password address data on-success on-error]}] + (-> {:data data + :account address + :password (security/safe-unmask-data password)} + bean/->js + transforms/clj->json + native-module/sign-message + (promesa/then wallet-connect-core/extract-native-call-signature) + (promesa/then on-success) + (promesa/catch on-error)))) + +(rf/reg-fx + :effects.wallet-connect/sign-typed-data + (fn [{:keys [password address data version on-success on-error]}] + (-> (wallet-connect-core/sign-typed-data version data address password) + (promesa/then wallet-connect-core/extract-native-call-signature) + (promesa/then on-success) + (promesa/catch on-error)))) + +(rf/reg-fx + :effects.wallet-connect/respond-session-request + (fn [{:keys [web3-wallet topic id result on-success on-error]}] + (-> + (.respondSessionRequest web3-wallet + (clj->js {:topic topic + :response {:id id + :jsonrpc "2.0" + :result result}})) + (promesa/then on-success) + (promesa/catch on-error)))) diff --git a/src/status_im/contexts/wallet/wallet_connect/events.cljs b/src/status_im/contexts/wallet/wallet_connect/events.cljs index 4f9f6ca0be..08177376f4 100644 --- a/src/status_im/contexts/wallet/wallet_connect/events.cljs +++ b/src/status_im/contexts/wallet/wallet_connect/events.cljs @@ -1,8 +1,12 @@ (ns status-im.contexts.wallet.wallet-connect.events (:require [re-frame.core :as rf] [status-im.constants :as constants] + [status-im.contexts.wallet.wallet-connect.core :as wallet-connect-core] status-im.contexts.wallet.wallet-connect.effects - [taoensso.timbre :as log])) + status-im.contexts.wallet.wallet-connect.processing-events + status-im.contexts.wallet.wallet-connect.responding-events + [taoensso.timbre :as log] + [utils.ethereum.chain :as chain])) (rf/reg-event-fx :wallet-connect/init @@ -30,7 +34,11 @@ {:fx [[:effects.wallet-connect/register-event-listener [web3-wallet constants/wallet-connect-session-proposal-event - #(rf/dispatch [:wallet-connect/on-session-proposal %])]]]}))) + #(rf/dispatch [:wallet-connect/on-session-proposal %])]] + [:effects.wallet-connect/register-event-listener + [web3-wallet + constants/wallet-connect-session-request-event + #(rf/dispatch [:wallet-connect/on-session-request %])]]]}))) (rf/reg-event-fx :wallet-connect/on-init-fail @@ -42,13 +50,25 @@ (rf/reg-event-fx :wallet-connect/on-session-proposal (fn [{:keys [db]} [proposal]] + (log/info "Received Wallet Connect session proposal: " {:id (:id proposal)}) {:db (assoc db :wallet-connect/current-proposal proposal)})) (rf/reg-event-fx - :wallet-connect/reset-current-session + :wallet-connect/on-session-request + (fn [_ [event]] + (log/info "Received Wallet Connect session request: " event) + {:fx [[:dispatch [:wallet-connect/process-session-request event]]]})) + +(rf/reg-event-fx + :wallet-connect/reset-current-session-proposal (fn [{:keys [db]}] {:db (dissoc db :wallet-connect/current-proposal)})) +(rf/reg-event-fx + :wallet-connect/reset-current-session-request + (fn [{:keys [db]}] + {:db (dissoc db :wallet-connect/current-request)})) + (rf/reg-event-fx :wallet-connect/set-pairings (fn [{:keys [db]} [pairings]] @@ -82,6 +102,12 @@ :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 [:navigate-back]] + [:dispatch [:wallet-connect/reset-current-session-request]]]})) + (rf/reg-event-fx :wallet-connect/fetch-active-sessions (fn [{:keys [db]}] @@ -94,33 +120,36 @@ (rf/reg-event-fx :wallet-connect/approve-session (fn [{:keys [db]}] - ;; NOTE: hardcoding optimism for the base implementation - (let [crosschain-ids [constants/optimism-crosschain-id] - web3-wallet (get db :wallet-connect/web3-wallet) + (let [web3-wallet (get db :wallet-connect/web3-wallet) current-proposal (get db :wallet-connect/current-proposal) accounts (get-in db [:wallet :accounts]) + supported-chain-ids (->> db + chain/chain-ids + (map wallet-connect-core/chain-id->eip155) + vec) ;; NOTE: for now using the first account, but should be using the account selected by the ;; user on the connection screen. The default would depend on where the connection started ;; from: ;; - global scanner -> first account in list ;; - wallet account dapps -> account that is selected address (-> accounts keys first) - formatted-address (str (first crosschain-ids) ":" address) - supported-namespaces (clj->js - {:eip155 - {:chains crosschain-ids - :methods constants/wallet-connect-supported-methods - :events constants/wallet-connect-supported-events - :accounts [formatted-address]}})] + accounts (-> (partial wallet-connect-core/format-eip155-address address) + (map supported-chain-ids)) + supported-namespaces (clj->js {:eip155 + {:chains supported-chain-ids + :methods constants/wallet-connect-supported-methods + :events constants/wallet-connect-supported-events + :accounts accounts}})] {:fx [[:effects.wallet-connect/approve-session {:web3-wallet web3-wallet :proposal current-proposal :supported-namespaces supported-namespaces :on-success (fn [] (log/info "Wallet Connect session approved") - (rf/dispatch [:wallet-connect/reset-current-session])) + (rf/dispatch [:wallet-connect/reset-current-session-proposal])) :on-fail (fn [error] (log/error "Wallet Connect session approval failed" {:error error :event :wallet-connect/approve-session}) - (rf/dispatch [:wallet-connect/reset-current-session]))}]]}))) + (rf/dispatch + [:wallet-connect/reset-current-session-proposal]))}]]}))) diff --git a/src/status_im/contexts/wallet/wallet_connect/processing_events.cljs b/src/status_im/contexts/wallet/wallet_connect/processing_events.cljs new file mode 100644 index 0000000000..54fee0c108 --- /dev/null +++ b/src/status_im/contexts/wallet/wallet_connect/processing_events.cljs @@ -0,0 +1,79 @@ +(ns status-im.contexts.wallet.wallet-connect.processing-events + (:require [native-module.core :as native-module] + [re-frame.core :as rf] + [status-im.constants :as constants] + [status-im.contexts.wallet.wallet-connect.core :as wallet-connect-core] + [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)] + (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-sign-method + [:dispatch [:wallet-connect/process-eth-sign]] + + 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 [:open-modal screen]]]} + (log/error "Didn't find screen for Wallet Connect method" + {:method method + :event :wallet-connect/process-session-request}))))) + +(rf/reg-event-fx + :wallet-connect/process-personal-sign + (fn [{:keys [db]}] + (let [[raw-data address] (wallet-connect-core/get-db-current-request-params db) + parsed-data (native-module/hex-to-utf8 raw-data)] + {:db (update-in db + [:wallet-connect/current-request] + assoc + :address address + :raw-data raw-data + :display-data (or parsed-data raw-data))}))) + +(rf/reg-event-fx + :wallet-connect/process-eth-sign + (fn [{:keys [db]}] + (let [[address raw-data] (wallet-connect-core/get-db-current-request-params db) + parsed-data (native-module/hex-to-utf8 raw-data)] + {:db (update-in db + [:wallet-connect/current-request] + assoc + :address address + :raw-data raw-data + :display-data (or parsed-data raw-data))}))) + +(rf/reg-event-fx + :wallet-connect/process-sign-typed + (fn [{:keys [db]}] + (let [[address raw-data] (wallet-connect-core/get-db-current-request-params db) + parsed-data (try (-> raw-data + transforms/js-parse + (transforms/js-dissoc :types :primaryType) + (transforms/js-stringify 2)) + (catch js/Error _ nil))] + ;; TODO: decide if we should proceed if the typed-data is invalid JSON or fail ahead of time + (when (nil? parsed-data) (log/error "Invalid typed data")) + {:db (update-in db + [:wallet-connect/current-request] + assoc + :address address + :raw-data (or parsed-data raw-data) + :display-data parsed-data)}))) diff --git a/src/status_im/contexts/wallet/wallet_connect/responding_events.cljs b/src/status_im/contexts/wallet/wallet_connect/responding_events.cljs new file mode 100644 index 0000000000..6f096f5188 --- /dev/null +++ b/src/status_im/contexts/wallet/wallet_connect/responding_events.cljs @@ -0,0 +1,96 @@ +(ns status-im.contexts.wallet.wallet-connect.responding-events + (:require [re-frame.core :as rf] + [status-im.constants :as constants] + [status-im.contexts.wallet.wallet-connect.core :as wallet-connect-core] + [taoensso.timbre :as log])) + +(rf/reg-event-fx + :wallet-connect/respond-current-session + (fn [{:keys [db]} [password]] + (let [event (get-in db [:wallet-connect/current-request :event]) + method (wallet-connect-core/get-request-method event)] + {:fx [(condp = method + constants/wallet-connect-personal-sign-method + [:dispatch [:wallet-connect/respond-personal-sign password]] + + constants/wallet-connect-eth-sign-method + [:dispatch [:wallet-connect/respond-eth-sign password]] + + constants/wallet-connect-eth-sign-typed-method + [:dispatch [:wallet-connect/respond-sign-typed-data password :v1]] + + constants/wallet-connect-eth-sign-typed-v4-method + [:dispatch [:wallet-connect/respond-sign-typed-data password :v4]])]}))) + +(rf/reg-event-fx + :wallet-connect/respond-eth-sign + (fn [{:keys [db]} [password]] + (let [{:keys [address raw-data]} (get db :wallet-connect/current-request)] + {:fx [[:effects.wallet-connect/sign-message + {:password password + :address address + :data raw-data + :on-error #(rf/dispatch [:wallet-connect/on-sign-error %]) + :on-success #(rf/dispatch [:wallet-connect/send-response %])}]]}))) + + +(rf/reg-event-fx + :wallet-connect/respond-personal-sign + (fn [{:keys [db]} [password]] + (let [{:keys [address raw-data]} (get db :wallet-connect/current-request)] + {:fx [[:effects.wallet-connect/sign-message + {:password password + :address address + :data raw-data + :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-typed-data + (fn [{:keys [db]} [password typed-data-version]] + (let [{:keys [address raw-data]} (get db :wallet-connect/current-request)] + {:fx [[:effects.wallet-connect/sign-typed-data + {:password password + :address address + :data raw-data + :version typed-data-version + :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)] + (log/error "Failed to sign Wallet Connect request" + {:error error + :address address + :sign-data raw-data + :method method + :wallet-connect-event event + :event :wallet-connect/on-sign-error}) + {:fx [[:dispatch [:wallet-connect/close-session-request]]]}))) + + +(rf/reg-event-fx + :wallet-connect/send-response + (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) + web3-wallet (get db :wallet-connect/web3-wallet)] + {:fx [[:effects.wallet-connect/respond-session-request + {:web3-wallet web3-wallet + :topic topic + :id id + :result result + :on-error (fn [error] + (log/error "Failed to send Wallet Connect response" + {:error error + :method method + :event :wallet-connect/send-response + :wallet-connect-event event}) + (rf/dispatch [:wallet-connect/close-session-request])) + :on-success (fn [] + (log/info "Successfully sent Wallet Connect response to dApp") + (rf/dispatch [:wallet-connect/close-session-request]))}]]}))) diff --git a/src/status_im/contexts/wallet/wallet_connect/sign_message/style.cljs b/src/status_im/contexts/wallet/wallet_connect/sign_message/style.cljs new file mode 100644 index 0000000000..3484858cd7 --- /dev/null +++ b/src/status_im/contexts/wallet/wallet_connect/sign_message/style.cljs @@ -0,0 +1,29 @@ +(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}) diff --git a/src/status_im/contexts/wallet/wallet_connect/sign_message/view.cljs b/src/status_im/contexts/wallet/wallet_connect/sign_message/view.cljs new file mode 100644 index 0000000000..34e040ef27 --- /dev/null +++ b/src/status_im/contexts/wallet/wallet_connect/sign_message/view.cljs @@ -0,0 +1,82 @@ +(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)]]]])) diff --git a/src/status_im/navigation/screens.cljs b/src/status_im/navigation/screens.cljs index 8814546364..4ec4f279de 100644 --- a/src/status_im/navigation/screens.cljs +++ b/src/status_im/navigation/screens.cljs @@ -106,6 +106,7 @@ [status-im.contexts.wallet.send.send-amount.view :as wallet-send-input-amount] [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.wallet-connect.sign-message.view :as wallet-connect-sign-message] [status-im.navigation.options :as options] [status-im.navigation.transitions :as transitions])) @@ -499,6 +500,12 @@ :options {:sheet? true} :component communities.invite/view} + ;; Wallet Connect + + {:name :screen/wallet-connect.sign-message + :options {:sheet? true} + :component wallet-connect-sign-message/view} + ;; Settings {:name :screen/settings-password diff --git a/src/status_im/subs/root.cljs b/src/status_im/subs/root.cljs index 84794229bf..ee04ebfeda 100644 --- a/src/status_im/subs/root.cljs +++ b/src/status_im/subs/root.cljs @@ -21,7 +21,8 @@ status-im.subs.wallet.networks status-im.subs.wallet.saved-addresses status-im.subs.wallet.send - status-im.subs.wallet.wallet)) + status-im.subs.wallet.wallet + status-im.subs.wallet.wallet-connect)) (defn reg-root-key-sub [sub-name db-key] @@ -169,6 +170,7 @@ ;;wallet-connect (reg-root-key-sub :wallet-connect/web3-wallet :wallet-connect/web3-wallet) (reg-root-key-sub :wallet-connect/current-proposal :wallet-connect/current-proposal) +(reg-root-key-sub :wallet-connect/current-request :wallet-connect/current-request) (reg-root-key-sub :wallet-connect/pairings :wallet-connect/pairings) ;;biometrics diff --git a/src/status_im/subs/wallet/wallet_connect.cljs b/src/status_im/subs/wallet/wallet_connect.cljs new file mode 100644 index 0000000000..e0694af70c --- /dev/null +++ b/src/status_im/subs/wallet/wallet_connect.cljs @@ -0,0 +1,32 @@ +(ns status-im.subs.wallet.wallet-connect + (:require [re-frame.core :as rf] + [status-im.contexts.wallet.common.utils :as wallet-utils])) + +(rf/reg-sub + :wallet-connect/current-request-address + :<- [:wallet-connect/current-request] + :-> :address) + +(rf/reg-sub + :wallet-connect/current-request-display-data + :<- [:wallet-connect/current-request] + :-> :display-data) + +(rf/reg-sub + :wallet-connect/account-details-by-address + :<- [:wallet/accounts-without-watched-accounts] + (fn [accounts [_ address]] + (let [{:keys [customization-color name emoji]} (wallet-utils/get-account-by-address accounts address)] + {:customization-color customization-color + :name name + :emoji emoji}))) + +(rf/reg-sub + :wallet-connect/current-request-account-details + :<- [:wallet-connect/current-request-address] + :<- [:wallet/accounts-without-watched-accounts] + (fn [[address accounts]] + (let [{:keys [customization-color name emoji]} (wallet-utils/get-account-by-address accounts address)] + {:customization-color customization-color + :name name + :emoji emoji}))) diff --git a/src/utils/transforms.cljs b/src/utils/transforms.cljs index b143e2edae..6adb4e3a5a 100644 --- a/src/utils/transforms.cljs +++ b/src/utils/transforms.cljs @@ -15,6 +15,21 @@ (defn clj->json [data] (clj->pretty-json data 0)) +(defn js-stringify + [js-object spaces] + (.stringify js/JSON js-object nil spaces)) + +(defn js-parse + [data] + (.parse js/JSON data)) + +(defn js-dissoc + [js-object & ks] + (let [object-copy (.assign js/Object #js {} js-object)] + (doseq [js-key ks] + (js-delete object-copy (name js-key))) + object-copy)) + (defn json->clj [json] (when-not (= json "undefined") diff --git a/translations/en.json b/translations/en.json index 3e12c7fe14..ad97951076 100644 --- a/translations/en.json +++ b/translations/en.json @@ -1916,6 +1916,7 @@ "pinned-messages-empty": "Pinned messages will appear here. To pin a message, press and hold it and tap `Pin`", "pinned-by": "Pinned by", "pin-limit-reached": "Pin limit reached. Unpin a previous message first.", + "no-fees": "No fees", "max-fee": "Max fee", "max-fees": "Max fees", "max-priority-fee": "Max priority fee", @@ -2014,6 +2015,8 @@ "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", "reject": "Reject", "manage-connections": "Manage connections from within Application Connections", "contact-request-was-ignored": "Contact request ignored",