Metamask address support (#20844)
* wip, small renamings * Added metamask regex * Added tests for metamask conversion * Add metamask address to shell scanner and wallet address scanner * unify address functions usage * address-related functions moved to a dedicated namespace * minor fixes * fix lint and tests * review notes fixes * return back function * lint fix * Support metamask addresses without suffix, prefixed `:ethereum`
This commit is contained in:
parent
96b88a427d
commit
bf7b86ccd5
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
(def web-prefixes ["https://" "http://" "https://www." "http://www."])
|
(def web-prefixes ["https://" "http://" "https://www." "http://www."])
|
||||||
|
|
||||||
(def web2-domain "status.app")
|
(def status-web2-domain "status.app")
|
||||||
|
|
||||||
(def user-path "u#")
|
(def user-path "u#")
|
||||||
(def user-with-data-path "u/")
|
(def user-with-data-path "u/")
|
||||||
|
@ -32,13 +32,14 @@
|
||||||
(def community-with-data-path "c/")
|
(def community-with-data-path "c/")
|
||||||
(def channel-path "cc/")
|
(def channel-path "cc/")
|
||||||
|
|
||||||
(def web-urls (map #(str % web2-domain "/") web-prefixes))
|
(def status-web-urls (map #(str % status-web2-domain "/") web-prefixes))
|
||||||
|
|
||||||
(defn path-urls
|
(defn prepend-status-urls
|
||||||
[path]
|
[path]
|
||||||
(map #(str % path) web-urls))
|
(map #(str % path) status-web-urls))
|
||||||
|
|
||||||
(def handled-schemes (set (into uri-schemes web-urls)))
|
|
||||||
|
(def handled-schemes (set (into uri-schemes status-web-urls)))
|
||||||
|
|
||||||
(def group-chat-extractor
|
(def group-chat-extractor
|
||||||
{[#"(.*)" :params] {"" :group-chat
|
{[#"(.*)" :params] {"" :group-chat
|
||||||
|
|
|
@ -260,9 +260,7 @@
|
||||||
(def regx-community-universal-link #"((^https?://status.app/)|(^status-app://))c/([\x00-\x7F]+)$")
|
(def regx-community-universal-link #"((^https?://status.app/)|(^status-app://))c/([\x00-\x7F]+)$")
|
||||||
(def regx-deep-link #"((^ethereum:.*)|(^status-app://[\x00-\x7F]+$))")
|
(def regx-deep-link #"((^ethereum:.*)|(^status-app://[\x00-\x7F]+$))")
|
||||||
(def regx-ens #"^(?=.{5,255}$)([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.[a-zA-Z]{2,}$")
|
(def regx-ens #"^(?=.{5,255}$)([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.[a-zA-Z]{2,}$")
|
||||||
(def regx-multichain-address #"^(?:(?:eth:|arb1:|oeth:)(?=:|))*0x[0-9a-fA-F]{40}$")
|
|
||||||
|
|
||||||
(def regx-address-contains #"(?i)0x[a-fA-F0-9]{40}")
|
|
||||||
(def regx-starts-with-uuid #"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")
|
(def regx-starts-with-uuid #"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")
|
||||||
(def regx-full-or-partial-address #"^0x[a-fA-F0-9]{1,40}$")
|
(def regx-full-or-partial-address #"^0x[a-fA-F0-9]{1,40}$")
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
[status-im.contexts.settings.wallet.saved-addresses.add-address-to-save.style :as style]
|
[status-im.contexts.settings.wallet.saved-addresses.add-address-to-save.style :as style]
|
||||||
[status-im.contexts.wallet.common.utils :as utils]
|
[status-im.contexts.wallet.common.utils :as utils]
|
||||||
[status-im.contexts.wallet.common.validation :as validation]
|
[status-im.contexts.wallet.common.validation :as validation]
|
||||||
|
[utils.address :as utils-address]
|
||||||
[utils.debounce :as debounce]
|
[utils.debounce :as debounce]
|
||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
@ -31,7 +32,7 @@
|
||||||
:own-account
|
:own-account
|
||||||
|
|
||||||
(not
|
(not
|
||||||
(or (validation/eth-address? user-input)
|
(or (utils-address/eip-3770-address? user-input)
|
||||||
(validation/ens-name? user-input)))
|
(validation/ens-name? user-input)))
|
||||||
:invalid-address-or-ens)))
|
:invalid-address-or-ens)))
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
[status-im.common.scan-qr-code.view :as scan-qr-code]
|
[status-im.common.scan-qr-code.view :as scan-qr-code]
|
||||||
[status-im.common.validation.general :as validators]
|
[status-im.common.validation.general :as validators]
|
||||||
[status-im.contexts.communities.events]
|
[status-im.contexts.communities.events]
|
||||||
[status-im.contexts.wallet.common.validation :as wallet-validation]
|
|
||||||
[status-im.contexts.wallet.wallet-connect.utils :as wc-utils]
|
[status-im.contexts.wallet.wallet-connect.utils :as wc-utils]
|
||||||
[status-im.feature-flags :as ff]
|
[status-im.feature-flags :as ff]
|
||||||
|
[utils.address :as utils-address]
|
||||||
[utils.debounce :as debounce]
|
[utils.debounce :as debounce]
|
||||||
[utils.ethereum.eip.eip681 :as eip681]
|
[utils.ethereum.eip.eip681 :as eip681]
|
||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
|
@ -19,19 +19,15 @@
|
||||||
:theme :dark
|
:theme :dark
|
||||||
:text (i18n/label :t/invalid-qr)})
|
:text (i18n/label :t/invalid-qr)})
|
||||||
|
|
||||||
(defn- text-for-url-path?
|
(defn- text-a-status-url-for-path?
|
||||||
[text path]
|
[text path]
|
||||||
(some #(string/starts-with? text %) (router/path-urls path)))
|
(some #(string/starts-with? text %) (router/prepend-status-urls path)))
|
||||||
|
|
||||||
(defn- extract-id
|
(defn- extract-id
|
||||||
[scanned-text]
|
[scanned-text]
|
||||||
(let [index (string/index-of scanned-text "#")]
|
(let [index (string/index-of scanned-text "#")]
|
||||||
(subs scanned-text (inc index))))
|
(subs scanned-text (inc index))))
|
||||||
|
|
||||||
(defn eth-address?
|
|
||||||
[scanned-text]
|
|
||||||
(wallet-validation/eth-address? scanned-text))
|
|
||||||
|
|
||||||
(defn eip681-address?
|
(defn eip681-address?
|
||||||
[scanned-text]
|
[scanned-text]
|
||||||
(-> scanned-text
|
(-> scanned-text
|
||||||
|
@ -71,15 +67,15 @@
|
||||||
[:wallet-connect/on-scan-connection scanned-text]
|
[:wallet-connect/on-scan-connection scanned-text]
|
||||||
300))
|
300))
|
||||||
|
|
||||||
(defn on-qr-code-scanned
|
(defn- on-qr-code-scanned
|
||||||
[scanned-text]
|
[scanned-text]
|
||||||
(cond
|
(cond
|
||||||
(or
|
(or
|
||||||
(text-for-url-path? scanned-text router/community-with-data-path)
|
(text-a-status-url-for-path? scanned-text router/community-with-data-path)
|
||||||
(text-for-url-path? scanned-text router/channel-path))
|
(text-a-status-url-for-path? scanned-text router/channel-path))
|
||||||
(debounce/debounce-and-dispatch [:universal-links/handle-url scanned-text] 300)
|
(debounce/debounce-and-dispatch [:universal-links/handle-url scanned-text] 300)
|
||||||
|
|
||||||
(text-for-url-path? scanned-text router/user-with-data-path)
|
(text-a-status-url-for-path? scanned-text router/user-with-data-path)
|
||||||
(let [address (extract-id scanned-text)]
|
(let [address (extract-id scanned-text)]
|
||||||
(load-and-show-profile address))
|
(load-and-show-profile address))
|
||||||
|
|
||||||
|
@ -87,9 +83,9 @@
|
||||||
(validators/valid-compressed-key? scanned-text))
|
(validators/valid-compressed-key? scanned-text))
|
||||||
(load-and-show-profile scanned-text)
|
(load-and-show-profile scanned-text)
|
||||||
|
|
||||||
(eth-address? scanned-text)
|
(utils-address/supported-address? scanned-text)
|
||||||
(do
|
(when-let [address (utils-address/supported-address->status-address scanned-text)]
|
||||||
(debounce/debounce-and-dispatch [:generic-scanner/scan-success scanned-text] 300)
|
(debounce/debounce-and-dispatch [:generic-scanner/scan-success address] 300)
|
||||||
(debounce/debounce-and-dispatch [:navigate-change-tab :wallet-stack] 300))
|
(debounce/debounce-and-dispatch [:navigate-change-tab :wallet-stack] 300))
|
||||||
|
|
||||||
(eip681-address? scanned-text)
|
(eip681-address? scanned-text)
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
[reagent.core :as reagent]
|
[reagent.core :as reagent]
|
||||||
[status-im.common.floating-button-page.view :as floating-button-page]
|
[status-im.common.floating-button-page.view :as floating-button-page]
|
||||||
[status-im.constants :as constants]
|
|
||||||
[status-im.contexts.wallet.add-account.add-address-to-watch.style :as style]
|
[status-im.contexts.wallet.add-account.add-address-to-watch.style :as style]
|
||||||
[status-im.contexts.wallet.common.validation :as validation]
|
[status-im.contexts.wallet.common.validation :as validation]
|
||||||
[status-im.subs.wallet.add-account.address-to-watch]
|
[status-im.subs.wallet.add-account.address-to-watch]
|
||||||
|
[utils.address :as utils-address]
|
||||||
[utils.debounce :as debounce]
|
[utils.debounce :as debounce]
|
||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
@ -20,13 +20,9 @@
|
||||||
(or (nil? user-input) (= user-input "")) nil
|
(or (nil? user-input) (= user-input "")) nil
|
||||||
(contains? known-addresses user-input) (i18n/label :t/address-already-in-use)
|
(contains? known-addresses user-input) (i18n/label :t/address-already-in-use)
|
||||||
(not
|
(not
|
||||||
(or (validation/eth-address? user-input)
|
(or (utils-address/supported-address? user-input)
|
||||||
(validation/ens-name? user-input))) (i18n/label :t/invalid-address)))
|
(validation/ens-name? user-input))) (i18n/label :t/invalid-address)))
|
||||||
|
|
||||||
(defn- extract-address
|
|
||||||
[scanned-text]
|
|
||||||
(re-find constants/regx-address-contains scanned-text))
|
|
||||||
|
|
||||||
(defn- address-input
|
(defn- address-input
|
||||||
[{:keys [input-value validation-msg validate clear-input]}]
|
[{:keys [input-value validation-msg validate clear-input]}]
|
||||||
(let [scanned-address (rf/sub [:wallet/scanned-address])
|
(let [scanned-address (rf/sub [:wallet/scanned-address])
|
||||||
|
@ -141,9 +137,11 @@
|
||||||
(= activity-state :scanning)
|
(= activity-state :scanning)
|
||||||
(not validated-address))
|
(not validated-address))
|
||||||
:on-press (fn []
|
:on-press (fn []
|
||||||
(rf/dispatch [:navigate-to
|
(rf/dispatch
|
||||||
|
[:navigate-to
|
||||||
:screen/wallet.confirm-address-to-watch
|
:screen/wallet.confirm-address-to-watch
|
||||||
{:address (extract-address
|
{:address
|
||||||
|
(utils-address/extract-address-without-chains-info
|
||||||
validated-address)}])
|
validated-address)}])
|
||||||
(clear-input))
|
(clear-input))
|
||||||
:container-style {:z-index 2}}
|
:container-style {:z-index 2}}
|
||||||
|
|
|
@ -1,28 +1,11 @@
|
||||||
(ns status-im.contexts.wallet.common.scan-account.view
|
(ns status-im.contexts.wallet.common.scan-account.view
|
||||||
(:require
|
(:require
|
||||||
[clojure.string :as string]
|
|
||||||
[status-im.common.scan-qr-code.view :as scan-qr-code]
|
[status-im.common.scan-qr-code.view :as scan-qr-code]
|
||||||
[status-im.constants :as constants]
|
[utils.address :as utils-address]
|
||||||
[utils.debounce :as debounce]
|
[utils.debounce :as debounce]
|
||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
(def ^:private supported-networks #{:eth :arb1 :oeth})
|
|
||||||
|
|
||||||
(defn- contains-supported-address?
|
|
||||||
[s]
|
|
||||||
(let [address? (boolean (re-find constants/regx-address-contains s))
|
|
||||||
networks (when address?
|
|
||||||
(as-> s $
|
|
||||||
(string/split $ ":")
|
|
||||||
(butlast $)))
|
|
||||||
supported? (every? supported-networks (map keyword networks))]
|
|
||||||
(and address? supported?)))
|
|
||||||
|
|
||||||
(defn- extract-address
|
|
||||||
[scanned-text]
|
|
||||||
(first (re-seq constants/regx-multichain-address scanned-text)))
|
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[]
|
[]
|
||||||
(let [{:keys [on-result]} (rf/sub [:get-screen-params])]
|
(let [{:keys [on-result]} (rf/sub [:get-screen-params])]
|
||||||
|
@ -30,9 +13,9 @@
|
||||||
{:title (i18n/label :t/scan-qr)
|
{:title (i18n/label :t/scan-qr)
|
||||||
:subtitle (i18n/label :t/scan-an-address-qr-code)
|
:subtitle (i18n/label :t/scan-an-address-qr-code)
|
||||||
:error-message (i18n/label :t/oops-this-qr-does-not-contain-an-address)
|
:error-message (i18n/label :t/oops-this-qr-does-not-contain-an-address)
|
||||||
:validate-fn #(contains-supported-address? %)
|
:validate-fn #(utils-address/supported-address? %)
|
||||||
:on-success-scan (fn [result]
|
:on-success-scan (fn [result]
|
||||||
(let [address (extract-address result)]
|
(let [address (utils-address/supported-address->status-address result)]
|
||||||
(when on-result (on-result address))
|
(when on-result (on-result address))
|
||||||
(debounce/debounce-and-dispatch
|
(debounce/debounce-and-dispatch
|
||||||
[:wallet/scan-address-success address]
|
[:wallet/scan-address-success address]
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
(:require [status-im.constants :as constants]))
|
(:require [status-im.constants :as constants]))
|
||||||
|
|
||||||
(defn ens-name? [s] (boolean (re-find constants/regx-ens s)))
|
(defn ens-name? [s] (boolean (re-find constants/regx-ens s)))
|
||||||
(defn eth-address? [s] (re-find constants/regx-multichain-address s))
|
|
||||||
(defn private-key?
|
(defn private-key?
|
||||||
[s]
|
[s]
|
||||||
(or (re-find constants/regx-private-key-hex s)
|
(or (re-find constants/regx-private-key-hex s)
|
||||||
|
|
|
@ -12,12 +12,12 @@
|
||||||
[status-im.contexts.wallet.common.account-switcher.view :as account-switcher]
|
[status-im.contexts.wallet.common.account-switcher.view :as account-switcher]
|
||||||
[status-im.contexts.wallet.common.utils :as utils]
|
[status-im.contexts.wallet.common.utils :as utils]
|
||||||
[status-im.contexts.wallet.common.utils.networks :as network-utils]
|
[status-im.contexts.wallet.common.utils.networks :as network-utils]
|
||||||
[status-im.contexts.wallet.common.validation :as validation]
|
|
||||||
[status-im.contexts.wallet.item-types :as types]
|
[status-im.contexts.wallet.item-types :as types]
|
||||||
[status-im.contexts.wallet.send.select-address.style :as style]
|
[status-im.contexts.wallet.send.select-address.style :as style]
|
||||||
[status-im.contexts.wallet.send.select-address.tabs.view :as tabs]
|
[status-im.contexts.wallet.send.select-address.tabs.view :as tabs]
|
||||||
[status-im.feature-flags :as ff]
|
[status-im.feature-flags :as ff]
|
||||||
[status-im.setup.hot-reload :as hot-reload]
|
[status-im.setup.hot-reload :as hot-reload]
|
||||||
|
[utils.address :as utils-address]
|
||||||
[utils.debounce :as debounce]
|
[utils.debounce :as debounce]
|
||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
(debounce/debounce-and-dispatch
|
(debounce/debounce-and-dispatch
|
||||||
(cond
|
(cond
|
||||||
(<= (count address) 0) [:wallet/address-validation-failed address]
|
(<= (count address) 0) [:wallet/address-validation-failed address]
|
||||||
(validation/eth-address? address) [:wallet/address-validation-success address]
|
(utils-address/eip-3770-address? address) [:wallet/address-validation-success address]
|
||||||
:else [:wallet/address-validation-failed address])
|
:else [:wallet/address-validation-failed address])
|
||||||
300))
|
300))
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@
|
||||||
{:on-result on-result}]))
|
{:on-result on-result}]))
|
||||||
:ens-regex constants/regx-ens
|
:ens-regex constants/regx-ens
|
||||||
:scanned-value (or (when recipient-plain-address? send-address) scanned-address)
|
:scanned-value (or (when recipient-plain-address? send-address) scanned-address)
|
||||||
:address-regex constants/regx-multichain-address
|
:address-regex utils-address/regx-eip-3770-address
|
||||||
:on-detect-address (fn [address]
|
:on-detect-address (fn [address]
|
||||||
(when (or (= current-screen-id :screen/wallet.select-address)
|
(when (or (= current-screen-id :screen/wallet.select-address)
|
||||||
(= current-screen-id :screen/wallet.scan-address))
|
(= current-screen-id :screen/wallet.scan-address))
|
||||||
|
|
|
@ -4,7 +4,12 @@
|
||||||
[native-module.core :as native-module]
|
[native-module.core :as native-module]
|
||||||
[utils.ethereum.eip.eip55 :as eip55]))
|
[utils.ethereum.eip.eip55 :as eip55]))
|
||||||
|
|
||||||
|
|
||||||
(def hex-prefix "0x")
|
(def hex-prefix "0x")
|
||||||
|
;; EIP-3770 is a format used by Status and described here: https://eips.ethereum.org/EIPS/eip-3770
|
||||||
|
(def regx-eip-3770-address #"^(?:(?:eth:|arb1:|oeth:)(?=:|))*0x[0-9a-fA-F]{40}$")
|
||||||
|
(def regx-metamask-address #"^ethereum:(0x[0-9a-fA-F]{40})(?:@(0x1|0xa|0xa4b1))?$")
|
||||||
|
(def regx-address-contains #"(?i)0x[a-fA-F0-9]{40}")
|
||||||
|
|
||||||
(defn normalized-hex
|
(defn normalized-hex
|
||||||
[hex]
|
[hex]
|
||||||
|
@ -77,3 +82,49 @@
|
||||||
[value]
|
[value]
|
||||||
(when value
|
(when value
|
||||||
(str (subs value 0 5) "..." (subs value (- (count value) 3) (count value)))))
|
(str (subs value 0 5) "..." (subs value (- (count value) 3) (count value)))))
|
||||||
|
|
||||||
|
(defn eip-155-suffix->eip-3770-prefix
|
||||||
|
[eip-155-suffix]
|
||||||
|
(case eip-155-suffix
|
||||||
|
"0x1" "eth:"
|
||||||
|
"0xa4b1" "arb1:"
|
||||||
|
"0xa" "oeth:"
|
||||||
|
nil))
|
||||||
|
|
||||||
|
(defn split-metamask-address
|
||||||
|
[address]
|
||||||
|
(re-find regx-metamask-address address))
|
||||||
|
|
||||||
|
(defn metamask-address?
|
||||||
|
[address]
|
||||||
|
(boolean (split-metamask-address address)))
|
||||||
|
|
||||||
|
(defn eip-3770-address?
|
||||||
|
"Checks if address follows EIP-3770 format which is default for Status"
|
||||||
|
[s]
|
||||||
|
(re-find regx-eip-3770-address s))
|
||||||
|
|
||||||
|
(defn supported-address?
|
||||||
|
[s]
|
||||||
|
(boolean (or (eip-3770-address? s)
|
||||||
|
(metamask-address? s))))
|
||||||
|
|
||||||
|
(defn metamask-address->status-address
|
||||||
|
[metamask-address]
|
||||||
|
(when-let [[_ address metamask-network-suffix] (split-metamask-address metamask-address)]
|
||||||
|
(if-let [status-network-prefix (eip-155-suffix->eip-3770-prefix metamask-network-suffix)]
|
||||||
|
(str status-network-prefix address)
|
||||||
|
address)))
|
||||||
|
|
||||||
|
(defn supported-address->status-address
|
||||||
|
[address]
|
||||||
|
(cond
|
||||||
|
(eip-3770-address? address)
|
||||||
|
address
|
||||||
|
|
||||||
|
(metamask-address? address)
|
||||||
|
(metamask-address->status-address address)))
|
||||||
|
|
||||||
|
(defn extract-address-without-chains-info
|
||||||
|
[address]
|
||||||
|
(re-find regx-address-contains address))
|
||||||
|
|
|
@ -39,3 +39,50 @@
|
||||||
|
|
||||||
(testing "Ensure the function returns nil when given nil"
|
(testing "Ensure the function returns nil when given nil"
|
||||||
(is (nil? (utils.address/get-abbreviated-profile-url nil)))))
|
(is (nil? (utils.address/get-abbreviated-profile-url nil)))))
|
||||||
|
|
||||||
|
(def valid-metamask-addresses
|
||||||
|
["ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2@0x1"
|
||||||
|
"ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2@0xa4b1"
|
||||||
|
"ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2@0xa"
|
||||||
|
"ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"])
|
||||||
|
|
||||||
|
(def invalid-metamask-addresses
|
||||||
|
["ethe:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2@0x1"
|
||||||
|
":0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2@0xa4b1"
|
||||||
|
"0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2@0xa"
|
||||||
|
"ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2@0x1d"
|
||||||
|
"ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd20xa4b1"
|
||||||
|
"ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2:0xa"])
|
||||||
|
|
||||||
|
(def metamask-to-status
|
||||||
|
[{:metamask "ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2@0x1"
|
||||||
|
:status "eth:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"}
|
||||||
|
{:metamask "ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2@0xa4b1"
|
||||||
|
:status "arb1:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"}
|
||||||
|
{:metamask "ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2@0xa"
|
||||||
|
:status "oeth:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"}
|
||||||
|
{:metamask "ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"
|
||||||
|
:status "0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"}
|
||||||
|
{:metamask "ethe:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2@0x1" :status nil}
|
||||||
|
{:metamask ":0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2@0xa4b1" :status nil}
|
||||||
|
{:metamask "0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2@0xa" :status nil}
|
||||||
|
{:metamask "ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2@0x1d" :status nil}
|
||||||
|
{:metamask "ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd20xa4b1" :status nil}
|
||||||
|
{:metamask "ethereum:0x38cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2:0xa" :status nil}])
|
||||||
|
|
||||||
|
(deftest metamask-address?-test
|
||||||
|
(testing "Check valid metamask addresses"
|
||||||
|
(dorun
|
||||||
|
(for [address valid-metamask-addresses]
|
||||||
|
(is (utils.address/metamask-address? address)))))
|
||||||
|
(testing "Check invalid metamask addresses"
|
||||||
|
(dorun
|
||||||
|
(for [address invalid-metamask-addresses]
|
||||||
|
(is (not (utils.address/metamask-address? address)))))))
|
||||||
|
|
||||||
|
(deftest metamask-address->status-address-test
|
||||||
|
(testing "Check metamask to status address conversion is valid"
|
||||||
|
(dorun
|
||||||
|
(for [{metamask-address :metamask
|
||||||
|
status-address :status} metamask-to-status]
|
||||||
|
(is (= status-address (utils.address/metamask-address->status-address metamask-address)))))))
|
||||||
|
|
Loading…
Reference in New Issue