From 9bbea373f33ffd52fc12874e66bfd5cd3cf8aed0 Mon Sep 17 00:00:00 2001 From: Julien Eluard Date: Tue, 24 Jul 2018 11:45:29 +0200 Subject: [PATCH] WIP --- src/status_im/utils/ethereum/core.cljs | 11 ++- src/status_im/utils/ethereum/eip165.cljs | 22 ++++++ src/status_im/utils/ethereum/eip681.cljs | 2 +- src/status_im/utils/ethereum/ens.cljs | 73 +++++++++++++++++++ src/status_im/utils/ethereum/stateofus.cljs | 8 ++ test/cljs/status_im/test/runner.cljs | 2 + .../status_im/test/utils/ethereum/ens.cljs | 11 +++ 7 files changed, 126 insertions(+), 3 deletions(-) create mode 100644 src/status_im/utils/ethereum/eip165.cljs create mode 100644 src/status_im/utils/ethereum/ens.cljs create mode 100644 src/status_im/utils/ethereum/stateofus.cljs create mode 100644 test/cljs/status_im/test/utils/ethereum/ens.cljs diff --git a/src/status_im/utils/ethereum/core.cljs b/src/status_im/utils/ethereum/core.cljs index 508bd7bcdf..24d93ad688 100644 --- a/src/status_im/utils/ethereum/core.cljs +++ b/src/status_im/utils/ethereum/core.cljs @@ -70,8 +70,15 @@ network->chain-keyword name)) -(defn sha3 [s] - (.sha3 dependencies/Web3.prototype (str s))) +(defn sha3 + ([s] + (.sha3 dependencies/Web3.prototype (str s))) + ([s opts] + (.sha3 dependencies/Web3.prototype (str s) (clj->js opts)))) + +(defn hex->string [s] + (when s + (.toAscii dependencies/Web3.prototype s))) (defn hex->boolean [s] (= s "0x0")) diff --git a/src/status_im/utils/ethereum/eip165.cljs b/src/status_im/utils/ethereum/eip165.cljs new file mode 100644 index 0000000000..14b0927769 --- /dev/null +++ b/src/status_im/utils/ethereum/eip165.cljs @@ -0,0 +1,22 @@ +(ns status-im.utils.ethereum.eip165 + "Utility function related to [EIP165](https://eips.ethereum.org/EIPS/eip-165)" + (:require [status-im.utils.ethereum.core :as ethereum])) + +(def supports-interface-hash "0x01ffc9a7") +(def marker-hash "0xffffffff") + +(defn supports-interface? [web3 contract hash cb] + (ethereum/call web3 + (ethereum/call-params contract "supportsInterface(bytes4)" hash) + #(cb %1 %2))) + +(defn supports? + "Calls cb with true if `supportsInterface` is supported by this contract. + See EIP for details." + [web3 contract cb] + (supports-interface? web3 contract supports-interface-hash + #(if (true? (ethereum/hex->boolean %2)) + (supports-interface? web3 contract marker-hash + (fn [o oo] + (cb o (false? (ethereum/hex->boolean oo))))) + (cb %1 false)))) diff --git a/src/status_im/utils/ethereum/eip681.cljs b/src/status_im/utils/ethereum/eip681.cljs index a597b0d0d6..7c39fb12de 100644 --- a/src/status_im/utils/ethereum/eip681.cljs +++ b/src/status_im/utils/ethereum/eip681.cljs @@ -1,5 +1,5 @@ (ns status-im.utils.ethereum.eip681 - "Utility function related to [EIP681](https://github.com/ethereum/EIPs/issues/681) + "Utility function related to [EIP681](https://eips.ethereum.org/EIPS/eip-681) This EIP standardize how ethereum payment request can be represented as URI (say to embed them in a QR code). diff --git a/src/status_im/utils/ethereum/ens.cljs b/src/status_im/utils/ethereum/ens.cljs new file mode 100644 index 0000000000..c5f7a86372 --- /dev/null +++ b/src/status_im/utils/ethereum/ens.cljs @@ -0,0 +1,73 @@ +(ns status-im.utils.ethereum.ens + " + https://docs.ens.domains/en/latest/index.html + https://eips.ethereum.org/EIPS/eip-137 + https://eips.ethereum.org/EIPS/eip-181 + " + (:require [clojure.string :as string] + [status-im.utils.ethereum.core :as ethereum])) + +(def registries + {:mainnet "0x314159265dd8dbb310642f98f50c066173c1259b" + :ropsten "0x112234455c3a32fd11230c42e7bccd4a84e02010" + :rinkeby "0xe7410170f87102DF0055eB195163A03B7F2Bff4A"}) + +(def default-namehash "0000000000000000000000000000000000000000000000000000000000000000") + +(defn namehash [s] + (if (string/blank? s) + default-namehash + (let [[label remainder] (string/split s #"\." 2)] + (ethereum/sha3 (+ (namehash remainder) (subs (ethereum/sha3 label) 2)) {:encoding "hex"})))) + +;; Registry contract + +(defn resolver [web3 registry name cb] + (ethereum/call web3 + (ethereum/call-params registry "resolver(bytes32)" (namehash name)) + #(cb %1 (ethereum/hex->string %2)))) + +(defn owner [web3 registry name cb] + (ethereum/call web3 + (ethereum/call-params registry "owner(bytes32)" (namehash name)) + #(cb %1 (ethereum/hex->string %2)))) + +(defn ttl [web3 registry name cb] + (ethereum/call web3 + (ethereum/call-params registry "ttl(bytes32)" (namehash name)) + #(cb %1 (ethereum/hex->int %2)))) + +;; Resolver contract + +;; Resolver must implement EIP65 (supportsInterface). When interacting with an unknown resolver it's safer to rely on it. + +(def addr-hash "0x3b3b57de") + +(defn addr [web3 resolver name cb] + (ethereum/call web3 + (ethereum/call-params resolver "addr(bytes32)" (namehash name)) + #(cb %1 %2))) + +(defn content [web3 resolver name cb] + (ethereum/call web3 + (ethereum/call-params resolver "content(bytes32)" (namehash name)) + #(cb %1 (ethereum/hex->string %2)))) + +(def name-hash "0x691f3431") + +;; Defined by https://eips.ethereum.org/EIPS/eip-181 + +(defn name [web3 resolver name cb] + (ethereum/call web3 + (ethereum/call-params resolver "name(bytes32)" (namehash name)) + #(cb %1 (ethereum/hex->string %2)))) + +(defn text [web3 resolver name key cb] + (ethereum/call web3 + (ethereum/call-params resolver "text(bytes32,string)" (namehash name) key) + #(cb %1 (ethereum/hex->string %2)))) + +(def ABI-hash "0x2203ab56") +(def pubkey-hash "0xc8690233") + +;; TODO ABI, pubkey diff --git a/src/status_im/utils/ethereum/stateofus.cljs b/src/status_im/utils/ethereum/stateofus.cljs new file mode 100644 index 0000000000..925627d5f9 --- /dev/null +++ b/src/status_im/utils/ethereum/stateofus.cljs @@ -0,0 +1,8 @@ +(ns status-im.utils.ethereum.stateofus + (:require [clojure.string :as string] + [status-im.utils.ethereum.core :as ethereum] + [status-im.utils.ethereum.ens :as ens])) + +(defn name [web3 registry name cb] + (ens/resolver web3 registry name + #(ens/name web3 %2 name cb))) diff --git a/test/cljs/status_im/test/runner.cljs b/test/cljs/status_im/test/runner.cljs index e3a404a8fc..5b1a635535 100644 --- a/test/cljs/status_im/test/runner.cljs +++ b/test/cljs/status_im/test/runner.cljs @@ -35,6 +35,7 @@ [status-im.test.utils.clocks] [status-im.test.utils.ethereum.eip681] [status-im.test.utils.ethereum.core] + [status-im.test.utils.ethereum.ens] [status-im.test.utils.random] [status-im.test.utils.gfycat.core] [status-im.test.utils.signing-phrase.core] @@ -93,6 +94,7 @@ 'status-im.test.utils.clocks 'status-im.test.utils.ethereum.eip681 'status-im.test.utils.ethereum.core + 'status-im.test.utils.ethereum.ens 'status-im.test.utils.random 'status-im.test.utils.gfycat.core 'status-im.test.utils.signing-phrase.core diff --git a/test/cljs/status_im/test/utils/ethereum/ens.cljs b/test/cljs/status_im/test/utils/ethereum/ens.cljs new file mode 100644 index 0000000000..4bb0e1d387 --- /dev/null +++ b/test/cljs/status_im/test/utils/ethereum/ens.cljs @@ -0,0 +1,11 @@ +(ns status-im.test.utils.ethereum.ens + (:require [cljs.test :refer-macros [deftest is testing]] + [status-im.utils.ethereum.ens :as ens])) + +(deftest namehash + (is (= ens/default-namehash (ens/namehash nil))) + (is (= ens/default-namehash (ens/namehash ""))) + (is (= "0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae" + (ens/namehash "eth"))) + (is (= "0xde9b09fd7c5f901e23a3f19fecc54828e9c848539801e86591bd9801b019f84f" + (ens/namehash "foo.eth"))))