[BUG #2025] Ensure QR code data is properly parsed
This commit is contained in:
parent
0a94d10559
commit
3b6b5e2da1
|
@ -27,3 +27,7 @@
|
||||||
|
|
||||||
(defn camera [props]
|
(defn camera [props]
|
||||||
(r/create-element default-camera (clj->js (merge {:inverted true} props))))
|
(r/create-element default-camera (clj->js (merge {:inverted true} props))))
|
||||||
|
|
||||||
|
(defn get-qr-code-data [code]
|
||||||
|
(when (= "QR_CODE" (.-type code))
|
||||||
|
(.-data code)))
|
|
@ -136,12 +136,18 @@
|
||||||
:delimiter delimiter
|
:delimiter delimiter
|
||||||
:separator separator})))))
|
:separator separator})))))
|
||||||
|
|
||||||
|
(def default-option-value "<no value>")
|
||||||
|
|
||||||
|
(defn label-options [options]
|
||||||
|
;; i18n ignores nil value, leading to misleading messages
|
||||||
|
(into {} (for [[k v] options] [k (or v default-option-value)])))
|
||||||
|
|
||||||
(defn label
|
(defn label
|
||||||
([path] (label path {}))
|
([path] (label path {}))
|
||||||
([path options]
|
([path options]
|
||||||
(if (exists? rn-dependencies/i18n.t)
|
(if (exists? rn-dependencies/i18n.t)
|
||||||
(let [options (update options :amount label-number)]
|
(let [options (update options :amount label-number)]
|
||||||
(.t rn-dependencies/i18n (name path) (clj->js options)))
|
(.t rn-dependencies/i18n (name path) (clj->js (label-options options))))
|
||||||
(name path))))
|
(name path))))
|
||||||
|
|
||||||
(defn label-pluralize [count path & options]
|
(defn label-pluralize [count path & options]
|
||||||
|
|
|
@ -413,7 +413,7 @@
|
||||||
:wallet-choose-recipient "Choose Recipient"
|
:wallet-choose-recipient "Choose Recipient"
|
||||||
:wallet-choose-from-contacts "Choose From Contacts"
|
:wallet-choose-from-contacts "Choose From Contacts"
|
||||||
:wallet-address-from-clipboard "Use Address From Clipboard"
|
:wallet-address-from-clipboard "Use Address From Clipboard"
|
||||||
:wallet-invalid-address "Address is invalid"
|
:wallet-invalid-address "Invalid address: \n {{data}}"
|
||||||
:wallet-browse-photos "Browse Photos"
|
:wallet-browse-photos "Browse Photos"
|
||||||
:validation-amount-invalid "Amount is not valid"
|
:validation-amount-invalid "Amount is not valid"
|
||||||
:validation-amount-invalid-number "Amount is not a valid number"
|
:validation-amount-invalid-number "Amount is not a valid number"
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
[status-im.components.icons.vector-icons :as vi]
|
[status-im.components.icons.vector-icons :as vi]
|
||||||
[status-im.components.status-bar :refer [status-bar]]
|
[status-im.components.status-bar :refer [status-bar]]
|
||||||
[status-im.i18n :refer [label]]
|
[status-im.i18n :refer [label]]
|
||||||
[status-im.ui.screens.profile.qr-code.styles :as styles])
|
[status-im.ui.screens.profile.qr-code.styles :as styles]
|
||||||
|
[status-im.utils.eip.eip67 :as eip67])
|
||||||
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
||||||
|
|
||||||
(defview qr-code-view []
|
(defview qr-code-view []
|
||||||
|
@ -34,10 +35,7 @@
|
||||||
:height (.-height layout)}]))}
|
:height (.-height layout)}]))}
|
||||||
(when (:width dimensions)
|
(when (:width dimensions)
|
||||||
[react/view {:style (styles/qr-code-container dimensions)}
|
[react/view {:style (styles/qr-code-container dimensions)}
|
||||||
[qr-code {:value (if amount?
|
[qr-code {:value (eip67/generate-uri (get contact qr-source) (when amount? {:value amount}))
|
||||||
(prn-str {:address (get contact qr-source)
|
|
||||||
:amount amount})
|
|
||||||
(str "ethereum:" (get contact qr-source)))
|
|
||||||
:size (- (min (:width dimensions)
|
:size (- (min (:width dimensions)
|
||||||
(:height dimensions))
|
(:height dimensions))
|
||||||
80)}]])]
|
80)}]])]
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
(ns status-im.ui.screens.qr-scanner.events
|
(ns status-im.ui.screens.qr-scanner.events
|
||||||
(:require [re-frame.core :refer [after dispatch debug enrich]]
|
(:require [re-frame.core :as re-frame]
|
||||||
[status-im.components.camera :as camera]
|
[status-im.components.camera :as camera]
|
||||||
[status-im.ui.screens.navigation :as nav]
|
[status-im.ui.screens.navigation :as nav]
|
||||||
[status-im.utils.handlers :as u :refer [register-handler]]
|
[status-im.utils.handlers :as u :refer [register-handler]]
|
||||||
[status-im.utils.utils :as utils]
|
[status-im.utils.utils :as utils]
|
||||||
[status-im.i18n :as i18n]))
|
[status-im.i18n :as i18n]
|
||||||
|
[status-im.utils.eip.eip67 :as eip67]))
|
||||||
|
|
||||||
(defmethod nav/preload-data! :qr-scanner
|
(defmethod nav/preload-data! :qr-scanner
|
||||||
[db [_ _ identifier]]
|
[db [_ _ identifier]]
|
||||||
|
@ -15,16 +16,16 @@
|
||||||
|
|
||||||
(defn navigate-to-scanner
|
(defn navigate-to-scanner
|
||||||
[_ [_ identifier]]
|
[_ [_ identifier]]
|
||||||
(dispatch [:request-permissions
|
(re-frame/dispatch [:request-permissions
|
||||||
[:camera]
|
[:camera]
|
||||||
(fn []
|
(fn []
|
||||||
(camera/request-access
|
(camera/request-access
|
||||||
#(if % (dispatch [:navigate-to :qr-scanner identifier])
|
#(if % (re-frame/dispatch [:navigate-to :qr-scanner identifier])
|
||||||
(utils/show-popup (i18n/label :t/error)
|
(utils/show-popup (i18n/label :t/error)
|
||||||
(i18n/label :t/camera-access-error)))))]))
|
(i18n/label :t/camera-access-error)))))]))
|
||||||
|
|
||||||
(register-handler :scan-qr-code
|
(register-handler :scan-qr-code
|
||||||
(after navigate-to-scanner)
|
(re-frame/after navigate-to-scanner)
|
||||||
set-current-identifier)
|
set-current-identifier)
|
||||||
|
|
||||||
(register-handler :clear-qr-code
|
(register-handler :clear-qr-code
|
||||||
|
@ -34,7 +35,7 @@
|
||||||
(defn handle-qr-request
|
(defn handle-qr-request
|
||||||
[db [_ context data]]
|
[db [_ context data]]
|
||||||
(when-let [handler (get-in db [:qr-codes context])]
|
(when-let [handler (get-in db [:qr-codes context])]
|
||||||
(dispatch [handler context data])))
|
(re-frame/dispatch [handler context (:address (eip67/parse-uri data))])))
|
||||||
|
|
||||||
(defn clear-qr-request [db [_ context]]
|
(defn clear-qr-request [db [_ context]]
|
||||||
(-> db
|
(-> db
|
||||||
|
@ -44,7 +45,7 @@
|
||||||
(defn navigate-back!
|
(defn navigate-back!
|
||||||
[{:keys [view-id]} _]
|
[{:keys [view-id]} _]
|
||||||
(when (= :qr-scanner view-id)
|
(when (= :qr-scanner view-id)
|
||||||
(dispatch [:navigate-back])))
|
(re-frame/dispatch [:navigate-back])))
|
||||||
|
|
||||||
(register-handler :set-qr-code
|
(register-handler :set-qr-code
|
||||||
(u/handlers->
|
(u/handlers->
|
||||||
|
|
|
@ -1,50 +1,42 @@
|
||||||
(ns status-im.ui.screens.qr-scanner.views
|
(ns status-im.ui.screens.qr-scanner.views
|
||||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||||
(:require [re-frame.core :refer [subscribe dispatch dispatch-sync]]
|
(:require [reagent.core :as reagent]
|
||||||
[status-im.components.react :refer [view
|
[re-frame.core :as re-frame]
|
||||||
image]]
|
[status-im.components.react :as react]
|
||||||
[status-im.components.camera :refer [camera]]
|
[status-im.components.camera :as camera]
|
||||||
[status-im.components.styles :refer [icon-search
|
[status-im.components.status-bar :as status-bar]
|
||||||
icon-back]]
|
[status-im.components.toolbar.view :as toolbar]
|
||||||
[status-im.components.status-bar :refer [status-bar]]
|
[status-im.components.toolbar.actions :as action]
|
||||||
[status-im.components.toolbar.view :refer [toolbar]]
|
[status-im.components.toolbar.styles :as toolbar.styles]
|
||||||
[status-im.components.toolbar.actions :as act]
|
[status-im.ui.screens.qr-scanner.styles :as styles]))
|
||||||
[status-im.components.toolbar.styles :refer [toolbar-background1]]
|
|
||||||
[status-im.ui.screens.qr-scanner.styles :as st]
|
|
||||||
[status-im.utils.types :refer [json->clj]]
|
|
||||||
[clojure.string :as str]
|
|
||||||
[reagent.core :as r]))
|
|
||||||
|
|
||||||
(defview qr-scanner-toolbar [title hide-nav?]
|
(defview qr-scanner-toolbar [title hide-nav?]
|
||||||
(letsubs [modal [:get :modal]]
|
(letsubs [modal [:get :modal]]
|
||||||
[view
|
[react/view
|
||||||
[status-bar]
|
[status-bar/status-bar]
|
||||||
[toolbar {:title title
|
[toolbar/toolbar {:title title
|
||||||
:background-color toolbar-background1
|
:background-color toolbar.styles/toolbar-background1
|
||||||
:hide-nav? hide-nav?
|
:hide-nav? hide-nav?
|
||||||
:nav-action (when modal
|
:nav-action (when modal
|
||||||
(act/back #(dispatch [:navigate-back])))}]]))
|
(action/back #(re-frame/dispatch [:navigate-back])))}]]))
|
||||||
|
|
||||||
(defview qr-scanner []
|
(defview qr-scanner []
|
||||||
(letsubs [identifier [:get :current-qr-context]
|
(letsubs [identifier [:get :current-qr-context]
|
||||||
camera-initialized? (r/atom false)]
|
camera-initialized? (reagent/atom false)]
|
||||||
[view st/barcode-scanner-container
|
[react/view styles/barcode-scanner-container
|
||||||
[qr-scanner-toolbar (:toolbar-title identifier) (not @camera-initialized?)]
|
[qr-scanner-toolbar (:toolbar-title identifier) (not @camera-initialized?)]
|
||||||
[camera {:onBarCodeRead (fn [code]
|
[camera/camera {:onBarCodeRead #(re-frame/dispatch [:set-qr-code identifier (camera/get-qr-code-data %)])
|
||||||
(let [data (-> (.-data code)
|
;:barCodeTypes [:qr]
|
||||||
(str/replace #"ethereum:" ""))]
|
:ref #(reset! camera-initialized? true)
|
||||||
(dispatch [:set-qr-code identifier data])))
|
:captureAudio false
|
||||||
;:barCodeTypes [:qr]
|
:style styles/barcode-scanner}]
|
||||||
:ref #(reset! camera-initialized? true)
|
[react/view styles/rectangle-container
|
||||||
:captureAudio false
|
[react/view styles/rectangle
|
||||||
:style st/barcode-scanner}]
|
[react/image {:source {:uri :corner_left_top}
|
||||||
[view st/rectangle-container
|
:style styles/corner-left-top}]
|
||||||
[view st/rectangle
|
[react/image {:source {:uri :corner_right_top}
|
||||||
[image {:source {:uri :corner_left_top}
|
:style styles/corner-right-top}]
|
||||||
:style st/corner-left-top}]
|
[react/image {:source {:uri :corner_right_bottom}
|
||||||
[image {:source {:uri :corner_right_top}
|
:style styles/corner-right-bottom}]
|
||||||
:style st/corner-right-top}]
|
[react/image {:source {:uri :corner_left_bottom}
|
||||||
[image {:source {:uri :corner_right_bottom}
|
:style styles/corner-left-bottom}]]]]))
|
||||||
:style st/corner-right-bottom}]
|
|
||||||
[image {:source {:uri :corner_left_bottom}
|
|
||||||
:style st/corner-left-bottom}]]]]))
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
(ns status-im.ui.screens.wallet.choose-recipient.events
|
(ns status-im.ui.screens.wallet.choose-recipient.events
|
||||||
(:require [status-im.i18n :as i18n]
|
(:require [status-im.i18n :as i18n]
|
||||||
|
[status-im.utils.eip.eip67 :as eip67]
|
||||||
[status-im.utils.handlers :as handlers]))
|
[status-im.utils.handlers :as handlers]))
|
||||||
|
|
||||||
(handlers/register-handler-db
|
(handlers/register-handler-db
|
||||||
|
@ -14,13 +15,14 @@
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
(handlers/register-handler-fx
|
||||||
:choose-recipient
|
:choose-recipient
|
||||||
(fn [{{:keys [web3] :as db} :db} [_ address name]]
|
(fn [{{:keys [web3] :as db} :db} [_ data name]]
|
||||||
(let [{:keys [view-id]} db
|
(let [{:keys [view-id]} db
|
||||||
|
address (:address (eip67/parse-uri data))
|
||||||
valid-address? (.isAddress web3 address)]
|
valid-address? (.isAddress web3 address)]
|
||||||
(cond-> {:db db}
|
(cond-> {:db db}
|
||||||
(= :choose-recipient view-id) (assoc :dispatch [:navigate-back])
|
(= :choose-recipient view-id) (assoc :dispatch [:navigate-back])
|
||||||
valid-address? (update :db #(choose-address-and-name % address name))
|
valid-address? (update :db #(choose-address-and-name % address name))
|
||||||
(not valid-address?) (assoc :show-error (i18n/label :t/wallet-invalid-address))))))
|
(not valid-address?) (assoc :show-error (i18n/label :t/wallet-invalid-address {:data data}))))))
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
(handlers/register-handler-fx
|
||||||
:wallet-open-send-transaction
|
:wallet-open-send-transaction
|
||||||
|
|
|
@ -1,21 +1,16 @@
|
||||||
(ns status-im.ui.screens.wallet.choose-recipient.views
|
(ns status-im.ui.screens.wallet.choose-recipient.views
|
||||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||||
(:require [re-frame.core :as re-frame]
|
(:require [re-frame.core :as re-frame]
|
||||||
[status-im.utils.utils :as utils]
|
[status-im.components.camera :as camera]
|
||||||
|
[status-im.components.icons.vector-icons :as vector-icons]
|
||||||
|
[status-im.components.react :as react]
|
||||||
|
[status-im.components.status-bar :as status-bar]
|
||||||
[status-im.components.toolbar-new.view :as toolbar]
|
[status-im.components.toolbar-new.view :as toolbar]
|
||||||
[status-im.components.toolbar-new.actions :as act]
|
[status-im.components.toolbar-new.actions :as act]
|
||||||
[status-im.i18n :as i18n]
|
[status-im.i18n :as i18n]
|
||||||
[status-im.ui.screens.wallet.styles :as wallet.styles]
|
|
||||||
[status-im.components.react :as react]
|
|
||||||
[status-im.components.icons.vector-icons :as vector-icons]
|
|
||||||
[status-im.ui.screens.wallet.choose-recipient.styles :as styles]
|
[status-im.ui.screens.wallet.choose-recipient.styles :as styles]
|
||||||
[status-im.utils.platform :as platform]
|
[status-im.utils.platform :as platform]
|
||||||
[status-im.components.status-bar :as status-bar]
|
[status-im.ui.screens.wallet.styles :as wallet.styles]))
|
||||||
[status-im.components.camera :as camera]
|
|
||||||
[clojure.string :as string]))
|
|
||||||
|
|
||||||
(defn- show-not-implemented! []
|
|
||||||
(utils/show-popup "TODO" "Not implemented yet!"))
|
|
||||||
|
|
||||||
(defn choose-from-contacts []
|
(defn choose-from-contacts []
|
||||||
(re-frame/dispatch [:navigate-to-modal
|
(re-frame/dispatch [:navigate-to-modal
|
||||||
|
@ -88,15 +83,10 @@
|
||||||
{:width (.-width layout)
|
{:width (.-width layout)
|
||||||
:height (.-height layout)}]))}
|
:height (.-height layout)}]))}
|
||||||
(when (or platform/android?
|
(when (or platform/android?
|
||||||
camera-permitted?)
|
camera-permitted?)[camera/camera {:style styles/preview
|
||||||
[camera/camera {:style styles/preview
|
:aspect :fill
|
||||||
:aspect :fill
|
:captureAudio false
|
||||||
:captureAudio false
|
:torchMode (camera/set-torch camera-flashlight)
|
||||||
:torchMode (camera/set-torch camera-flashlight)
|
:onBarCodeRead #(re-frame/dispatch [:choose-recipient (camera/get-qr-code-data %) nil])}])
|
||||||
:onBarCodeRead (fn [code]
|
|
||||||
(let [data (-> code
|
|
||||||
.-data
|
|
||||||
(string/replace #"ethereum:" ""))]
|
|
||||||
(re-frame/dispatch [:choose-recipient data nil])))}])
|
|
||||||
[viewfinder camera-dimensions]]
|
[viewfinder camera-dimensions]]
|
||||||
[recipient-buttons]]))
|
[recipient-buttons]]))
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
[status-im.ui.screens.wallet.request.styles :as styles]
|
[status-im.ui.screens.wallet.request.styles :as styles]
|
||||||
[status-im.components.styles :as components.styles]
|
[status-im.components.styles :as components.styles]
|
||||||
[status-im.i18n :as i18n]
|
[status-im.i18n :as i18n]
|
||||||
|
[status-im.utils.eip.eip67 :as eip67]
|
||||||
[status-im.utils.platform :as platform]))
|
[status-im.utils.platform :as platform]))
|
||||||
|
|
||||||
(defn toolbar-view []
|
(defn toolbar-view []
|
||||||
|
@ -30,8 +31,7 @@
|
||||||
(views/defview qr-code []
|
(views/defview qr-code []
|
||||||
(views/letsubs [account [:get-current-account]]
|
(views/letsubs [account [:get-current-account]]
|
||||||
[components.qr-code/qr-code
|
[components.qr-code/qr-code
|
||||||
{:value (.stringify js/JSON (clj->js {:address (:address account)
|
{:value (eip67/generate-uri (:address account))
|
||||||
:amount 0}))
|
|
||||||
:size 256}]))
|
:size 256}]))
|
||||||
|
|
||||||
(views/defview request-transaction []
|
(views/defview request-transaction []
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
(ns status-im.ui.screens.wallet.send.events
|
(ns status-im.ui.screens.wallet.send.events
|
||||||
(:require [re-frame.core :as re-frame]
|
(:require [clojure.string :as string]
|
||||||
|
[re-frame.core :as re-frame]
|
||||||
|
[status-im.i18n :as i18n]
|
||||||
|
[status-im.native-module.core :as status]
|
||||||
[status-im.utils.handlers :as handlers]
|
[status-im.utils.handlers :as handlers]
|
||||||
[status-im.ui.screens.wallet.db :as wallet.db]
|
[status-im.ui.screens.wallet.db :as wallet.db]
|
||||||
[status-im.native-module.core :as status]
|
|
||||||
[status-im.utils.types :as types]
|
[status-im.utils.types :as types]
|
||||||
[clojure.string :as string]
|
|
||||||
[status-im.utils.money :as money]
|
[status-im.utils.money :as money]
|
||||||
[status-im.utils.utils :as utils]
|
[status-im.utils.utils :as utils]))
|
||||||
[status-im.i18n :as i18n]))
|
|
||||||
|
|
||||||
;;;; FX
|
;;;; FX
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
(ns status-im.utils.eip.eip67
|
||||||
|
"Utility function related to [EIP67](https://github.com/ethereum/EIPs/issues/67)"
|
||||||
|
(:require [clojure.string :as string]))
|
||||||
|
|
||||||
|
(def scheme "ethereum")
|
||||||
|
(def scheme-separator ":")
|
||||||
|
(def parameters-separator "?")
|
||||||
|
(def parameter-separator "&")
|
||||||
|
(def key-value-separator "=")
|
||||||
|
|
||||||
|
(def key-value-format (str "([^" parameter-separator key-value-separator "]+)"))
|
||||||
|
(def parameters-pattern (re-pattern (str key-value-format key-value-separator key-value-format)))
|
||||||
|
|
||||||
|
(defn- parse-parameters [s]
|
||||||
|
(when s
|
||||||
|
(into {} (for [[_ k v] (re-seq parameters-pattern s)]
|
||||||
|
[(keyword k) v]))))
|
||||||
|
|
||||||
|
(defn parse-uri
|
||||||
|
"Parse a EIP 67 URI as a map of keyword / strings. Parsed map will contain at least the key `address`.
|
||||||
|
Invalid URI will be parsed as `nil`."
|
||||||
|
[s]
|
||||||
|
(when (and s (string/starts-with? s scheme))
|
||||||
|
(let [[address parameters] (string/split (string/replace s (str scheme scheme-separator) "") parameters-separator)]
|
||||||
|
(when-not (zero? (count address))
|
||||||
|
(merge
|
||||||
|
{:address address}
|
||||||
|
(parse-parameters parameters))))))
|
||||||
|
|
||||||
|
(defn- generate-parameter-string [m]
|
||||||
|
(string/join parameter-separator (for [[k v] m]
|
||||||
|
(str (name k) key-value-separator v))))
|
||||||
|
|
||||||
|
(defn generate-uri
|
||||||
|
"Generate a EIP 67 URI based on `address` and an optional map of extra properties.
|
||||||
|
No validation of address format is performed."
|
||||||
|
([address] (generate-uri address nil))
|
||||||
|
([address m]
|
||||||
|
(when address
|
||||||
|
(str scheme scheme-separator address (when m (str parameters-separator (generate-parameter-string m)))))))
|
|
@ -1,3 +0,0 @@
|
||||||
(ns status-im.test.handlers
|
|
||||||
(:require [cljs.test :refer-macros [deftest is]]
|
|
||||||
[status-im.ui.screens.events :as events]))
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
(ns status-im.test.i18n
|
||||||
|
(:require [cljs.test :refer-macros [deftest is]]
|
||||||
|
[status-im.i18n :as i18n]))
|
||||||
|
|
||||||
|
(deftest label-options
|
||||||
|
(is (not (nil? (:key (i18n/label-options {:key nil}))))))
|
|
@ -8,7 +8,7 @@
|
||||||
[status-im.test.profile.events]
|
[status-im.test.profile.events]
|
||||||
[status-im.test.chat.models.input]
|
[status-im.test.chat.models.input]
|
||||||
[status-im.test.components.main-tabs]
|
[status-im.test.components.main-tabs]
|
||||||
[status-im.test.handlers]
|
[status-im.test.i18n]
|
||||||
[status-im.test.utils.utils]
|
[status-im.test.utils.utils]
|
||||||
[status-im.test.utils.money]
|
[status-im.test.utils.money]
|
||||||
[status-im.test.utils.clocks]
|
[status-im.test.utils.clocks]
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
'status-im.test.wallet.transactions.subs
|
'status-im.test.wallet.transactions.subs
|
||||||
'status-im.test.chat.models.input
|
'status-im.test.chat.models.input
|
||||||
'status-im.test.components.main-tabs
|
'status-im.test.components.main-tabs
|
||||||
'status-im.test.handlers
|
'status-im.test.i18n
|
||||||
'status-im.test.utils.utils
|
'status-im.test.utils.utils
|
||||||
'status-im.test.utils.money
|
'status-im.test.utils.money
|
||||||
'status-im.test.utils.clocks
|
'status-im.test.utils.clocks
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
(ns status-im.test.utils.eip.eip67
|
||||||
|
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||||
|
[status-im.utils.eip.eip67 :as eip67]))
|
||||||
|
|
||||||
|
(deftest parse-uri
|
||||||
|
(is (= nil (eip67/parse-uri nil)))
|
||||||
|
(is (= nil (eip67/parse-uri "random")))
|
||||||
|
(is (= nil (eip67/parse-uri "ethereum:")))
|
||||||
|
(is (= nil (eip67/parse-uri "ethereum:?value=1")))
|
||||||
|
(is (= nil (eip67/parse-uri "bitcoin:0x1234")))
|
||||||
|
(is (= {:address "0x1234"} (eip67/parse-uri "ethereum:0x1234")))
|
||||||
|
(is (= {:address "0x1234" :to "0x5678" :value "1"} (eip67/parse-uri "ethereum:0x1234?to=0x5678&value=1"))))
|
||||||
|
|
||||||
|
(deftest generate-uri
|
||||||
|
(is (= nil (eip67/generate-uri nil)))
|
||||||
|
(is (= "ethereum:0x1234" (eip67/generate-uri "0x1234")))
|
||||||
|
(is (= "ethereum:0x1234?to=0x5678" (eip67/generate-uri "0x1234" {:to "0x5678"})))
|
||||||
|
(is (= "ethereum:0x1234?to=0x5678&value=1" (eip67/generate-uri "0x1234" {:to "0x5678" :value 1}))))
|
Loading…
Reference in New Issue