Skip to content

Commit

Permalink
qr testing mode, fixed qr pure address and EIP681 issues
Browse files Browse the repository at this point in the history
Signed-off-by: Andrey Shovkoplyas <motor4ik@gmail.com>
  • Loading branch information
flexsurfer committed Apr 14, 2020
1 parent e813d1e commit 45dae49
Show file tree
Hide file tree
Showing 20 changed files with 303 additions and 321 deletions.
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions .env.e2e
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ BLANK_PREVIEW=0
TOOLTIP_EVENTS=1
COMMANDS_ENABLED=1
KEYCARD_TEST_MENU=1
QR_READ_TEST_MENU=1
71 changes: 37 additions & 34 deletions src/status_im/ethereum/eip681.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -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 ""))]
Expand All @@ -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"
Expand All @@ -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
Expand All @@ -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"
Expand Down
5 changes: 4 additions & 1 deletion src/status_im/ethereum/macros.clj
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
85 changes: 36 additions & 49 deletions src/status_im/ethereum/subscriptions.cljs
Original file line number Diff line number Diff line change
@@ -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]
Expand All @@ -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]}]
Expand All @@ -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}]
Expand Down
29 changes: 9 additions & 20 deletions src/status_im/ethereum/tokens.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -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))))
11 changes: 2 additions & 9 deletions src/status_im/ethereum/transactions/core.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 2 additions & 3 deletions src/status_im/signing/core.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
Loading

0 comments on commit 45dae49

Please sign in to comment.