diff --git a/src/schema/common.cljs b/src/schema/common.cljs index 7945b1fa25..934714ffb1 100644 --- a/src/schema/common.cljs +++ b/src/schema/common.cljs @@ -36,11 +36,16 @@ (def ^:private ?hiccup vector?) +(def ^:private ?promise + [:fn {:error/message "schema.common/promise should be of type Promise"} + (fn [v] (instance? js/Promise v))]) + (defn register-schemas [] (registry/register ::theme ?theme) (registry/register ::customization-color ?customization-color) (registry/register ::public-key ?public-key) + (registry/register ::promise ?promise) (registry/register ::image-source ?image-source) (registry/register ::rpc-call ?rpc-call) (registry/register ::exception ?exception) diff --git a/src/status_im/contexts/wallet/wallet_connect/utils/signing.cljs b/src/status_im/contexts/wallet/wallet_connect/utils/signing.cljs index 2c18298c89..d37e78b95a 100644 --- a/src/status_im/contexts/wallet/wallet_connect/utils/signing.cljs +++ b/src/status_im/contexts/wallet/wallet_connect/utils/signing.cljs @@ -1,6 +1,7 @@ (ns status-im.contexts.wallet.wallet-connect.utils.signing (:require [native-module.core :as native-module] [promesa.core :as promesa] + [schema.core :as schema] [status-im.contexts.wallet.wallet-connect.utils.data-store :as data-store] [status-im.contexts.wallet.wallet-connect.utils.networks :as networks] @@ -21,9 +22,30 @@ :domain :chainId number/parse-int)] - (when chain-id-type? + (when (and chain-id-type? + (not (zero? data-chain-id))) data-chain-id))) +(def ?eip712-type + [:map + [:name :string] + [:type :string]]) + +(def ?eip712-data + [:map + [:types + [:map + [:EIP712Domain {:optional true} [:vector ?eip712-type]] + [:malli.core/default [:map-of :keyword [:vector ?eip712-type]]]]] + [:domain {:optional true} [:map-of :keyword :any]] + [:primaryType :string] + [:message map?]]) + +(schema/=> typed-data-chain-id + [:=> + [:cat ?eip712-data] + [:maybe :int]]) + (defn eth-sign [password address data] (-> {:data data @@ -33,12 +55,28 @@ native-module/sign-message (promesa/then data-store/extract-native-call-signature))) +(schema/=> eth-sign + [:=> + [:catn + [:password :string] + [:address :string] + [:data :string]] + :schema.common/promise]) + (defn personal-sign [password address data] (-> (rpc/wallet-hash-message-eip-191 data) (promesa/then #(rpc/wallet-sign-message % address password)) (promesa/then hex/prefix-hex))) +(schema/=> personal-sign + [:=> + [:catn + [:password :string] + [:address :string] + [:data :string]] + :schema.common/promise]) + (defn eth-sign-typed-data [password address data chain-id-eip155 version] (let [legacy? (= version :v1) @@ -48,3 +86,13 @@ password chain-id legacy?))) + +(schema/=> eth-sign-typed-data + [:=> + [:catn + [:password :string] + [:address :string] + [:data :string] + [:chain-id-eip155 :string] + [:version [:enum :v1 :v4]]] + :schema.common/promise]) diff --git a/src/status_im/contexts/wallet/wallet_connect/utils/signing_test.cljs b/src/status_im/contexts/wallet/wallet_connect/utils/signing_test.cljs new file mode 100644 index 0000000000..7b834f6219 --- /dev/null +++ b/src/status_im/contexts/wallet/wallet_connect/utils/signing_test.cljs @@ -0,0 +1,39 @@ +(ns status-im.contexts.wallet.wallet-connect.utils.signing-test + (:require + [cljs.test :refer-macros [deftest is testing]] + [status-im.contexts.wallet.wallet-connect.utils.signing :as sut])) + +(deftest typed-data-chain-id-test + (testing "chainId is extracted correctly" + (let [typed-data {:types {:EIP712Domain [{:name "chainId" :type "string"}]} + :domain {:chainId "1"} + :primaryType "EIP712Domain" + :message {}}] + (is (= (sut/typed-data-chain-id typed-data) + 1)))) + + (testing "chainId not extracted if it is not defined in the domain types" + (let [typed-data {:types {:EIP712Domain []} + :domain {:chainId "1"} + :primaryType "EIP712Domain" + :message {}}] + (is (nil? (sut/typed-data-chain-id typed-data))))) + + (testing "chainId not extracted if it is not defined in the domain" + (let [typed-data {:types {:EIP712Domain [{:name "chainId" :type "string"}]} + :domain {} + :primaryType "EIP712Domain" + :message {}}] + (is (nil? (sut/typed-data-chain-id typed-data))))) + + (testing "chainId not extracted if chainId is not a valid int" + (let [typed-data {:types {:EIP712Domain [{:name "chainId" :type "string"}]} + :domain {:chainId "not an int"} + :primaryType "EIP712Domain" + :message {}}] + (is (nil? (sut/typed-data-chain-id typed-data))))) + + (testing "invalid typed data is passed" + (is (thrown? js/Error (sut/typed-data-chain-id {}))))) + +(cljs.test/run-tests) diff --git a/src/status_im/contexts/wallet/wallet_connect/utils/transactions.cljs b/src/status_im/contexts/wallet/wallet_connect/utils/transactions.cljs index 0f2deff465..c906acf444 100644 --- a/src/status_im/contexts/wallet/wallet_connect/utils/transactions.cljs +++ b/src/status_im/contexts/wallet/wallet_connect/utils/transactions.cljs @@ -212,9 +212,9 @@ (schema/=> prepare-transaction [:=> [:catn - [:tx ?transaction - :chain-id :int - :tx-priority ?tx-priority]] + [:tx ?transaction] + [:chain-id :int] + [:tx-priority ?tx-priority]] [:map {:closed true} [:tx-args :string] [:tx-hash :string]