bug #4123 - fixes incorrect number of decimals for tokens, fixes incorrect network id lookup for token send, fixes token amount formatting where needed
This commit is contained in:
parent
ae56eec40f
commit
5e33c98008
|
@ -14,7 +14,7 @@
|
|||
|
||||
(defn send-shortcut-fx [db contact params]
|
||||
(merge {:db (-> db
|
||||
(send.events/set-and-validate-amount-db (:amount params))
|
||||
(send.events/set-and-validate-amount-db (:amount params) :ETH 18)
|
||||
(choose-recipient.events/fill-request-details (transaction-details contact))
|
||||
(navigation/navigate-to :wallet-send-transaction-chat))}
|
||||
(send.events/update-gas-price db false)))
|
||||
|
|
|
@ -86,3 +86,7 @@
|
|||
(fn [db [_ item-id]]
|
||||
(let [item-animation (get-in db [:chat-animations item-id])]
|
||||
(if (some? item-animation) (:delete-swiped item-animation) nil))))
|
||||
|
||||
(reg-sub :get-current-account-network
|
||||
(fn [{:keys [network] :as db} [_]]
|
||||
(get-in db [:account/account :networks network])))
|
||||
|
|
|
@ -185,7 +185,8 @@
|
|||
[recipient-contact address name request?]
|
||||
[recipient-address address])]])
|
||||
|
||||
(defn- amount-input [{:keys [input-options amount amount-text disabled?]}]
|
||||
(defn- amount-input [{:keys [input-options amount amount-text disabled?]}
|
||||
{:keys [symbol decimals]}]
|
||||
[react/view {:style components.styles/flex
|
||||
:accessibility-label :specify-amount-button}
|
||||
[components/text-input
|
||||
|
@ -195,7 +196,9 @@
|
|||
;; Otherwise, user might want to fix his input and autocorrection will give more harm than good.
|
||||
;; Positive check is because we don't want to replace unfinished 0.000 with just plain 0, that is annoying and
|
||||
;; potentially dangerous on this screen (e.g. sending 7 ETH instead of 0.0007)
|
||||
{:default-value (if (empty? amount-text) (str (money/to-fixed (money/wei->ether amount))) amount-text)}
|
||||
{:default-value (if (empty? amount-text)
|
||||
(str (money/to-fixed (money/internal->formatted amount symbol decimals)))
|
||||
amount-text)}
|
||||
(if disabled?
|
||||
{:editable false}
|
||||
{:keyboard-type :numeric
|
||||
|
@ -203,7 +206,7 @@
|
|||
:style components.styles/flex
|
||||
:accessibility-label :amount-input}))]])
|
||||
|
||||
(defn amount-selector [{:keys [error disabled?] :as m}]
|
||||
(defn amount-selector [{:keys [error disabled?] :as m} token]
|
||||
[react/view
|
||||
[components/cartouche {:disabled? disabled?}
|
||||
(i18n/label :t/amount)
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
;; Placeholder namespace for wallet specs, which are a WIP depending on data
|
||||
;; model we decide on for balances, prices, etc.
|
||||
|
||||
(defn- too-precise-amount? [amount]
|
||||
(defn- too-precise-amount? [amount decimals]
|
||||
(let [amount-splited (string/split amount #"[.]")]
|
||||
(and (= (count amount-splited) 2) (> (count (last amount-splited)) 18))))
|
||||
(and (= (count amount-splited) 2) (> (count (last amount-splited)) decimals))))
|
||||
|
||||
(defn parse-amount [amount]
|
||||
(defn parse-amount [amount decimals]
|
||||
(when-not (empty? amount)
|
||||
(let [normalized-amount (money/normalize amount)
|
||||
value (money/bignumber normalized-amount)]
|
||||
|
@ -28,7 +28,7 @@
|
|||
(not (money/valid? value))
|
||||
{:error (i18n/label :t/validation-amount-invalid-number) :value value}
|
||||
|
||||
(too-precise-amount? normalized-amount)
|
||||
(too-precise-amount? normalized-amount decimals)
|
||||
{:error (i18n/label :t/validation-amount-is-too-precise) :value value}
|
||||
|
||||
:else
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
(handlers/register-handler-fx
|
||||
:wallet.request/set-and-validate-amount
|
||||
(fn [{:keys [db]} [_ amount]]
|
||||
(let [{:keys [value error]} (wallet-db/parse-amount amount)]
|
||||
(let [{:keys [value error]} (wallet-db/parse-amount amount :ETH)]
|
||||
{:db (-> db
|
||||
(assoc-in [:wallet :request-transaction :amount] (money/ether->wei value))
|
||||
(assoc-in [:wallet :request-transaction :amount-text] amount)
|
||||
|
|
|
@ -45,7 +45,9 @@
|
|||
:amount-text amount-text
|
||||
:input-options {:max-length 21
|
||||
:on-focus (fn [] (when @scroll (utils/set-timeout #(.scrollToEnd @scroll) 100)))
|
||||
:on-change-text #(re-frame/dispatch [:wallet.request/set-and-validate-amount %])}}]]]
|
||||
:on-change-text #(re-frame/dispatch [:wallet.request/set-and-validate-amount %])}}
|
||||
{:decimals 18
|
||||
:symbol :ETH}]]]
|
||||
[bottom-buttons/bottom-buttons styles/bottom-buttons
|
||||
nil ;; Force a phantom button to ensure consistency with other transaction screens which define 2 buttons
|
||||
[button/button {:disabled? (not (and to amount))
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#()))
|
||||
|
||||
(defn- send-tokens [{:keys [web3 from to value gas gas-price symbol network]}]
|
||||
(let [contract (:address (tokens/symbol->token (ethereum/network->chain-keyword network) symbol))]
|
||||
(let [contract (:address (tokens/symbol->token (keyword (ethereum/network-names network)) symbol))]
|
||||
(erc20/transfer web3 contract from to value {:gas gas :gasPrice gas-price} #())))
|
||||
|
||||
(re-frame/reg-fx
|
||||
|
@ -68,22 +68,25 @@
|
|||
(re-frame/dispatch [::transaction-completed {:id (name (key result)) :response (second result)} modal?]))
|
||||
;;;; Handlers
|
||||
|
||||
(defn set-and-validate-amount-db [db amount]
|
||||
(let [{:keys [value error]} (wallet.db/parse-amount amount)]
|
||||
(defn set-and-validate-amount-db [db amount symbol decimals]
|
||||
(let [{:keys [value error]} (wallet.db/parse-amount amount decimals)]
|
||||
(-> db
|
||||
(assoc-in [:wallet :send-transaction :amount] (money/ether->wei value))
|
||||
(assoc-in [:wallet :send-transaction :amount] (money/formatted->internal value symbol decimals))
|
||||
(assoc-in [:wallet :send-transaction :amount-text] amount)
|
||||
(assoc-in [:wallet :send-transaction :amount-error] error))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:wallet.send/set-and-validate-amount
|
||||
(fn [{:keys [db]} [_ amount]]
|
||||
{:db (set-and-validate-amount-db db amount)}))
|
||||
(fn [{:keys [db]} [_ amount symbol decimals]]
|
||||
{:db (set-and-validate-amount-db db amount symbol decimals)}))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:wallet.send/set-symbol
|
||||
(fn [{:keys [db]} [_ symbol]]
|
||||
{:db (-> (assoc-in db [:wallet :send-transaction :symbol] symbol)
|
||||
{:db (-> db
|
||||
(assoc-in [:wallet :send-transaction :symbol] symbol)
|
||||
(assoc-in [:wallet :send-transaction :amount] nil)
|
||||
(assoc-in [:wallet :send-transaction :amount-text] nil)
|
||||
(assoc-in [:wallet :send-transaction :gas] (ethereum/estimate-gas symbol)))}))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
|
|
|
@ -21,7 +21,9 @@
|
|||
[status-im.ui.screens.wallet.styles :as wallet.styles]
|
||||
[status-im.utils.money :as money]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.transport.utils :as transport.utils]))
|
||||
[status-im.transport.utils :as transport.utils]
|
||||
[status-im.utils.ethereum.tokens :as tokens]
|
||||
[status-im.utils.ethereum.core :as ethereum]))
|
||||
|
||||
(defn sign-later-popup
|
||||
[from-chat?]
|
||||
|
@ -192,8 +194,9 @@
|
|||
(when advanced?
|
||||
[advanced-cartouche transaction modal?])])
|
||||
|
||||
(defn- send-transaction-panel [{:keys [modal? transaction scroll advanced? symbol]}]
|
||||
(let [{:keys [amount amount-text amount-error signing? to to-name sufficient-funds? in-progress? from-chat?]} transaction
|
||||
(defn- send-transaction-panel [{:keys [modal? transaction scroll advanced? network]}]
|
||||
(let [{:keys [amount amount-text amount-error signing? to to-name sufficient-funds? in-progress? from-chat? symbol]} transaction
|
||||
{:keys [decimals] :as token} (tokens/asset-for (ethereum/network->chain-keyword network) symbol)
|
||||
timeout (atom nil)]
|
||||
[wallet.components/simple-screen {:avoid-keyboard? (not modal?)
|
||||
:status-bar-type (if modal? :modal-wallet :wallet)}
|
||||
|
@ -219,7 +222,7 @@
|
|||
:amount-text amount-text
|
||||
:input-options {:max-length 21
|
||||
:on-focus (fn [] (when (and scroll @scroll) (utils/set-timeout #(.scrollToEnd @scroll) 100)))
|
||||
:on-change-text #(re-frame/dispatch [:wallet.send/set-and-validate-amount %])}}]
|
||||
:on-change-text #(re-frame/dispatch [:wallet.send/set-and-validate-amount % symbol decimals])}} token]
|
||||
[advanced-options advanced? transaction modal? scroll]]]
|
||||
(if signing?
|
||||
[signing-buttons
|
||||
|
@ -244,16 +247,20 @@
|
|||
(letsubs [transaction [:wallet.send/transaction]
|
||||
symbol [:wallet.send/symbol]
|
||||
advanced? [:wallet.send/advanced?]
|
||||
network [:get-current-account-network]
|
||||
scroll (atom nil)]
|
||||
[send-transaction-panel {:modal? false :transaction transaction :scroll scroll :advanced? advanced? :symbol symbol}]))
|
||||
[send-transaction-panel {:modal? false :transaction transaction :scroll scroll :advanced? advanced?
|
||||
:symbol symbol :network network}]))
|
||||
|
||||
(defview send-transaction-modal []
|
||||
(letsubs [transaction [:wallet.send/unsigned-transaction]
|
||||
symbol [:wallet.send/symbol]
|
||||
advanced? [:wallet.send/advanced?]
|
||||
network [:get-current-account-network]
|
||||
scroll (atom nil)]
|
||||
(if transaction
|
||||
[send-transaction-panel {:modal? true :transaction transaction :scroll scroll :advanced? advanced? :symbol symbol}]
|
||||
[send-transaction-panel {:modal? true :transaction transaction :scroll scroll :advanced? advanced?
|
||||
symbol symbol :network network}]
|
||||
[react/view wallet.styles/wallet-modal-container
|
||||
[react/view components.styles/flex
|
||||
[status-bar/status-bar {:type :modal-wallet}]
|
||||
|
|
|
@ -10,7 +10,9 @@
|
|||
[status-im.ui.components.toolbar.view :as toolbar]
|
||||
[status-im.ui.components.status-bar.view :as status-bar]
|
||||
[status-im.ui.screens.wallet.transactions.styles :as styles]
|
||||
[status-im.utils.money :as money]))
|
||||
[status-im.utils.money :as money]
|
||||
[status-im.utils.ethereum.tokens :as tokens]
|
||||
[status-im.utils.ethereum.core :as ethereum]))
|
||||
|
||||
(defn history-action [filter?]
|
||||
(cond->
|
||||
|
@ -44,12 +46,13 @@
|
|||
(:postponed :pending) (transaction-icon :icons/arrow-right components.styles/color-gray4-transparent components.styles/color-gray7)
|
||||
(throw (str "Unknown transaction type: " k))))
|
||||
|
||||
(defn render-transaction [{:keys [hash from-contact to-contact to from type value time-formatted symbol] :as transaction}]
|
||||
(defn render-transaction [{:keys [hash from-contact to-contact to from type value time-formatted symbol] :as transaction} network]
|
||||
(let [[label contact address
|
||||
contact-accessibility-label
|
||||
address-accessibility-label] (if (inbound? type)
|
||||
[(i18n/label :t/from) from-contact from :sender-text :sender-address-text]
|
||||
[(i18n/label :t/to) to-contact to :recipient-name-text :recipient-address-text])]
|
||||
[(i18n/label :t/to) to-contact to :recipient-name-text :recipient-address-text])
|
||||
{:keys [decimals]} (tokens/asset-for (ethereum/network->chain-keyword network) symbol)]
|
||||
[list/touchable-item #(re-frame/dispatch [:show-transaction-details hash])
|
||||
[react/view {:accessibility-label :transaction-item}
|
||||
[list/item
|
||||
|
@ -60,7 +63,7 @@
|
|||
:ellipsize-mode "tail"
|
||||
:number-of-lines 1}
|
||||
[react/text {:accessibility-label :amount-text}
|
||||
(->> value (money/wei-> :eth) money/to-fixed str)]
|
||||
(-> value (money/internal->formatted symbol decimals) money/to-fixed str)]
|
||||
" "
|
||||
[react/text {:accessibility-label :currency-text}
|
||||
(clojure.string/upper-case (name symbol))]]
|
||||
|
@ -91,11 +94,12 @@
|
|||
|
||||
(defview history-list []
|
||||
(letsubs [transactions-history-list [:wallet.transactions/transactions-history-list]
|
||||
filter-data [:wallet.transactions/filters]]
|
||||
filter-data [:wallet.transactions/filters]
|
||||
network [:get-current-account-network]]
|
||||
[react/view components.styles/flex
|
||||
[list/section-list {:sections (map #(update-transactions % filter-data) transactions-history-list)
|
||||
:key-fn :hash
|
||||
:render-fn render-transaction
|
||||
:render-fn #(render-transaction % network)
|
||||
:empty-component [react/text {:style styles/empty-text}
|
||||
(i18n/label :t/transactions-history-empty)]
|
||||
:on-refresh #(re-frame/dispatch [:update-transactions])
|
||||
|
|
|
@ -380,30 +380,26 @@
|
|||
:symbol :STT
|
||||
:decimals 18
|
||||
:address "0xc55cf4b03948d7ebc8b9e8bad92643703811d162"}
|
||||
{:name "Aragon Test Token"
|
||||
:symbol :ATT
|
||||
:decimals 1
|
||||
:address "0x00a8e52df8f4f1f4b67bded9ae6090b35489a973"}
|
||||
{:name "Handy Test Token"
|
||||
:symbol :HND
|
||||
:decimals 18
|
||||
:address "0x9e47fb3049f0d9c953f5428ce2e6c3a8321780bf"}
|
||||
:decimals 0
|
||||
:address "0xdee43a267e8726efd60c2e7d5b81552dcd4fa35c"}
|
||||
{:name "Lucky XS Test"
|
||||
:symbol :LXS
|
||||
:decimals 18
|
||||
:address "0xf29d2dc0687d7d49f57d4a731ac8bfb6edc23473"}
|
||||
:decimals 2
|
||||
:address "0x703d7dc0bc8e314d65436adf985dda51e09ad43b"}
|
||||
{:name "Adi Test Token"
|
||||
:symbol :ADI
|
||||
:decimals 18
|
||||
:address "0xd2a816110c1177478c7e644ae4853d8e80aaec35"}
|
||||
:decimals 7
|
||||
:address "0xe639e24346d646e927f323558e6e0031bfc93581"}
|
||||
{:name "Wagner Test Token"
|
||||
:symbol :WGN
|
||||
:decimals 18
|
||||
:address "0x65c69bc258afa0906683f42e576b272a95c203dd"}
|
||||
:decimals 10
|
||||
:address "0x2e7cd05f437eb256f363417fd8f920e2efa77540"}
|
||||
{:name "Modest Test Token"
|
||||
:symbol :MDS
|
||||
:decimals 18
|
||||
:address "0x972b0570d9cd8b7c41aa8349f707ec7356daa825"}])})
|
||||
:address "0x57cc9b83730e6d22b224e9dc3e370967b44a2de0"}])})
|
||||
|
||||
(defn tokens-for [chain]
|
||||
(get all chain))
|
||||
|
|
|
@ -90,6 +90,32 @@
|
|||
(when-let [bn (bignumber n)]
|
||||
(.dividedBy bn (bignumber (from-decimal decimals)))))
|
||||
|
||||
(defn unit->token [n decimals]
|
||||
(when-let [bn (bignumber n)]
|
||||
(.times bn (bignumber (from-decimal decimals)))))
|
||||
|
||||
;;NOTE(goranjovic) - We have two basic representations of values that refer to cryptocurrency amounts: formatted and
|
||||
;; internal. Formatted representation is the one we show on screens and include in reports, whereas internal
|
||||
;; representation is the one that we pass on to ethereum network for execution, transfer, etc.
|
||||
;; The difference between the two depends on the number of decimals, i.e. internal representation is expressed in terms
|
||||
;; of a whole number of smallest divisible parts of the formatted value.
|
||||
;;
|
||||
;; E.g. for Ether, it's smallest part is wei or 10^(-18) of 1 ether
|
||||
;; for arbitrary ERC20 token the smallest part is 10^(-decimals) of 1 token
|
||||
;;
|
||||
;; Different tokens can have different number of allowed decimals, so it's neccessary to include the decimals parameter
|
||||
;; to get the amount scale right.
|
||||
|
||||
(defn formatted->internal [n symbol decimals]
|
||||
(if (= :ETH symbol)
|
||||
(ether->wei n)
|
||||
(unit->token n decimals)))
|
||||
|
||||
(defn internal->formatted [n symbol decimals]
|
||||
(if (= :ETH symbol)
|
||||
(wei->ether n)
|
||||
(token->unit n decimals)))
|
||||
|
||||
(defn fee-value [gas gas-price]
|
||||
(.times (bignumber gas) (bignumber gas-price)))
|
||||
|
||||
|
|
Loading…
Reference in New Issue