Enable EIP 1559

This commit is contained in:
Roman Volosovskyi 2021-08-20 16:41:25 +03:00
parent f76b400a7d
commit f5f47ae636
No known key found for this signature in database
GPG Key ID: 0238A4B5ECEE70DE
19 changed files with 413 additions and 194 deletions

2
.env
View File

@ -29,4 +29,4 @@ APN_TOPIC=im.status.ethereum.pr
COMMUNITIES_ENABLED=1
DATABASE_MANAGEMENT_ENABLED=1
METRICS_ENABLED=0
EIP1559_ENABLED=0
EIP1559_ENABLED=1

View File

@ -30,3 +30,4 @@ DATABASE_MANAGEMENT_ENABLED=1
COMMUNITIES_ENABLED=1
COMMUNITIES_MANAGEMENT_ENABLED=1
METRICS_ENABLED=0
EIP1559_ENABLED=1

View File

@ -30,3 +30,4 @@ DATABASE_MANAGEMENT_ENABLED=1
COMMUNITIES_ENABLED=1
COMMUNITIES_MANAGEMENT_ENABLED=1
METRICS_ENABLED=0
EIP1559_ENABLED=1

View File

@ -23,3 +23,4 @@ BLANK_PREVIEW=0
COMMUNITIES_ENABLED=1
DATABASE_MANAGEMENT_ENABLED=1
METRICS_ENABLED=0
EIP1559_ENABLED=1

View File

@ -19,3 +19,4 @@ ENABLE_ROOT_ALERT=1
MAX_IMAGES_BATCH=1
ENABLE_REFERRAL_INVITE=0
METRICS_ENABLED=0
EIP1559_ENABLED=1

View File

@ -406,7 +406,10 @@
:typed? typed?
:pinless? (= method constants/web3-keycard-sign-typed-data)
:from dapps-address}}
{:tx-obj (update (first params) :from #(or % dapps-address))})
{:tx-obj (-> params
first
(update :from #(or % dapps-address))
(dissoc :gasPrice))})
{:on-result [:browser.dapp/transaction-on-result message-id id]
:on-error [:browser.dapp/transaction-on-error message-id]}))))
(if (#{"eth_accounts" "eth_coinbase"} method)

View File

@ -28,6 +28,7 @@
"eth_newFilter" {:subscription? true}
"eth_getCode" {}
"eth_syncing" {}
"eth_feeHistory" {}
"net_version" {}
"web3_clientVersion" {}
"shh_generateSymKeyFromPassword" {}

View File

@ -50,7 +50,8 @@
(defn enrich-transfer
[chain-tokens
{:keys [address blockNumber timestamp from txStatus txHash gasPrice
gasUsed contract value gasLimit input nonce to type id]}]
gasUsed contract value gasLimit input nonce to type id
maxFeePerGas maxPriorityFeePerGas]}]
(let [erc20? (= type "erc20")
failed? (= txStatus "0x0")]
(merge {:address (eip55/address->checksum address)
@ -59,6 +60,8 @@
:timestamp (* (decode/uint timestamp) 1000)
:gas-used (str (decode/uint gasUsed))
:gas-price (str (decode/uint gasPrice))
:fee-cap (str (decode/uint maxFeePerGas))
:tip-cap (str (decode/uint maxPriorityFeePerGas))
:gas-limit (str (decode/uint gasLimit))
:nonce (str (decode/uint nonce))
:hash txHash

View File

@ -103,9 +103,11 @@
(when gasPrice
{:gasPrice (str "0x" (abi-spec/number-to-hex gasPrice))})
(when maxPriorityFeePerGas
{:maxPriorityFeePerGas (str "0x" (abi-spec/number-to-hex (.decimalPlaces maxPriorityFeePerGas 0)))})
{:maxPriorityFeePerGas (str "0x" (abi-spec/number-to-hex
(js/parseInt maxPriorityFeePerGas)))})
(when maxFeePerGas
{:maxFeePerGas (str "0x" (abi-spec/number-to-hex (.decimalPlaces maxFeePerGas 0)))}))]
{:maxFeePerGas (str "0x" (abi-spec/number-to-hex
(js/parseInt maxFeePerGas)))}))]
(when-not in-progress?
{:db (update db :signing/sign assoc :error nil :in-progress? true)
:signing/send-transaction-fx {:tx-obj tx-obj-to-send
@ -113,7 +115,8 @@
:cb #(re-frame/dispatch [:signing/transaction-completed % tx-obj-to-send hashed-password])}})))))
(fx/defn prepare-unconfirmed-transaction
[{:keys [db now]} new-tx-hash {:keys [value gasPrice gas data to from hash]} symbol amount]
[{:keys [db now]} new-tx-hash
{:keys [value gasPrice maxFeePerGas maxPriorityFeePerGas gas data to from hash]} symbol amount]
(let [token (tokens/symbol->token (:wallet/all-tokens db) symbol)
from (eip55/address->checksum from)
;;if there is a hash in the tx object that means we resending transaction
@ -132,6 +135,8 @@
(money/to-fixed (money/unit->token amount (:decimals token)))
(money/to-fixed (money/bignumber value)))
:gas-price gas-price
:fee-cap maxFeePerGas
:tip-cap maxPriorityFeePerGas
:gas-limit gas-limit}]
(log/info "[signing] prepare-unconfirmed-transaction" tx)
{:db (-> db
@ -246,15 +251,25 @@
(prices/update-prices)
#(when-not gas
{:db (assoc-in (:db %) [:signing/edit-fee :gas-loading?] true)
:signing/update-estimated-gas {:obj (dissoc tx-obj :gasPrice)
:signing/update-estimated-gas {:obj (-> tx-obj
(dissoc :gasPrice)
(update :maxFeePerGas
(fn [fee]
(some-> fee
money/bignumber
(money/mul 2)
money/to-hex))))
:success-event :signing/update-estimated-gas-success
:error-event :signing/update-estimated-gas-error}})
#(when-not (or maxFeePerGas gasPrice)
{:db (assoc-in (:db %) [:signing/edit-fee :gas-price-loading?] true)
:signing/update-gas-price {:success-event :signing/update-gas-price-success
:error-event :signing/update-gas-price-error
:network-id (get-in (ethereum/current-network db)
[:config :NetworkId])}})))))
(fn [cofx]
(when-not (or maxFeePerGas gasPrice)
{:db (assoc-in (:db cofx) [:signing/edit-fee :gas-price-loading?] true)
:signing/update-gas-price
{:success-callback #(re-frame/dispatch
[:wallet.send/update-gas-price-success :signing/tx %])
:error-callback #(re-frame/dispatch [:signing/update-gas-price-error %])
:network-id (get-in (ethereum/current-network db)
[:config :NetworkId])}}))))))
(fx/defn check-queue [{:keys [db] :as cofx}]
(let [{:signing/keys [tx queue]} db]
@ -436,7 +451,7 @@
to-norm (ethereum/normalized-hex (if (string? to) to (:address to)))
from-address (:address from)
identity (:current-chat-id db)
db (dissoc db :wallet/prepare-transaction)]
db (dissoc db :wallet/prepare-transaction :signing/edit-fee)]
(if to-norm
(fx/merge
cofx
@ -474,7 +489,7 @@
to-norm (:address request-parameters)
from-address (:address from)]
(fx/merge cofx
{:db (dissoc db :wallet/prepare-transaction)}
{:db (dissoc db :wallet/prepare-transaction :signing/edit-fee)}
(fn [cofx]
(sign
cofx
@ -502,7 +517,7 @@
to-norm (ethereum/normalized-hex (if (string? to) to (:address to)))
from-address (:address from)]
(fx/merge cofx
{:db (dissoc db :wallet/prepare-transaction)}
{:db (dissoc db :wallet/prepare-transaction :signing/edit-fee)}
(sign
{:tx-obj (merge (if (eip1559/sync-enabled?)
{:from from-address

View File

@ -34,11 +34,10 @@
:on-error #(callback nil)}))
(defn sync-enabled? []
(and config/eip1559-enabled?
@activated-on-current-network?))
config/eip1559-enabled?)
(defn enabled? [network-id enabled-callback disabled-callback]
(let [london-activated? (get @activated? network-id)]
(let [london-activated? true]
(cond
(not config/eip1559-enabled?)
(disabled-callback)

View File

@ -62,17 +62,36 @@
(assoc key data)
edit-max-fee)))
(def minimum-priority-fee
(money/wei-> :gwei (money/->wei :gwei 1)))
;; TODO(rasom): this number is almost arbitrary, I was able to sent txs with
;; 0.2 gwei tip, so it should be revisited lately
(def minimum-priority-fee-gwei
(money/bignumber 0.3))
(defn get-suggested-tip [latest-priority-fee]
(money/bignumber latest-priority-fee))
(defn get-minimum-priority-fee [latest-priority-fee]
(let [latest-priority-fee-bn (money/bignumber latest-priority-fee)
suggested-tip-gwei (money/wei->gwei (get-suggested-tip latest-priority-fee-bn))]
(if (money/greater-than minimum-priority-fee-gwei suggested-tip-gwei)
(money/div suggested-tip-gwei 2)
minimum-priority-fee-gwei)))
(defn get-suggestions-range [latest-priority-fee]
(let [current-minimum-fee (get-minimum-priority-fee latest-priority-fee)]
[(if (money/greater-than minimum-priority-fee-gwei current-minimum-fee)
current-minimum-fee
minimum-priority-fee-gwei)
(money/wei->gwei (money/bignumber latest-priority-fee))]))
(def average-priority-fee
(money/wei-> :gwei (money/->wei :gwei 1.5)))
(money/wei->gwei (money/->wei :gwei 1.5)))
(defn validate-max-fee [db]
(let [{:keys [maxFeePerGas maxPriorityFeePerGas]} (get db :signing/edit-fee)
latest-base-fee (money/wei-> :gwei
(money/bignumber
(get db :wallet/latest-base-fee)))
latest-base-fee (money/wei->gwei
(money/bignumber
(get db :wallet/current-base-fee)))
fee-error (cond
(or (:error maxFeePerGas)
(:error maxPriorityFeePerGas))
@ -81,12 +100,6 @@
(money/greater-than latest-base-fee
(:value-number maxFeePerGas))
{:label (i18n/label :t/below-base-fee)
:severity :error}
(money/greater-than (:value-number maxPriorityFeePerGas)
(money/sub (:value-number maxFeePerGas)
latest-base-fee))
{:label (i18n/label :t/reduced-tip)
:severity :error})]
(if fee-error
(assoc-in db [:signing/edit-fee :maxFeePerGas :fee-error] fee-error)
@ -94,19 +107,22 @@
(defn validate-max-priority-fee [db]
(let [{:keys [maxPriorityFeePerGas]} (get db :signing/edit-fee)
latest-priority-fee (get db :wallet/current-priority-fee)
fee-error (cond
(:error maxPriorityFeePerGas)
nil
(money/greater-than minimum-priority-fee
(money/greater-than (get-minimum-priority-fee
(money/div
(money/wei->gwei (money/bignumber latest-priority-fee)) 2))
(:value-number maxPriorityFeePerGas))
{:label (i18n/label :t/low-tip)
:severity :error}
(money/greater-than average-priority-fee
(:value-number maxPriorityFeePerGas))
{:label (i18n/label :t/lower-than-average-tip)
:severity :error})]
#_(money/greater-than average-priority-fee
(:value-number maxPriorityFeePerGas))
#_{:label (i18n/label :t/lower-than-average-tip)
:severity :error})]
(if fee-error
(assoc-in db [:signing/edit-fee :maxPriorityFeePerGas :fee-error] fee-error)
(update-in db [:signing/edit-fee :maxPriorityFeePerGas] dissoc :fee-error))))
@ -125,20 +141,54 @@
{:events [:signing.edit-fee.ui/edit-value]}
[{:keys [db]} key value]
{:db (-> db
(assoc-in [:signing/edit-fee :selected-fee-option] :custom)
(update :signing/edit-fee build-edit key value)
validate-eip1559-fees)})
(defn get-fee-options [tip slow normal fast]
(let [tip-bn (money/bignumber tip)
normal-bn (money/bignumber normal)
slow-bn (money/bignumber slow)
fast-bn (money/bignumber fast)]
{:normal
{:base-fee normal-bn
:tip tip-bn
:fee (money/add normal-bn tip-bn)}
:slow
{:base-fee slow-bn
:tip tip-bn
:fee (money/add slow-bn tip-bn)}
:fast
{:base-fee fast-bn
:tip tip-bn
:fee (money/add fast-bn tip-bn)}}))
(fx/defn set-fee-option
{:events [:signing.edit-fee.ui/set-option]}
[{:keys [db] :as cofx} option]
(let [tip (get db :wallet/current-priority-fee)
slow (get db :wallet/slow-base-fee)
normal (get db :wallet/normal-base-fee)
fast (get db :wallet/fast-base-fee)
{:keys [fee tip]} (get (get-fee-options tip slow normal fast) option)]
{:db (-> db
(assoc-in [:signing/edit-fee :selected-fee-option] option)
(update :signing/edit-fee
build-edit :maxFeePerGas (money/wei->gwei fee))
(update :signing/edit-fee
build-edit :maxPriorityFeePerGas (money/wei->gwei tip)))}))
(fx/defn set-priority-fee
{:events [:signing.edit-fee.ui/set-priority-fee]}
[{:keys [db]} value]
(let [{:keys [maxFeePerGas maxPriorityFeePerGas]}
(get db :signing/edit-fee)
latest-base-fee (get db :wallet/latest-base-fee)
latest-base-fee (get db :wallet/current-base-fee)
max-fee-value (:value-number maxFeePerGas)
max-priority-fee-value (:value-number maxPriorityFeePerGas)
new-value (money/bignumber value)
fee-without-tip (money/sub max-fee-value max-priority-fee-value)
base-fee (money/wei-> :gwei (money/bignumber latest-base-fee))
base-fee (money/wei->gwei (money/bignumber latest-base-fee))
new-max-fee-value
(money/to-fixed
(if (money/greater-than base-fee fee-without-tip)
@ -159,9 +209,21 @@
(fx/defn update-gas-price-success
{:events [:signing/update-gas-price-success]}
[{db :db} price]
{:db (-> db
(assoc-in [:signing/tx :gasPrice] price)
(assoc-in [:signing/edit-fee :gas-price-loading?] false))})
(if (eip1559/sync-enabled?)
(let [{:keys [normal-base-fee max-priority-fee]} price
max-priority-fee-bn (money/with-precision
(get-suggested-tip max-priority-fee)
0)]
{:db (-> db
(assoc-in [:signing/tx :maxFeePerGas]
(money/to-hex (money/add max-priority-fee-bn
(money/bignumber normal-base-fee))))
(assoc-in [:signing/tx :maxPriorityFeePerGas]
(money/to-hex max-priority-fee-bn))
(assoc-in [:signing/edit-fee :gas-price-loading?] false))})
{:db (-> db
(assoc-in [:signing/tx :gasPrice] price)
(assoc-in [:signing/edit-fee :gas-price-loading?] false))}))
(fx/defn update-estimated-gas-error
{:events [:signing/update-estimated-gas-error]}
@ -179,12 +241,12 @@
{:events [:signing.ui/open-fee-sheet]}
[{{:signing/keys [tx] :as db} :db :as cofx} sheet-opts]
(let [{:keys [gas gasPrice maxFeePerGas maxPriorityFeePerGas]} tx
max-fee (money/to-fixed (money/wei-> :gwei maxFeePerGas))
max-priority-fee (money/to-fixed (money/wei-> :gwei maxPriorityFeePerGas))
max-fee (money/to-fixed (money/wei->gwei maxFeePerGas))
max-priority-fee (money/to-fixed (money/wei->gwei maxPriorityFeePerGas))
edit-fee (reduce (partial apply build-edit)
{}
{:selected-fee-option (get-in db [:signing/edit-fee :selected-fee-option])}
{:gas (money/to-fixed gas)
:gasPrice (money/to-fixed (money/wei-> :gwei gasPrice))
:gasPrice (money/to-fixed (money/wei->gwei gasPrice))
:maxFeePerGas max-fee
:maxPriorityFeePerGas max-priority-fee})]
(fx/merge cofx
@ -214,57 +276,100 @@
(re-frame/reg-fx
:signing/update-gas-price
(fn [{:keys [success-event error-event network-id] :as params}]
(fn [{:keys [success-callback error-callback network-id] :as params}]
(eip1559/enabled?
network-id
(fn []
(json-rpc/call
{:method "eth_getBlockByNumber"
:params ["latest" false]
{:method "eth_feeHistory"
:params [101 "latest" nil]
:on-success #(re-frame/dispatch [::header-fetched
(assoc params :header %)])
:on-error #(re-frame/dispatch [error-event %])}))
(assoc params :fee-history %)])}))
(fn []
(json-rpc/call
{:method "eth_gasPrice"
:on-success #(re-frame/dispatch [success-event %])
:on-error #(re-frame/dispatch [error-event %])})))))
(fx/defn header-fetched
{:events [::header-fetched]}
[_ {:keys [error-event] :as params}]
{::json-rpc/call
[{:method "eth_maxPriorityFeePerGas"
:on-success #(re-frame/dispatch [::max-priority-fee-per-gas-fetched
(assoc params :max-priority-fee %)])
:on-error (if error-event
#(re-frame/dispatch [error-event %])
#(log/error "Can't fetch header" %))}]})
:on-success #(success-callback %)
:on-error #(error-callback %)})))))
(def london-block-gas-limit (money/bignumber 30000000))
(defn check-base-fee [{:keys [gasUsed baseFeePerGas]}]
{:base-fee baseFeePerGas
:spike? (or (money/greater-than-or-equals
(money/bignumber 0)
(money/bignumber gasUsed))
(money/greater-than-or-equals
(money/bignumber gasUsed)
(money/bignumber london-block-gas-limit)))})
(defn calc-percentiles [v ps]
(let [sorted-v (sort-by
identity
(fn [a b]
(status-im.utils.money/greater-than b a))
v)]
(reduce
(fn [acc p]
(assoc acc p (nth sorted-v p)))
{}
ps)))
(fx/defn max-priority-fee-per-gas-fetched
{:events [::max-priority-fee-per-gas-fetched]}
[_ {:keys [success-event header max-priority-fee]}]
(let [{:keys [base-fee spike?]} (check-base-fee header)]
{:dispatch [success-event {:base-fee base-fee
:max-priority-fee max-priority-fee
:spike? spike?}]}))
;; It is very unlikely to be that small on mainnet, but on testnets current base
;; fee might be very small and using this value might slow transaction
(def minimum-base-fee (money/->wei :gwei (money/bignumber 1)))
(defn recommended-base-fee [current perc20 perc80]
(let [fee
(cond (and (money/greater-than-or-equals current perc20)
(money/greater-than-or-equals perc80 current))
current
(money/greater-than perc20 current)
perc20
:else
perc80)]
(if (money/greater-than minimum-base-fee fee)
minimum-base-fee
fee)))
(defn slow-base-fee [_ perc10] perc10)
(defn fast-base-fee [current _]
(let [fee (money/mul current 2)]
(if (money/greater-than minimum-base-fee fee)
(money/mul minimum-base-fee 2)
fee)))
(defn check-base-fee [{:keys [baseFeePerGas]}]
(let [all-base-fees (mapv money/bignumber baseFeePerGas)
current-base-fee (last all-base-fees)
previous-fees (subvec all-base-fees 0 101)
percentiles (calc-percentiles previous-fees [10 20 80])]
{:normal-base-fee (money/to-hex
(recommended-base-fee
current-base-fee
(get percentiles 20)
(get percentiles 80)))
:slow-base-fee (money/to-hex
(slow-base-fee
current-base-fee
(get percentiles 10)))
:fast-base-fee (money/to-hex
(fast-base-fee
current-base-fee
(get percentiles 80)))
:current-base-fee (money/to-hex current-base-fee)}))
(fx/defn header-fetched
{:events [::header-fetched]}
[_ {:keys [error-callback success-callback fee-history] :as params}]
{::json-rpc/call
[{:method "eth_maxPriorityFeePerGas"
:on-success #(success-callback (merge {:max-priority-fee %}
(check-base-fee fee-history)))
:on-error (if error-callback
#(error-callback %)
#(log/error "Can't fetch header" %))}]})
(re-frame/reg-fx
:signing/update-estimated-gas
(fn [{:keys [obj success-event error-event]}]
(json-rpc/call
{:method "eth_estimateGas"
:params [obj]
:on-success #(re-frame/dispatch [success-event %])
:on-error #(re-frame/dispatch [error-event %])})))
(if (nil? (:data obj))
(re-frame/dispatch [success-event (money/bignumber 21000)])
(json-rpc/call
{:method "eth_estimateGas"
:params [obj]
:on-success #(re-frame/dispatch [success-event %])
:on-error #(re-frame/dispatch [error-event %])}))))

View File

@ -25,16 +25,26 @@
(status/hash-typed-data data on-completed))))
(defn prepare-transaction
[{:keys [gas gasPrice data nonce tx-obj]}]
(let [{:keys [from to value chat-id message-id command?]} tx-obj]
[{:keys [gas gasPrice data nonce tx-obj] :as params}]
(let [{:keys [from to value chat-id message-id command? maxPriorityFeePerGas maxFeePerGas]} tx-obj
maxPriorityFeePerGas (or maxPriorityFeePerGas (get params :maxPriorityFeePerGas))
maxFeePerGas (or maxFeePerGas (get params :maxFeePerGas))]
(cond-> {:from from
:to to
:value value
:gas (str "0x" (abi-spec/number-to-hex gas))
:gasPrice (str "0x" (abi-spec/number-to-hex gasPrice))
:chat-id chat-id
:message-id message-id
:command? command?}
maxPriorityFeePerGas
(assoc :maxPriorityFeePerGas (str "0x" (abi-spec/number-to-hex
(js/parseInt maxPriorityFeePerGas))))
maxFeePerGas
(assoc :maxFeePerGas (str "0x" (abi-spec/number-to-hex
(js/parseInt maxFeePerGas))))
gas
(assoc :gas (str "0x" (abi-spec/number-to-hex gas)))
gasPrice
(assoc :gasPrice (str "0x" (abi-spec/number-to-hex gasPrice)))
data
(assoc :data data)
nonce
@ -93,7 +103,7 @@
(fx/defn sign-with-keycard
{:events [:signing.ui/sign-with-keycard-pressed]}
[{:keys [db] :as cofx}]
(let [message (get-in db [:signing/tx :message])]
(let [{:keys [message maxPriorityFeePerGas maxFeePerGas]} (get db :signing/tx)]
(fx/merge
cofx
{:db (-> db

View File

@ -165,8 +165,11 @@
(reg-root-key-sub :wallet/refreshing-history? :wallet/refreshing-history?)
(reg-root-key-sub :wallet/fetching-error :wallet/fetching-error)
(reg-root-key-sub :wallet/non-archival-node :wallet/non-archival-node)
(reg-root-key-sub :wallet/latest-base-fee :wallet/latest-base-fee)
(reg-root-key-sub :wallet/latest-priority-fee :wallet/latest-priority-fee)
(reg-root-key-sub :wallet/current-base-fee :wallet/current-base-fee)
(reg-root-key-sub :wallet/slow-base-fee :wallet/slow-base-fee)
(reg-root-key-sub :wallet/normal-base-fee :wallet/normal-base-fee)
(reg-root-key-sub :wallet/fast-base-fee :wallet/fast-base-fee)
(reg-root-key-sub :wallet/current-priority-fee :wallet/current-priority-fee)
(reg-root-key-sub :wallet/transactions-management-enabled? :wallet/transactions-management-enabled?)
;;commands
(reg-root-key-sub :commands/select-account :commands/select-account)
@ -2005,7 +2008,7 @@
(re-frame/subscribe [:ethereum/native-currency])
(re-frame/subscribe [:ethereum/chain-keyword])])
(fn [[transactions native-currency chain-keyword] [_ hash _]]
(let [{:keys [gas-used gas-price hash timestamp type]
(let [{:keys [gas-used gas-price fee-cap tip-cap hash timestamp type]
:as transaction}
(get transactions hash)
native-currency-text (name (or (:symbol-display native-currency)
@ -2021,6 +2024,14 @@
(money/wei->str :gwei
gas-price)
"-")
:fee-cap-gwei (if fee-cap
(money/wei->str :gwei
fee-cap)
"-")
:tip-cap-gwei (if tip-cap
(money/wei->str :gwei
tip-cap)
"-")
:date (datetime/timestamp->long-date timestamp)}
(if (= type :unsigned)
{:block (i18n/label :not-applicable)
@ -2587,14 +2598,22 @@
(re-frame/reg-sub
:signing/priority-fee-suggestions-range
:<- [:wallet/latest-priority-fee]
(fn [latest-fee]
[0 (->> latest-fee
money/bignumber
(money/wei-> :gwei)
(money/mul (money/bignumber 2))
money/to-fixed
js/parseFloat)]))
:<- [:wallet/current-priority-fee]
:<- [:wallet/slow-base-fee]
:<- [:wallet/normal-base-fee]
:<- [:wallet/fast-base-fee]
(fn [[latest-tip slow normal fast]]
(reduce
(fn [acc [k fees]]
(assoc acc k (reduce
(fn [acc [k fee]]
(assoc acc k (-> fee
money/wei->gwei
(money/to-fixed 2))))
{}
fees)))
{}
(signing.gas/get-fee-options latest-tip slow normal fast))))
(re-frame/reg-sub
:signing/phrase

View File

@ -6,7 +6,6 @@
[quo.core :as quo]
[quo.design-system.colors :as quo-colors]
[status-im.ui.components.colors :as colors]
[status-im.ui.components.slider :as slider]
[status-im.utils.money :as money]
[status-im.ui.components.icons.icons :as icons]
[clojure.string :as clojure.string]
@ -69,12 +68,15 @@
(declare fee-bottom-sheet-eip1559)
(defn fee-bottom-sheet-eip1559-custom [fee-display-symbol]
(defn fee-bottom-sheet-eip1559-custom [_ #_fee-display-symbol]
(let [{gas-edit :gas
max-fee-per-gas-edit :maxFeePerGas
max-priority-fee-per-gas-edit :maxPriorityFeePerGas}
@(re-frame/subscribe [:signing/edit-fee])
base-fee @(re-frame/subscribe [:wallet/latest-base-fee])
error? (some :error [gas-edit
max-fee-per-gas-edit
max-priority-fee-per-gas-edit])
base-fee @(re-frame/subscribe [:wallet/current-base-fee])
[fee-currency fiat-currency price]
@(re-frame/subscribe [:signing/currencies])
fee-eth
@ -123,7 +125,7 @@
{:label (i18n/label :t/per-gas-tip-limit)
:error (or (:error max-priority-fee-per-gas-edit)
(get-in max-priority-fee-per-gas-edit [:fee-error :label]))
:default-value (:value max-priority-fee-per-gas-edit)
:default-value (str (:value max-priority-fee-per-gas-edit))
:on-change-text #(re-frame/dispatch [:signing.edit-fee.ui/edit-value :maxPriorityFeePerGas %])
:show-cancel false
:after {:component [quo/text
@ -137,7 +139,7 @@
{:label (i18n/label :t/per-gas-price-limit)
:error (or (:error max-fee-per-gas-edit)
(get-in max-fee-per-gas-edit [:fee-error :label]))
:default-value (:value max-fee-per-gas-edit)
:default-value (str (:value max-fee-per-gas-edit))
:on-change-text #(re-frame/dispatch [:signing.edit-fee.ui/edit-value :maxFeePerGas %])
:show-cancel false
:after {:component [quo/text
@ -176,66 +178,75 @@
:justify-content :space-between}}
[quo/button
{:type :secondary
:on-press #(re-frame/dispatch
[:bottom-sheet/show-sheet
{:content (fn []
[fee-bottom-sheet-eip1559 fee-display-symbol])
:content-height 270}])}
(i18n/label :t/see-suggestions)]
:accessibility-label :see-fee-suggestions
;;:on-press
#_(re-frame/dispatch
[:bottom-sheet/show-sheet
{:content (fn []
[fee-bottom-sheet-eip1559 fee-display-symbol])
:content-height 270}])}
"" #_(i18n/label :t/see-suggestions)]
[quo/button
{:type :primary
{:type :primary
:disabled error?
:on-press #(re-frame/dispatch [:signing.edit-fee.ui/submit])
:theme :accent}
:theme :accent}
(i18n/label :t/save)]]]))
(defn fee-bottom-sheet-eip1559 [fee-display-symbol]
(let [{priority-fee-edit :maxPriorityFeePerGas
fee-edit :maxFeePerGas
gas :gas}
option :selected-fee-option
fee-edit :maxFeePerGas}
@(re-frame/subscribe [:signing/edit-fee])
[min-value max-value]
@(re-frame/subscribe [:signing/priority-fee-suggestions-range])
[fee-currency fiat-currency price] @(re-frame/subscribe [:signing/currencies])
fee-eth
(if (and (:value-number gas)
(:value-number fee-edit))
(money/mul
(money/wei->ether
(money/->wei :gwei (:value-number fee-edit)))
(:value-number gas))
(money/bignumber 0))]
{:keys [normal fast slow]}
@(re-frame/subscribe [:signing/priority-fee-suggestions-range])]
[react/view
[react/view {:style {:margin-horizontal 16 :margin-top 8}}
[react/text {:style {:typography :title-bold}} (i18n/label :t/max-priority-fee)]
[react/text {:style {:color (quo-colors/get-color :text-02)
:margin-top 12}}
(i18n/label :t/miners-higher-fee)]
[quo/text {:style {:margin-horizontal 8
:margin-top 24}
:size :large}
[react/text {:style {:typography :title-bold}} (i18n/label :t/fee-options)]
[react/text {:style {:margin-top 12}
:accessibility-label :slow-fee
:on-press #(re-frame/dispatch [:signing.edit-fee.ui/set-option :slow])}
(clojure.string/join
" "
[(money/to-fixed fee-eth 6)
fee-currency
"•"
(money/to-fixed (money/mul fee-eth (money/bignumber (or price 0))) 2)
fiat-currency])]
[slider/animated-slider
{:style {:margin-horizontal 5
:margin-vertical 4}
:minimumValue min-value
:value (js/parseFloat (:value priority-fee-edit))
:onValueChange #(re-frame/dispatch [:signing.edit-fee.ui/set-priority-fee (str %)])
:maximumValue max-value
:minimumTrackTintColor (quo-colors/get-color :icon-04)}]
[react/view
{:style {:margin-horizontal 8
:flex-direction :row
:align-items :center
:justify-content :space-between}}
[react/text {:style {:color (quo-colors/get-color :text-02)}} (i18n/label :t/slow)]
[react/text {:style {:color (quo-colors/get-color :text-02)}} (i18n/label :t/optimal)]
[react/text {:style {:color (quo-colors/get-color :text-02)}} (i18n/label :t/fast)]]]
[(str (i18n/label :t/slow) ":")
(str (:base-fee slow) " gwei")
(str (:tip slow) " gwei")
(when (= :slow option)
"<- selected")])]
[react/text {:style {:margin-top 12}
:accessibility-label :normal-fee
:on-press #(re-frame/dispatch [:signing.edit-fee.ui/set-option :normal])}
(clojure.string/join
" "
[(str (i18n/label :t/normal) ":")
(str (:base-fee normal) " gwei")
(str (:tip normal) " gwei")
(when (or (nil? option)
(= :normal option))
"<- selected")])]
[react/text {:style {:margin-top 12}
:accessibility-label :fast-fee
:on-press #(re-frame/dispatch [:signing.edit-fee.ui/set-option :fast])}
(clojure.string/join
" "
[(str (i18n/label :t/fast) ":")
(str (:base-fee fast) " gwei")
(str (:tip fast) " gwei")
(when (= :fast option)
"<- selected")])]
(when (= :custom option)
[react/text {:style {:margin-top 12}}
(clojure.string/join
" "
[(str (i18n/label :t/custom) ":")
(str (-> fee-edit
:value-number
(money/to-fixed 2)) " gwei")
(str (-> priority-fee-edit
:value-number
(money/to-fixed 2)) " gwei")
(when (= :custom option)
"<- selected")])])]
[react/view
{:style {:margin-left 12
:margin-right 16
@ -245,6 +256,7 @@
:justify-content :space-between}
[quo/button
{:type :secondary
:accessibility-label :set-custom-fee
:on-press #(re-frame/dispatch
[:bottom-sheet/show-sheet
{:content (fn []
@ -253,17 +265,18 @@
(i18n/label :t/set-custom-fee)]
[quo/button
{:type :primary
:accessibility-label :save-custom-fee
:theme :accent
:on-press #(re-frame/dispatch [:signing.edit-fee.ui/submit])}
(i18n/label :t/save)]]]))
(defn gwei [val]
(str val " " (i18n/label :t/gwei)))
(str (money/to-fixed val 2) " " (i18n/label :t/gwei)))
(defn fees-warning []
(let [base-fee @(re-frame/subscribe [:wallet/latest-base-fee])
(let [base-fee @(re-frame/subscribe [:wallet/current-base-fee])
base-fee-gwei (money/wei-> :gwei (money/bignumber base-fee))
priority-fee @(re-frame/subscribe [:wallet/latest-priority-fee])
priority-fee @(re-frame/subscribe [:wallet/current-priority-fee])
priority-fee-gwei (money/wei-> :gwei (money/bignumber priority-fee))
{priority-fee-edit :maxPriorityFeePerGas
fee-edit :maxFeePerGas}
@ -293,19 +306,21 @@
:justify-content :space-between
:margin-horizontal 32}}
[react/text (i18n/label :t/current-base-fee)]
[react/text (gwei (money/to-fixed base-fee-gwei 2))]]
[react/text (gwei base-fee-gwei)]]
[react/view
{:style {:flex-direction :row
:justify-content :space-between
:margin-horizontal 32}}
[react/text (i18n/label :t/current-minimum-tip)]
[react/text (gwei gas/minimum-priority-fee)]]
[react/view
{:style {:flex-direction :row
:justify-content :space-between
:margin-horizontal 32}}
[react/text (i18n/label :t/current-average-tip)]
[react/text (gwei (money/to-fixed priority-fee-gwei 2))]]
[react/text (gwei (gas/get-minimum-priority-fee priority-fee))]]
;;TODO(rasom): we can uncomment it once it will be clear which value can be
;;used as "average" here
#_[react/view
{:style {:flex-direction :row
:justify-content :space-between
:margin-horizontal 32}}
[react/text (i18n/label :t/current-average-tip)]
[react/text (gwei (money/to-fixed priority-fee-gwei 2))]]
[react/view {:margin-vertical 16
:height 1
:background-color colors/gray-lighter}]
@ -317,7 +332,7 @@
[react/text {:style {:color (quo-colors/get-color :negative-01)}}
(i18n/label :t/your-tip-limit)]
[react/text {:style {:color (quo-colors/get-color :negative-01)}}
(gwei (money/to-fixed (:value-number priority-fee-edit) 2))]]
(gwei (:value-number priority-fee-edit))]]
[react/view
{:style {:flex-direction :row
:justify-content :space-between
@ -325,7 +340,7 @@
[react/text {:style {:color (quo-colors/get-color :negative-01)}}
(i18n/label :t/your-price-limit)]
[react/text {:style {:color (quo-colors/get-color :negative-01)}}
(gwei (money/to-fixed (:value-number fee-edit) 2))]]
(gwei (:value-number fee-edit))]]
[react/view {:style
{:background-color colors/gray-lighter
:padding-horizontal 32
@ -335,12 +350,12 @@
{:style {:flex-direction :row
:justify-content :space-between}}
[react/text (i18n/label :t/suggested-min-tip)]
[react/text (gwei gas/minimum-priority-fee)]]
[react/text (gwei priority-fee-gwei)]]
[react/view
{:style {:flex-direction :row
:justify-content :space-between}}
[react/text (i18n/label :t/suggested-price-limit)]
[react/text (gwei (money/to-fixed (money/add base-fee-gwei priority-fee-gwei) 2))]]]
[react/text (gwei (money/add base-fee-gwei priority-fee-gwei))]]]
[react/view
{:style {:align-items :center
:justify-content :center

View File

@ -25,8 +25,7 @@
[status-im.ui.screens.keycard.pin.views :as pin.views]
[status-im.ui.components.bottom-panel.views :as bottom-panel]
[status-im.utils.utils :as utils]
[reagent.core :as reagent]
[status-im.signing.eip1559 :as eip1559]))
[reagent.core :as reagent]))
(defn separator []
[react/view {:height 1 :background-color colors/gray-lighter}])
@ -382,13 +381,18 @@
[react/text {:style {:color colors/black}}
(i18n/format-currency converted-fee-value (:code wallet-currency))])
[react/text {:style {:color colors/gray}} (str " " (:code wallet-currency))]]))
:on-press #(re-frame/dispatch
[:signing.ui/open-fee-sheet
{:content (fn []
(if (eip1559/sync-enabled?)
[sheets/fee-bottom-sheet-eip1559 fee-display-symbol]
[sheets/fee-bottom-sheet fee-display-symbol]))
:content-height 270}])}])))
:on-press #(re-frame/dispatch
[:signing.ui/open-fee-sheet
{:content (fn []
[sheets/fee-bottom-sheet-eip1559-custom fee-display-symbol])
:content-height 270}])
#_(re-frame/dispatch
[:signing.ui/open-fee-sheet
{:content (fn []
(if (eip1559/sync-enabled?)
[sheets/fee-bottom-sheet-eip1559 fee-display-symbol]
[sheets/fee-bottom-sheet fee-display-symbol]))
:content-height 270}])}])))
(views/defview network-item []
(views/letsubs [network-name [:network-name]]

View File

@ -243,6 +243,7 @@
from from-wallet from-contact
to to-wallet to-contact
gas-limit gas-price-gwei gas-price-eth gas-used
fee-cap-gwei tip-cap-gwei
cost nonce data]}]
[react/view {:style styles/details-block}
[details-list-row :t/block block]
@ -261,6 +262,8 @@
to])]
[details-list-row :t/gas-limit [{:monospace true} gas-limit]]
[details-list-row :t/gas-price gas-price-gwei [{:monospace false} gas-price-eth]]
[details-list-row :t/fee-cap fee-cap-gwei]
[details-list-row :t/tip-cap tip-cap-gwei]
[details-list-row :t/gas-used gas-used]
[details-list-row :t/cost-fee [{:monospace false} cost]]
[details-list-row :t/nonce nonce]

View File

@ -39,10 +39,10 @@
(defn greater-than
[bn1 bn2]
(.greaterThan bn1 bn2))
(.greaterThan ^js bn1 bn2))
(defn sub [bn1 bn2]
(.sub bn1 bn2))
(.sub ^js bn1 bn2))
(defn valid? [^js bn]
(when bn
@ -103,6 +103,9 @@
(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))))
@ -171,7 +174,16 @@
str))
(defn add [bn1 n2]
(.add bn1 n2))
(.add ^js bn1 n2))
(defn mul [bn1 bn2]
(.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))

View File

@ -28,6 +28,7 @@
[status-im.async-storage.core :as async-storage]
[status-im.popover.core :as popover.core]
[status-im.signing.eip1559 :as eip1559]
[status-im.signing.gas :as signing.gas]
[clojure.set :as clojure.set]))
(defn get-balance
@ -380,23 +381,40 @@
(fx/defn wallet-send-gas-price-success
{:events [:wallet.send/update-gas-price-success]}
[{db :db} price]
[{db :db} tx-entry price]
(if (eip1559/sync-enabled?)
(let [{:keys [base-fee max-priority-fee]} price
max-priority-fee-bn (money/bignumber max-priority-fee)]
(let [{:keys [slow-base-fee normal-base-fee fast-base-fee
current-base-fee max-priority-fee]}
price
max-priority-fee-bn (money/with-precision
(signing.gas/get-suggested-tip max-priority-fee)
0)
fee-cap (-> normal-base-fee
money/bignumber
(money/add max-priority-fee-bn)
money/to-hex)
tip-cap (money/to-hex max-priority-fee-bn)]
{:db (-> db
(update :wallet/prepare-transaction assoc
:maxFeePerGas (money/to-hex (money/add max-priority-fee-bn base-fee))
:maxPriorityFeePerGas max-priority-fee)
(assoc :wallet/latest-base-fee base-fee
:wallet/latest-priority-fee max-priority-fee))})
{:db (assoc-in db [:wallet/prepare-transaction :gasPrice] price)}))
(update tx-entry assoc
:maxFeePerGas fee-cap
:maxPriorityFeePerGas tip-cap)
(assoc :wallet/current-base-fee current-base-fee
:wallet/normal-base-fee normal-base-fee
:wallet/slow-base-fee slow-base-fee
:wallet/fast-base-fee fast-base-fee
:wallet/current-priority-fee max-priority-fee)
(assoc-in [:signing/edit-fee :gas-price-loading?] false))})
{:db (-> db
(assoc-in [:wallet/prepare-transaction :gasPrice] price)
(assoc-in [:signing/edit-fee :gas-price-loading?] false))}))
(fx/defn set-max-amount
{:events [:wallet.send/set-max-amount]}
[{:keys [db]} {:keys [amount decimals symbol]}]
(let [^js gas (money/bignumber 21000)
^js gasPrice (get-in db [:wallet/prepare-transaction :gasPrice])
^js gasPrice (or
(get-in db [:wallet/prepare-transaction :maxFeePerGas])
(get-in db [:wallet/prepare-transaction :gasPrice]))
^js fee (when gasPrice (.times gas gasPrice))
amount-text (if (= :ETH symbol)
(when (and fee (money/sufficient-funds? fee amount))
@ -478,7 +496,9 @@
{:events [::recipient-address-resolved]}
[{:keys [db]} address]
{:db (assoc-in db [:wallet/prepare-transaction :to :address] address)
:signing/update-gas-price {:success-event :wallet.send/update-gas-price-success
:signing/update-gas-price {:success-callback
#(re-frame/dispatch
[:wallet.send/update-gas-price-success :wallet/prepare-transaction %])
:network-id (get-in (ethereum/current-network db)
[:config :NetworkId])}})
@ -533,7 +553,9 @@
:symbol :ETH
:from-chat? false})
:dispatch [:open-modal :prepare-send-transaction]
:signing/update-gas-price {:success-event :wallet.send/update-gas-price-success
:signing/update-gas-price {:success-callback
#(re-frame/dispatch
[:wallet.send/update-gas-price-success :wallet/prepare-transaction %])
:network-id (get-in (ethereum/current-network db)
[:config :NetworkId])}})

View File

@ -1648,5 +1648,9 @@
"category": "Category",
"edit-chats": "Edit chats",
"hide": "Hide",
"account-is-used": "The account is being used with Dapps in the browser."
"account-is-used": "The account is being used with Dapps in the browser.",
"normal": "Normal",
"fee-options": "Suggested fee options",
"fee-cap": "Fee cap",
"tip-cap": "Tip cap"
}