[#13007] Move ENS logic to status-go
Signed-off-by: andrey <motor4ik@gmail.com>
This commit is contained in:
parent
c0e30b459f
commit
8e560d313d
|
@ -1,6 +1,5 @@
|
|||
status-im.utils.build/warning-handler
|
||||
status-im.utils.build/get-current-sha
|
||||
status-im.ethereum.resolver/name
|
||||
status-im.chat.constants/spacing-char
|
||||
status-im.chat.constants/arg-wrapping-char
|
||||
status-im.ios.core/init
|
||||
|
|
|
@ -101,23 +101,22 @@
|
|||
|
||||
(re-frame/reg-fx
|
||||
::resolve-contract
|
||||
(fn [{:keys [chain contract on-success]}]
|
||||
(let [register (get ens/ens-registries chain)]
|
||||
(fn [{:keys [chain-id contract on-success]}]
|
||||
(when contract
|
||||
(if (string/starts-with? contract "0x")
|
||||
(on-success contract)
|
||||
(ens/get-addr register contract on-success))))))
|
||||
(ens/address chain-id contract on-success)))))
|
||||
|
||||
(fx/defn create [{:keys [db]}]
|
||||
(when-not config/google-free
|
||||
{::resolve-contract {:chain (ethereum/chain-keyword db)
|
||||
{::resolve-contract {:chain (ethereum/chain-id db)
|
||||
:contract (contracts/get-address db :status/acquisition)
|
||||
:on-success #(re-frame/dispatch [:set-in [:acquisition :contract] %])}
|
||||
::get-referrer nil}))
|
||||
|
||||
(fx/defn login [{:keys [db]}]
|
||||
(when-not config/google-free
|
||||
{::resolve-contract {:chain (ethereum/chain-keyword db)
|
||||
{::resolve-contract {:chain (ethereum/chain-id db)
|
||||
:contract (contracts/get-address db :status/acquisition)
|
||||
:on-success #(re-frame/dispatch [:set-in [:acquisition :contract] %])}
|
||||
::check-referrer nil}))
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
[re-frame.core :as re-frame]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.ens :as ens]
|
||||
[status-im.ethereum.resolver :as resolver]
|
||||
[status-im.add-new.db :as db]
|
||||
[status-im.utils.random :as random]
|
||||
[status-im.utils.utils :as utils]
|
||||
|
@ -13,14 +12,14 @@
|
|||
[status-im.contact.core :as contact]
|
||||
[status-im.router.core :as router]
|
||||
[status-im.navigation :as navigation]
|
||||
[status-im.ethereum.stateofus :as stateofus]
|
||||
[status-im.utils.db :as utils.db]))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:resolve-public-key
|
||||
(fn [{:keys [chain contact-identity cb]}]
|
||||
(let [registry (get ens/ens-registries chain)
|
||||
ens-name (resolver/ens-name-parse contact-identity)]
|
||||
(resolver/pubkey registry ens-name cb))))
|
||||
(fn [{:keys [chain-id contact-identity cb]}]
|
||||
(let [ens-name (stateofus/ens-name-parse contact-identity)]
|
||||
(ens/pubkey chain-id ens-name cb))))
|
||||
|
||||
;;NOTE we want to handle only last resolve
|
||||
(def resolve-last-id (atom nil))
|
||||
|
@ -53,17 +52,16 @@
|
|||
:else
|
||||
:valid)
|
||||
:error error
|
||||
:ens-name (resolver/ens-name-parse new-ens-name)})}
|
||||
:ens-name (stateofus/ens-name-parse new-ens-name)})}
|
||||
(when is-ens?
|
||||
(reset! resolve-last-id (random/id))
|
||||
(let [chain (ethereum/chain-keyword db)]
|
||||
{:resolve-public-key
|
||||
{:chain chain
|
||||
{:chain-id (ethereum/chain-id db)
|
||||
:contact-identity new-identity
|
||||
:cb #(re-frame/dispatch [:new-chat/set-new-identity
|
||||
%
|
||||
new-identity
|
||||
@resolve-last-id])}}))))))))
|
||||
@resolve-last-id])}})))))))
|
||||
|
||||
(fx/defn clear-new-identity
|
||||
{:events [::clear-new-identity ::new-chat-focus]}
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.ens :as ens]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.ethereum.resolver :as resolver]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.native-module.core :as status]
|
||||
[status-im.ui.components.list-selection :as list-selection]
|
||||
|
@ -14,7 +13,6 @@
|
|||
[status-im.utils.contenthash :as contenthash]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.http :as http]
|
||||
[status-im.utils.multihash :as multihash]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.utils.random :as random]
|
||||
[status-im.utils.types :as types]
|
||||
|
@ -73,22 +71,10 @@
|
|||
(let [history-host (http/url-host (try (nth history history-index) (catch js/Error _)))]
|
||||
(cond-> browser history-host (assoc :unsafe? (eth-phishing-detect history-host)))))
|
||||
|
||||
(defn- content->hash [hex]
|
||||
(when (and hex (not= hex "0x"))
|
||||
;; TODO(julien) Remove once our ENS DApp are migrated
|
||||
(multihash/base58 (multihash/create :sha2-256 (subs hex 2)))))
|
||||
|
||||
(defn resolve-ens-content-callback [hex]
|
||||
(let [hash (content->hash hex)]
|
||||
(if (and hash (not= hash resolver/default-hash))
|
||||
(re-frame/dispatch [:browser.callback/resolve-ens-multihash-success {:namespace :ipfs :hash hash}])
|
||||
(re-frame/dispatch [:browser.callback/resolve-ens-contenthash]))))
|
||||
|
||||
(defn resolve-ens-contenthash-callback [hex]
|
||||
(let [{:keys [hash] :as m} (contenthash/decode hex)]
|
||||
(if (and hash (not= hash resolver/default-hash))
|
||||
(re-frame/dispatch [:browser.callback/resolve-ens-multihash-success m])
|
||||
(re-frame/dispatch [:browser.callback/resolve-ens-multihash-error]))))
|
||||
(defn resolve-ens-contenthash-callback [url]
|
||||
(if (not (string/blank? url))
|
||||
(re-frame/dispatch [:browser.callback/resolve-ens-multihash-success url])
|
||||
(re-frame/dispatch [:browser.callback/resolve-ens-multihash-error])))
|
||||
|
||||
(fx/defn resolve-url
|
||||
[{:keys [db]} {:keys [error? resolved-url]}]
|
||||
|
@ -96,26 +82,12 @@
|
|||
(let [current-url (get-current-url (get-current-browser db))
|
||||
host (http/url-host current-url)]
|
||||
(if (and (not resolved-url) (ens/is-valid-eth-name? host))
|
||||
(let [chain (ethereum/chain-keyword db)]
|
||||
{:db (update db :browser/options assoc :resolving? true)
|
||||
:browser/resolve-ens-content {:registry (get ens/ens-registries
|
||||
chain)
|
||||
:browser/resolve-ens-contenthash {:chain-id (ethereum/chain-id db)
|
||||
:ens-name host
|
||||
:cb resolve-ens-content-callback}})
|
||||
:cb resolve-ens-contenthash-callback}}
|
||||
{:db (update db :browser/options assoc :url (or resolved-url current-url) :resolving? false)}))))
|
||||
|
||||
(fx/defn resolve-ens-contenthash
|
||||
{:events [:browser.callback/resolve-ens-contenthash]}
|
||||
[{:keys [db]}]
|
||||
(let [current-url (get-current-url (get-current-browser db))
|
||||
host (http/url-host current-url)
|
||||
chain (ethereum/chain-keyword db)]
|
||||
{:db (update db :browser/options assoc :resolving? true)
|
||||
:browser/resolve-ens-contenthash {:registry (get ens/ens-registries
|
||||
chain)
|
||||
:ens-name host
|
||||
:cb resolve-ens-contenthash-callback}}))
|
||||
|
||||
(fx/defn update-browser
|
||||
[{:keys [db]}
|
||||
{:keys [browser-id] :as browser}]
|
||||
|
@ -217,11 +189,11 @@
|
|||
|
||||
(fx/defn resolve-ens-multihash-success
|
||||
{:events [:browser.callback/resolve-ens-multihash-success]}
|
||||
[{:keys [db] :as cofx} m]
|
||||
[{:keys [db] :as cofx} url]
|
||||
(let [current-url (get-current-url (get-current-browser db))
|
||||
host (http/url-host current-url)
|
||||
path (subs current-url (+ (.indexOf ^js current-url host) (count host)))
|
||||
gateway (storage-gateway m)]
|
||||
gateway url]
|
||||
(fx/merge cofx
|
||||
{:db (-> (update db :browser/options
|
||||
assoc
|
||||
|
@ -497,15 +469,10 @@
|
|||
(= type constants/api-request)
|
||||
(browser.permissions/process-permission cofx dapp-name permission messageId params))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:browser/resolve-ens-content
|
||||
(fn [{:keys [registry ens-name cb]}]
|
||||
(resolver/content registry ens-name cb)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:browser/resolve-ens-contenthash
|
||||
(fn [{:keys [registry ens-name cb]}]
|
||||
(resolver/contenthash registry ens-name cb)))
|
||||
(fn [{:keys [chain-id ens-name cb]}]
|
||||
(ens/resource-url chain-id ens-name cb)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:browser/send-to-bridge
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.eip55 :as eip55]
|
||||
[status-im.ethereum.ens :as ens]
|
||||
[status-im.ethereum.resolver :as resolver]
|
||||
[status-im.ethereum.stateofus :as stateofus]
|
||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[status-im.signing.core :as signing]
|
||||
|
@ -23,6 +22,26 @@
|
|||
username
|
||||
(stateofus/subdomain username)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::resolve-address
|
||||
(fn [[chain-id name cb]]
|
||||
(ens/address chain-id name cb)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::resolve-owner
|
||||
(fn [[chain-id name cb]]
|
||||
(ens/owner chain-id name cb)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::resolve-pubkey
|
||||
(fn [[chain-id name cb]]
|
||||
(ens/pubkey chain-id name cb)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::get-expiration-time
|
||||
(fn [[chain-id name cb]]
|
||||
(ens/expire-at chain-id name cb)))
|
||||
|
||||
(fx/defn update-ens-tx-state
|
||||
{:events [:update-ens-tx-state]}
|
||||
[{:keys [db]} new-state username custom-domain? tx-hash]
|
||||
|
@ -52,29 +71,6 @@
|
|||
[{:keys [db]} tx-hash]
|
||||
{:db (update db :ens/registrations dissoc tx-hash)})
|
||||
|
||||
(re-frame/reg-fx
|
||||
::resolve-address
|
||||
(fn [[registry name cb]]
|
||||
(ens/get-addr registry name cb)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::resolve-owner
|
||||
(fn [[registry name cb]]
|
||||
(ens/get-owner registry name cb)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::resolve-pubkey
|
||||
(fn [[registry name cb]]
|
||||
(resolver/pubkey registry name cb)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::get-expiration-time
|
||||
(fn [[chain label-hash cb]]
|
||||
(stateofus/get-registrar
|
||||
chain
|
||||
(fn [registrar]
|
||||
(stateofus/get-expiration-time registrar label-hash cb)))))
|
||||
|
||||
(fx/defn set-state
|
||||
{:events [::name-resolved]}
|
||||
[{:keys [db]} username state address]
|
||||
|
@ -135,7 +131,7 @@
|
|||
nil)))
|
||||
|
||||
(defn- on-resolve-owner
|
||||
[registry custom-domain? username addresses public-key response resolve-last-id* resolve-last-id]
|
||||
[chain-id custom-domain? username addresses public-key response resolve-last-id* resolve-last-id]
|
||||
(when (= @resolve-last-id* resolve-last-id)
|
||||
(cond
|
||||
|
||||
|
@ -146,14 +142,15 @@
|
|||
;; if we get an address back, we try to get the public key associated
|
||||
;; with the username as well
|
||||
(get addresses (eip55/address->checksum response))
|
||||
(resolver/pubkey registry (fullname custom-domain? username)
|
||||
(ens/pubkey
|
||||
chain-id
|
||||
(fullname custom-domain? username)
|
||||
#(re-frame/dispatch [::name-resolved username
|
||||
(cond
|
||||
(not public-key) :owned
|
||||
(= % public-key) :connected
|
||||
:else :connected-with-different-key)
|
||||
(eip55/address->checksum response)]))
|
||||
|
||||
:else
|
||||
(re-frame/dispatch [::name-resolved username :taken]))))
|
||||
|
||||
|
@ -163,6 +160,9 @@
|
|||
3 50
|
||||
1 10))
|
||||
|
||||
;; (andrey) there is the method "register" in status-go, but im not sure how we could use it
|
||||
;; because we still need to prepare tx and show it to user, and then have a condition to do not sign tx but
|
||||
;; call register method instead, doesn't look like a good solution
|
||||
(fx/defn register-name
|
||||
{:events [::register-name-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
|
@ -225,11 +225,11 @@
|
|||
(let [{:keys [multiaccount]} db
|
||||
{:keys [public-key]} multiaccount
|
||||
addresses (ethereum/addresses-without-watch db)
|
||||
registry (get ens/ens-registries (ethereum/chain-keyword db))]
|
||||
{::resolve-owner [registry
|
||||
chain-id (ethereum/chain-id db)]
|
||||
{::resolve-owner [chain-id
|
||||
(fullname custom-domain? username)
|
||||
#(on-resolve-owner
|
||||
registry custom-domain? username addresses public-key %
|
||||
chain-id custom-domain? username addresses public-key %
|
||||
resolve-last-id @resolve-last-id)]})))))
|
||||
|
||||
(fx/defn return-to-ens-main-screen
|
||||
|
@ -260,7 +260,7 @@
|
|||
|
||||
(fx/defn save-preferred-name
|
||||
{:events [::save-preferred-name]}
|
||||
[{:keys [db] :as cofx} name]
|
||||
[cofx name]
|
||||
(multiaccounts.update/multiaccount-update cofx
|
||||
:preferred-name name
|
||||
{}))
|
||||
|
@ -270,7 +270,7 @@
|
|||
it should only be called if the user cancels the signing
|
||||
Actual registration failure has not been implemented properly"
|
||||
{:events [::on-registration-failure]}
|
||||
[{:keys [db]} username])
|
||||
[_ _])
|
||||
|
||||
(fx/defn store-name-address
|
||||
{:events [::address-resolved]}
|
||||
|
@ -293,20 +293,17 @@
|
|||
(fx/defn navigate-to-name
|
||||
{:events [::navigate-to-name]}
|
||||
[{:keys [db] :as cofx} username]
|
||||
(let [chain (ethereum/chain-keyword db)
|
||||
registry (get ens/ens-registries chain)]
|
||||
(let [chain-id (ethereum/chain-id db)]
|
||||
(fx/merge cofx
|
||||
{::get-expiration-time
|
||||
[chain
|
||||
(-> username
|
||||
stateofus/username
|
||||
ethereum/sha3)
|
||||
[chain-id
|
||||
(stateofus/username username)
|
||||
#(re-frame/dispatch [::get-expiration-time-success username %])]
|
||||
::resolve-address
|
||||
[registry username
|
||||
[chain-id username
|
||||
#(re-frame/dispatch [::address-resolved username %])]
|
||||
::resolve-pubkey
|
||||
[registry username
|
||||
[chain-id username
|
||||
#(re-frame/dispatch [::public-key-resolved username %])]}
|
||||
(navigation/navigate-to-cofx :ens-name-details username))))
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
(def default-namehash "0000000000000000000000000000000000000000000000000000000000000000")
|
||||
(def default-address "0x0000000000000000000000000000000000000000")
|
||||
(def default-key "0x0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
|
||||
(def default-hash "0x0000000000000000000000000000000000000000000000000000000000000000")
|
||||
|
||||
(defn namehash
|
||||
[s]
|
||||
|
@ -33,8 +34,6 @@
|
|||
(ethereum/sha3 (str (namehash remainder)
|
||||
(subs (ethereum/sha3 label) 2))))))))
|
||||
|
||||
;; Registry contract
|
||||
|
||||
(defn resolver
|
||||
[registry ens-name cb]
|
||||
(json-rpc/eth-call
|
||||
|
@ -47,113 +46,6 @@
|
|||
(fn [[address]]
|
||||
(cb (when-not (= address default-address) address)))}))
|
||||
|
||||
(defn owner
|
||||
[registry ens-name cb]
|
||||
(json-rpc/eth-call
|
||||
{:contract registry
|
||||
:method "owner(bytes32)"
|
||||
:params [(namehash ens-name)]
|
||||
:outputs ["address"]
|
||||
:on-error #(cb "0x")
|
||||
:on-success
|
||||
(fn [[address]]
|
||||
(cb address))}))
|
||||
|
||||
(defn ttl
|
||||
[registry ens-name cb]
|
||||
(json-rpc/eth-call
|
||||
{:contract registry
|
||||
:method "ttl(bytes32)"
|
||||
:params [(namehash ens-name)]
|
||||
:outputs ["uint256"]
|
||||
:on-success
|
||||
(fn [[ttl]]
|
||||
(cb ttl))}))
|
||||
|
||||
;; 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
|
||||
[resolver ens-name cb]
|
||||
(json-rpc/eth-call
|
||||
{:contract resolver
|
||||
:method "addr(bytes32)"
|
||||
:params [(namehash ens-name)]
|
||||
:outputs ["address"]
|
||||
:on-error #(cb "0x")
|
||||
:on-success
|
||||
(fn [[address]]
|
||||
(cb address))}))
|
||||
|
||||
(def name-hash "0x691f3431")
|
||||
|
||||
;; Defined by https://eips.ethereum.org/EIPS/eip-181
|
||||
|
||||
(defn name
|
||||
[resolver ens-name cb]
|
||||
(json-rpc/eth-call
|
||||
{:contract resolver
|
||||
:method "name(bytes32)"
|
||||
:params [(namehash ens-name)]
|
||||
:outputs ["string"]
|
||||
:on-error #(cb "0x")
|
||||
:on-success
|
||||
(fn [[name]]
|
||||
(cb name))}))
|
||||
|
||||
(defn cleanup-hash [raw-hash]
|
||||
;; NOTE: it would be better if our abi-spec/decode was able to do that
|
||||
(let [;; ignore hex prefix
|
||||
[_ raw-hash-rest] (split-at 2 raw-hash)
|
||||
;; the first field gives us the length of the next one in hex and has
|
||||
;; a length of 32 bytes
|
||||
;; 1 byte is 2 chars here
|
||||
[next-field-length-hex raw-hash-rest] (split-at 64 raw-hash-rest)
|
||||
next-field-length (* ^number (abi-spec/hex-to-number (string/join next-field-length-hex)) 2)
|
||||
;; we get the next field which is the length of the hash and is
|
||||
;; expected to be 32 bytes as well
|
||||
[hash-field-length-hex raw-hash-rest] (split-at next-field-length
|
||||
raw-hash-rest)
|
||||
hash-field-length (* ^number (abi-spec/hex-to-number (string/join hash-field-length-hex)) 2)
|
||||
;; we get the hash
|
||||
[hash _] (split-at hash-field-length raw-hash-rest)]
|
||||
(str "0x" (string/join hash))))
|
||||
|
||||
(defn contenthash
|
||||
[resolver ens-name cb]
|
||||
(json-rpc/eth-call
|
||||
{:contract resolver
|
||||
:method "contenthash(bytes32)"
|
||||
:params [(namehash ens-name)]
|
||||
:on-error #(cb "0x")
|
||||
:on-success
|
||||
(fn [raw-hash]
|
||||
;; NOTE: it would be better if our abi-spec/decode was able to do that
|
||||
(cb (cleanup-hash raw-hash)))}))
|
||||
|
||||
(defn content
|
||||
[resolver ens-name cb]
|
||||
(json-rpc/eth-call
|
||||
{:contract resolver
|
||||
:method "content(bytes32)"
|
||||
:params [(namehash ens-name)]
|
||||
:on-success
|
||||
(fn [hash]
|
||||
(cb hash))
|
||||
;;at some point infura started to return execution reverted error instead of "0x" result
|
||||
;;our code expects "0x" result
|
||||
:on-error #(cb "0x")}))
|
||||
|
||||
(def ABI-hash "0x2203ab56")
|
||||
(def pubkey-hash "0xc8690233")
|
||||
|
||||
(defn uncompressed-public-key
|
||||
[x y]
|
||||
(when (and x y)
|
||||
(str "0x04" x y)))
|
||||
|
||||
(defn valid-eth-name-prefix?
|
||||
[prefix]
|
||||
(not
|
||||
|
@ -167,29 +59,43 @@
|
|||
(string? ens-name)
|
||||
(string/ends-with? ens-name ".eth")))
|
||||
|
||||
(defn address
|
||||
[chain-id ens-name cb]
|
||||
{:pre [(is-valid-eth-name? ens-name)]}
|
||||
(json-rpc/call {:method "ens_addressOf"
|
||||
:params [chain-id ens-name]
|
||||
:on-success cb
|
||||
:on-error #(cb "0x")}))
|
||||
|
||||
(defn pubkey
|
||||
[resolver ens-name cb]
|
||||
(json-rpc/eth-call
|
||||
{:contract resolver
|
||||
:method "pubkey(bytes32)"
|
||||
:params [(namehash ens-name)]
|
||||
:outputs ["bytes32" "bytes32"]
|
||||
:on-success
|
||||
(fn [[x y]]
|
||||
(let [public-key (uncompressed-public-key x y)]
|
||||
(cb public-key)))
|
||||
[chain-id ens-name cb]
|
||||
{:pre [(is-valid-eth-name? ens-name)]}
|
||||
(json-rpc/call {:method "ens_publicKeyOf"
|
||||
:params [chain-id ens-name]
|
||||
:on-success (fn [result]
|
||||
(cb (str "0x04" (subs result 2))))
|
||||
;;at some point infura started to return execution reverted error instead of "0x" result
|
||||
;;our code expects "0x" result
|
||||
:on-error #(cb "0x")}))
|
||||
|
||||
(defn get-addr
|
||||
[registry ens-name cb]
|
||||
{:pre [(is-valid-eth-name? ens-name)]}
|
||||
(resolver registry
|
||||
ens-name
|
||||
#(addr % ens-name cb)))
|
||||
(defn owner
|
||||
[chain-id ens-name cb]
|
||||
(json-rpc/call {:method "ens_ownerOf"
|
||||
:params [chain-id ens-name]
|
||||
:on-success cb
|
||||
:on-error #(cb "0x")}))
|
||||
|
||||
(defn get-owner
|
||||
[registry ens-name cb]
|
||||
{:pre [(is-valid-eth-name? ens-name)]}
|
||||
(owner registry ens-name cb))
|
||||
(defn resource-url
|
||||
[chain-id ens-name cb]
|
||||
(json-rpc/call {:method "ens_resourceURL"
|
||||
:params [chain-id ens-name]
|
||||
:on-success #(cb (str "https://" (:Host %)))
|
||||
:on-error #(cb "0x")}))
|
||||
|
||||
(defn expire-at
|
||||
[chain-id ens-name cb]
|
||||
(json-rpc/call {:method "ens_expireAt"
|
||||
:params [chain-id ens-name]
|
||||
:on-success
|
||||
;;NOTE: returns a timestamp in s and we want ms
|
||||
#(cb (* (js/Number (abi-spec/hex-to-number %)) 1000))}))
|
|
@ -9,11 +9,3 @@
|
|||
(ens/namehash "eth")))
|
||||
(is (= "0xde9b09fd7c5f901e23a3f19fecc54828e9c848539801e86591bd9801b019f84f"
|
||||
(ens/namehash "foo.eth"))))
|
||||
|
||||
(deftest cleanup-hash
|
||||
;; simpledapp.eth
|
||||
(is (= "0xe30101701220795c1ea0ceaf4ceedc9896f14b73bb30e978e4855ee221b9a57f5a934268280e"
|
||||
(ens/cleanup-hash "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000026e30101701220795c1ea0ceaf4ceedc9896f14b73bb30e978e4855ee221b9a57f5a934268280e0000000000000000000000000000000000000000000000000000")))
|
||||
;; ethereum.eth
|
||||
(is (= "0xe301017012206e70f0f72e2bcd0ad69bb2b15ee9e0f4f88693f6b2f485e48699e7d6f8dbd62a"
|
||||
(ens/cleanup-hash "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000026e301017012206e70f0f72e2bcd0ad69bb2b15ee9e0f4f88693f6b2f485e48699e7d6f8dbd62a0000000000000000000000000000000000000000000000000000"))))
|
||||
|
|
|
@ -29,6 +29,12 @@
|
|||
"eth_getCode" {}
|
||||
"eth_syncing" {}
|
||||
"eth_feeHistory" {}
|
||||
"ens_publicKeyOf" {}
|
||||
"ens_addressOf" {}
|
||||
"ens_expireAt" {}
|
||||
"ens_ownerOf" {}
|
||||
"ens_contentHash" {}
|
||||
"ens_resourceURL" {}
|
||||
"net_version" {}
|
||||
"web3_clientVersion" {}
|
||||
"shh_generateSymKeyFromPassword" {}
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
(ns status-im.ethereum.resolver
|
||||
(:refer-clojure :exclude [name])
|
||||
(:require [status-im.ethereum.ens :as ens]
|
||||
[status-im.ethereum.stateofus :as stateofus]
|
||||
[clojure.string :as string]))
|
||||
|
||||
(def default-hash "0x0000000000000000000000000000000000000000000000000000000000000000")
|
||||
(defn contenthash [registry ens-name cb]
|
||||
(ens/resolver registry
|
||||
ens-name
|
||||
#(ens/contenthash % ens-name cb)))
|
||||
|
||||
(defn content [registry ens-name cb]
|
||||
(ens/resolver registry
|
||||
ens-name
|
||||
#(ens/content % ens-name cb)))
|
||||
|
||||
(defn name [registry ens-name cb]
|
||||
(ens/resolver registry
|
||||
ens-name
|
||||
#(ens/name % ens-name cb)))
|
||||
|
||||
(defn pubkey
|
||||
[registry ens-name cb]
|
||||
{:pre [(ens/is-valid-eth-name? ens-name)]}
|
||||
(ens/resolver registry
|
||||
ens-name
|
||||
#(ens/pubkey % ens-name cb)))
|
||||
|
||||
(defn ens-name-parse [contact-identity]
|
||||
(when (string? contact-identity)
|
||||
(string/lower-case
|
||||
(if (ens/is-valid-eth-name? contact-identity)
|
||||
contact-identity
|
||||
(stateofus/subdomain contact-identity)))))
|
|
@ -1,8 +1,8 @@
|
|||
(ns status-im.ethereum.stateofus
|
||||
(:require [clojure.string :as string]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.utils.config :as config]
|
||||
[status-im.ethereum.ens :as ens]))
|
||||
[status-im.ethereum.ens :as ens]
|
||||
[status-im.ethereum.core :as ethereum]))
|
||||
|
||||
(def domain "stateofus.eth")
|
||||
|
||||
|
@ -37,14 +37,13 @@
|
|||
(defn get-registrar [chain callback]
|
||||
(if-let [contract (get @registrars-cache chain)]
|
||||
(callback contract)
|
||||
(let [registry (get ens/ens-registries chain)]
|
||||
(ens/get-owner
|
||||
registry
|
||||
(ens/owner
|
||||
(ethereum/chain-keyword->chain-id chain)
|
||||
domain
|
||||
(fn [addr]
|
||||
(let [addr (or addr (get old-registrars chain))]
|
||||
(swap! registrars-cache assoc chain addr)
|
||||
(callback addr)))))))
|
||||
(callback addr))))))
|
||||
|
||||
(defn get-cached-registrar [chain]
|
||||
(get @registrars-cache chain (get old-registrars chain)))
|
||||
|
@ -58,14 +57,9 @@
|
|||
(and (lower-case? username)
|
||||
(re-find #"^[a-z0-9]+$" username))))
|
||||
|
||||
(defn get-expiration-time
|
||||
[registrar label-hash cb]
|
||||
(json-rpc/eth-call
|
||||
{:contract registrar
|
||||
:method "getExpirationTime(bytes32)"
|
||||
:params [label-hash]
|
||||
:outputs ["uint256"]
|
||||
:on-success
|
||||
(fn [[release-time]]
|
||||
;;NOTE: returns a timestamp in s and we want ms
|
||||
(cb (* release-time 1000)))}))
|
||||
(defn ens-name-parse [contact-identity]
|
||||
(when (string? contact-identity)
|
||||
(string/lower-case
|
||||
(if (ens/is-valid-eth-name? contact-identity)
|
||||
contact-identity
|
||||
(subdomain contact-identity)))))
|
||||
|
|
|
@ -7,12 +7,12 @@
|
|||
[status-im.utils.security :as security]
|
||||
[status-im.ethereum.eip681 :as eip681]
|
||||
[status-im.ethereum.ens :as ens]
|
||||
[status-im.ethereum.resolver :as resolver]
|
||||
[cljs.spec.alpha :as spec]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.utils.db :as utils.db]
|
||||
[status-im.utils.http :as http]
|
||||
[status-im.chat.models :as chat.models]))
|
||||
[status-im.chat.models :as chat.models]
|
||||
[status-im.ethereum.stateofus :as stateofus]))
|
||||
|
||||
(def ethereum-scheme "ethereum:")
|
||||
|
||||
|
@ -61,12 +61,6 @@
|
|||
(defn match-uri [uri]
|
||||
(assoc (bidi/match-route routes uri) :uri uri :query-params (parse-query-params uri)))
|
||||
|
||||
(defn resolve-public-key
|
||||
[{:keys [chain contact-identity cb]}]
|
||||
(let [registry (get ens/ens-registries chain)
|
||||
ens-name (resolver/ens-name-parse contact-identity)]
|
||||
(resolver/pubkey registry ens-name cb)))
|
||||
|
||||
(defn match-contact-async
|
||||
[chain {:keys [user-id]} callback]
|
||||
(let [valid-key (and (spec/valid? :global/public-key user-id)
|
||||
|
@ -78,10 +72,10 @@
|
|||
|
||||
(and (not valid-key) (string? user-id) (not (string/blank? user-id))
|
||||
(not= user-id "0x"))
|
||||
(let [registry (get ens/ens-registries chain)
|
||||
ens-name (resolver/ens-name-parse user-id)
|
||||
(let [chain-id (ethereum/chain-keyword->chain-id chain)
|
||||
ens-name (stateofus/ens-name-parse user-id)
|
||||
on-success #(match-contact-async chain {:user-id %} callback)]
|
||||
(resolver/pubkey registry ens-name on-success))
|
||||
(ens/pubkey chain-id ens-name on-success))
|
||||
|
||||
:else
|
||||
(callback {:type :contact
|
||||
|
|
|
@ -1,185 +0,0 @@
|
|||
(ns status-im.utils.multihash
|
||||
"Core multihash type definition and helper methods."
|
||||
(:require
|
||||
[alphabase.base58 :as b58]
|
||||
[alphabase.bytes :as bytes]
|
||||
[alphabase.hex :as hex]))
|
||||
|
||||
(def algorithm-codes
|
||||
"Map of information about the available content hashing algorithms."
|
||||
{:sha1 0x11
|
||||
:sha2-256 0x12
|
||||
:sha2-512 0x13
|
||||
:sha3 0x14
|
||||
:blake2b 0x40
|
||||
:blake2s 0x41})
|
||||
|
||||
(defn app-code?
|
||||
"True if the given code number is assigned to the application-specfic range.
|
||||
Returns nil if the argument is not an integer."
|
||||
[code]
|
||||
(when (integer? code)
|
||||
(< 0 code 0x10)))
|
||||
|
||||
(defn get-algorithm
|
||||
"Looks up an algorithm by keyword name or code number. Returns `nil` if the
|
||||
value does not map to any valid algorithm."
|
||||
[value]
|
||||
(cond
|
||||
(keyword? value)
|
||||
(when-let [code (get algorithm-codes value)]
|
||||
{:code code, :name value})
|
||||
|
||||
(not (integer? value))
|
||||
nil
|
||||
|
||||
(app-code? value)
|
||||
{:code value, :name (keyword (str "app-" value))}
|
||||
|
||||
:else
|
||||
(some #(when (= value (val %))
|
||||
{:code value, :name (key %)})
|
||||
algorithm-codes)))
|
||||
|
||||
;; ## Multihash Type
|
||||
|
||||
;; Multihash identifiers have two properties:
|
||||
;;
|
||||
;; - `code` is a numeric code for an algorithm entry in `algorithm-codes` or an
|
||||
;; application-specific algorithm code.
|
||||
;; - `hex-digest` is a string holding the hex-encoded algorithm output.
|
||||
;;
|
||||
;; Multihash values also support metadata.
|
||||
(deftype Multihash [code hex-digest _meta]
|
||||
|
||||
Object
|
||||
|
||||
(toString
|
||||
[this]
|
||||
(str "hash:" (name (:name (get-algorithm code))) \: hex-digest))
|
||||
|
||||
(-equiv
|
||||
[this that]
|
||||
(cond
|
||||
(identical? this that) true
|
||||
(instance? Multihash that)
|
||||
(and (= code (:code that))
|
||||
(= hex-digest (:hex-digest that)))
|
||||
:else false))
|
||||
|
||||
IHash
|
||||
|
||||
(-hash
|
||||
[this]
|
||||
(hash-combine code hex-digest))
|
||||
|
||||
IComparable
|
||||
|
||||
(-compare
|
||||
[this that]
|
||||
(cond
|
||||
(= this that) 0
|
||||
(< code (:code that)) -1
|
||||
(> code (:code that)) 1
|
||||
:else (compare hex-digest (:hex-digest that))))
|
||||
|
||||
ILookup
|
||||
|
||||
(-lookup
|
||||
[this k]
|
||||
(-lookup this k nil))
|
||||
|
||||
(-lookup
|
||||
[this k not-found]
|
||||
(case k
|
||||
:code code
|
||||
:algorithm (:name (get-algorithm code))
|
||||
:length (/ (count hex-digest) 2)
|
||||
:digest (hex/decode hex-digest)
|
||||
:hex-digest hex-digest
|
||||
not-found))
|
||||
|
||||
IMeta
|
||||
|
||||
(-meta
|
||||
[this]
|
||||
_meta)
|
||||
|
||||
IWithMeta
|
||||
|
||||
(-with-meta
|
||||
[this meta-map]
|
||||
(Multihash. code hex-digest meta-map)))
|
||||
|
||||
(defn create
|
||||
"Constructs a new Multihash identifier. Accepts either a numeric algorithm
|
||||
code or a keyword name as the first argument. The digest may either by a byte
|
||||
array or a hex string."
|
||||
[algorithm digest]
|
||||
(let [algo (get-algorithm algorithm)]
|
||||
(when-not (integer? (:code algo))
|
||||
(throw (ex-info
|
||||
(str "Argument " (pr-str algorithm) " does not "
|
||||
"represent a valid hash algorithm.")
|
||||
{:algorithm algorithm})))
|
||||
(let [hex-digest (if (string? digest) digest (hex/encode digest))
|
||||
byte-len (/ (count hex-digest) 2)]
|
||||
(when (< 127 byte-len)
|
||||
(throw (ex-info (str "Digest length must be less than 128 bytes: "
|
||||
byte-len)
|
||||
{:length byte-len})))
|
||||
(when-let [err (hex/validate hex-digest)]
|
||||
(throw (ex-info err {:hex-digest hex-digest})))
|
||||
(->Multihash (:code algo) hex-digest nil))))
|
||||
|
||||
;; ## Encoding and Decoding
|
||||
|
||||
(defn encode
|
||||
"Encodes a multihash into a binary representation."
|
||||
^bytes
|
||||
[mhash]
|
||||
(let [length (:length mhash)
|
||||
encoded (bytes/byte-array (+ length 2))]
|
||||
(bytes/set-byte encoded 0 (:code mhash))
|
||||
(bytes/set-byte encoded 1 length)
|
||||
(bytes/copy (:digest mhash) 0 encoded 2 length)
|
||||
encoded))
|
||||
|
||||
(defn hex
|
||||
"Encodes a multihash into a hexadecimal string."
|
||||
[mhash]
|
||||
(when mhash
|
||||
(hex/encode (encode mhash))))
|
||||
|
||||
(defn base58
|
||||
"Encodes a multihash into a Base-58 string."
|
||||
[mhash]
|
||||
(when mhash
|
||||
(b58/encode (encode mhash))))
|
||||
|
||||
(defn decode-array
|
||||
"Decodes a byte array directly into multihash. Throws `ex-info` with a `:type`
|
||||
of `:multihash/bad-input` if the data is malformed or invalid."
|
||||
[^bytes encoded]
|
||||
(let [encoded-size (alength encoded)
|
||||
min-size 3]
|
||||
(when (< encoded-size min-size)
|
||||
(throw (ex-info
|
||||
(str "Cannot read multihash from byte array: " encoded-size
|
||||
" is less than the minimum of " min-size)
|
||||
{:type :multihash/bad-input}))))
|
||||
(let [code (bytes/get-byte encoded 0)
|
||||
length (bytes/get-byte encoded 1)
|
||||
payload (- (alength encoded) 2)]
|
||||
(when-not (pos? length)
|
||||
(throw (ex-info
|
||||
(str "Encoded length " length " is invalid")
|
||||
{:type :multihash/bad-input})))
|
||||
(when (< payload length)
|
||||
(throw (ex-info
|
||||
(str "Encoded digest length " length " exceeds actual "
|
||||
"remaining payload of " payload " bytes")
|
||||
{:type :multihash/bad-input})))
|
||||
(let [digest (bytes/byte-array length)]
|
||||
(bytes/copy encoded 2 digest 0 length)
|
||||
(create code digest))))
|
|
@ -21,11 +21,10 @@
|
|||
[taoensso.timbre :as log]
|
||||
[status-im.wallet.prices :as prices]
|
||||
[status-im.utils.hex :as hex]
|
||||
[status-im.ethereum.ens :as ens]
|
||||
[status-im.ens.core :as ens.core]
|
||||
[status-im.ethereum.resolver :as resolver]
|
||||
[status-im.utils.mobile-sync :as utils.mobile-sync]
|
||||
[status-im.multiaccounts.key-storage.core :as key-storage]))
|
||||
[status-im.multiaccounts.key-storage.core :as key-storage]
|
||||
[status-im.ethereum.stateofus :as stateofus]))
|
||||
|
||||
(fx/defn start-adding-new-account
|
||||
{:events [:wallet.accounts/start-adding-new-account]}
|
||||
|
@ -242,21 +241,18 @@
|
|||
|
||||
(fx/defn set-account-to-watch
|
||||
{:events [:wallet.accounts/set-account-to-watch]}
|
||||
[{:keys [db] :as cofx} account]
|
||||
[{:keys [db]} account]
|
||||
(let [name? (and (>= (count account) 3)
|
||||
(not (hex/valid-hex? account)))
|
||||
chain (ethereum/chain-keyword db)]
|
||||
(not (hex/valid-hex? account)))]
|
||||
(log/debug "[wallet] set-account-to-watch" account
|
||||
"name?" name?)
|
||||
(cond-> {:db (assoc-in db [:add-account :address] account)}
|
||||
name?
|
||||
(assoc ::ens.core/resolve-address
|
||||
(let [registry (get ens/ens-registries chain)
|
||||
ens-name (resolver/ens-name-parse account)]
|
||||
[registry
|
||||
ens-name
|
||||
[(ethereum/chain-id db)
|
||||
(stateofus/ens-name-parse account)
|
||||
#(re-frame/dispatch
|
||||
[:wallet.accounts/set-account-to-watch %])])))))
|
||||
[:wallet.accounts/set-account-to-watch %])]))))
|
||||
|
||||
(fx/defn add-new-account
|
||||
{:events [:wallet.accounts/add-new-account]}
|
||||
|
|
|
@ -36,14 +36,14 @@
|
|||
|
||||
(re-frame/reg-fx
|
||||
::resolve-addresses
|
||||
(fn [{:keys [registry ens-names callback]}]
|
||||
(fn [{:keys [chain-id ens-names callback]}]
|
||||
;; resolve all addresses then call the callback function with the array of
|
||||
;;addresses as parameter
|
||||
(-> (js/Promise.all
|
||||
(clj->js (mapv (fn [ens-name]
|
||||
(js/Promise.
|
||||
(fn [resolve _]
|
||||
(ens/get-addr registry ens-name resolve))))
|
||||
(ens/address chain-id ens-name resolve))))
|
||||
ens-names)))
|
||||
(.then callback)
|
||||
(.catch (fn [error]
|
||||
|
@ -108,7 +108,7 @@
|
|||
;; if there are no ens-names, we dispatch request-uri-parsed immediately
|
||||
(request-uri-parsed cofx message uri)
|
||||
{::resolve-addresses
|
||||
{:registry (get ens/ens-registries (ethereum/chain-keyword db))
|
||||
{:chain-id (ethereum/chain-id db)
|
||||
:ens-names ens-names
|
||||
:callback
|
||||
(fn [addresses]
|
||||
|
|
|
@ -538,8 +538,8 @@
|
|||
|
||||
(re-frame/reg-fx
|
||||
::resolve-address
|
||||
(fn [{:keys [registry ens-name cb]}]
|
||||
(ens/get-addr registry ens-name cb)))
|
||||
(fn [{:keys [chain-id ens-name cb]}]
|
||||
(ens/address chain-id ens-name cb)))
|
||||
|
||||
(fx/defn on-recipient-address-resolved
|
||||
{:events [::recipient-address-resolved]}
|
||||
|
@ -554,8 +554,7 @@
|
|||
(fx/defn prepare-transaction-from-chat
|
||||
{:events [:wallet/prepare-transaction-from-chat]}
|
||||
[{:keys [db]}]
|
||||
(let [chain (ethereum/chain-keyword db)
|
||||
identity (:current-chat-id db)
|
||||
(let [identity (:current-chat-id db)
|
||||
{:keys [ens-verified name] :as contact}
|
||||
(or (get-in db [:contacts/contacts identity])
|
||||
(-> identity
|
||||
|
@ -571,7 +570,7 @@
|
|||
:dispatch [:open-modal :prepare-send-transaction]}
|
||||
ens-verified
|
||||
(assoc ::resolve-address
|
||||
{:registry (get ens/ens-registries chain)
|
||||
{:chain-id (ethereum/chain-id db)
|
||||
:ens-name (if (= (.indexOf ^js name ".") -1)
|
||||
(stateofus/subdomain name)
|
||||
name)
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
|
||||
(re-frame/reg-fx
|
||||
::resolve-address
|
||||
(fn [{:keys [registry ens-name cb]}]
|
||||
(ens/get-addr registry ens-name cb)))
|
||||
(fn [{:keys [chain-id ens-name cb]}]
|
||||
(ens/address chain-id ens-name cb)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wallet.recipient/address-paste
|
||||
|
@ -37,8 +37,7 @@
|
|||
[{:keys [db] :as cofx} raw-recipient id]
|
||||
(when (or (not id) (= id @resolve-last-id))
|
||||
(reset! resolve-last-id nil)
|
||||
(let [chain (ethereum/chain-keyword db)
|
||||
recipient (utils/safe-trim raw-recipient)]
|
||||
(let [recipient (utils/safe-trim raw-recipient)]
|
||||
(cond
|
||||
(ethereum/address? recipient)
|
||||
(let [checksum (eip55/address->checksum recipient)]
|
||||
|
@ -65,7 +64,7 @@
|
|||
(do
|
||||
(reset! resolve-last-id (random/id))
|
||||
{::resolve-address
|
||||
{:registry (get ens/ens-registries chain)
|
||||
{:chain-id (ethereum/chain-id db)
|
||||
:ens-name ens-name
|
||||
:cb #(re-frame/dispatch [::recipient-address-resolved % @resolve-last-id])}})
|
||||
{:db (assoc-in db [:wallet/recipient :searching] false)}))
|
||||
|
|
Loading…
Reference in New Issue