Fix WalletConnect transactions (#20608)
* fix: sign-transaction Signed-off-by: Lungu Cristian <lungucristian95@gmail.com> * fix: sendTranasaction not working Signed-off-by: Lungu Cristian <lungucristian95@gmail.com> * ref: removing 0x from the signature Signed-off-by: Lungu Cristian <lungucristian95@gmail.com> * ref: tx data from responding to processing events Signed-off-by: Lungu Cristian <lungucristian95@gmail.com> * fix: request dapp subscription Signed-off-by: Lungu Cristian <lungucristian95@gmail.com> * fix: tx data bug Signed-off-by: Lungu Cristian <lungucristian95@gmail.com> --------- Signed-off-by: Lungu Cristian <lungucristian95@gmail.com>
This commit is contained in:
parent
e58e2209bb
commit
f51f52ec27
|
@ -282,6 +282,8 @@
|
||||||
(def ^:const wallet-connect-session-proposal-event "session_proposal")
|
(def ^:const wallet-connect-session-proposal-event "session_proposal")
|
||||||
(def ^:const wallet-connect-session-request-event "session_request")
|
(def ^:const wallet-connect-session-request-event "session_request")
|
||||||
|
|
||||||
|
(def ^:const transaction-pending-type-wallet-connect-transfer "WalletConnectTransfer")
|
||||||
|
|
||||||
(def ^:const dapp-permission-contact-code "contact-code")
|
(def ^:const dapp-permission-contact-code "contact-code")
|
||||||
(def ^:const dapp-permission-web3 "web3")
|
(def ^:const dapp-permission-web3 "web3")
|
||||||
(def ^:const dapp-permission-qr-code "qr-code")
|
(def ^:const dapp-permission-qr-code "qr-code")
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
(ns status-im.contexts.wallet.wallet-connect.effects
|
(ns status-im.contexts.wallet.wallet-connect.effects
|
||||||
(:require [cljs-bean.core :as bean]
|
(:require
|
||||||
|
[cljs-bean.core :as bean]
|
||||||
[native-module.core :as native-module]
|
[native-module.core :as native-module]
|
||||||
[promesa.core :as promesa]
|
[promesa.core :as promesa]
|
||||||
[re-frame.core :as rf]
|
[re-frame.core :as rf]
|
||||||
|
@ -7,6 +8,7 @@
|
||||||
[status-im.config :as config]
|
[status-im.config :as config]
|
||||||
[status-im.constants :as constants]
|
[status-im.constants :as constants]
|
||||||
[status-im.contexts.wallet.wallet-connect.core :as wallet-connect-core]
|
[status-im.contexts.wallet.wallet-connect.core :as wallet-connect-core]
|
||||||
|
[status-im.contexts.wallet.wallet-connect.transactions :as transactions]
|
||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
[utils.security.core :as security]
|
[utils.security.core :as security]
|
||||||
[utils.transforms :as transforms]))
|
[utils.transforms :as transforms]))
|
||||||
|
@ -92,10 +94,24 @@
|
||||||
(promesa/then on-success)
|
(promesa/then on-success)
|
||||||
(promesa/catch on-error))))
|
(promesa/catch on-error))))
|
||||||
|
|
||||||
|
(rf/reg-fx
|
||||||
|
:effects.wallet-connect/sign-transaction
|
||||||
|
(fn [{:keys [password address chain-id tx on-success on-error]}]
|
||||||
|
(-> (transactions/sign-transaction (security/safe-unmask-data password) address tx chain-id)
|
||||||
|
(promesa/then on-success)
|
||||||
|
(promesa/catch on-error))))
|
||||||
|
|
||||||
|
(rf/reg-fx
|
||||||
|
:effects.wallet-connect/send-transaction
|
||||||
|
(fn [{:keys [password address chain-id tx on-success on-error]}]
|
||||||
|
(-> (transactions/send-transaction (security/safe-unmask-data password) address tx chain-id)
|
||||||
|
(promesa/then on-success)
|
||||||
|
(promesa/catch on-error))))
|
||||||
|
|
||||||
(rf/reg-fx
|
(rf/reg-fx
|
||||||
:effects.wallet-connect/sign-typed-data
|
:effects.wallet-connect/sign-typed-data
|
||||||
(fn [{:keys [password address data version on-success on-error]}]
|
(fn [{:keys [password address data version on-success on-error]}]
|
||||||
(-> (wallet-connect-core/sign-typed-data version data address password)
|
(-> (wallet-connect-core/sign-typed-data version data address (security/safe-unmask-data password))
|
||||||
(promesa/then wallet-connect-core/extract-native-call-signature)
|
(promesa/then wallet-connect-core/extract-native-call-signature)
|
||||||
(promesa/then on-success)
|
(promesa/then on-success)
|
||||||
(promesa/catch on-error))))
|
(promesa/catch on-error))))
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
(ns status-im.contexts.wallet.wallet-connect.processing-events
|
(ns status-im.contexts.wallet.wallet-connect.processing-events
|
||||||
(:require [native-module.core :as native-module]
|
(:require [clojure.string :as string]
|
||||||
|
[native-module.core :as native-module]
|
||||||
[re-frame.core :as rf]
|
[re-frame.core :as rf]
|
||||||
[status-im.constants :as constants]
|
[status-im.constants :as constants]
|
||||||
[status-im.contexts.wallet.wallet-connect.core :as wallet-connect-core]
|
[status-im.contexts.wallet.wallet-connect.core :as wallet-connect-core]
|
||||||
|
@ -45,7 +46,7 @@
|
||||||
{:db (update-in db
|
{:db (update-in db
|
||||||
[:wallet-connect/current-request]
|
[:wallet-connect/current-request]
|
||||||
assoc
|
assoc
|
||||||
:address address
|
:address (string/lower-case address)
|
||||||
:raw-data raw-data
|
:raw-data raw-data
|
||||||
:display-data (or parsed-data raw-data))})))
|
:display-data (or parsed-data raw-data))})))
|
||||||
|
|
||||||
|
@ -57,7 +58,7 @@
|
||||||
{:db (update-in db
|
{:db (update-in db
|
||||||
[:wallet-connect/current-request]
|
[:wallet-connect/current-request]
|
||||||
assoc
|
assoc
|
||||||
:address address
|
:address (string/lower-case address)
|
||||||
:raw-data raw-data
|
:raw-data raw-data
|
||||||
:display-data (or parsed-data raw-data))})))
|
:display-data (or parsed-data raw-data))})))
|
||||||
|
|
||||||
|
@ -68,12 +69,17 @@
|
||||||
display-data (-> event
|
display-data (-> event
|
||||||
clj->js
|
clj->js
|
||||||
(js/JSON.stringify nil 2))
|
(js/JSON.stringify nil 2))
|
||||||
{:keys [to]} (-> event wallet-connect-core/get-request-params first)]
|
|
||||||
|
{:keys [from] :as tx} (-> event wallet-connect-core/get-request-params first)
|
||||||
|
chain-id (-> event
|
||||||
|
(get-in [:params :chainId])
|
||||||
|
wallet-connect-core/eip155->chain-id)]
|
||||||
{:db (update-in db
|
{:db (update-in db
|
||||||
[:wallet-connect/current-request]
|
[:wallet-connect/current-request]
|
||||||
assoc
|
assoc
|
||||||
:address to
|
:address (string/lower-case from)
|
||||||
:raw-data event
|
:raw-data tx
|
||||||
|
:chain-id chain-id
|
||||||
:display-data display-data)})))
|
:display-data display-data)})))
|
||||||
|
|
||||||
(rf/reg-event-fx
|
(rf/reg-event-fx
|
||||||
|
@ -81,12 +87,16 @@
|
||||||
(fn [{:keys [db]}]
|
(fn [{:keys [db]}]
|
||||||
(let [event (wallet-connect-core/get-db-current-request-event db)
|
(let [event (wallet-connect-core/get-db-current-request-event db)
|
||||||
display-data (.stringify js/JSON (clj->js event) nil 2)
|
display-data (.stringify js/JSON (clj->js event) nil 2)
|
||||||
{:keys [to]} (-> event wallet-connect-core/get-request-params first)]
|
{:keys [from] :as tx} (-> event wallet-connect-core/get-request-params first)
|
||||||
|
chain-id (-> event
|
||||||
|
(get-in [:params :chainId])
|
||||||
|
wallet-connect-core/eip155->chain-id)]
|
||||||
{:db (update-in db
|
{:db (update-in db
|
||||||
[:wallet-connect/current-request]
|
[:wallet-connect/current-request]
|
||||||
assoc
|
assoc
|
||||||
:address to
|
:address (string/lower-case from)
|
||||||
:raw-data event
|
:raw-data tx
|
||||||
|
:chain-id chain-id
|
||||||
:display-data display-data)})))
|
:display-data display-data)})))
|
||||||
|
|
||||||
(rf/reg-event-fx
|
(rf/reg-event-fx
|
||||||
|
@ -103,6 +113,6 @@
|
||||||
{:db (update-in db
|
{:db (update-in db
|
||||||
[:wallet-connect/current-request]
|
[:wallet-connect/current-request]
|
||||||
assoc
|
assoc
|
||||||
:address address
|
:address (string/lower-case address)
|
||||||
:raw-data (or parsed-data raw-data)
|
:display-data (or parsed-data raw-data)
|
||||||
:display-data parsed-data)})))
|
:raw-data raw-data)})))
|
||||||
|
|
|
@ -14,17 +14,13 @@
|
||||||
[:dispatch [:wallet-connect/respond-personal-sign password]]
|
[:dispatch [:wallet-connect/respond-personal-sign password]]
|
||||||
|
|
||||||
constants/wallet-connect-eth-send-transaction-method
|
constants/wallet-connect-eth-send-transaction-method
|
||||||
[:dispatch
|
[:dispatch [:wallet-connect/respond-send-transaction-data password]]
|
||||||
[:wallet-connect/respond-build-transaction
|
|
||||||
#(rf/dispatch [:wallet-connect/respond-send-transaction-data password %])]]
|
|
||||||
|
|
||||||
constants/wallet-connect-eth-sign-method
|
constants/wallet-connect-eth-sign-method
|
||||||
[:dispatch [:wallet-connect/respond-eth-sign password]]
|
[:dispatch [:wallet-connect/respond-eth-sign password]]
|
||||||
|
|
||||||
constants/wallet-connect-eth-sign-transaction-method
|
constants/wallet-connect-eth-sign-transaction-method
|
||||||
[:dispatch
|
[:dispatch [:wallet-connect/respond-sign-transaction-data password]]
|
||||||
[:wallet-connect/respond-build-transaction
|
|
||||||
#(rf/dispatch [:wallet-connect/respond-sign-transaction-data password %])]]
|
|
||||||
|
|
||||||
constants/wallet-connect-eth-sign-typed-method
|
constants/wallet-connect-eth-sign-typed-method
|
||||||
[:dispatch [:wallet-connect/respond-sign-typed-data password :v1]]
|
[:dispatch [:wallet-connect/respond-sign-typed-data password :v1]]
|
||||||
|
@ -67,40 +63,27 @@
|
||||||
:on-error #(rf/dispatch [:wallet-connect/on-sign-error %])
|
:on-error #(rf/dispatch [:wallet-connect/on-sign-error %])
|
||||||
:on-success #(rf/dispatch [:wallet-connect/send-response %])}]]})))
|
: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
|
(rf/reg-event-fx
|
||||||
:wallet-connect/respond-send-transaction-data
|
:wallet-connect/respond-send-transaction-data
|
||||||
(fn [_ [password data]]
|
(fn [{:keys [db]} [password]]
|
||||||
(let [{:keys [address]
|
(let [{:keys [chain-id raw-data address]} (get db :wallet-connect/current-request)]
|
||||||
message-to-sign :messageToSign} data]
|
{:fx [[:effects.wallet-connect/send-transaction
|
||||||
{:fx [[:effects.wallet-connect/sign-message
|
|
||||||
{:password password
|
{:password password
|
||||||
:address address
|
:address address
|
||||||
:data message-to-sign
|
:chain-id chain-id
|
||||||
|
:tx raw-data
|
||||||
:on-error #(rf/dispatch [:wallet-connect/on-sign-error %])
|
:on-error #(rf/dispatch [:wallet-connect/on-sign-error %])
|
||||||
:on-success #(rf/dispatch [:wallet-connect/send-response %])}]]})))
|
:on-success #(rf/dispatch [:wallet-connect/send-response %])}]]})))
|
||||||
|
|
||||||
(rf/reg-event-fx
|
(rf/reg-event-fx
|
||||||
:wallet-connect/respond-sign-transaction-data
|
:wallet-connect/respond-sign-transaction-data
|
||||||
(fn [_ [password data]]
|
(fn [{:keys [db]} [password]]
|
||||||
(let [{:keys [address]
|
(let [{:keys [chain-id raw-data address]} (get db :wallet-connect/current-request)]
|
||||||
message-to-sign :messageToSign} data]
|
{:fx [[:effects.wallet-connect/sign-transaction
|
||||||
{:fx [[:effects.wallet-connect/sign-message
|
|
||||||
{:password password
|
{:password password
|
||||||
:address address
|
:address address
|
||||||
:data message-to-sign
|
:chain-id chain-id
|
||||||
|
:tx raw-data
|
||||||
:on-error #(rf/dispatch [:wallet-connect/on-sign-error %])
|
:on-error #(rf/dispatch [:wallet-connect/on-sign-error %])
|
||||||
:on-success #(rf/dispatch [:wallet-connect/send-response %])}]]})))
|
:on-success #(rf/dispatch [:wallet-connect/send-response %])}]]})))
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
(ns status-im.contexts.wallet.wallet-connect.transactions
|
||||||
|
(:require [cljs-bean.core :as bean]
|
||||||
|
[clojure.string :as string]
|
||||||
|
[oops.core :as oops]
|
||||||
|
[promesa.core :as promesa]
|
||||||
|
[status-im.common.json-rpc.events :as rpc-events]
|
||||||
|
[status-im.constants :as constants]
|
||||||
|
[utils.transforms :as transforms]))
|
||||||
|
|
||||||
|
(defn- call-rpc
|
||||||
|
"Helper to handle RPC calls to status-go as promises"
|
||||||
|
[method & args]
|
||||||
|
(promesa/create
|
||||||
|
(fn [p-resolve p-reject]
|
||||||
|
(rpc-events/call {:method method
|
||||||
|
:params (vec args)
|
||||||
|
:on-success p-resolve
|
||||||
|
:on-error p-reject
|
||||||
|
:js-response true}))))
|
||||||
|
|
||||||
|
(defn- strip-hex-prefix
|
||||||
|
"Strips the extra 0 in hex value if present"
|
||||||
|
[hex-value]
|
||||||
|
(let [formatted-hex (string/replace hex-value #"^0x0*" "0x")]
|
||||||
|
(if (= formatted-hex "0x")
|
||||||
|
"0x0"
|
||||||
|
formatted-hex)))
|
||||||
|
|
||||||
|
(defn- format-tx-hex-values
|
||||||
|
"Due to how status-go expects hex values, we should remove the extra 0s in transaction hex values e.g. 0x0f -> 0xf"
|
||||||
|
[tx]
|
||||||
|
(let [tx-keys [:gasLimit :gas :gasPrice :nonce :value :maxFeePerGas :maxPriorityFeePerGas]]
|
||||||
|
(reduce (fn [acc tx-key]
|
||||||
|
(if (and (contains? tx tx-key)
|
||||||
|
(not (nil? (get tx tx-key))))
|
||||||
|
(update acc tx-key strip-hex-prefix)
|
||||||
|
acc))
|
||||||
|
tx
|
||||||
|
tx-keys)))
|
||||||
|
|
||||||
|
(defn- prepare-transaction-for-rpc
|
||||||
|
"Formats the transaction and transforms it into a stringified JS object, ready to be passed to an RPC call."
|
||||||
|
[tx]
|
||||||
|
(-> tx
|
||||||
|
format-tx-hex-values
|
||||||
|
bean/->js
|
||||||
|
(transforms/js-stringify 0)))
|
||||||
|
|
||||||
|
(defn wallet-sign-message-rpc
|
||||||
|
[password address data]
|
||||||
|
(-> (call-rpc "wallet_signMessage"
|
||||||
|
data
|
||||||
|
address
|
||||||
|
password)
|
||||||
|
;; NOTE: removing `0x`, as status-go expects the signature without it.
|
||||||
|
(promesa/then #(subs % 2))))
|
||||||
|
|
||||||
|
(defn- wallet-build-transaction-rpc
|
||||||
|
[chain-id tx]
|
||||||
|
(-> (call-rpc "wallet_buildTransaction" chain-id tx)
|
||||||
|
(promesa/then #(hash-map :message-to-sign (oops/oget % "messageToSign")
|
||||||
|
:tx-args (oops/oget % "txArgs")))))
|
||||||
|
|
||||||
|
(defn- wallet-build-raw-transaction-rpc
|
||||||
|
[chain-id tx-args signature]
|
||||||
|
(-> (call-rpc "wallet_buildRawTransaction"
|
||||||
|
chain-id
|
||||||
|
(transforms/js-stringify tx-args 0)
|
||||||
|
signature)
|
||||||
|
(promesa/then #(oops/oget % "rawTx"))))
|
||||||
|
|
||||||
|
(defn- wallet-send-transaction-with-signature-rpc
|
||||||
|
[chain-id tx-args signature]
|
||||||
|
(call-rpc "wallet_sendTransactionWithSignature"
|
||||||
|
chain-id
|
||||||
|
constants/transaction-pending-type-wallet-connect-transfer
|
||||||
|
(transforms/js-stringify tx-args 0)
|
||||||
|
signature))
|
||||||
|
|
||||||
|
(defn sign-transaction
|
||||||
|
[password address tx chain-id]
|
||||||
|
(promesa/let
|
||||||
|
[formatted-tx (prepare-transaction-for-rpc tx)
|
||||||
|
{:keys [message-to-sign tx-args]} (wallet-build-transaction-rpc chain-id formatted-tx)
|
||||||
|
signature (wallet-sign-message-rpc password address message-to-sign)
|
||||||
|
raw-tx (wallet-build-raw-transaction-rpc chain-id tx-args signature)]
|
||||||
|
raw-tx))
|
||||||
|
|
||||||
|
(defn send-transaction
|
||||||
|
[password address tx chain-id]
|
||||||
|
(promesa/let
|
||||||
|
[formatted-tx (prepare-transaction-for-rpc tx)
|
||||||
|
{:keys [message-to-sign tx-args]} (wallet-build-transaction-rpc chain-id formatted-tx)
|
||||||
|
signature (wallet-sign-message-rpc password address message-to-sign)
|
||||||
|
tx (wallet-send-transaction-with-signature-rpc chain-id
|
||||||
|
tx-args
|
||||||
|
signature)]
|
||||||
|
tx))
|
|
@ -39,7 +39,7 @@
|
||||||
:<- [:wallet-connect/current-request]
|
:<- [:wallet-connect/current-request]
|
||||||
:<- [:wallet-connect/pairings]
|
:<- [:wallet-connect/pairings]
|
||||||
(fn [[request pairings]]
|
(fn [[request pairings]]
|
||||||
(let [dapp-url (get-in request [:raw-data :verifyContext :verified :origin])]
|
(let [dapp-url (get-in request [:event :verifyContext :verified :origin])]
|
||||||
(->> pairings
|
(->> pairings
|
||||||
(filter (fn [pairing]
|
(filter (fn [pairing]
|
||||||
(= dapp-url (get-in pairing [:peerMetadata :url]))))
|
(= dapp-url (get-in pairing [:peerMetadata :url]))))
|
||||||
|
|
Loading…
Reference in New Issue