Add wallet connect signing flow (#20199)
* feat: added session request event & fx * Added signing flow * fix: addressed @ilmotta's review comments * fix: addressed @shivekkhurana's review comments * fix: addressed @ilmotta's review comments * fix: converting typed data to clj and back to JSON
This commit is contained in:
parent
615ad2f02b
commit
5193f981f8
|
@ -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]
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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})
|
|
@ -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]])
|
|
@ -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")
|
||||
|
|
|
@ -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))))
|
|
@ -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))))
|
||||
|
|
|
@ -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]))}]]})))
|
||||
|
|
|
@ -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)})))
|
|
@ -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]))}]]})))
|
|
@ -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})
|
|
@ -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)]]]]))
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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})))
|
|
@ -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")
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in New Issue