From 45dae49fc0964aa49d8221b6de07409895bc9f25 Mon Sep 17 00:00:00 2001 From: Andrey Shovkoplyas Date: Fri, 3 Apr 2020 15:29:41 +0200 Subject: [PATCH] qr testing mode, fixed qr pure address and EIP681 issues Signed-off-by: Andrey Shovkoplyas --- .env | 1 + .env.e2e | 1 + src/status_im/ethereum/eip681.cljs | 71 +++++----- src/status_im/ethereum/macros.clj | 5 +- src/status_im/ethereum/subscriptions.cljs | 85 +++++------- src/status_im/ethereum/tokens.cljs | 29 ++-- src/status_im/ethereum/transactions/core.cljs | 11 +- src/status_im/signing/core.cljs | 5 +- src/status_im/subs.cljs | 47 +++---- .../ui/screens/chat/message/command.cljs | 2 +- .../ui/screens/qr_scanner/views.cljs | 49 +++++-- .../ui/screens/wallet/send/sheets.cljs | 3 +- src/status_im/utils/config.cljs | 1 + src/status_im/utils/universal_links/core.cljs | 4 +- src/status_im/wallet/accounts/core.cljs | 3 +- .../wallet/choose_recipient/core.cljs | 127 +++++++----------- src/status_im/wallet/collectibles/core.cljs | 25 ++-- src/status_im/wallet/core.cljs | 36 +++-- src/status_im/wallet/custom_tokens/core.cljs | 17 +-- test/cljs/status_im/test/ethereum/eip681.cljs | 102 +++++++++----- 20 files changed, 303 insertions(+), 321 deletions(-) diff --git a/.env b/.env index 1760e79c49..851083e2a2 100644 --- a/.env +++ b/.env @@ -23,3 +23,4 @@ MOBILE_UI_FOR_DESKTOP=1 STATUS_GO_PROTOCOL=0 STATUS_GO_ENABLE_NIMBUS=0 KEYCARD_TEST_MENU=0 +QR_READ_TEST_MENU=1 \ No newline at end of file diff --git a/.env.e2e b/.env.e2e index caf30c951d..dfb41e9c21 100644 --- a/.env.e2e +++ b/.env.e2e @@ -23,3 +23,4 @@ BLANK_PREVIEW=0 TOOLTIP_EVENTS=1 COMMANDS_ENABLED=1 KEYCARD_TEST_MENU=1 +QR_READ_TEST_MENU=1 \ No newline at end of file diff --git a/src/status_im/ethereum/eip681.cljs b/src/status_im/ethereum/eip681.cljs index 24f3fc81da..acc9f63850 100644 --- a/src/status_im/ethereum/eip681.cljs +++ b/src/status_im/ethereum/eip681.cljs @@ -25,7 +25,7 @@ (def key-value-format (str "([^" parameter-separator key-value-separator "]+)")) (def query-pattern (re-pattern (str key-value-format key-value-separator key-value-format))) -(def valid-native-arguments #{:value :gas :gasPrice}) +(def valid-native-arguments #{:value :gas :gasPrice :gasLimit}) (defn- parse-query [s] (into {} (for [[_ k v] (re-seq query-pattern (or s ""))] @@ -51,26 +51,28 @@ Invalid URI will be parsed as `nil`." [s] (when (string? s) - (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 (ethereum/address? raw-address) - (if (string/starts-with? raw-address "pay-") - (let [pay-address (string/replace-first raw-address "pay-" "")] - (or (ens/is-valid-eth-name? pay-address) - (ethereum/address? pay-address))))) - (let [address (if (string/starts-with? raw-address "pay-") - (string/replace-first raw-address "pay-" "") - raw-address)] - (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) (ethereum/address? contract-address))) - nil - (merge {:address address - :chain-id (if chain-id - (js/parseInt chain-id) - (ethereum/chain-keyword->chain-id :mainnet))} - arguments))))))))))) + (if (ethereum/address? s) + {:address s} + (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 (ethereum/address? raw-address) + (if (string/starts-with? raw-address "pay-") + (let [pay-address (string/replace-first raw-address "pay-" "")] + (or (ens/is-valid-eth-name? pay-address) + (ethereum/address? pay-address))))) + (let [address (if (string/starts-with? raw-address "pay-") + (string/replace-first raw-address "pay-" "") + raw-address)] + (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) (ethereum/address? contract-address))) + nil + (merge {:address address + :chain-id (if chain-id + (js/parseInt chain-id) + (ethereum/chain-keyword->chain-id :mainnet))} + arguments)))))))))))) (defn parse-eth-value [s] "Takes a map as returned by `parse-uri` and returns value as BigNumber" @@ -79,20 +81,21 @@ n (money/bignumber (string/replace s "ETH" ""))] (if eth? (.times n 1e18) n)))) -(defn extract-request-details [{:keys [value address chain-id function-name function-arguments]} all-tokens] +(defn extract-request-details [{:keys [value address function-name function-arguments] :as details} all-tokens] "Return a map encapsulating request details (with keys `value`, `address` and `symbol`) from a parsed URI. Supports ethereum and erc20 token." (when address - (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 (ethereum/chain-id->chain-keyword chain-id) address)) - :address (:address function-arguments)} - nil))) + (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 @@ -118,8 +121,8 @@ (defn generate-erc20-uri "Generate a EIP 681 URI encapsulating ERC20 token transfer" - [address {:keys [symbol value chain-id] :as m} all-tokens] - (when-let [token (tokens/symbol->token all-tokens (if chain-id (ethereum/chain-id->chain-keyword chain-id) :mainnet) symbol)] + [address {:keys [symbol value] :as m} all-tokens] + (when-let [token (tokens/symbol->token all-tokens symbol)] (generate-uri (:address token) (merge (dissoc m :value :symbol) {:function-name "transfer" diff --git a/src/status_im/ethereum/macros.clj b/src/status_im/ethereum/macros.clj index 2009b03b3d..4891fa0dce 100644 --- a/src/status_im/ethereum/macros.clj +++ b/src/status_im/ethereum/macros.clj @@ -27,7 +27,10 @@ "In react-native arguments to require must be static strings. Resolve all icons at compilation time so no variable is used." [network tokens] - (mapv #(assoc-in % [:icon :source] (token->icon network %)) tokens)) + (mapv #(-> % + (assoc-in [:icon :source] (token->icon network %)) + (update :address string/lower-case)) + tokens)) (defn network->icon [network] (let [s (str "./resources/images/tokens/" (name network) "/0-native.png") diff --git a/src/status_im/ethereum/subscriptions.cljs b/src/status_im/ethereum/subscriptions.cljs index 4462a747a7..0bcf6c8c98 100644 --- a/src/status_im/ethereum/subscriptions.cljs +++ b/src/status_im/ethereum/subscriptions.cljs @@ -1,10 +1,5 @@ (ns status-im.ethereum.subscriptions - (:require [re-frame.core :as re-frame] - [status-im.constants :as constants] - [status-im.ethereum.eip55 :as eip55] - [status-im.ethereum.core :as ethereum] - [status-im.ethereum.json-rpc :as json-rpc] - [status-im.ethereum.tokens :as tokens] + (:require [status-im.ethereum.eip55 :as eip55] [status-im.wallet.db :as wallet] [status-im.ethereum.transactions.core :as transactions] [status-im.utils.fx :as fx] @@ -26,28 +21,24 @@ (fx/defn new-block [{:keys [db] :as cofx} historical? block-number accounts transactions-per-account] - (let [{:keys [:wallet/all-tokens]} db - chain (ethereum/chain-keyword db) - chain-tokens (into {} (map (juxt :address identity) - (tokens/tokens-for all-tokens chain)))] - (log/debug "[wallet-subs] new-block" - "accounts" accounts - "block" block-number - "transactions-per-account" transactions-per-account) - (fx/merge cofx - (cond-> {} - (not historical?) - (assoc :db (assoc db :ethereum/current-block block-number)) + (log/debug "[wallet-subs] new-block" + "accounts" accounts + "block" block-number + "transactions-per-account" transactions-per-account) + (fx/merge cofx + (cond-> {} + (not historical?) + (assoc :db (assoc db :ethereum/current-block block-number)) - ;;NOTE only get transfers if the new block contains some - ;; from/to one of the multiaccount accounts - (not-empty accounts) - (assoc :transactions/get-transfers - {:chain-tokens chain-tokens - :addresses accounts - :before-block block-number - :historical? historical?})) - (transactions/check-watched-transactions)))) + ;;NOTE only get transfers if the new block contains some + ;; from/to one of the multiaccount accounts + (not-empty accounts) + (assoc :transactions/get-transfers + {:chain-tokens (:wallet/all-tokens db) + :addresses accounts + :before-block block-number + :historical? historical?})) + (transactions/check-watched-transactions))) (fx/defn reorg [{:keys [db] :as cofx} {:keys [blockNumber accounts]}] @@ -68,28 +59,24 @@ (log/debug "[wallet-subs] recent-history-fetching-ended" "accounts" accounts "block" blockNumber) - (let [{:keys [:wallet/all-tokens]} db - chain (ethereum/chain-keyword db) - chain-tokens (into {} (map (juxt :address identity) - (tokens/tokens-for all-tokens chain)))] - {:db (-> db - (update-in [:wallet :accounts] - wallet/remove-transactions-since-block blockNumber) - (transactions/update-fetching-status accounts :recent? false)) - :transactions/get-transfers - {:chain-tokens chain-tokens - :addresses (reduce - (fn [v address] - (let [normalized-address - (eip55/address->checksum address)] - (if (contains? v normalized-address) - v - (conj v address)))) - [] - accounts) - :before-block blockNumber - :limit 20 - :historical? true}})) + {:db (-> db + (update-in [:wallet :accounts] + wallet/remove-transactions-since-block blockNumber) + (transactions/update-fetching-status accounts :recent? false)) + :transactions/get-transfers + {:chain-tokens (:wallet/all-tokens db) + :addresses (reduce + (fn [v address] + (let [normalized-address + (eip55/address->checksum address)] + (if (contains? v normalized-address) + v + (conj v address)))) + [] + accounts) + :before-block blockNumber + :limit 20 + :historical? true}}) (fx/defn new-wallet-event [cofx {:keys [type blockNumber accounts newTransactions] :as event}] diff --git a/src/status_im/ethereum/tokens.cljs b/src/status_im/ethereum/tokens.cljs index 67bc0eded4..c2762a8ef4 100644 --- a/src/status_im/ethereum/tokens.cljs +++ b/src/status_im/ethereum/tokens.cljs @@ -543,35 +543,24 @@ :custom []}) -;; TODO all these should be improved, we don't need to recalculate this each time, it can be done only once -(defn tokens-for - "makes sure all addresses are lower-case - TODO: token list should be speced and not accept non-lower-cased addresses" - [all-tokens chain] - (mapv #(update % :address string/lower-case) (vals (get all-tokens chain)))) +(defn nfts-for [all-tokens] + (filter :nft? (vals all-tokens))) -(defn nfts-for [all-tokens chain] - (filter :nft? (tokens-for all-tokens chain))) - -(defn token-for [chain all-tokens token] - (some #(when (= token (name (:symbol %))) %) (tokens-for all-tokens chain))) - -(defn sorted-tokens-for [all-tokens chain] - (->> (tokens-for all-tokens chain) +(defn sorted-tokens-for [all-tokens] + (->> (vals all-tokens) (filter #(not (:hidden? %))) (sort #(compare (string/lower-case (:name %1)) (string/lower-case (:name %2)))))) -(defn symbol->token [all-tokens chain symbol] - (some #(when (= symbol (:symbol %)) %) (tokens-for all-tokens chain))) +(defn symbol->token [all-tokens symbol] + (some #(when (= symbol (:symbol %)) %) (vals all-tokens))) -(defn address->token [all-tokens chain address] - (some #(when (= (string/lower-case address) - (string/lower-case (:address %))) %) (tokens-for all-tokens chain))) +(defn address->token [all-tokens address] + (get all-tokens (string/lower-case address))) (defn asset-for [all-tokens chain symbol] (let [native-coin (native-currency chain)] (if (or (= (:symbol-display native-coin) symbol) (= (:symbol native-coin) symbol)) native-coin - (symbol->token all-tokens chain symbol)))) + (symbol->token all-tokens symbol)))) diff --git a/src/status_im/ethereum/transactions/core.cljs b/src/status_im/ethereum/transactions/core.cljs index 5950b17f2c..491b42a4ae 100644 --- a/src/status_im/ethereum/transactions/core.cljs +++ b/src/status_im/ethereum/transactions/core.cljs @@ -275,20 +275,13 @@ (fx/defn fetch-more-tx {:events [:transactions/fetch-more]} [{:keys [db] :as cofx} address] - (let [all-tokens (:wallet/all-tokens db) - chain (ethereum/chain-keyword db) - chain-tokens (into - {} - (map (juxt :address identity) - (tokens/tokens-for - all-tokens chain))) - min-known-block (or (get-min-known-block db address) + (let [min-known-block (or (get-min-known-block db address) (:ethereum/current-block db)) min-block-transfers-count (or (min-block-transfers-count db address) 0)] (fx/merge cofx {:transactions/get-transfers - {:chain-tokens chain-tokens + {:chain-tokens (:wallet/all-tokens db) :addresses [address] :before-block min-known-block :historical? true diff --git a/src/status_im/signing/core.cljs b/src/status_im/signing/core.cljs index 53d7beafbe..592696e252 100644 --- a/src/status_im/signing/core.cljs +++ b/src/status_im/signing/core.cljs @@ -106,8 +106,7 @@ (fx/defn prepare-unconfirmed-transaction [{:keys [db now]} hash {:keys [value gasPrice gas data to from]} symbol amount] - (let [all-tokens (:wallet/all-tokens db) - token (tokens/symbol->token all-tokens (ethereum/chain-keyword db) symbol)] + (let [token (tokens/symbol->token (:wallet/all-tokens db) symbol)] {:db (assoc-in db [:wallet :accounts from :transactions hash] {:timestamp (str now) :to to @@ -133,7 +132,7 @@ :approve-and-call)) (defn get-transfer-token [db to data] - (let [{:keys [symbol decimals] :as token} (tokens/address->token (:wallet/all-tokens db) (ethereum/chain-keyword db) to)] + (let [{:keys [symbol decimals] :as token} (tokens/address->token (:wallet/all-tokens db) to)] (when (and token data (string? data)) (when-let [type (get-method-type data)] (let [[address value _] (abi-spec/decode diff --git a/src/status_im/subs.cljs b/src/status_im/subs.cljs index 4dcadde3af..3903b8ccad 100644 --- a/src/status_im/subs.cljs +++ b/src/status_im/subs.cljs @@ -1118,18 +1118,21 @@ 0)) acc)) 0 balance)) +(re-frame/reg-sub + :wallet/token->decimals + :<- [:wallet/all-tokens] + (fn [all-tokens] + (into {} (map #(vector (:symbol %) (:decimals %)) (vals all-tokens))))) + (re-frame/reg-sub :portfolio-value :<- [:balances] :<- [:prices] :<- [:wallet/currency] - :<- [:ethereum/chain-keyword] - :<- [:wallet/all-tokens] - (fn [[balances prices currency chain all-tokens]] + :<- [:wallet/token->decimals] + (fn [[balances prices currency token->decimals]] (if (and balances prices) - (let [assets (tokens/tokens-for all-tokens chain) - token->decimals (into {} (map #(vector (:symbol %) (:decimals %)) assets)) - currency-key (-> currency :code keyword) + (let [currency-key (-> currency :code keyword) balance-total-value (apply + (map #(get-balance-total-value % prices currency-key token->decimals) balances))] (if (pos? balance-total-value) (-> balance-total-value @@ -1145,13 +1148,10 @@ [(re-frame/subscribe [:balance address]) (re-frame/subscribe [:prices]) (re-frame/subscribe [:wallet/currency]) - (re-frame/subscribe [:ethereum/chain-keyword]) - (re-frame/subscribe [:wallet/all-tokens])]) - (fn [[balance prices currency chain all-tokens]] + (re-frame/subscribe [:wallet/token->decimals])]) + (fn [[balance prices currency token->decimals]] (if (and balance prices) - (let [assets (tokens/tokens-for all-tokens chain) - token->decimals (into {} (map #(vector (:symbol %) (:decimals %)) assets)) - currency-key (-> currency :code keyword) + (let [currency-key (-> currency :code keyword) balance-total-value (get-balance-total-value balance prices currency-key token->decimals)] (if (pos? balance-total-value) (-> balance-total-value @@ -1162,22 +1162,14 @@ "..."))) (re-frame/reg-sub - :wallet/chain-tokens + :wallet/sorted-tokens :<- [:wallet/all-tokens] - :<- [:ethereum/chain-keyword] - (fn [[all-tokens chain]] - (get all-tokens chain))) - -(re-frame/reg-sub - :wallet/sorted-chain-tokens - :<- [:wallet/all-tokens] - :<- [:ethereum/chain-keyword] - (fn [[all-tokens chain]] - (tokens/sorted-tokens-for all-tokens chain))) + (fn [all-tokens] + (tokens/sorted-tokens-for all-tokens))) (re-frame/reg-sub :wallet/grouped-chain-tokens - :<- [:wallet/sorted-chain-tokens] + :<- [:wallet/sorted-tokens] :<- [:wallet/visible-tokens-symbols] (fn [[all-tokens visible-tokens]] (let [vt-set (set visible-tokens)] @@ -1228,10 +1220,9 @@ :wallet/visible-assets :<- [:ethereum/chain-keyword] :<- [:wallet/visible-tokens-symbols] - :<- [:wallet/all-tokens] - (fn [[chain visible-tokens-symbols all-tokens]] - (conj (filter #(contains? visible-tokens-symbols (:symbol %)) - (tokens/sorted-tokens-for all-tokens chain)) + :<- [:wallet/sorted-tokens] + (fn [[chain visible-tokens-symbols all-tokens-sorted]] + (conj (filter #(contains? visible-tokens-symbols (:symbol %)) all-tokens-sorted) (tokens/native-currency chain)))) (re-frame/reg-sub diff --git a/src/status_im/ui/screens/chat/message/command.cljs b/src/status_im/ui/screens/chat/message/command.cljs index 4743d776ea..da968bfb4d 100644 --- a/src/status_im/ui/screens/chat/message/command.cljs +++ b/src/status_im/ui/screens/chat/message/command.cljs @@ -146,7 +146,7 @@ [contract value] (let [{:keys [symbol icon decimals color] :as token} (if (seq contract) - (get @(re-frame/subscribe [:wallet/chain-tokens]) + (get @(re-frame/subscribe [:wallet/all-tokens]) contract transactions/default-erc20-token) @(re-frame/subscribe [:ethereum/native-currency])) diff --git a/src/status_im/ui/screens/qr_scanner/views.cljs b/src/status_im/ui/screens/qr_scanner/views.cljs index 2269336c8e..1783ef8837 100644 --- a/src/status_im/ui/screens/qr_scanner/views.cljs +++ b/src/status_im/ui/screens/qr_scanner/views.cljs @@ -6,7 +6,9 @@ [status-im.ui.components.react :as react] [status-im.ui.components.toolbar.view :as topbar] [status-im.ui.screens.qr-scanner.styles :as styles] - [status-im.ui.components.colors :as colors])) + [status-im.ui.components.colors :as colors] + [status-im.utils.config :as config] + [status-im.ui.components.button :as button])) (defn- topbar [camera-flashlight {:keys [title] :as opts}] [topbar/toolbar @@ -23,6 +25,25 @@ :icon-opts {:color colors/white} :handler #(re-frame/dispatch [:wallet/toggle-flashlight])}]]]) +(defn qr-test-view [opts] + (let [text-value (atom "")] + [react/safe-area-view {:style {:flex 1 + :background-color colors/black-persist}} + [topbar nil opts] + [react/view {:flex 1 + :align-items :center + :justify-content :center} + [react/text-input {:multiline true + :style {:color colors/white-persist} + :on-change-text #(reset! text-value %)}] + [react/view {:flex-direction :row} + [button/button + {:label "Cancel" + :on-press #(re-frame/dispatch [:qr-scanner.callback/scan-qr-code-cancel opts])}] + [button/button + {:label "OK" + :on-press #(re-frame/dispatch [:qr-scanner.callback/scan-qr-code-success opts @text-value])}]]]])) + (defn corner [border1 border2 corner] [react/view (assoc {:border-color colors/white-persist :width 60 :height 60} border1 5 border2 5 corner 32)]) @@ -44,15 +65,17 @@ {:keys [height width]} [:dimensions/window] camera-flashlight [:wallet.send/camera-flashlight] opts [:get-screen-params]] - [react/safe-area-view {:style {:flex 1 - :background-color colors/black-persist}} - [topbar camera-flashlight opts] - [react/with-activity-indicator - {} - [camera/camera - {:style {:flex 1} - :captureAudio false - :onBarCodeRead #(when-not @read-once? - (reset! read-once? true) - (on-barcode-read opts %))}]] - [viewfinder (int (* 2 (/ (min height width) 3)))]])) + (if config/qr-test-menu-enabled? + [qr-test-view opts] + [react/safe-area-view {:style {:flex 1 + :background-color colors/black-persist}} + [topbar camera-flashlight opts] + [react/with-activity-indicator + {} + [camera/camera + {:style {:flex 1} + :captureAudio false + :onBarCodeRead #(when-not @read-once? + (reset! read-once? true) + (on-barcode-read opts %))}]] + [viewfinder (int (* 2 (/ (min height width) 3)))]]))) diff --git a/src/status_im/ui/screens/wallet/send/sheets.cljs b/src/status_im/ui/screens/wallet/send/sheets.cljs index 82383eb184..d68e478e99 100644 --- a/src/status_im/ui/screens/wallet/send/sheets.cljs +++ b/src/status_im/ui/screens/wallet/send/sheets.cljs @@ -37,7 +37,8 @@ (defn- request-camera-permissions [] (let [options {:handler :wallet.send/qr-scanner-result - :cancel-handler :wallet.send/qr-scanner-cancel}] + :cancel-handler :wallet.send/qr-scanner-cancel + :modal-opened? true}] (re-frame/dispatch [:request-permissions {:permissions [:camera] diff --git a/src/status_im/utils/config.cljs b/src/status_im/utils/config.cljs index cc3346248a..d99be06fee 100644 --- a/src/status_im/utils/config.cljs +++ b/src/status_im/utils/config.cljs @@ -40,6 +40,7 @@ (def waku-enabled? (enabled? (get-config :WAKU_ENABLED "0"))) (def commands-enabled? (enabled? (get-config :COMMANDS_ENABLED "0"))) (def keycard-test-menu-enabled? (enabled? (get-config :KEYCARD_TEST_MENU "0"))) +(def qr-test-menu-enabled? (enabled? (get-config :QR_READ_TEST_MENU "0"))) ;; CONFIG VALUES (def log-level diff --git a/src/status_im/utils/universal_links/core.cljs b/src/status_im/utils/universal_links/core.cljs index 0f9b8046eb..57daf6c04b 100644 --- a/src/status_im/utils/universal_links/core.cljs +++ b/src/status_im/utils/universal_links/core.cljs @@ -102,8 +102,8 @@ (fx/defn handle-eip681 [cofx url] (fx/merge cofx - (choose-recipient/resolve-ens-addresses url) - (navigation/navigate-to-cofx :wallet nil))) + (choose-recipient/parse-eip681-uri-and-resolve-ens url) + (navigation/navigate-to-cofx :wallet nil))) (defn handle-not-found [full-url] (log/info "universal-links: no handler for " full-url)) diff --git a/src/status_im/wallet/accounts/core.cljs b/src/status_im/wallet/accounts/core.cljs index 49ea2c0627..eba9858656 100644 --- a/src/status_im/wallet/accounts/core.cljs +++ b/src/status_im/wallet/accounts/core.cljs @@ -271,8 +271,7 @@ (fx/defn view-only-qr-scanner-result {:events [:wallet.add-new/qr-scanner-result]} [{db :db :as cofx} data _] - (let [address (or (when (ethereum/address? data) data) - (:address (eip681/parse-uri data)))] + (let [address (:address (eip681/parse-uri data))] (fx/merge cofx (merge {:db (-> db (assoc-in [:add-account :scanned-address] address) diff --git a/src/status_im/wallet/choose_recipient/core.cljs b/src/status_im/wallet/choose_recipient/core.cljs index 15cf506cf8..ac239bad2a 100644 --- a/src/status_im/wallet/choose_recipient/core.cljs +++ b/src/status_im/wallet/choose_recipient/core.cljs @@ -1,6 +1,5 @@ (ns status-im.wallet.choose-recipient.core (:require [re-frame.core :as re-frame] - [status-im.constants :as constants] [status-im.contact.db :as contact.db] [status-im.ethereum.core :as ethereum] [status-im.ethereum.eip55 :as eip55] @@ -23,51 +22,6 @@ (defn- find-address-name [db address] (:name (contact.db/find-contact-by-address (:contacts/contacts db) address))) -(defn- fill-request-details [db {:keys [address name value symbol gas gasPrice public-key from-chat?]} request?] - {:pre [(not (nil? address))]} - (let [name (or name (find-address-name db address)) - ;;TODO request isn't implemented - data-path (if request? - :wallet/prepare-transaction - :wallet/prepare-transaction)] - (update db data-path - (fn [{old-symbol :symbol :as old-transaction}] - (let [symbol-changed? (not= old-symbol symbol)] - (cond-> (assoc old-transaction - :to address :to-name name :public-key public-key - :gas (money/bignumber gas) - :gas-price (money/bignumber gasPrice)) - value (assoc :amount value) - symbol (assoc :symbol symbol) - from-chat? (assoc :from-chat? from-chat?))))))) - -;;TODO request isn't implemented -(fx/defn fill-request-from-contact - {:events [:wallet/fill-request-from-contact]} - [{db :db} {:keys [address name public-key]} request?] - {:db (fill-request-details db {:address address :name name :public-key public-key} request?) - :dispatch [:navigate-back]}) - -(defn- extract-details - "First try to parse as EIP681 URI, if not assume this is an address directly. - Returns a map containing at least the `address` and `chain-id` keys" - [m chain-id all-tokens] - (or (merge m (eip681/extract-request-details m all-tokens)) - (when (ethereum/address? m) - {:address m :chain-id chain-id}))) - -;; NOTE(janherich) - whenever changing assets, we want to clear the previusly set amount/amount-text -(defn changed-asset [{:keys [db] :as fx} old-symbol new-symbol] - (-> fx - (assoc-in [:db :wallet/prepare-transaction :amount] nil) - (assoc-in [:db :wallet/prepare-transaction :amount-text] nil) - (assoc-in [:db :wallet/prepare-transaction :asset-error] - (i18n/label :t/changed-asset-warning {:old old-symbol :new new-symbol})))) - -(defn changed-amount-warning [fx old-amount new-amount] - (assoc-in fx [:db :wallet/prepare-transaction :amount-error] - (i18n/label :t/changed-amount-warning {:old old-amount :new new-amount}))) - (defn use-default-eth-gas [fx] (assoc-in fx [:db :wallet :send-transaction :gas] ethereum/default-transaction-gas)) @@ -115,44 +69,54 @@ :else {:ui/show-error (i18n/label :t/wallet-invalid-address {:data recipient})}))) +(defn- fill-prepare-transaction-details + [db + {:keys [address name value symbol gas gasPrice gasLimit] + :or {symbol :ETH}} + all-tokens] + (assoc db :wallet/prepare-transaction + (cond-> {:to address + :to-name (or name (find-address-name db address)) + :from (ethereum/get-default-account + (get db :multiaccount/accounts))} + gas (assoc :gas (money/bignumber gas)) + gasLimit (assoc :gas (money/bignumber gasLimit)) + gasPrice (assoc :gasPrice (money/bignumber gasPrice)) + value (assoc :amount-text + (if (= :ETH symbol) + (str (money/internal->formatted value symbol (get all-tokens symbol))) + (str value))) + symbol (assoc :symbol symbol)))) + (fx/defn request-uri-parsed {:events [:wallet/request-uri-parsed]} - [{{:networks/keys [networks current-network] :wallet/keys [all-tokens] :as db} :db} data uri] - (let [current-chain-id (get-in networks [current-network :config :NetworkId]) - {:keys [address chain-id] :as details} (extract-details data current-chain-id all-tokens) - valid-network? (boolean (= current-chain-id chain-id)) - previous-state (get db :wallet/prepare-transaction) - old-symbol (:symbol previous-state) - new-symbol (:symbol details) - old-amount (:amount previous-state) - new-amount (:value details) - symbol-changed? (and old-symbol new-symbol (not= old-symbol new-symbol)) - amount-changed? (and old-amount new-amount (not= old-amount new-amount))] - (cond-> {:db db} - (and address valid-network?) (update :db #(fill-request-details % details false)) - symbol-changed? (changed-asset old-symbol new-symbol) - amount-changed? (changed-amount-warning old-amount new-amount) - (not (:from previous-state)) - (update :db assoc-in [:wallet/prepare-transaction :from] - (ethereum/get-default-account (get db :multiaccount/accounts))) - (not old-symbol) - (update :db assoc-in [:wallet/prepare-transaction :symbol] (or new-symbol :ETH)) - (not address) (assoc :ui/show-error (i18n/label :t/wallet-invalid-address {:data uri})) - (and address (not valid-network?)) - (assoc :ui/show-error (i18n/label :t/wallet-invalid-chain-id - {:data uri :chain current-chain-id}))))) + [{{:networks/keys [networks current-network] + :wallet/keys [all-tokens] :as db} :db} + {:keys [chain-id] :as data} + uri] + (let [{:keys [address] :as details} + (eip681/extract-request-details data all-tokens)] + (if address + (if (:wallet/prepare-transaction db) + {:db (update db :wallet/prepare-transaction assoc + :to address :to-name (find-address-name db address))} + (let [current-chain-id (get-in networks [current-network :config :NetworkId])] + (merge {:db (fill-prepare-transaction-details db details all-tokens)} + (when (and chain-id (not= current-chain-id chain-id)) + {:ui/show-error (i18n/label :t/wallet-invalid-chain-id + {:data uri :chain current-chain-id})})))) + {:ui/show-error (i18n/label :t/wallet-invalid-address {:data uri})}))) (fx/defn qr-scanner-cancel {:events [:wallet.send/qr-scanner-cancel]} [{db :db} _] {:db (assoc-in db [:wallet/prepare-transaction :modal-opened?] false)}) -(fx/defn resolve-ens-addresses - {:events [:wallet.send/resolve-ens-addresses :wallet.send/qr-code-request-scanned]} - [{{:networks/keys [current-network] :wallet/keys [all-tokens] :as db} :db :as cofx} uri] +(fx/defn parse-eip681-uri-and-resolve-ens + [{db :db :as cofx} uri] (if-let [message (eip681/parse-uri uri)] - ;; first we get a vector of ens-names to resolve and a vector of paths of - ;; these names + ;; first we get a vector of ens-names to resolve and a vector of paths of + ;; these names (let [{:keys [paths ens-names]} (reduce (fn [acc path] (let [address (get-in message path)] @@ -163,8 +127,9 @@ acc))) {:paths [] :ens-names []} [[:address] [:function-arguments :address]])] + (println "message" message) (if (empty? ens-names) - ;; if there is no ens-names, we dispatch request-uri-parsed immediately + ;; if there are no ens-names, we dispatch request-uri-parsed immediately (request-uri-parsed cofx message uri) {::resolve-addresses {:registry (get ens/ens-registries (ethereum/chain-keyword db)) @@ -173,8 +138,8 @@ (fn [addresses] (re-frame/dispatch [:wallet/request-uri-parsed - ;; we replace the ens-names at their path in the message by their - ;; actual address + ;; we replace ens-names at their path in the message by their + ;; actual address (reduce (fn [message [path address]] (assoc-in message path address)) message @@ -185,6 +150,8 @@ {:events [:wallet.send/qr-scanner-result]} [{db :db :as cofx} data opts] (fx/merge cofx - {:db (assoc-in db [:wallet/prepare-transaction :modal-opened?] false)} (navigation/navigate-back) - (resolve-ens-addresses data))) + (parse-eip681-uri-and-resolve-ens data) + (fn [{:keys [db]}] + (when (get-in db [:wallet/prepare-transaction :modal-opened?]) + {:db (assoc-in db [:wallet/prepare-transaction :modal-opened?] false)})))) diff --git a/src/status_im/wallet/collectibles/core.cljs b/src/status_im/wallet/collectibles/core.cljs index 5079cfa2a5..7e46effcb3 100644 --- a/src/status_im/wallet/collectibles/core.cljs +++ b/src/status_im/wallet/collectibles/core.cljs @@ -19,8 +19,8 @@ (defmulti load-collectibles-fx (fn [_ symbol _ _ _] symbol)) -(defmethod load-collectibles-fx :default [all-tokens symbol items-number address chain] - {:load-collectibles-fx [all-tokens symbol items-number address chain]}) +(defmethod load-collectibles-fx :default [all-tokens symbol items-number address] + {:load-collectibles-fx [all-tokens symbol items-number address]}) (defn load-token [i items-number contract address symbol] (when (< i items-number) @@ -31,21 +31,18 @@ (re-frame/reg-fx :load-collectibles-fx - (fn [[all-tokens symbol items-number address chain]] - (let [contract (:address (tokens/symbol->token all-tokens chain symbol))] + (fn [[all-tokens symbol items-number address]] + (let [contract (:address (tokens/symbol->token all-tokens symbol))] (load-token 0 items-number contract address symbol)))) (handlers/register-handler-fx :show-collectibles-list (fn [{:keys [db]} [_ {:keys [symbol amount] :as collectible} address]] - (let [{:networks/keys [current-network networks]} db - chain (ethereum/chain-id->chain-keyword - (get-in networks [current-network :config :NetworkId])) - all-tokens (:wallet/all-tokens db) + (let [all-tokens (:wallet/all-tokens db) items-number (money/to-number amount) loaded-items-number (count (get-in db [:collectibles symbol]))] (merge (when (not= items-number loaded-items-number) - (load-collectibles-fx all-tokens symbol items-number address chain)) + (load-collectibles-fx all-tokens symbol items-number address)) {:dispatch [:navigate-to :collectibles-list collectible]})))) ;; Crypto Kitties @@ -101,16 +98,12 @@ (def kudos :KDO) (defmethod load-collectible-fx kudos [{db :db} symbol id] - (let [{:networks/keys [current-network networks]} db - chain-id (get-in networks [current-network :config :NetworkId]) - all-tokens (:wallet/all-tokens db)] - {:erc721-token-uri [all-tokens symbol id chain-id]})) + {:erc721-token-uri [(:wallet/all-tokens db) symbol id]}) (re-frame/reg-fx :erc721-token-uri - (fn [[all-tokens symbol tokenId chain-id]] - (let [chain (ethereum/chain-id->chain-keyword chain-id) - contract (:address (tokens/symbol->token all-tokens chain symbol))] + (fn [[all-tokens symbol tokenId]] + (let [contract (:address (tokens/symbol->token all-tokens symbol))] (erc721/token-uri contract tokenId #(re-frame/dispatch [:token-uri-success diff --git a/src/status_im/wallet/core.cljs b/src/status_im/wallet/core.cljs index c462126636..98c5b2ba1a 100644 --- a/src/status_im/wallet/core.cljs +++ b/src/status_im/wallet/core.cljs @@ -200,9 +200,9 @@ (update-in db [:wallet :errors] dissoc error-type)) (defn tokens-symbols - [visible-token-symbols all-tokens chain] + [visible-token-symbols all-tokens] (set/difference (set visible-token-symbols) - (set (map :symbol (tokens/nfts-for all-tokens chain))))) + (set (map :symbol (tokens/nfts-for all-tokens))))) (defn rpc->token [tokens] (reduce (fn [acc {:keys [address] :as token}] @@ -213,21 +213,14 @@ tokens)) (fx/defn initialize-tokens - [{:keys [db] :as cofx} custom-tokens] - (let [chain (ethereum/chain-keyword db) - custom-tokens {chain (rpc->token custom-tokens)} - ;;TODO why do we need all tokens ? chain can be changed only through relogin - all-tokens (merge-with - merge - (utils.core/map-values #(utils.core/index-by :address %) - tokens/all-default-tokens) - custom-tokens)] - (fx/merge - cofx - (merge - {:db (assoc db :wallet/all-tokens all-tokens)} - (when config/erc20-contract-warnings-enabled? - {:wallet/validate-tokens (get tokens/all-default-tokens chain)}))))) + [{:keys [db]} custom-tokens] + (let [default-tokens (utils.core/index-by :address (get tokens/all-default-tokens + (ethereum/chain-keyword db))) + all-tokens (merge default-tokens (rpc->token custom-tokens))] + (merge + {:db (assoc db :wallet/all-tokens all-tokens)} + (when config/erc20-contract-warnings-enabled? + {:wallet/validate-tokens default-tokens})))) (fx/defn update-balances [{{:keys [network-status :wallet/all-tokens @@ -239,7 +232,7 @@ assets (get visible-tokens chain) init? (or (empty? assets) (= assets (constants/default-visible-tokens chain))) - tokens (->> (tokens/tokens-for all-tokens chain) + tokens (->> (vals all-tokens) (remove #(or (:hidden? %) ;;if not init remove not visible tokens (and (not init?) @@ -269,7 +262,7 @@ (let [chain (ethereum/chain-keyword db) mainnet? (= :mainnet chain) assets (get visible-tokens chain #{}) - tokens (tokens-symbols assets all-tokens chain) + tokens (tokens-symbols assets all-tokens) currency (get constants/currencies currency)] (when (not= network-status :offline) {:wallet/get-prices @@ -446,7 +439,7 @@ chain (ethereum/network->chain-keyword current-network) {:keys [symbol decimals]} (if (seq contract) - (get (get all-tokens chain) contract) + (get all-tokens contract) (tokens/native-currency chain)) amount-text (str (money/internal->formatted value symbol decimals))] {:db (assoc db :wallet/prepare-transaction @@ -608,7 +601,8 @@ {:events [:wallet.send/qr-scanner-allowed]} [{:keys [db] :as cofx} options] (fx/merge cofx - {:db (assoc-in db [:wallet/prepare-transaction :modal-opened?] true)} + (when (:modal-opened? options) + {:db (assoc-in db [:wallet/prepare-transaction :modal-opened?] true)}) (bottom-sheet/hide-bottom-sheet) (navigation/navigate-to-cofx :qr-scanner options))) diff --git a/src/status_im/wallet/custom_tokens/core.cljs b/src/status_im/wallet/custom_tokens/core.cljs index 77e76cc4f7..bd92cd0f35 100644 --- a/src/status_im/wallet/custom_tokens/core.cljs +++ b/src/status_im/wallet/custom_tokens/core.cljs @@ -85,10 +85,9 @@ (string/trim %)])))) (defn field-exists? - [{:wallet/keys [all-tokens] :as db} field-key field-value] - (let [chain-key (ethereum/chain-keyword db)] - (some #(= field-value (get % field-key)) - (vals (get all-tokens chain-key))))) + [{:wallet/keys [all-tokens]} field-key field-value] + (some #(= field-value (get % field-key)) + (vals all-tokens))) (fx/defn total-supply-result [{:keys [db]} contract total-supply] @@ -100,10 +99,8 @@ :error (i18n/label :t/wrong-contract)})})) (defn token-in-list? - [{:wallet/keys [all-tokens] :as db} contract] - (let [chain-key (ethereum/chain-keyword db) - addresses (set (map string/lower-case (keys (get all-tokens chain-key))))] - (not (nil? (get addresses (string/lower-case contract)))))) + [{:wallet/keys [all-tokens]} contract] + (not (nil? (get all-tokens (string/lower-case contract))))) (fx/defn contract-address-is-changed [{:keys [db]} contract] @@ -177,7 +174,7 @@ :decimals (int decimals) :color (rand-nth colors/chat-colors)}] (fx/merge cofx - {:db (assoc-in db [:wallet/all-tokens chain-key contract] + {:db (assoc-in db [:wallet/all-tokens contract] (assoc new-token :custom? true)) ::json-rpc/call [{:method "wallet_addCustomToken" :params [new-token] @@ -191,7 +188,7 @@ [{:keys [db] :as cofx} {:keys [address] :as token} navigate-back?] (let [chain-key (ethereum/chain-keyword db)] (fx/merge cofx - {:db (update-in db [:wallet/all-tokens chain-key] dissoc address) + {:db (update db :wallet/all-tokens dissoc address) ::json-rpc/call [{:method "wallet_deleteCustomToken" :params [address] :on-success #()}]} diff --git a/test/cljs/status_im/test/ethereum/eip681.cljs b/test/cljs/status_im/test/ethereum/eip681.cljs index 74a8a571ee..456abd98b1 100644 --- a/test/cljs/status_im/test/ethereum/eip681.cljs +++ b/test/cljs/status_im/test/ethereum/eip681.cljs @@ -16,34 +16,73 @@ (is (= nil (eip681/parse-uri "ethereum:pay-gimme.ether?value=1e18"))) (is (= nil (eip681/parse-uri "ethereum:pay-snt.thetoken.ether/transfer?address=gimme.eth&uint256=1&gas=100"))) (is (= nil (eip681/parse-uri "ethereum:pay-snt.thetoken.eth/transfer?address=gimme.ether&uint256=1&gas=100"))) - (is (= {:address "gimme.eth" :value "1e18" :chain-id 1} (eip681/parse-uri "ethereum:pay-gimme.eth?value=1e18"))) - (is (= {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" :value "1e18" :chain-id 1} (eip681/parse-uri "ethereum:pay-0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7?value=1e18"))) - (is (= {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" :chain-id 1} (eip681/parse-uri "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7"))) - (is (= {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" :value "1" :chain-id 1} (eip681/parse-uri "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7?value=1"))) - (is (= {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7", :chain-id 1} (eip681/parse-uri "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7?unknown=1"))) - (is (= {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7", :chain-id 1} (eip681/parse-uri "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7?address=0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7"))) - (is (= {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" :value "2.014e18" :chain-id 1} (eip681/parse-uri "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7?value=2.014e18"))) - (is (= {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" :value "-1e18" :chain-id 1} (eip681/parse-uri "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7?value=-1e18"))) - (is (= {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" :value "+1E18" :chain-id 1} (eip681/parse-uri "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7?value=+1E18"))) - (is (= {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" :value "1E18" :gas "100" :chain-id 1} (eip681/parse-uri "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7?value=1E18&gas=100"))) - (is (= {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" :value "NOT_NUMBER" :chain-id 1} (eip681/parse-uri "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7?value=NOT_NUMBER"))) - (is (= {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" :value "1ETH" :chain-id 1} (eip681/parse-uri "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7?value=1ETH"))) - (is (= {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" :value "1e18" :gas "5000" :chain-id 1} (eip681/parse-uri "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7@1?value=1e18&gas=5000"))) - (is (= {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" :value "1e18" :gas "5000" :chain-id 3} (eip681/parse-uri "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7@3?value=1e18&gas=5000"))) - (is (= {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" :chain-id 1 :function-name "transfer"} (eip681/parse-uri "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7/transfer"))) - (is (= {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" :chain-id 1 :function-name "transfer" :function-arguments {:address "0x8e23ee67d1332ad560396262c48ffbb01f93d052" :uint256 "1"}} - (eip681/parse-uri "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7/transfer?address=0x8e23ee67d1332ad560396262c48ffbb01f93d052&uint256=1"))) - (is (= {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" :chain-id 1 :function-name "transfer" :gas "100" :function-arguments {:address "0x8e23ee67d1332ad560396262c48ffbb01f93d052" :uint256 "1"}} - (eip681/parse-uri "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7/transfer?address=0x8e23ee67d1332ad560396262c48ffbb01f93d052&uint256=1&gas=100"))) - (is (= {:address "snt.thetoken.eth" :chain-id 1 :function-name "transfer" :gas "100" :function-arguments {:address "gimme.eth" :uint256 "1"}} - (eip681/parse-uri "ethereum:pay-snt.thetoken.eth/transfer?address=gimme.eth&uint256=1&gas=100")))) + + (is (= (eip681/parse-uri "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7") + {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7"})) + + (is (= (eip681/parse-uri "ethereum:pay-gimme.eth?value=1e18") + {:address "gimme.eth" :value "1e18" :chain-id 1})) + + (is (= (eip681/parse-uri "ethereum:pay-0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7?value=1e18") + {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" :value "1e18" :chain-id 1})) + + (is (= (eip681/parse-uri "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7") + {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" :chain-id 1})) + + (is (= (eip681/parse-uri "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7?value=1") + {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" :value "1" :chain-id 1})) + + (is (= (eip681/parse-uri "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7?unknown=1") + {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7", :chain-id 1})) + + (is (= (eip681/parse-uri "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7?address=0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7") + {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7", :chain-id 1})) + + (is (= (eip681/parse-uri "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7?value=2.014e18") + {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" :value "2.014e18" :chain-id 1})) + + (is (= (eip681/parse-uri "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7?value=-1e18") + {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" :value "-1e18" :chain-id 1})) + + (is (= (eip681/parse-uri "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7?value=+1E18") + {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" :value "+1E18" :chain-id 1})) + + (is (= (eip681/parse-uri "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7?value=1E18&gas=100") + {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" :value "1E18" :gas "100" :chain-id 1})) + + (is (= (eip681/parse-uri "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7?value=NOT_NUMBER") + {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" :value "NOT_NUMBER" :chain-id 1})) + + (is (= (eip681/parse-uri "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7?value=1ETH") + {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" :value "1ETH" :chain-id 1})) + + (is (= (eip681/parse-uri "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7@1?value=1e18&gas=5000") + {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" :value "1e18" :gas "5000" :chain-id 1})) + + (is (= (eip681/parse-uri "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7@3?value=1e18&gas=5000") + {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" :value "1e18" :gas "5000" :chain-id 3})) + + (is (= (eip681/parse-uri "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7/transfer") + {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" :chain-id 1 :function-name "transfer"})) + + (is (= (eip681/parse-uri "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7/transfer?address=0x8e23ee67d1332ad560396262c48ffbb01f93d052&uint256=1") + {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" :chain-id 1 + :function-name "transfer" :function-arguments {:address "0x8e23ee67d1332ad560396262c48ffbb01f93d052" :uint256 "1"}})) + + (is (= (eip681/parse-uri "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7/transfer?address=0x8e23ee67d1332ad560396262c48ffbb01f93d052&uint256=1&gas=100") + {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" :chain-id 1 :gas "100" + :function-name "transfer" :function-arguments {:address "0x8e23ee67d1332ad560396262c48ffbb01f93d052" :uint256 "1"}})) + + (is (= (eip681/parse-uri "ethereum:pay-snt.thetoken.eth/transfer?address=gimme.eth&uint256=1&gas=100") + {:address "snt.thetoken.eth" :chain-id 1 :gas "100" + :function-name "transfer" :function-arguments {:address "gimme.eth" :uint256 "1"}}))) (def all-tokens {:mainnet {"0x744d70fdbe2ba4cf95131626614a1763df805b9e" {:address "0x744d70fdbe2ba4cf95131626614a1763df805b9e" :name "Status Network Token" :symbol :SNT :decimals 18}} - :testnet {"0xc55cF4B03948D7EBc8b9E8BAD92643703811d162" {:address "0xc55cF4B03948D7EBc8b9E8BAD92643703811d162" + :testnet {"0xc55cf4b03948d7ebc8b9e8bad92643703811d162" {:address "0xc55cf4b03948d7ebc8b9e8bad92643703811d162" :name "Status Test Token" :symbol :STT :decimals 18}}}) @@ -51,13 +90,13 @@ (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} all-tokens))) + (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} all-tokens))) + (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} all-tokens))) + (eip681/generate-erc20-uri "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" {:symbol :SNT :chain-id 1 :value 5} (:mainnet all-tokens)))) (is (= "ethereum:0xc55cf4b03948d7ebc8b9e8bad92643703811d162@3/transfer?uint256=5&address=0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" - (eip681/generate-erc20-uri "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" {:symbol :STT :chain-id 3 :value 5} all-tokens)))) + (eip681/generate-erc20-uri "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" {:symbol :STT :chain-id 3 :value 5} (:testnet all-tokens))))) (deftest generate-uri (is (= nil (eip681/generate-uri nil nil))) @@ -96,13 +135,14 @@ (is (.equals (money/ether->wei (money/bignumber 1)) value)) (is (= :ETH symbol)) (is (= "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" address))) - (is (nil? (eip681/extract-request-details {:address "0x744d70fdbe2ba4cf95131626614a1763df805b9e" :chain-id 1 :function-name "unknown"} {}))) + (is (= (eip681/extract-request-details {:address "0x744d70fdbe2ba4cf95131626614a1763df805b9e" :chain-id 1 :function-name "unknown"} + {:address "0x744d70fdbe2ba4cf95131626614a1763df805b9e" :chain-id 1 :function-name "unknown"}))) (let [{:keys [value symbol address]} (eip681/extract-request-details {:address "0x744d70fdbe2ba4cf95131626614a1763df805b9e" :chain-id 1 :function-name "transfer" :function-arguments {:uint256 1000 :address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7"}} - {:mainnet {"0x744d70fdbe2ba4cf95131626614a1763df805b9e" {:address "0x744d70fdbe2ba4cf95131626614a1763df805b9e" - :name "Status Network Token" - :symbol :SNT - :decimals 18}}})] + {"0x744d70fdbe2ba4cf95131626614a1763df805b9e" {:address "0x744d70fdbe2ba4cf95131626614a1763df805b9e" + :name "Status Network Token" + :symbol :SNT + :decimals 18}})] (is (.equals (money/bignumber 1000) value)) (is (= :SNT symbol)) (is (= "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" address))))