[#17611] move status-im.utils.universal-links.core (#17855)

This commit is contained in:
flexsurfer 2023-11-09 21:22:15 +01:00 committed by GitHub
parent 27e27aa113
commit 69f87ce8b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 165 additions and 239 deletions

View File

@ -16,16 +16,17 @@
[status-im.ui.components.list-selection :as list-selection]
[status-im.utils.deprecated-types :as types]
[status-im.utils.random :as random]
[status-im.utils.universal-links.utils :as links]
[status-im2.constants :as constants]
[status-im2.navigation.events :as navigation]
[taoensso.timbre :as log]
[utils.address :as address]
[utils.debounce :as debounce]
[utils.ens.core :as utils.ens]
[utils.ethereum.chain :as chain]
[utils.i18n :as i18n]
[utils.re-frame :as rf]
[utils.security.core :as security]
[utils.universal-links :as links]
[utils.url :as url]))
(rf/defn update-browser-option
@ -90,7 +91,7 @@
(when (not error?)
(let [current-url (get-current-url (get-current-browser db))
host (url/url-host current-url)]
(if (and (not resolved-url) (ens/is-valid-eth-name? host))
(if (and (not resolved-url) (utils.ens/is-valid-eth-name? host))
{:db (update db :browser/options assoc :resolving? true)
:browser/resolve-ens-contenthash {:chain-id (chain/chain-id db)
:ens-name host

View File

@ -8,9 +8,9 @@
[status-im.bottom-sheet.events :as bottom-sheet]
[status-im.ui.components.colors :as colors]
[status-im.utils.deprecated-types :as types]
[status-im.utils.universal-links.core :as universal-links]
[status-im2.common.muting.helpers :refer [format-mute-till]]
[status-im2.common.toasts.events :as toasts]
[status-im2.common.universal-links :as universal-links]
[status-im2.constants :as constants]
[status-im2.contexts.chat.events :as chat.events]
[status-im2.contexts.shell.activity-center.events :as activity-center]

View File

@ -6,7 +6,6 @@
[re-frame.core :as re-frame]
[status-im.bottom-sheet.events :as bottom-sheet]
[status-im.ethereum.ens :as ens]
[status-im.ethereum.stateofus :as stateofus]
[status-im.multiaccounts.update.core :as multiaccounts.update]
[status-im.utils.random :as random]
[status-im.wallet.utils :as wallet.utils]
@ -14,6 +13,8 @@
[status-im2.navigation.events :as navigation]
[taoensso.timbre :as log]
[utils.datetime :as datetime]
[utils.ens.core :as utils.ens]
[utils.ens.stateofus :as stateofus]
[utils.ethereum.chain :as chain]
[utils.ethereum.eip.eip55 :as eip55]
[utils.re-frame :as rf]))
@ -158,7 +159,7 @@
(cond
;; No address for a stateofus subdomain: it can be registered
(and (= response ens/default-address) (not custom-domain?))
(and (= response utils.ens/default-address) (not custom-domain?))
(re-frame/dispatch [::name-resolved username :available])
;; if we get an address back, we try to get the public key associated
@ -205,7 +206,7 @@
(defn- valid-custom-domain?
[username]
(and (ens/is-valid-eth-name? username)
(and (utils.ens/is-valid-eth-name? username)
(stateofus/lower-case? username)))
(defn- valid-username?

View File

@ -1,35 +1,12 @@
(ns status-im.ethereum.ens
(:require
[clojure.string :as string]
[native-module.core :as native-module]
[status-im2.common.json-rpc.events :as json-rpc]))
;; this is the addresses of ens registries for the different networks
(def ens-registries
{:mainnet "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e"
:goerli "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e"})
(def default-address "0x0000000000000000000000000000000000000000")
(def default-key
"0x0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
(def default-hash "0x0000000000000000000000000000000000000000000000000000000000000000")
(defn valid-eth-name-prefix?
[prefix]
(not
(or (string/blank? prefix)
(string/ends-with? prefix ".")
(string/includes? prefix ".."))))
(defn is-valid-eth-name?
[ens-name]
(and ens-name
(string? ens-name)
(string/ends-with? ens-name ".eth")))
[status-im2.common.json-rpc.events :as json-rpc]
[utils.ens.core :as utils.ens]))
(defn address
[chain-id ens-name cb]
{:pre [(is-valid-eth-name? ens-name)]}
{:pre [(utils.ens/is-valid-eth-name? ens-name)]}
(json-rpc/call {:method "ens_addressOf"
:params [chain-id ens-name]
:on-success cb
@ -37,7 +14,7 @@
(defn pubkey
([chain-id ens-name on-success on-error]
{:pre [(is-valid-eth-name? ens-name)]}
{:pre [(utils.ens/is-valid-eth-name? ens-name)]}
(json-rpc/call {:method "ens_publicKeyOf"
:params [chain-id ens-name]
:on-success on-success

View File

@ -41,7 +41,6 @@
status-im.ui.screens.privacy-and-security-settings.events
[status-im.utils.dimensions :as dimensions]
status-im.utils.logging.core
[status-im.utils.universal-links.core :as universal-links]
[status-im.utils.utils :as utils]
status-im.visibility-status-popover.core
status-im.visibility-status-updates.core
@ -53,6 +52,7 @@
status-im.wallet.custom-tokens.core
[status-im2.common.biometric.events :as biometric]
[status-im2.common.theme.core :as theme]
[status-im2.common.universal-links :as universal-links]
[status-im2.constants :as constants]
status-im2.contexts.chat.home.events
status-im2.contexts.communities.home.events

View File

@ -77,6 +77,7 @@
:on-success #(re-frame/dispatch [:chat-updated %])}]}))
(rf/defn create-from-link
{:events [:group-chats/create-from-link]}
[cofx {:keys [chat-id invitation-admin chat-name]}]
(if (get-in cofx [:db :chats chat-id])
{:dispatch [:chat/navigate-to-chat chat-id]}

View File

@ -1,9 +1,9 @@
(ns status-im.multiaccounts.update.core
(:require
[status-im.ethereum.ens :as ens]
[status-im.utils.deprecated-types :as types]
[status-im2.constants :as constants]
[taoensso.timbre :as log]
[utils.ens.core :as utils.ens]
[utils.re-frame :as rf]))
(rf/defn send-contact-update
@ -23,7 +23,9 @@
(when-let [new-name (and account (or preferred-name display-name name))]
(rf/merge
cofx
{:db (assoc-in db [:profile/profile :ens-name?] (ens/is-valid-eth-name? new-name))
{:db (assoc-in db
[:profile/profile :ens-name?]
(utils.ens/is-valid-eth-name? new-name))
:json-rpc/call [{:method "multiaccounts_updateAccount"
:params [(assoc account :name new-name)]
:on-success #(log/debug "sent multiaccount update")}]}))))

View File

@ -5,8 +5,8 @@
[status-im.multiaccounts.update.core :as multiaccounts.update]
[status-im.ui.components.list-selection :as list-selection]
[status-im.ui.components.react :as react]
[status-im.utils.universal-links.utils :as universal-links]
[utils.re-frame :as rf]))
[utils.re-frame :as rf]
[utils.universal-links :as universal-links]))
(re-frame/reg-fx
:copy-to-clipboard

View File

@ -2,7 +2,6 @@
(:require
[re-frame.core :as re-frame]
[status-im.group-chats.core :as group-chats]
[status-im.router.core :as router]
[status-im.utils.utils :as utils]
[status-im2.navigation.events :as navigation]
[taoensso.timbre :as log]
@ -111,7 +110,7 @@
(rf/defn on-scan
{:events [::on-scan-success]}
[{:keys [db]} uri]
{::router/handle-uri {:chain (chain/chain-keyword db)
:chats (get db :chats)
:uri uri
:cb #(re-frame/dispatch [::match-scanned-value %])}})
{:router/handle-uri {:chain (chain/chain-keyword db)
:chats (get db :chats)
:uri uri
:cb #(re-frame/dispatch [::match-scanned-value %])}})

View File

@ -4,7 +4,7 @@
[status-im.pairing.core :as pairing]
[status-im.stickers.core :as stickers]
status-im.transport.shh
[status-im.utils.universal-links.core :as universal-links]
[status-im2.common.universal-links :as universal-links]
[taoensso.timbre :as log]
[utils.re-frame :as rf]))

View File

@ -6,13 +6,13 @@
[quo.theme :as theme]
[re-frame.core :as re-frame.core]
[react-native.core :as rn]
[status-im.ethereum.ens :as ens]
[status-im.ui.components.chat-icon.styles :as styles]
[status-im.ui.components.colors :as colors]
[status-im.ui.components.icons.icons :as icons]
[status-im.ui.screens.chat.photos :as photos]
[status-im.ui.screens.profile.visibility-status.utils :as visibility-status-utils]
[status-im2.contexts.profile.utils :as profile.utils]))
[status-im2.contexts.profile.utils :as profile.utils]
[utils.ens.core :as utils.ens]))
;;TODO REWORK THIS NAMESPACE
@ -78,7 +78,7 @@
:indicator-color "#000000"
:color (get text-style :color)
:length 2
:ring? (not (ens/is-valid-eth-name? full-name))
:ring? (not (utils.ens/is-valid-eth-name? full-name))
:ring-width 2})}
{:size size}]
[photos/photo photo-path {:size size}])
@ -221,7 +221,7 @@
:indicator-color "#000000"
:color (get-in styles [:default-chat-icon-text :color])
:length 2
:ring? (not (ens/is-valid-eth-name? name))
:ring? (not (utils.ens/is-valid-eth-name? name))
:ring-width 2})}
photo-path)]
[rn/view (:container styles)

View File

@ -2,9 +2,9 @@
(:require
[re-frame.core :as re-frame]
[status-im.ui.components.react :as react]
[status-im.utils.universal-links.utils :as universal-links]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
[utils.re-frame :as rf]
[utils.universal-links :as universal-links]))
(re-frame/reg-fx
::share

View File

@ -4,8 +4,6 @@
[re-frame.core :as re-frame]
[reagent.core :as reagent]
[status-im.ens.core :as ens]
[status-im.ethereum.ens :as ethereum.ens]
[status-im.ethereum.stateofus :as stateofus]
[status-im.ethereum.tokens :as tokens]
[status-im.react-native.resources :as resources]
[status-im.ui.components.chat-icon.screen :as chat-icon]
@ -22,8 +20,11 @@
[status-im.ui.screens.profile.components.views :as profile.components]
[status-im.ui.screens.wallet.send.sheets :as sheets]
[status-im.utils.utils :as utils]
[status-im2.config :as config]
[utils.address :as address]
[utils.debounce :as debounce]
[utils.ens.core :as utils.ens]
[utils.ens.stateofus :as stateofus]
[utils.i18n :as i18n])
(:require-macros [status-im.utils.views :as views]))
@ -343,7 +344,12 @@
:typography :main-medium}}
(domain-label custom-domain?)]
[react/view {:flex 1 :min-width 24}]]]
[registration checked? (stateofus/get-cached-registrar chain) address public-key]]
[registration
checked?
(when (or (not= chain :goerli) config/test-stateofus?)
(stateofus/get-cached-registrar chain))
address
public-key]]
[toolbar/toolbar
{:show-border? true
:size :large
@ -512,7 +518,7 @@
(i18n/label :t/ens-terms-point-10)]
[react/view {:style {:align-items :center :margin-top 16 :margin-bottom 8}}
[link
{:on-press #(.openURL ^js react/linking (etherscan-url (:mainnet ethereum.ens/ens-registries)))}
{:on-press #(.openURL ^js react/linking (etherscan-url (:mainnet utils.ens/ens-registries)))}
(i18n/label :t/etherscan-lookup)]]]]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -4,7 +4,6 @@
[quo.theme :as theme]
[re-frame.core :as re-frame]
[reagent.core :as reagent]
[status-im.ethereum.stateofus :as stateofus]
[status-im.ui.components.colors :as colors]
[status-im.ui.components.common.common :as components.common]
[status-im.ui.components.copyable-text :as copyable-text]
@ -17,12 +16,13 @@
[status-im.ui.screens.profile.user.edit-picture :as edit]
[status-im.ui.screens.profile.user.styles :as styles]
[status-im.ui.screens.profile.visibility-status.views :as visibility-status]
[status-im.utils.universal-links.utils :as universal-links]
[status-im.utils.utils :as utils]
[status-im2.common.qr-codes.view :as qr-codes]
[status-im2.config :as config]
[status-im2.contexts.profile.utils :as profile.utils]
[utils.i18n :as i18n])
[utils.ens.stateofus :as stateofus]
[utils.i18n :as i18n]
[utils.universal-links :as universal-links])
(:require-macros [status-im.utils.views :as views]))
(views/defview share-chat-key
@ -79,7 +79,8 @@
@(re-frame/subscribe [:profile/profile])
active-contacts-count @(re-frame/subscribe [:contacts/active-count])
chain @(re-frame/subscribe [:chain-keyword])
registrar (stateofus/get-cached-registrar chain)
registrar (when (or (not= chain :goerli) config/test-stateofus?)
(stateofus/get-cached-registrar chain))
local-pairing-mode-enabled? config/local-pairing-mode-enabled?]
[:<>
[visibility-status/visibility-status-button

View File

@ -3,7 +3,6 @@
[clojure.string :as string]
[re-frame.core :as re-frame]
[reagent.core :as reagent]
[status-im.ethereum.stateofus :as stateofus]
[status-im.ui.components.chat-icon.screen :as chat-icon]
[status-im.ui.components.colors :as colors]
[status-im.ui.components.core :as quo]
@ -18,6 +17,7 @@
[status-im.utils.utils :as utils]
[utils.address :as address]
[utils.debounce :as debounce]
[utils.ens.stateofus :as stateofus]
[utils.i18n :as i18n]
[utils.string :as utils.string])
(:require-macros [status-im.utils.views :as views]))

View File

@ -2,12 +2,12 @@
(:require
[re-frame.core :as re-frame]
[reagent.core :as reagent]
[status-im.ethereum.eip681 :as eip681]
[status-im.ui.components.copyable-text :as copyable-text]
[status-im.ui.components.core :as quo]
[status-im.ui.components.react :as react]
[status-im2.common.qr-codes.view :as qr-codes]
[utils.ethereum.eip.eip55 :as eip55]
[utils.ethereum.eip.eip681 :as eip681]
[utils.i18n :as i18n])
(:require-macros [status-im.utils.views :as views]))

View File

@ -4,9 +4,7 @@
[native-module.core :as native-module]
[re-frame.core :as re-frame]
[status-im.ens.core :as ens.core]
[status-im.ethereum.eip681 :as eip681]
[status-im.ethereum.mnemonic :as mnemonic]
[status-im.ethereum.stateofus :as stateofus]
[status-im.multiaccounts.update.core :as multiaccounts.update]
[status-im.ui.components.colors :as colors]
[status-im.ui.components.list-selection :as list-selection]
@ -19,8 +17,10 @@
[status-im2.navigation.events :as navigation]
[taoensso.timbre :as log]
[utils.address :as address]
[utils.ens.stateofus :as stateofus]
[utils.ethereum.chain :as chain]
[utils.ethereum.eip.eip55 :as eip55]
[utils.ethereum.eip.eip681 :as eip681]
[utils.i18n :as i18n]
[utils.re-frame :as rf]
[utils.security.core :as security]))

View File

@ -1,20 +1,21 @@
(ns status-im.wallet.choose-recipient.core
(:require
[clojure.string :as string]
[re-frame.core :as re-frame]
[status-im.bottom-sheet.events :as bottom-sheet]
[status-im.contact.db :as contact.db]
[status-im.ethereum.eip681 :as eip681]
[status-im.ethereum.ens :as ens]
[status-im.ethereum.tokens :as tokens]
[status-im.qr-scanner.core :as qr-scaner]
[status-im.router.core :as router]
[status-im.utils.universal-links.utils :as links]
[status-im.utils.wallet-connect :as wallet-connect]
[status-im.wallet.utils :as wallet.utils]
[status-im2.common.router :as router]
[status-im2.navigation.events :as navigation]
[utils.ethereum.chain :as chain]
[utils.i18n :as i18n]
[utils.money :as money]
[utils.re-frame :as rf]
[utils.universal-links :as links]
[utils.url :as url]))
;; FIXME(Ferossgp): Should be part of QR scanner not wallet
@ -79,6 +80,31 @@
(str value)))
sym (assoc :symbol sym))))
(defn parse-eth-value
"Takes a map as returned by `parse-uri` and returns value as BigNumber"
[s]
(when (string? s)
(let [eth? (string/ends-with? s "ETH")
^js n (money/bignumber (string/replace s "ETH" ""))]
(if eth? (.times n 1e18) n))))
(defn extract-request-details
"Return a map encapsulating request details (with keys `value`, `address` and `symbol`) from a parsed URI.
Supports ethereum and erc20 token."
[{:keys [value address function-name function-arguments] :as details} all-tokens]
(when address
(merge details
(case function-name
nil
{:value (parse-eth-value value)
:symbol :ETH
:address address}
"transfer"
{:value (money/bignumber (:uint256 function-arguments))
:symbol (:symbol (tokens/address->token all-tokens address))
:address (:address function-arguments)}
nil))))
(rf/defn request-uri-parsed
{:events [:wallet-legacy/request-uri-parsed]}
[{{:networks/keys [networks current-network]
@ -88,7 +114,7 @@
{:keys [chain-id] :as data}
uri]
(let [{:keys [address gasPrice] :as details}
(eip681/extract-request-details data all-tokens)]
(extract-request-details data all-tokens)]
(if address
(if (:wallet-legacy/recipient db)
{:db (update db

View File

@ -8,7 +8,6 @@
[status-im.bottom-sheet.events :as bottom-sheet]
[status-im.contact.db :as contact.db]
[status-im.ethereum.ens :as ens]
[status-im.ethereum.stateofus :as stateofus]
[status-im.ethereum.tokens :as tokens]
[status-im.multiaccounts.update.core :as multiaccounts.update]
[status-im.popover.core :as popover.core]
@ -27,6 +26,7 @@
[status-im2.navigation.events :as navigation]
[taoensso.timbre :as log]
[utils.datetime :as datetime]
[utils.ens.stateofus :as stateofus]
[utils.ethereum.chain :as chain]
[utils.ethereum.eip.eip55 :as eip55]
[utils.i18n :as i18n]

View File

@ -3,13 +3,14 @@
[clojure.string :as string]
[re-frame.core :as re-frame]
[status-im.ethereum.ens :as ens]
[status-im.ethereum.stateofus :as stateofus]
[status-im.ui.components.react :as react]
[status-im.utils.random :as random]
[status-im.utils.utils :as utils]
[status-im2.common.json-rpc.events :as json-rpc]
[status-im2.navigation.events :as navigation]
[utils.address :as address]
[utils.ens.core :as utils.ens]
[utils.ens.stateofus :as stateofus]
[utils.ethereum.chain :as chain]
[utils.ethereum.eip.eip55 :as eip55]
[utils.i18n :as i18n]
@ -61,11 +62,11 @@
:db (assoc-in db [:wallet-legacy/recipient :searching] false)}))
(and (not (string/blank? recipient))
(not (string/starts-with? recipient "0x"))
(ens/valid-eth-name-prefix? recipient))
(utils.ens/valid-eth-name-prefix? recipient))
(let [ens-name (if (= (.indexOf ^js recipient ".") -1)
(stateofus/subdomain recipient)
recipient)]
(if (ens/is-valid-eth-name? ens-name)
(if (utils.ens/is-valid-eth-name? ens-name)
(do
(reset! resolve-last-id (random/id))
{::resolve-address

View File

@ -1,18 +1,18 @@
(ns status-im.router.core
(ns status-im2.common.router
(:require
[bidi.bidi :as bidi]
[clojure.string :as string]
[native-module.core :as native-module]
[re-frame.core :as re-frame]
[status-im.ethereum.eip681 :as eip681]
[status-im.ethereum.ens :as ens]
[status-im.ethereum.stateofus :as stateofus]
[status-im.utils.wallet-connect :as wallet-connect]
[status-im2.constants :as constants]
[status-im2.contexts.chat.events :as chat.events]
[taoensso.timbre :as log]
[utils.address :as address]
[utils.ens.core :as utils.ens]
[utils.ens.stateofus :as stateofus]
[utils.ethereum.chain :as chain]
[utils.ethereum.eip.eip681 :as eip681]
[utils.security.core :as security]
[utils.transforms :as transforms]
[utils.url :as url]
@ -81,7 +81,7 @@
;; fragment is the one after `#`, usually user-id, ens-name, community-id
fragment (parse-fragment uri)
ens? (ens/is-valid-eth-name? fragment)
ens? (utils.ens/is-valid-eth-name? fragment)
{:keys [handler route-params] :as parsed}
(assoc (bidi/match-route routes uri-without-equal-in-path)
@ -119,7 +119,7 @@
(defn match-contact-async
[chain {:keys [user-id ens-name]} callback]
(let [valid-public-key? (and (validators/valid-public-key? user-id)
(not= user-id ens/default-key))
(not= user-id utils.ens/default-key))
valid-compressed-key? (validators/valid-compressed-key? user-id)]
(cond
valid-public-key?
@ -230,7 +230,7 @@
(let [{:keys [paths ens-names]}
(reduce (fn [acc path]
(let [address (get-in message path)]
(if (ens/is-valid-eth-name? address)
(if (utils.ens/is-valid-eth-name? address)
(-> acc
(update :paths conj path)
(update :ens-names conj address))
@ -318,9 +318,6 @@
(url/url? uri)
(cb (match-browser-string uri))
(wallet-connect/url? uri)
(cb {:type :wallet-connect :data uri})
(string/starts-with? uri constants/local-pairing-connection-string-identifier)
(cb {:type :localpairing :data uri})
@ -329,6 +326,6 @@
:data uri}))))
(re-frame/reg-fx
::handle-uri
:router/handle-uri
(fn [{:keys [chain chats uri cb]}]
(handle-uri chain chats uri cb)))

View File

@ -1,7 +1,7 @@
(ns status-im.router.core-test
(ns status-im2.common.router-test
(:require
[cljs.test :refer [are deftest]]
[status-im.router.core :as router]))
[status-im2.common.router :as router]))
(def public-key
"0x04fbce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073")

View File

@ -1,22 +1,15 @@
(ns status-im.utils.universal-links.core
(ns status-im2.common.universal-links
(:require
[clojure.string :as string]
[native-module.core :as native-module]
[re-frame.core :as re-frame]
[status-im.group-chats.core :as group-chats]
[status-im.multiaccounts.model :as multiaccounts.model]
[status-im.router.core :as router]
[status-im.ui.components.react :as react]
[status-im.wallet.choose-recipient.core :as choose-recipient]
[react-native.core :as rn]
[status-im2.navigation.events :as navigation]
[taoensso.timbre :as log]
[utils.ethereum.chain :as chain]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
;; TODO(yenda) investigate why `handle-universal-link` event is
;; dispatched 7 times for the same link
;; domains should be without the trailing slash
(def domains
{:external "https://status.app"
@ -31,21 +24,21 @@
:browse "%s/b/%s"})
(rf/defn handle-browse
[cofx {:keys [url]}]
[_ {:keys [url]}]
(log/info "universal-links: handling browse" url)
{:browser/show-browser-selection url})
(rf/defn handle-group-chat
[cofx params]
[_ params]
(log/info "universal-links: handling group" params)
(group-chats/create-from-link cofx params))
{:dispatch [:group-chats/create-from-link params]})
(defn own-public-key?
[{:keys [profile/profile]} public-key]
(= (:public-key profile) public-key))
(rf/defn handle-private-chat
[{:keys [db] :as cofx} {:keys [chat-id]}]
[{:keys [db]} {:keys [chat-id]}]
(log/info "universal-links: handling private chat" chat-id)
(when chat-id
(if-not (own-public-key? db chat-id)
@ -72,7 +65,7 @@
(navigation/pop-to-root :shell-stack)))
(rf/defn handle-desktop-community
[cofx {:keys [community-id]}]
[_ {:keys [community-id]}]
(native-module/deserialize-and-compress-key
community-id
(fn [deserialized-key]
@ -99,7 +92,7 @@
(rf/defn handle-eip681
[cofx data]
(rf/merge cofx
(choose-recipient/parse-eip681-uri-and-resolve-ens data true)
{:dispatch [:wallet-legacy/parse-eip681-uri-and-resolve-ens data true]}
(navigation/navigate-to :wallet-legacy nil)))
(defn existing-account?
@ -147,10 +140,10 @@
(rf/defn route-url
"Match a url against a list of routes and handle accordingly"
[{:keys [db]} url]
{::router/handle-uri {:chain (chain/chain-keyword db)
:chats (:chats db)
:uri url
:cb #(re-frame/dispatch [::match-value url %])}})
{:router/handle-uri {:chain (chain/chain-keyword db)
:chats (:chats db)
:uri url
:cb #(re-frame/dispatch [::match-value url %])}})
(rf/defn store-url-for-later
"Store the url in the db to be processed on login"
@ -163,7 +156,7 @@
on login, otherwise just handle it."
{:events [:universal-links/handle-url]}
[{:keys [db] :as cofx} url]
(if (multiaccounts.model/logged-in? db)
(if (:profile/profile db)
(route-url cofx url)
(store-url-for-later cofx url)))
@ -193,10 +186,10 @@
;;NOTE: https://github.com/facebook/react-native/issues/15961
;; workaround for getInitialURL returning null when opening the
;; app from a universal link after closing it with the back button
(js/setTimeout #(-> (.getInitialURL ^js react/linking)
(js/setTimeout #(-> (.getInitialURL ^js rn/linking)
(.then dispatch-url))
200)
(.addEventListener ^js react/linking "url" url-event-listener)
(.addEventListener ^js rn/linking "url" url-event-listener)
;;StartSearchForLocalPairingPeers() shouldn't be called ATM from the UI It can be called after the
;;error "route ip+net: netlinkrib: permission denied" is fixed on status-go side
#_(native-module/start-searching-for-local-pairing-peers
@ -206,4 +199,4 @@
"Remove event listener for url"
[]
(log/debug "universal-links: finalizing")
(.removeEventListener ^js react/linking "url" url-event-listener))
(.removeEventListener ^js rn/linking "url" url-event-listener))

View File

@ -1,9 +1,8 @@
(ns status-im.utils.universal-links.core-test
(ns status-im2.common.universal-links-test
(:require
[cljs.test :refer-macros [deftest is testing]]
[re-frame.core :as re-frame]
[status-im.router.core :as router]
[status-im.utils.universal-links.core :as links]))
[status-im2.common.universal-links :as links]))
(deftest handle-url-test
(testing "the user is not logged in"
@ -19,7 +18,7 @@
[:db :universal-links/url]))))
(testing "Handle a custom string"
(is (= (get-in (links/handle-url {:db db} "https://status.app/u#statuse2e")
[::router/handle-uri :uri])
[:router/handle-uri :uri])
"https://status.app/u#statuse2e"))))))
(deftest url-event-listener

View File

@ -2,7 +2,7 @@
(:require
[clojure.string :as string]
[react-native.config :as react-native-config]
[status-im.ethereum.ens :as ens]
[utils.ens.core :as utils.ens]
[utils.ethereum.chain :as chain]))
(def get-config react-native-config/get-config)
@ -67,7 +67,7 @@
goerli-rpc-url))
(def verify-ens-contract-address
(get-config :VERIFY_ENS_CONTRACT_ADDRESS
((chain/chain-id->chain-keyword verify-ens-chain-id) ens/ens-registries)))
((chain/chain-id->chain-keyword verify-ens-chain-id) utils.ens/ens-registries)))
(def fast-create-community-enabled?
(enabled? (get-config :FAST_CREATE_COMMUNITY_ENABLED "0")))

View File

@ -4,10 +4,10 @@
[native-module.core :as native-module]
[re-frame.core :as re-frame]
[status-im.ethereum.ens :as ens]
[status-im.ethereum.stateofus :as stateofus]
[status-im2.constants :as constants]
[status-im2.contexts.contacts.events :as data-store.contacts]
[status-im2.navigation.events :as navigation]
[utils.ens.stateofus :as stateofus]
[utils.ethereum.chain :as chain]
[utils.re-frame :as rf]
[utils.string :as utils.string]

View File

@ -6,10 +6,10 @@
[react-native.core :as rn]
[react-native.linear-gradient :as linear-gradient]
[react-native.reanimated :as reanimated]
[status-im.ethereum.stateofus :as stateofus]
[status-im2.constants :as constant]
[status-im2.contexts.chat.composer.constants :as constants]
[status-im2.contexts.chat.composer.reply.style :as style]
[utils.ens.stateofus :as stateofus]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))

View File

@ -1,12 +1,12 @@
(ns status-im2.contexts.profile.rpc
(:require
[clojure.string :as string]
[status-im.ethereum.ens :as ens]))
[utils.ens.core :as utils.ens]))
(defn rpc->profiles-overview
[{:keys [customizationColor keycard-pairing] :as profile}]
(-> profile
(dissoc :customizationColor)
(assoc :customization-color (keyword customizationColor))
(assoc :ens-name? (ens/is-valid-eth-name? (:name profile)))
(assoc :ens-name? (utils.ens/is-valid-eth-name? (:name profile)))
(assoc :keycard-pairing (when-not (string/blank? keycard-pairing) keycard-pairing))))

View File

@ -15,8 +15,8 @@
[reagent.impl.batching :as batching]
status-im.events
status-im.subs.root
[status-im.utils.universal-links.core :as utils.universal-links]
[status-im2.common.log :as log]
[status-im2.common.universal-links :as universal-links]
[status-im2.config :as config]
[status-im2.contexts.push-notifications.events :as notifications]
[status-im2.contexts.shell.jump-to.state :as shell.state]
@ -47,7 +47,7 @@
(i18n/set-language "en")
(i18n-resources/load-language "en")
(react-native-shake/add-shake-listener #(re-frame/dispatch [:shake-event]))
(utils.universal-links/initialize)
(universal-links/initialize)
(interceptors/register-global-interceptors)
;; Shell

25
src/utils/ens/core.cljs Normal file
View File

@ -0,0 +1,25 @@
(ns utils.ens.core
(:require [clojure.string :as string]))
;; this is the addresses of ens registries for the different networks
(def ens-registries
{:mainnet "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e"
:goerli "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e"})
(def default-address "0x0000000000000000000000000000000000000000")
(def default-key
"0x0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
(def default-hash "0x0000000000000000000000000000000000000000000000000000000000000000")
(defn valid-eth-name-prefix?
[prefix]
(not
(or (string/blank? prefix)
(string/ends-with? prefix ".")
(string/includes? prefix ".."))))
(defn is-valid-eth-name?
[ens-name]
(and ens-name
(string? ens-name)
(string/ends-with? ens-name ".eth")))

View File

@ -1,8 +1,7 @@
(ns status-im.ethereum.stateofus
(ns utils.ens.stateofus
(:require
[clojure.string :as string]
[status-im.ethereum.ens :as ens]
[status-im2.config :as config]))
[utils.ens.core :as utils.ens]))
(def domain "stateofus.eth")
@ -29,9 +28,8 @@
(def old-registrars
(merge
{:mainnet "0xDB5ac1a559b02E12F29fC0eC0e37Be8E046DEF49"}
(when config/test-stateofus?
{:goerli "0xD1f7416F91E7Eb93dD96A61F12FC092aD6B67B11"})))
{:mainnet "0xDB5ac1a559b02E12F29fC0eC0e37Be8E046DEF49"
:goerli "0xD1f7416F91E7Eb93dD96A61F12FC092aD6B67B11"}))
(defn get-cached-registrar
[chain]
@ -51,6 +49,6 @@
[contact-identity]
(when (string? contact-identity)
(string/lower-case
(if (ens/is-valid-eth-name? contact-identity)
(if (utils.ens/is-valid-eth-name? contact-identity)
contact-identity
(subdomain contact-identity)))))

View File

@ -1,7 +1,7 @@
(ns status-im.ethereum.stateofus-test
(ns utils.ens.stateofus-test
(:require
[cljs.test :refer-macros [deftest is]]
[status-im.ethereum.stateofus :as stateofus]))
[utils.ens.stateofus :as stateofus]))
(deftest valid-username?
(is (false? (stateofus/valid-username? nil)))

View File

@ -1,4 +1,4 @@
(ns status-im.ethereum.eip681
(ns utils.ethereum.eip.eip681
"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).
@ -6,11 +6,9 @@
e.g. ethereum:0x1234@1/transfer?to=0x5678&value=1e18&gas=5000"
(:require
[clojure.string :as string]
[status-im.ethereum.ens :as ens]
[status-im.ethereum.tokens :as tokens]
[utils.address :as address]
[utils.ethereum.chain :as chain]
[utils.money :as money]))
[utils.ens.core :as utils.ens]
[utils.ethereum.chain :as chain]))
(def scheme "ethereum")
(def scheme-separator ":")
@ -20,7 +18,6 @@
(def parameter-separator "&")
(def key-value-separator "=")
;;TODO(goranjovic) - rewrite all of these with something more readable than regex
(def uri-pattern
(re-pattern (str scheme scheme-separator "([^" query-separator "]*)(?:\\" query-separator "(.*))?")))
(def authority-path-pattern
@ -71,10 +68,10 @@
(let [[_ authority-path query] (re-find uri-pattern s)]
(when authority-path
(let [[_ raw-address chain-id function-name] (re-find authority-path-pattern authority-path)]
(when (or (or (ens/is-valid-eth-name? raw-address) (address/address? raw-address))
(when (or (or (utils.ens/is-valid-eth-name? raw-address) (address/address? raw-address))
(when (string/starts-with? raw-address "pay-")
(let [pay-address (string/replace-first raw-address "pay-" "")]
(or (ens/is-valid-eth-name? pay-address)
(or (utils.ens/is-valid-eth-name? pay-address)
(address/address? pay-address)))))
(let [address (if (string/starts-with? raw-address "pay-")
(string/replace-first raw-address "pay-" "")
@ -82,7 +79,7 @@
(when-let [arguments (parse-arguments function-name query)]
(let [contract-address (get-in arguments [:function-arguments :address])]
(if-not (or (not contract-address)
(or (ens/is-valid-eth-name? contract-address)
(or (utils.ens/is-valid-eth-name? contract-address)
(address/address? contract-address)))
nil
(merge {:address address
@ -91,31 +88,6 @@
(chain/chain-keyword->chain-id :mainnet))}
arguments))))))))))))
(defn parse-eth-value
"Takes a map as returned by `parse-uri` and returns value as BigNumber"
[s]
(when (string? s)
(let [eth? (string/ends-with? s "ETH")
^js n (money/bignumber (string/replace s "ETH" ""))]
(if eth? (.times n 1e18) n))))
(defn extract-request-details
"Return a map encapsulating request details (with keys `value`, `address` and `symbol`) from a parsed URI.
Supports ethereum and erc20 token."
[{:keys [value address function-name function-arguments] :as details} all-tokens]
(when address
(merge details
(case function-name
nil
{:value (parse-eth-value value)
:symbol :ETH
:address address}
"transfer"
{:value (money/bignumber (:uint256 function-arguments))
:symbol (:symbol (tokens/address->token all-tokens address))
:address (:address function-arguments)}
nil))))
(defn- generate-query-string
[m]
(string/join parameter-separator
@ -142,12 +114,3 @@
(let [native-parameters (dissoc parameters :function-name :function-arguments)]
(generate-query-string (merge function-arguments native-parameters))))
(str query-separator (generate-query-string parameters))))))))
(defn generate-erc20-uri
"Generate a EIP 681 URI encapsulating ERC20 token transfer"
[address {sym :symbol value :value :as m} all-tokens]
(when-let [token (tokens/symbol->token all-tokens sym)]
(generate-uri (:address token)
(merge (dissoc m :value :symbol)
{:function-name "transfer"
:function-arguments {:uint256 value :address address}}))))

View File

@ -1,7 +1,7 @@
(ns status-im.ethereum.eip681-test
(ns utils.ethereum.eip.eip681-test
(:require
[cljs.test :refer-macros [deftest is]]
[status-im.ethereum.eip681 :as eip681]
[utils.ethereum.eip.eip681 :as eip681]
[utils.money :as money]))
(deftest parse-uri
@ -118,27 +118,6 @@
:symbol :STT
:decimals 18}}})
(deftest generate-erc20-uri
(is (= nil (eip681/generate-erc20-uri nil nil all-tokens)))
(is
(=
"ethereum:0x744d70fdbe2ba4cf95131626614a1763df805b9e/transfer?uint256=5&address=0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7"
(eip681/generate-erc20-uri "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7"
{:symbol :SNT :value 5}
(:mainnet all-tokens))))
(is
(=
"ethereum:0x744d70fdbe2ba4cf95131626614a1763df805b9e/transfer?uint256=5&address=0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7&gas=10000&gasPrice=10000"
(eip681/generate-erc20-uri "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7"
{:symbol :SNT :value 5 :gas 10000 :gasPrice 10000}
(:mainnet all-tokens))))
(is
(=
"ethereum:0x744d70fdbe2ba4cf95131626614a1763df805b9e/transfer?uint256=5&address=0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7"
(eip681/generate-erc20-uri "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7"
{:symbol :SNT :chain-id 1 :value 5}
(:mainnet all-tokens)))))
(deftest generate-uri
(is (= nil (eip681/generate-uri nil nil)))
(is (= "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7"
@ -178,46 +157,3 @@
"ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7@3/transfer?uint256=5&address=0xc55cF4B03948D7EBc8b9E8BAD92643703811d162"
{:keys [address] :as params} (eip681/parse-uri uri)]
(is (= uri (eip681/generate-uri address (dissoc params :address))))))
(deftest parse-eth-value
(is (= nil (eip681/parse-eth-value nil)))
(is (= nil (eip681/parse-eth-value 1)))
(is (= nil (eip681/parse-eth-value "NOT_NUMBER")))
(is (.equals (money/bignumber 1) (eip681/parse-eth-value "1")))
(is (.equals (money/bignumber 2.014e18) (eip681/parse-eth-value "2.014e18")))
(is (.equals (money/bignumber 1e18) (eip681/parse-eth-value "1ETH")))
(is (.equals (money/bignumber -1e18) (eip681/parse-eth-value "-1e18")))
(is (.equals (money/bignumber 1e18) (eip681/parse-eth-value "1E18")))
(is (.equals (money/bignumber "111122223333441239") (eip681/parse-eth-value "111122223333441239"))))
(deftest extract-request-details
(let [{value :value
sym :symbol
address :address}
(eip681/extract-request-details
{:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7"
:value "1ETH"}
{})]
(is (.equals (money/ether->wei (money/bignumber 1)) value))
(is (= :ETH sym))
(is (= "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" address)))
(is (= (eip681/extract-request-details
{:address "0x744d70fdbe2ba4cf95131626614a1763df805b9e" :chain-id 1 :function-name "unknown"}
{})
{:address "0x744d70fdbe2ba4cf95131626614a1763df805b9e" :chain-id 1 :function-name "unknown"}))
(let [{value :value
sym :symbol
address :address}
(eip681/extract-request-details
{:address "0x744d70fdbe2ba4cf95131626614a1763df805b9e"
:chain-id 1
:function-name "transfer"
:function-arguments {:uint256 1000 :address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7"}}
{"0x744d70fdbe2ba4cf95131626614a1763df805b9e" {:address
"0x744d70fdbe2ba4cf95131626614a1763df805b9e"
:name "Status Network Token"
:symbol :SNT
:decimals 18}})]
(is (.equals (money/bignumber 1000) value))
(is (= :SNT sym))
(is (= "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" address))))

View File

@ -1,4 +1,4 @@
(ns status-im.utils.universal-links.utils
(ns utils.universal-links
(:require
[goog.string :as gstring]
[status-im2.constants :as constants]))

View File

@ -1,7 +1,7 @@
(ns status-im.utils.universal-links.utils-test
(ns utils.universal-links-test
(:require
[cljs.test :refer-macros [deftest is testing]]
[status-im.utils.universal-links.utils :as links]))
[utils.universal-links :as links]))
(deftest universal-link-test
(testing "status-app://blah"