mirror of
https://github.com/status-im/status-mobile.git
synced 2025-01-13 18:25:45 +00:00
[#4772] Resolve ENS domains in browser
Signed-off-by: Andrey Shovkoplyas <motor4ik@gmail.com>
This commit is contained in:
parent
b7b6a252e1
commit
c96bc5aa8b
3
deps.edn
3
deps.edn
@ -11,7 +11,8 @@
|
|||||||
com.taoensso/timbre {:mvn/version "4.10.0"}
|
com.taoensso/timbre {:mvn/version "4.10.0"}
|
||||||
hickory {:mvn/version "0.7.1"}
|
hickory {:mvn/version "0.7.1"}
|
||||||
com.cognitect/transit-cljs {:mvn/version "0.8.248"}
|
com.cognitect/transit-cljs {:mvn/version "0.8.248"}
|
||||||
status-im/pluto {:mvn/version "iteration-2-SNAPSHOT"}}
|
status-im/pluto {:mvn/version "iteration-2-SNAPSHOT"}
|
||||||
|
mvxcvi/alphabase {:mvn/version "1.0.0"}}
|
||||||
|
|
||||||
:aliases
|
:aliases
|
||||||
{:dev {:extra-deps
|
{:dev {:extra-deps
|
||||||
|
@ -11,7 +11,8 @@
|
|||||||
[com.taoensso/timbre "4.10.0"]
|
[com.taoensso/timbre "4.10.0"]
|
||||||
[hickory "0.7.1"]
|
[hickory "0.7.1"]
|
||||||
[com.cognitect/transit-cljs "0.8.248"]
|
[com.cognitect/transit-cljs "0.8.248"]
|
||||||
[status-im/pluto "iteration-2-SNAPSHOT"]]
|
[status-im/pluto "iteration-2-SNAPSHOT"]
|
||||||
|
[mvxcvi/alphabase "1.0.0"]]
|
||||||
:plugins [[lein-cljsbuild "1.1.7"]
|
:plugins [[lein-cljsbuild "1.1.7"]
|
||||||
[lein-re-frisk "0.5.8"]
|
[lein-re-frisk "0.5.8"]
|
||||||
[lein-cljfmt "0.5.7"]
|
[lein-cljfmt "0.5.7"]
|
||||||
|
@ -5,7 +5,13 @@
|
|||||||
[status-im.data-store.dapp-permissions :as dapp-permissions]
|
[status-im.data-store.dapp-permissions :as dapp-permissions]
|
||||||
[status-im.i18n :as i18n]
|
[status-im.i18n :as i18n]
|
||||||
[status-im.ui.screens.browser.default-dapps :as default-dapps]
|
[status-im.ui.screens.browser.default-dapps :as default-dapps]
|
||||||
[status-im.utils.http :as http]))
|
[status-im.utils.http :as http]
|
||||||
|
[clojure.string :as string]
|
||||||
|
[status-im.utils.ethereum.resolver :as resolver]
|
||||||
|
[status-im.utils.ethereum.core :as ethereum]
|
||||||
|
[status-im.utils.ethereum.ens :as ens]
|
||||||
|
[status-im.utils.multihash :as multihash]
|
||||||
|
[status-im.utils.handlers-macro :as handlers-macro]))
|
||||||
|
|
||||||
(defn get-current-url [{:keys [history history-index]}]
|
(defn get-current-url [{:keys [history history-index]}]
|
||||||
(when (and history-index history)
|
(when (and history-index history)
|
||||||
@ -24,13 +30,13 @@
|
|||||||
(assoc browser :dapp? true :name (:name dapp))
|
(assoc browser :dapp? true :name (:name dapp))
|
||||||
(assoc browser :dapp? false :name (i18n/label :t/browser)))))
|
(assoc browser :dapp? false :name (i18n/label :t/browser)))))
|
||||||
|
|
||||||
(defn update-browser-fx [{:keys [db now]} browser]
|
(defn update-browser-fx [browser {:keys [db now]}]
|
||||||
(let [updated-browser (check-if-dapp-in-list (assoc browser :timestamp now))]
|
(let [updated-browser (check-if-dapp-in-list (assoc browser :timestamp now))]
|
||||||
{:db (update-in db [:browser/browsers (:browser-id updated-browser)]
|
{:db (update-in db [:browser/browsers (:browser-id updated-browser)]
|
||||||
merge updated-browser)
|
merge updated-browser)
|
||||||
:data-store/tx [(browser-store/save-browser-tx updated-browser)]}))
|
:data-store/tx [(browser-store/save-browser-tx updated-browser)]}))
|
||||||
|
|
||||||
(defn update-browser-history-fx [cofx browser url loading?]
|
(defn update-browser-history-fx [browser url loading? cofx]
|
||||||
(when-not loading?
|
(when-not loading?
|
||||||
(let [history-index (:history-index browser)
|
(let [history-index (:history-index browser)
|
||||||
history (:history browser)
|
history (:history browser)
|
||||||
@ -43,12 +49,41 @@
|
|||||||
new-index (if slash?
|
new-index (if slash?
|
||||||
history-index
|
history-index
|
||||||
(dec (count new-history)))]
|
(dec (count new-history)))]
|
||||||
(update-browser-fx cofx
|
(update-browser-fx (assoc browser :history new-history :history-index new-index)
|
||||||
(assoc browser :history new-history :history-index new-index)))))))
|
cofx))))))
|
||||||
|
|
||||||
(defn update-browser-and-navigate [cofx browser]
|
(defn ens? [host]
|
||||||
(merge (update-browser-fx cofx browser)
|
(string/ends-with? host ".eth"))
|
||||||
{:dispatch [:navigate-to :browser (:browser-id browser)]}))
|
|
||||||
|
(defn ens-multihash-callback [hex]
|
||||||
|
(let [hash (when hex (multihash/base58 (multihash/create :sha2-256 (subs hex 2))))]
|
||||||
|
(if (and hash (not= hash resolver/default-hash))
|
||||||
|
(re-frame/dispatch [:ens-multihash-resolved hash])
|
||||||
|
(re-frame/dispatch [:update-browser-options {:resolving? false}]))))
|
||||||
|
|
||||||
|
(defn resolve-multihash-fx [host loading error? {{:keys [web3 network] :as db} :db}]
|
||||||
|
(let [network (get-in db [:account/account :networks network])
|
||||||
|
chain (ethereum/network->chain-keyword network)]
|
||||||
|
(if (and (not loading) (not error?) (ens? host))
|
||||||
|
{:db (assoc-in db [:browser/options :resolving?] true)
|
||||||
|
:resolve-ens-multihash {:web3 web3
|
||||||
|
:registry (get ens/ens-registries
|
||||||
|
chain)
|
||||||
|
:ens-name host
|
||||||
|
:cb ens-multihash-callback}}
|
||||||
|
{})))
|
||||||
|
|
||||||
|
(defn update-new-browser-and-navigate [host browser cofx]
|
||||||
|
(handlers-macro/merge-fx
|
||||||
|
cofx
|
||||||
|
{:dispatch [:navigate-to :browser {:browser-id (:browser-id browser)
|
||||||
|
:resolving? (ens? host)}]}
|
||||||
|
(update-browser-fx browser)
|
||||||
|
(resolve-multihash-fx host false false)))
|
||||||
|
|
||||||
|
(defn update-browser-and-navigate [browser cofx]
|
||||||
|
(merge (update-browser-fx browser cofx)
|
||||||
|
{:dispatch [:navigate-to :browser {:browser-id (:browser-id browser)}]}))
|
||||||
|
|
||||||
(def permissions {constants/dapp-permission-contact-code {:title (i18n/label :t/wants-to-access-profile)
|
(def permissions {constants/dapp-permission-contact-code {:title (i18n/label :t/wants-to-access-profile)
|
||||||
:description (i18n/label :t/your-contact-code)
|
:description (i18n/label :t/your-contact-code)
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
(spec/def :browser/history (spec/nilable vector?))
|
(spec/def :browser/history (spec/nilable vector?))
|
||||||
(spec/def :browser/history-index (spec/nilable int?))
|
(spec/def :browser/history-index (spec/nilable int?))
|
||||||
(spec/def :browser/loading? (spec/nilable boolean?))
|
(spec/def :browser/loading? (spec/nilable boolean?))
|
||||||
|
(spec/def :browser/resolving? (spec/nilable boolean?))
|
||||||
(spec/def :browser/url-editing? (spec/nilable boolean?))
|
(spec/def :browser/url-editing? (spec/nilable boolean?))
|
||||||
(spec/def :browser/show-tooltip (spec/nilable keyword?))
|
(spec/def :browser/show-tooltip (spec/nilable keyword?))
|
||||||
(spec/def :browser/show-permission (spec/nilable map?))
|
(spec/def :browser/show-permission (spec/nilable map?))
|
||||||
@ -19,6 +20,7 @@
|
|||||||
(allowed-keys
|
(allowed-keys
|
||||||
:opt-un [:browser/browser-id
|
:opt-un [:browser/browser-id
|
||||||
:browser/loading?
|
:browser/loading?
|
||||||
|
:browser/resolving?
|
||||||
:browser/url-editing?
|
:browser/url-editing?
|
||||||
:browser/show-tooltip
|
:browser/show-tooltip
|
||||||
:browser/show-permission
|
:browser/show-permission
|
||||||
|
@ -13,7 +13,8 @@
|
|||||||
[status-im.utils.random :as random]
|
[status-im.utils.random :as random]
|
||||||
[status-im.utils.types :as types]
|
[status-im.utils.types :as types]
|
||||||
[status-im.utils.universal-links.core :as utils.universal-links]
|
[status-im.utils.universal-links.core :as utils.universal-links]
|
||||||
[taoensso.timbre :as log]))
|
[taoensso.timbre :as log]
|
||||||
|
[status-im.utils.ethereum.resolver :as resolver]))
|
||||||
|
|
||||||
(re-frame/reg-fx
|
(re-frame/reg-fx
|
||||||
:browse
|
:browse
|
||||||
@ -39,72 +40,89 @@
|
|||||||
(fn [[message webview]]
|
(fn [[message webview]]
|
||||||
(.sendToBridge webview (types/clj->json message))))
|
(.sendToBridge webview (types/clj->json message))))
|
||||||
|
|
||||||
|
(re-frame/reg-fx
|
||||||
|
:resolve-ens-multihash
|
||||||
|
(fn [{:keys [web3 registry ens-name cb]}]
|
||||||
|
(resolver/content web3 registry ens-name cb)))
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
(handlers/register-handler-fx
|
||||||
:browse-link-from-message
|
:browse-link-from-message
|
||||||
(fn [_ [_ link]]
|
(fn [_ [_ link]]
|
||||||
{:browse link}))
|
{:browse link}))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:ens-multihash-resolved
|
||||||
|
(fn [{:keys [db] :as cofx} [_ hash]]
|
||||||
|
(let [options (:browser/options db)
|
||||||
|
browsers (:browser/browsers db)
|
||||||
|
browser (get browsers (:browser-id options))
|
||||||
|
history-index (:history-index browser)]
|
||||||
|
(handlers-macro/merge-fx
|
||||||
|
cofx
|
||||||
|
{:db (assoc-in db [:browser/options :resolving?] false)}
|
||||||
|
(model/update-browser-fx
|
||||||
|
(assoc-in browser [:history history-index] (str "https://ipfs.infura.io/ipfs/" hash)))))))
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
(handlers/register-handler-fx
|
||||||
:open-url-in-browser
|
:open-url-in-browser
|
||||||
[re-frame/trim-v]
|
(fn [cofx [_ url]]
|
||||||
(fn [cofx [url]]
|
(let [normalized-url (http/normalize-and-decode-url url)
|
||||||
(let [normalized-url (http/normalize-and-decode-url url)]
|
host (http/url-host normalized-url)]
|
||||||
(model/update-browser-and-navigate cofx {:browser-id (or (http/url-host normalized-url) (random/id))
|
(model/update-new-browser-and-navigate
|
||||||
:history-index 0
|
host
|
||||||
:history [normalized-url]}))))
|
{:browser-id (or host (random/id))
|
||||||
|
:history-index 0
|
||||||
|
:history [normalized-url]}
|
||||||
|
cofx))))
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
(handlers/register-handler-fx
|
||||||
:send-to-bridge
|
:send-to-bridge
|
||||||
[re-frame/trim-v]
|
(fn [cofx [_ message]]
|
||||||
(fn [cofx [message]]
|
|
||||||
{:send-to-bridge-fx [message (get-in cofx [:db :webview-bridge])]}))
|
{:send-to-bridge-fx [message (get-in cofx [:db :webview-bridge])]}))
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
(handlers/register-handler-fx
|
||||||
:open-browser
|
:open-browser
|
||||||
[re-frame/trim-v]
|
(fn [cofx [_ browser]]
|
||||||
(fn [cofx [browser]]
|
(model/update-browser-and-navigate browser cofx)))
|
||||||
(model/update-browser-and-navigate cofx browser)))
|
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
(handlers/register-handler-fx
|
||||||
:update-browser-on-nav-change
|
:update-browser-on-nav-change
|
||||||
[re-frame/trim-v]
|
(fn [cofx [_ browser url loading error?]]
|
||||||
(fn [cofx [browser url loading]]
|
(let [host (http/url-host url)]
|
||||||
(model/update-browser-history-fx cofx browser url loading)))
|
(handlers-macro/merge-fx
|
||||||
|
cofx
|
||||||
|
(model/resolve-multihash-fx host loading error?)
|
||||||
|
(model/update-browser-history-fx browser url loading)))))
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
(handlers/register-handler-fx
|
||||||
:update-browser-options
|
:update-browser-options
|
||||||
[re-frame/trim-v]
|
(fn [{:keys [db]} [_ options]]
|
||||||
(fn [{:keys [db]} [options]]
|
|
||||||
{:db (update db :browser/options merge options)}))
|
{:db (update db :browser/options merge options)}))
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
(handlers/register-handler-fx
|
||||||
:remove-browser
|
:remove-browser
|
||||||
[re-frame/trim-v]
|
(fn [{:keys [db]} [_ browser-id]]
|
||||||
(fn [{:keys [db]} [browser-id]]
|
|
||||||
{:db (update-in db [:browser/browsers] dissoc browser-id)
|
{:db (update-in db [:browser/browsers] dissoc browser-id)
|
||||||
:data-store/tx [(browser-store/remove-browser-tx browser-id)]}))
|
:data-store/tx [(browser-store/remove-browser-tx browser-id)]}))
|
||||||
|
|
||||||
(defn nav-update-browser [cofx browser history-index]
|
(defn nav-update-browser [cofx browser history-index]
|
||||||
(model/update-browser-fx cofx (assoc browser :history-index history-index)))
|
(model/update-browser-fx (assoc browser :history-index history-index) cofx))
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
(handlers/register-handler-fx
|
||||||
:browser-nav-back
|
:browser-nav-back
|
||||||
[re-frame/trim-v]
|
(fn [cofx [_ {:keys [history-index] :as browser}]]
|
||||||
(fn [cofx [{:keys [history-index] :as browser}]]
|
|
||||||
(when (pos? history-index)
|
(when (pos? history-index)
|
||||||
(nav-update-browser cofx browser (dec history-index)))))
|
(nav-update-browser cofx browser (dec history-index)))))
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
(handlers/register-handler-fx
|
||||||
:browser-nav-forward
|
:browser-nav-forward
|
||||||
[re-frame/trim-v]
|
(fn [cofx [_ {:keys [history-index] :as browser}]]
|
||||||
(fn [cofx [{:keys [history-index] :as browser}]]
|
|
||||||
(when (< history-index (dec (count (:history browser))))
|
(when (< history-index (dec (count (:history browser))))
|
||||||
(nav-update-browser cofx browser (inc history-index)))))
|
(nav-update-browser cofx browser (inc history-index)))))
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
(handlers/register-handler-fx
|
||||||
:on-bridge-message
|
:on-bridge-message
|
||||||
[re-frame/trim-v]
|
(fn [{:keys [db] :as cofx} [_ message]]
|
||||||
(fn [{:keys [db] :as cofx} [message]]
|
|
||||||
(let [{:browser/keys [options browsers]} db
|
(let [{:browser/keys [options browsers]} db
|
||||||
{:keys [browser-id]} options
|
{:keys [browser-id]} options
|
||||||
browser (get browsers browser-id)
|
browser (get browsers browser-id)
|
||||||
@ -113,7 +131,7 @@
|
|||||||
(cond
|
(cond
|
||||||
|
|
||||||
(and (= type constants/history-state-changed) platform/ios? (not= "about:blank" url))
|
(and (= type constants/history-state-changed) platform/ios? (not= "about:blank" url))
|
||||||
(model/update-browser-history-fx cofx browser url false)
|
(model/update-browser-history-fx browser url false cofx)
|
||||||
|
|
||||||
(= type constants/web3-send-async)
|
(= type constants/web3-send-async)
|
||||||
(model/web3-send-async payload messageId cofx)
|
(model/web3-send-async payload messageId cofx)
|
||||||
@ -127,7 +145,6 @@
|
|||||||
|
|
||||||
(handlers/register-handler-fx
|
(handlers/register-handler-fx
|
||||||
:check-permissions-queue
|
:check-permissions-queue
|
||||||
[re-frame/trim-v]
|
|
||||||
(fn [{:keys [db] :as cofx} _]
|
(fn [{:keys [db] :as cofx} _]
|
||||||
(let [{:keys [show-permission permissions-queue]} (:browser/options db)]
|
(let [{:keys [show-permission permissions-queue]} (:browser/options db)]
|
||||||
(when (and (nil? show-permission) (last permissions-queue))
|
(when (and (nil? show-permission) (last permissions-queue))
|
||||||
@ -145,9 +162,8 @@
|
|||||||
|
|
||||||
(handlers/register-handler-fx
|
(handlers/register-handler-fx
|
||||||
:next-dapp-permission
|
:next-dapp-permission
|
||||||
[re-frame/trim-v]
|
(fn [cofx [_ params permission permissions-data]]
|
||||||
(fn [cofx [params permission permissions-data]]
|
|
||||||
(model/next-permission {:params params
|
(model/next-permission {:params params
|
||||||
:permission permission
|
:permission permission
|
||||||
:permissions-data permissions-data}
|
:permissions-data permissions-data}
|
||||||
cofx)))
|
cofx)))
|
@ -2,5 +2,5 @@
|
|||||||
(:require [status-im.ui.screens.navigation :as navigation]))
|
(:require [status-im.ui.screens.navigation :as navigation]))
|
||||||
|
|
||||||
(defmethod navigation/preload-data! :browser
|
(defmethod navigation/preload-data! :browser
|
||||||
[db [_ _ browser-id]]
|
[db [_ _ options]]
|
||||||
(assoc db :browser/options {:browser-id browser-id}))
|
(assoc db :browser/options options))
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
(re-frame/dispatch [:update-browser-on-nav-change
|
(re-frame/dispatch [:update-browser-on-nav-change
|
||||||
browser
|
browser
|
||||||
(http/normalize-and-decode-url @url-text)
|
(http/normalize-and-decode-url @url-text)
|
||||||
|
false
|
||||||
false]))
|
false]))
|
||||||
:placeholder (i18n/label :t/enter-url)
|
:placeholder (i18n/label :t/enter-url)
|
||||||
:auto-capitalize :none
|
:auto-capitalize :none
|
||||||
@ -81,12 +82,12 @@
|
|||||||
[react/text {:style styles/web-view-error-text}
|
[react/text {:style styles/web-view-error-text}
|
||||||
(str desc)]]))
|
(str desc)]]))
|
||||||
|
|
||||||
(defn on-navigation-change [event browser]
|
(defn on-navigation-change [event browser error?]
|
||||||
(let [{:strs [url loading]} (js->clj event)]
|
(let [{:strs [url loading]} (js->clj event)]
|
||||||
(when platform/ios?
|
(when platform/ios?
|
||||||
(re-frame/dispatch [:update-browser-options {:loading? loading}]))
|
(re-frame/dispatch [:update-browser-options {:loading? loading}]))
|
||||||
(when (not= "about:blank" url)
|
(when (not= "about:blank" url)
|
||||||
(re-frame/dispatch [:update-browser-on-nav-change browser url loading]))))
|
(re-frame/dispatch [:update-browser-on-nav-change browser url loading error?]))))
|
||||||
|
|
||||||
(defn get-inject-js [url]
|
(defn get-inject-js [url]
|
||||||
(let [domain-name (nth (re-find #"^\w+://(www\.)?([^/:]+)" url) 2)]
|
(let [domain-name (nth (re-find #"^\w+://(www\.)?([^/:]+)" url) 2)]
|
||||||
@ -115,7 +116,7 @@
|
|||||||
(views/letsubs [webview (atom nil)
|
(views/letsubs [webview (atom nil)
|
||||||
{:keys [address]} [:get-current-account]
|
{:keys [address]} [:get-current-account]
|
||||||
{:keys [browser-id dapp? name] :as browser} [:get-current-browser]
|
{:keys [browser-id dapp? name] :as browser} [:get-current-browser]
|
||||||
{:keys [error? loading? url-editing? show-tooltip show-permission]} [:get :browser/options]
|
{:keys [error? loading? url-editing? show-tooltip show-permission resolving?]} [:get :browser/options]
|
||||||
rpc-url [:get :rpc-url]
|
rpc-url [:get :rpc-url]
|
||||||
network-id [:get-network-id]]
|
network-id [:get-network-id]]
|
||||||
(let [can-go-back? (model/can-go-back? browser)
|
(let [can-go-back? (model/can-go-back? browser)
|
||||||
@ -131,12 +132,12 @@
|
|||||||
:ref #(do
|
:ref #(do
|
||||||
(reset! webview %)
|
(reset! webview %)
|
||||||
(re-frame/dispatch [:set :webview-bridge %]))
|
(re-frame/dispatch [:set :webview-bridge %]))
|
||||||
:source {:uri url}
|
:source (when-not resolving? {:uri url})
|
||||||
:java-script-enabled true
|
:java-script-enabled true
|
||||||
:bounces false
|
:bounces false
|
||||||
:local-storage-enabled true
|
:local-storage-enabled true
|
||||||
:render-error web-view-error
|
:render-error web-view-error
|
||||||
:on-navigation-state-change #(on-navigation-change % browser)
|
:on-navigation-state-change #(on-navigation-change % browser error?)
|
||||||
:on-bridge-message #(re-frame/dispatch [:on-bridge-message %])
|
:on-bridge-message #(re-frame/dispatch [:on-bridge-message %])
|
||||||
:on-load #(re-frame/dispatch [:update-browser-options {:error? false}])
|
:on-load #(re-frame/dispatch [:update-browser-options {:error? false}])
|
||||||
:on-error #(re-frame/dispatch [:update-browser-options {:error? true
|
:on-error #(re-frame/dispatch [:update-browser-options {:error? true
|
||||||
@ -148,7 +149,7 @@
|
|||||||
(ethereum/normalized-address address)
|
(ethereum/normalized-address address)
|
||||||
(str network-id)))
|
(str network-id)))
|
||||||
:injected-java-script js-res/webview-js}]
|
:injected-java-script js-res/webview-js}]
|
||||||
(when loading?
|
(when (or loading? resolving?)
|
||||||
[react/view styles/web-view-loading
|
[react/view styles/web-view-loading
|
||||||
[components/activity-indicator {:animating true}]])]
|
[components/activity-indicator {:animating true}]])]
|
||||||
[navigation webview browser can-go-back? can-go-forward?]
|
[navigation webview browser can-go-back? can-go-forward?]
|
||||||
|
@ -101,7 +101,7 @@
|
|||||||
(spec/def :navigation/prev-view-id (spec/nilable keyword?))
|
(spec/def :navigation/prev-view-id (spec/nilable keyword?))
|
||||||
;; navigation screen params
|
;; navigation screen params
|
||||||
(spec/def :navigation.screen-params/network-details (allowed-keys :req [:networks/selected-network]))
|
(spec/def :navigation.screen-params/network-details (allowed-keys :req [:networks/selected-network]))
|
||||||
(spec/def :navigation.screen-params/browser (spec/nilable string?))
|
(spec/def :navigation.screen-params/browser (spec/nilable map?))
|
||||||
(spec/def :navigation.screen-params.profile-qr-viewer/contact (spec/nilable map?))
|
(spec/def :navigation.screen-params.profile-qr-viewer/contact (spec/nilable map?))
|
||||||
(spec/def :navigation.screen-params.profile-qr-viewer/source (spec/nilable keyword?))
|
(spec/def :navigation.screen-params.profile-qr-viewer/source (spec/nilable keyword?))
|
||||||
(spec/def :navigation.screen-params.profile-qr-viewer/value (spec/nilable string?))
|
(spec/def :navigation.screen-params.profile-qr-viewer/value (spec/nilable string?))
|
||||||
|
@ -70,6 +70,11 @@
|
|||||||
(namehash ens-name))
|
(namehash ens-name))
|
||||||
(fn [_ address] (cb (ethereum/hex->address address)))))
|
(fn [_ address] (cb (ethereum/hex->address address)))))
|
||||||
|
|
||||||
|
(defn content [web3 resolver ens-name cb]
|
||||||
|
(ethereum/call web3
|
||||||
|
(ethereum/call-params resolver "content(bytes32)" (namehash ens-name))
|
||||||
|
(fn [_ hash] (cb hash))))
|
||||||
|
|
||||||
(def ABI-hash "0x2203ab56")
|
(def ABI-hash "0x2203ab56")
|
||||||
(def pubkey-hash "0xc8690233")
|
(def pubkey-hash "0xc8690233")
|
||||||
|
|
||||||
|
14
src/status_im/utils/ethereum/resolver.cljs
Normal file
14
src/status_im/utils/ethereum/resolver.cljs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
(ns status-im.utils.ethereum.resolver
|
||||||
|
(:require [status-im.utils.ethereum.ens :as ens]))
|
||||||
|
|
||||||
|
(def default-address "0x0000000000000000000000000000000000000000")
|
||||||
|
(def default-hash "0x0000000000000000000000000000000000000000000000000000000000000000")
|
||||||
|
|
||||||
|
(defn content [web3 registry ens-name cb]
|
||||||
|
(ens/resolver web3
|
||||||
|
registry
|
||||||
|
ens-name
|
||||||
|
(fn [address]
|
||||||
|
(if (and address (not= address default-address))
|
||||||
|
(ens/content web3 address ens-name cb)
|
||||||
|
(cb nil)))))
|
185
src/status_im/utils/multihash.cljs
Normal file
185
src/status_im/utils/multihash.cljs
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
(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 ^:const 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))))
|
Loading…
x
Reference in New Issue
Block a user