mirror of
https://github.com/status-im/status-mobile.git
synced 2025-01-27 17:06:18 +00:00
Move status-im.utils.money to utils.money (#16573)
This commit is contained in:
parent
645a5b312b
commit
88c4521321
@ -1,5 +1,5 @@
|
||||
(ns status-im.ethereum.decode
|
||||
(:require [status-im.utils.money :as money]))
|
||||
(:require [utils.money :as money]))
|
||||
|
||||
(defn uint
|
||||
[hex]
|
||||
|
@ -8,7 +8,7 @@
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.ens :as ens]
|
||||
[status-im.ethereum.tokens :as tokens]
|
||||
[status-im.utils.money :as money]))
|
||||
[utils.money :as money]))
|
||||
|
||||
(def scheme "ethereum")
|
||||
(def scheme-separator ":")
|
||||
|
@ -1,7 +1,7 @@
|
||||
(ns status-im.ethereum.eip681-test
|
||||
(:require [cljs.test :refer-macros [deftest is] :as test]
|
||||
[status-im.ethereum.eip681 :as eip681]
|
||||
[status-im.utils.money :as money]))
|
||||
[utils.money :as money]))
|
||||
|
||||
(deftest parse-uri
|
||||
(is (= nil (eip681/parse-uri nil)))
|
||||
|
@ -4,7 +4,7 @@
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.keycard.common :as common]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.utils.money :as money]
|
||||
[utils.money :as money]
|
||||
[status-im.utils.types :as types]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
@ -38,8 +38,8 @@
|
||||
{:db (assoc-in db [:signing/sign :keycard-step] :signing)}
|
||||
(common/set-on-card-connected :keycard/sign))
|
||||
|
||||
(pos? keycard-pin-retries) ; if 0, get-application-info will have already closed the connection
|
||||
; sheet and opened the frozen card popup
|
||||
(pos? keycard-pin-retries) ; if 0, get-application-info will have already closed the
|
||||
; connection sheet and opened the frozen card popup
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :card-read-in-progress?] true)
|
||||
(assoc-in [:keycard :pin :status] :verifying))
|
||||
|
@ -10,7 +10,7 @@
|
||||
[utils.i18n :as i18n]
|
||||
[status-im.notifications.android :as pn-android]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.utils.money :as money]
|
||||
[utils.money :as money]
|
||||
[status-im.utils.types :as types]
|
||||
[status-im.utils.utils :as utils]
|
||||
[react-native.core :as rn]))
|
||||
|
@ -14,7 +14,7 @@
|
||||
[status-im.signing.keycard :as signing.keycard]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.utils.hex :as utils.hex]
|
||||
[status-im.utils.money :as money]
|
||||
[utils.money :as money]
|
||||
[status-im.utils.types :as types]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.wallet.core :as wallet]
|
||||
@ -313,8 +313,8 @@
|
||||
{:events [:sign/send-transaction-message]}
|
||||
[cofx chat-id value contract transaction-hash signature]
|
||||
{:json-rpc/call [{:method "wakuext_sendTransaction"
|
||||
;; We make sure `value` is serialized as string, and not
|
||||
;; as an integer or big-int
|
||||
;; We make sure `value` is serialized as string, and not as an integer or
|
||||
;; big-int
|
||||
:params [chat-id (str value) contract transaction-hash
|
||||
(or (:result (types/json->clj signature))
|
||||
(ethereum/normalized-hex signature))]
|
||||
|
@ -7,7 +7,7 @@
|
||||
[status-im.popover.core :as popover]
|
||||
[status-im.signing.eip1559 :as eip1559]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.utils.money :as money]
|
||||
[utils.money :as money]
|
||||
[status-im2.common.json-rpc.events :as json-rpc]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
@ -336,7 +336,7 @@
|
||||
(let [sorted-v (sort-by
|
||||
identity
|
||||
(fn [a b]
|
||||
(status-im.utils.money/greater-than b a))
|
||||
(utils.money/greater-than b a))
|
||||
v)]
|
||||
(reduce
|
||||
(fn [acc p]
|
||||
|
@ -9,7 +9,7 @@
|
||||
[status-im.signing.gas :as gas]
|
||||
[status-im.ui.components.icons.icons :as icons]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.utils.money :as money]))
|
||||
[utils.money :as money]))
|
||||
|
||||
(views/defview fee-bottom-sheet
|
||||
[fee-display-symbol]
|
||||
|
@ -7,7 +7,7 @@
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.screens.stickers.styles :as styles]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.utils.money :as money])
|
||||
[utils.money :as money])
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
||||
|
||||
(defn cache
|
||||
|
@ -18,7 +18,7 @@
|
||||
[status-im.ui.screens.wallet.components.views :as components]
|
||||
[status-im.ui.screens.wallet.send.sheets :as sheets]
|
||||
[status-im.ui.screens.wallet.send.styles :as styles]
|
||||
[status-im.utils.money :as money]
|
||||
[utils.money :as money]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.wallet.utils :as wallet.utils]))
|
||||
|
||||
|
@ -1,223 +0,0 @@
|
||||
(ns status-im.utils.money
|
||||
(:require ["bignumber.js" :as BigNumber]
|
||||
[clojure.string :as string]))
|
||||
|
||||
;; The BigNumber version included in web3 sometimes hangs when dividing large
|
||||
;; numbers Hence we want to use these functions instead of fromWei etc, which
|
||||
;; come bundled with web3. See
|
||||
;; https://github.com/MikeMcl/bignumber.js/issues/120 for this regression being
|
||||
;; introduced in some JS environments. It is fixed in the MikeMcl/bignumber.js
|
||||
;; repo, but not in the web3 BigNumber fork:
|
||||
;; https://github.com/ethereum/web3.js/issues/877
|
||||
;;
|
||||
;; Additionally, while it is possible to use the BigNumber constructor without
|
||||
;; stringifying the number, this only works up to some 15 significant digits:
|
||||
;; https://github.com/MikeMcl/bignumber.js/issues/120
|
||||
;;
|
||||
;; Lastly, notice the bad rounding for native Javascript numbers above 17 digits
|
||||
;; that may result in errors earlier up the call chain. Ideally all money-related
|
||||
;; sensitive functions should be moved into this namespace to check for such
|
||||
;; matters:
|
||||
;; (str 111122223333441239) => "111122223333441230"
|
||||
|
||||
(defn normalize
|
||||
"A normalized string representation of an amount"
|
||||
[s]
|
||||
{:pre [(or (nil? s) (string? s))]}
|
||||
(when s
|
||||
(string/replace (string/trim s) #"," ".")))
|
||||
|
||||
(defn bignumber
|
||||
[n]
|
||||
(when n
|
||||
(try
|
||||
(new BigNumber (normalize (str n)))
|
||||
(catch :default _ nil))))
|
||||
|
||||
(defn greater-than-or-equals
|
||||
[^js bn1 ^js bn2]
|
||||
(.greaterThanOrEqualTo bn1 bn2))
|
||||
|
||||
(defn greater-than
|
||||
[bn1 bn2]
|
||||
(.greaterThan ^js bn1 bn2))
|
||||
|
||||
(defn equal-to
|
||||
[bn1 bn2]
|
||||
(.eq ^js bn1 bn2))
|
||||
|
||||
(defn sub
|
||||
[bn1 bn2]
|
||||
(.sub ^js bn1 bn2))
|
||||
|
||||
(defn valid?
|
||||
[^js bn]
|
||||
(when bn
|
||||
(greater-than-or-equals bn 0)))
|
||||
|
||||
(defn from-decimal
|
||||
[n]
|
||||
(when n
|
||||
(str "1" (string/join (repeat n "0")))))
|
||||
|
||||
(def eth-units
|
||||
{:wei (bignumber "1")
|
||||
:kwei (bignumber (from-decimal 3))
|
||||
:mwei (bignumber (from-decimal 6))
|
||||
:gwei (bignumber (from-decimal 9))
|
||||
:szabo (bignumber (from-decimal 12))
|
||||
:finney (bignumber (from-decimal 15))
|
||||
:eth (bignumber (from-decimal 18))
|
||||
:keth (bignumber (from-decimal 21))
|
||||
:meth (bignumber (from-decimal 24))
|
||||
:geth (bignumber (from-decimal 27))
|
||||
:teth (bignumber (from-decimal 30))})
|
||||
|
||||
(defn wei->
|
||||
[unit n]
|
||||
(when-let [^js bn (bignumber n)]
|
||||
(.dividedBy bn (eth-units unit))))
|
||||
|
||||
(defn ->wei
|
||||
[unit n]
|
||||
(when-let [^js bn (bignumber n)]
|
||||
(.times bn (eth-units unit))))
|
||||
|
||||
(defn to-fixed
|
||||
([^js bn]
|
||||
(when bn
|
||||
(.toFixed bn)))
|
||||
([^js bn b]
|
||||
(when bn
|
||||
(.toFixed bn b))))
|
||||
|
||||
(defn to-number
|
||||
[^js bn]
|
||||
(when bn
|
||||
(.toNumber bn)))
|
||||
|
||||
(defn to-string
|
||||
([^js bn]
|
||||
(to-string bn 10))
|
||||
([^js bn base]
|
||||
(when bn
|
||||
(.toString bn base))))
|
||||
|
||||
(defn to-hex
|
||||
[^js bn]
|
||||
(str "0x" (to-string bn 16)))
|
||||
|
||||
(defn wei->str
|
||||
([unit n display-unit]
|
||||
(str (to-fixed (wei-> unit n)) " " display-unit))
|
||||
([unit n] (wei->str unit n (string/upper-case (name unit)))))
|
||||
|
||||
(defn wei->ether
|
||||
[n]
|
||||
(wei-> :eth n))
|
||||
|
||||
(defn wei->gwei
|
||||
[n]
|
||||
(wei-> :gwei n))
|
||||
|
||||
(defn ether->wei
|
||||
[^js bn]
|
||||
(when bn
|
||||
(.times bn ^js (bignumber 1e18))))
|
||||
|
||||
(defn token->unit
|
||||
[n decimals]
|
||||
(when-let [^js bn (bignumber n)]
|
||||
(when-let [d (from-decimal decimals)]
|
||||
(.dividedBy bn ^js (bignumber d)))))
|
||||
|
||||
(defn unit->token
|
||||
[n decimals]
|
||||
(when-let [^js bn (bignumber n)]
|
||||
(when-let [d (from-decimal decimals)]
|
||||
(.times bn ^js (bignumber d)))))
|
||||
|
||||
;;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 ^js (bignumber gas) ^js (bignumber gas-price)))
|
||||
|
||||
(defn crypto->fiat
|
||||
[crypto fiat-price]
|
||||
(when-let [^js bn (bignumber crypto)]
|
||||
(.times bn ^js (bignumber fiat-price))))
|
||||
|
||||
(defn percent-change
|
||||
[from to]
|
||||
(let [^js bnf (bignumber from)
|
||||
^js bnt (bignumber to)]
|
||||
(when (and bnf bnt)
|
||||
(-> ^js (.dividedBy bnf bnt)
|
||||
^js (.minus 1)
|
||||
^js (.times 100)))))
|
||||
|
||||
(defn with-precision
|
||||
[n decimals]
|
||||
(when-let [^js bn (bignumber n)]
|
||||
(.round bn decimals)))
|
||||
|
||||
(defn sufficient-funds?
|
||||
[^js amount ^js balance]
|
||||
(when (and amount balance)
|
||||
(.greaterThanOrEqualTo balance amount)))
|
||||
|
||||
(defn fiat-amount-value
|
||||
[amount-str from to prices]
|
||||
(-> amount-str
|
||||
(js/parseFloat)
|
||||
bignumber
|
||||
(crypto->fiat (get-in prices [from to] ^js (bignumber 0)))
|
||||
(with-precision 2)
|
||||
str))
|
||||
|
||||
(defn add
|
||||
[bn1 n2]
|
||||
(.add ^js bn1 n2))
|
||||
|
||||
(defn mul
|
||||
[bn1 bn2]
|
||||
(.mul ^js bn1 bn2))
|
||||
|
||||
(defn mul-and-round
|
||||
[bn1 bn2]
|
||||
(.round (.mul ^js bn1 bn2) 0))
|
||||
|
||||
(defn div
|
||||
[bn1 bn2]
|
||||
(.dividedBy ^js bn1 bn2))
|
||||
|
||||
(defn div-and-round
|
||||
[bn1 bn2]
|
||||
(.round (.dividedBy ^js bn1 bn2) 0))
|
@ -1,23 +0,0 @@
|
||||
(ns status-im.utils.money-test
|
||||
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||
[status-im.utils.money :as money]))
|
||||
|
||||
(deftest wei->ether
|
||||
(testing "Numeric input, 15 significant digits"
|
||||
(is (= (str (money/wei->ether 111122223333444000))
|
||||
"0.111122223333444")))
|
||||
(testing "String input, 18 significant digits"
|
||||
(is (= (str (money/wei->ether "111122223333441239"))
|
||||
"0.111122223333441239"))))
|
||||
|
||||
(deftest valid?
|
||||
(is (not (true? (money/valid? nil))))
|
||||
(is (true? (money/valid? (money/bignumber 0))))
|
||||
(is (true? (money/valid? (money/bignumber 1))))
|
||||
(is (not (true? (money/valid? (money/bignumber -1))))))
|
||||
|
||||
(deftest normalize
|
||||
(is (= nil (money/normalize nil)))
|
||||
(is (= "1" (money/normalize " 1 ")))
|
||||
(is (= "1.1" (money/normalize "1.1")))
|
||||
(is (= "1.1" (money/normalize "1,1"))))
|
@ -10,7 +10,7 @@
|
||||
[status-im.router.core :as router]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.utils.http :as http]
|
||||
[status-im.utils.money :as money]
|
||||
[utils.money :as money]
|
||||
[status-im.utils.universal-links.utils :as links]
|
||||
[status-im.utils.wallet-connect :as wallet-connect]
|
||||
[status-im2.navigation.events :as navigation]))
|
||||
@ -118,8 +118,7 @@
|
||||
{:events [:wallet/parse-eip681-uri-and-resolve-ens]}
|
||||
[{db :db :as cofx} {:keys [message uri paths ens-names error]} ignore-url]
|
||||
(if-not error
|
||||
;; 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
|
||||
(if (empty? ens-names)
|
||||
;; if there are no ens-names, we dispatch request-uri-parsed immediately
|
||||
(request-uri-parsed cofx message uri)
|
||||
@ -130,8 +129,7 @@
|
||||
(fn [addresses]
|
||||
(re-frame/dispatch
|
||||
[:wallet/request-uri-parsed
|
||||
;; we replace 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
|
||||
|
@ -21,7 +21,7 @@
|
||||
[status-im.utils.core :as utils.core]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.datetime :as datetime]
|
||||
[status-im.utils.money :as money]
|
||||
[utils.money :as money]
|
||||
[status-im.utils.utils :as utils.utils]
|
||||
[status-im.wallet.db :as wallet.db]
|
||||
[status-im.wallet.prices :as prices]
|
||||
@ -247,8 +247,8 @@
|
||||
assets (get visible-tokens chain)
|
||||
tokens (->> (vals all-tokens)
|
||||
(remove #(or (:hidden? %)
|
||||
;;if not scan-all-tokens? remove not visible
|
||||
;;tokens
|
||||
;;if not scan-all-tokens? remove not
|
||||
;;visible tokens
|
||||
(and (not scan-all-tokens?)
|
||||
(not (get assets (:symbol %))))))
|
||||
(reduce (fn [acc {:keys [address symbol]}]
|
||||
@ -1141,8 +1141,7 @@
|
||||
eip55/address->checksum)
|
||||
type
|
||||
(update :type keyword))]
|
||||
;; if the account is the default wallet we
|
||||
;; put it first in the list
|
||||
;; if the account is the default wallet we put it first in the list
|
||||
(if wallet
|
||||
(into [account] acc)
|
||||
(conj acc account)))))
|
||||
|
@ -1,6 +1,6 @@
|
||||
(ns status-im.wallet.db
|
||||
(:require [utils.i18n :as i18n]
|
||||
[status-im.utils.money :as money]
|
||||
[utils.money :as money]
|
||||
[status-im.utils.priority-map :refer [empty-transaction-map]]))
|
||||
|
||||
(defn- too-precise-amount?
|
||||
|
@ -1,7 +1,7 @@
|
||||
(ns status-im.wallet.db-test
|
||||
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||
[utils.i18n :as i18n]
|
||||
[status-im.utils.money :as money]
|
||||
[utils.money :as money]
|
||||
[status-im.wallet.db :as wallet.db]))
|
||||
|
||||
(deftest test-too-precise-amount?
|
||||
|
@ -1,5 +1,5 @@
|
||||
(ns status-im.wallet.utils
|
||||
(:require [status-im.utils.money :as money]))
|
||||
(:require [utils.money :as money]))
|
||||
|
||||
(defn format-amount
|
||||
[amount decimals]
|
||||
|
@ -3,7 +3,7 @@
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.ens.core :as ens]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.utils.money :as money]))
|
||||
[utils.money :as money]))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:multiaccount/usernames
|
||||
|
@ -5,7 +5,7 @@
|
||||
[status-im.ethereum.tokens :as tokens]
|
||||
[utils.i18n :as i18n]
|
||||
[status-im.signing.gas :as signing.gas]
|
||||
[status-im.utils.money :as money]
|
||||
[utils.money :as money]
|
||||
[status-im.wallet.db :as wallet.db]))
|
||||
|
||||
(re-frame/reg-sub
|
||||
|
@ -4,7 +4,7 @@
|
||||
[utils.i18n :as i18n]
|
||||
[status-im.notifications.core :as notifications]
|
||||
[utils.datetime :as datetime]
|
||||
[status-im.utils.money :as money]
|
||||
[utils.money :as money]
|
||||
[status-im.wallet.db :as wallet.db]
|
||||
[status-im.wallet.utils :as wallet.utils]))
|
||||
|
||||
@ -69,11 +69,12 @@
|
||||
(reduce (fn [acc [hash transaction]]
|
||||
(assoc acc
|
||||
hash
|
||||
(enrich-transaction transaction contacts native-currency))) ;;TODO this doesn't look
|
||||
;;good for performance,
|
||||
;;we need to calculate
|
||||
;;this only once for each
|
||||
;;transaction
|
||||
(enrich-transaction transaction contacts native-currency))) ;;TODO this doesn't
|
||||
;;look good for
|
||||
;;performance, we
|
||||
;;need to calculate
|
||||
;;this only once for
|
||||
;;each transaction
|
||||
{}
|
||||
transactions)))
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.tokens :as tokens]
|
||||
[status-im.utils.currency :as currency]
|
||||
[status-im.utils.money :as money]
|
||||
[utils.money :as money]
|
||||
[status-im2.config :as config]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
(:require [cljs.test :refer [deftest is testing]]
|
||||
[re-frame.db :as rf-db]
|
||||
[test-helpers.unit :as h]
|
||||
[status-im.utils.money :as money]
|
||||
[utils.money :as money]
|
||||
[status-im2.subs.wallet.wallet :as wallet]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
|
@ -35,11 +35,194 @@
|
||||
(new BigNumber (normalize (str n)))
|
||||
(catch :default _ nil))))
|
||||
|
||||
(defn greater-than-or-equals
|
||||
[^js bn1 ^js bn2]
|
||||
(.greaterThanOrEqualTo bn1 bn2))
|
||||
|
||||
(defn greater-than
|
||||
[bn1 bn2]
|
||||
(.greaterThan ^js bn1 bn2))
|
||||
|
||||
(defn equal-to
|
||||
[bn1 bn2]
|
||||
(.eq ^js bn1 bn2))
|
||||
|
||||
(defn sub
|
||||
[bn1 bn2]
|
||||
(.sub ^js bn1 bn2))
|
||||
|
||||
(defn valid?
|
||||
[^js bn]
|
||||
(when bn
|
||||
(greater-than-or-equals bn 0)))
|
||||
|
||||
(defn from-decimal
|
||||
[n]
|
||||
(when n
|
||||
(str "1" (string/join (repeat n "0")))))
|
||||
|
||||
(def eth-units
|
||||
{:wei (bignumber "1")
|
||||
:kwei (bignumber (from-decimal 3))
|
||||
:mwei (bignumber (from-decimal 6))
|
||||
:gwei (bignumber (from-decimal 9))
|
||||
:szabo (bignumber (from-decimal 12))
|
||||
:finney (bignumber (from-decimal 15))
|
||||
:eth (bignumber (from-decimal 18))
|
||||
:keth (bignumber (from-decimal 21))
|
||||
:meth (bignumber (from-decimal 24))
|
||||
:geth (bignumber (from-decimal 27))
|
||||
:teth (bignumber (from-decimal 30))})
|
||||
|
||||
(defn wei->
|
||||
[unit n]
|
||||
(when-let [^js bn (bignumber n)]
|
||||
(.dividedBy bn (eth-units unit))))
|
||||
|
||||
(defn ->wei
|
||||
[unit n]
|
||||
(when-let [^js bn (bignumber n)]
|
||||
(.times bn (eth-units unit))))
|
||||
|
||||
(defn to-fixed
|
||||
([^js bn]
|
||||
(when bn
|
||||
(.toFixed bn)))
|
||||
([^js bn b]
|
||||
(when bn
|
||||
(.toFixed bn b))))
|
||||
|
||||
(defn to-number
|
||||
[^js bn]
|
||||
(when bn
|
||||
(.toNumber bn)))
|
||||
|
||||
(defn to-string
|
||||
([^js bn]
|
||||
(to-string bn 10))
|
||||
([^js bn base]
|
||||
(when bn
|
||||
(.toString bn base))))
|
||||
|
||||
(defn to-hex
|
||||
[^js bn]
|
||||
(str "0x" (to-string bn 16)))
|
||||
|
||||
(defn wei->str
|
||||
([unit n display-unit]
|
||||
(str (to-fixed (wei-> unit n)) " " display-unit))
|
||||
([unit n] (wei->str unit n (string/upper-case (name unit)))))
|
||||
|
||||
(defn wei->ether
|
||||
[n]
|
||||
(wei-> :eth n))
|
||||
|
||||
(defn wei->gwei
|
||||
[n]
|
||||
(wei-> :gwei n))
|
||||
|
||||
(defn ether->wei
|
||||
[^js bn]
|
||||
(when bn
|
||||
(.times bn ^js (bignumber 1e18))))
|
||||
|
||||
(defn token->unit
|
||||
[n decimals]
|
||||
(when-let [^js bn (bignumber n)]
|
||||
(when-let [d (from-decimal decimals)]
|
||||
(.dividedBy bn ^js (bignumber d)))))
|
||||
|
||||
(defn unit->token
|
||||
[n decimals]
|
||||
(when-let [^js bn (bignumber n)]
|
||||
(when-let [d (from-decimal decimals)]
|
||||
(.times bn ^js (bignumber d)))))
|
||||
|
||||
;;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 ^js (bignumber gas) ^js (bignumber gas-price)))
|
||||
|
||||
(defn crypto->fiat
|
||||
[crypto fiat-price]
|
||||
(when-let [^js bn (bignumber crypto)]
|
||||
(.times bn ^js (bignumber fiat-price))))
|
||||
|
||||
(defn percent-change
|
||||
[from to]
|
||||
(let [^js bnf (bignumber from)
|
||||
^js bnt (bignumber to)]
|
||||
(when (and bnf bnt)
|
||||
(-> ^js (.dividedBy bnf bnt)
|
||||
^js (.minus 1)
|
||||
^js (.times 100)))))
|
||||
|
||||
(defn with-precision
|
||||
[n decimals]
|
||||
(when-let [^js bn (bignumber n)]
|
||||
(.round bn decimals)))
|
||||
|
||||
(defn sufficient-funds?
|
||||
[^js amount ^js balance]
|
||||
(when (and amount balance)
|
||||
(.greaterThanOrEqualTo balance amount)))
|
||||
|
||||
(defn fiat-amount-value
|
||||
[amount-str from to prices]
|
||||
(-> amount-str
|
||||
(js/parseFloat)
|
||||
bignumber
|
||||
(crypto->fiat (get-in prices [from to] ^js (bignumber 0)))
|
||||
(with-precision 2)
|
||||
str))
|
||||
|
||||
(defn add
|
||||
[bn1 n2]
|
||||
(.add ^js bn1 n2))
|
||||
|
||||
(defn mul
|
||||
[bn1 bn2]
|
||||
(.mul ^js bn1 bn2))
|
||||
|
||||
(defn mul-and-round
|
||||
[bn1 bn2]
|
||||
(.round (.mul ^js bn1 bn2) 0))
|
||||
|
||||
(defn div
|
||||
[bn1 bn2]
|
||||
(.dividedBy ^js bn1 bn2))
|
||||
|
||||
(defn div-and-round
|
||||
[bn1 bn2]
|
||||
(.round (.dividedBy ^js bn1 bn2) 0))
|
||||
|
||||
(defn format-amount
|
||||
"Format `amount` to thousands or millions. Return nil if `amount` is not truthy."
|
||||
[amount]
|
||||
|
@ -1,7 +1,21 @@
|
||||
(ns utils.money-test
|
||||
(:require [cljs.test :refer-macros [deftest is are]]
|
||||
(:require [cljs.test :refer-macros [deftest testing is are]]
|
||||
[utils.money :as money]))
|
||||
|
||||
(deftest wei->ether
|
||||
(testing "Numeric input, 15 significant digits"
|
||||
(is (= (str (money/wei->ether 111122223333444000))
|
||||
"0.111122223333444")))
|
||||
(testing "String input, 18 significant digits"
|
||||
(is (= (str (money/wei->ether "111122223333441239"))
|
||||
"0.111122223333441239"))))
|
||||
|
||||
(deftest valid?
|
||||
(is (not (true? (money/valid? nil))))
|
||||
(is (true? (money/valid? (money/bignumber 0))))
|
||||
(is (true? (money/valid? (money/bignumber 1))))
|
||||
(is (not (true? (money/valid? (money/bignumber -1))))))
|
||||
|
||||
(deftest normalize
|
||||
(is (= nil (money/normalize nil)))
|
||||
(is (= "1" (money/normalize " 1 ")))
|
||||
|
Loading…
x
Reference in New Issue
Block a user