[#11214] Add option for user to increase the gas payment for a pending transaction
[#11215] Add option for user to cancel a pending transaction. Signed-off-by: andrey <motor4ik@gmail.com>
This commit is contained in:
parent
1f7e40cede
commit
f9095a492e
|
@ -19,7 +19,8 @@
|
|||
[status-im.utils.utils :as utils]
|
||||
[status-im.wallet.prices :as prices]
|
||||
[status-im.wallet.core :as wallet]
|
||||
[taoensso.timbre :as log]))
|
||||
[taoensso.timbre :as log]
|
||||
[clojure.set :as clojure.set]))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:signing/send-transaction-fx
|
||||
|
@ -103,24 +104,29 @@
|
|||
:cb #(re-frame/dispatch [:signing/transaction-completed % tx-obj-to-send hashed-password])}})))))
|
||||
|
||||
(fx/defn prepare-unconfirmed-transaction
|
||||
[{:keys [db now]} hash {:keys [value gasPrice gas data to from] :as tx} symbol amount]
|
||||
[{:keys [db now]} new-tx-hash {:keys [value gasPrice gas data to from hash]} symbol amount]
|
||||
(log/debug "[signing] prepare-unconfirmed-transaction")
|
||||
(let [token (tokens/symbol->token (:wallet/all-tokens db) symbol)
|
||||
from (eip55/address->checksum from)]
|
||||
{:db (assoc-in db [:wallet :accounts from :transactions hash]
|
||||
{:timestamp (str now)
|
||||
:to to
|
||||
:from from
|
||||
:type :pending
|
||||
:hash hash
|
||||
:data data
|
||||
:token token
|
||||
:symbol symbol
|
||||
:value (if token
|
||||
(money/unit->token amount (:decimals token))
|
||||
(money/to-fixed (money/bignumber value)))
|
||||
:gas-price (money/to-fixed (money/bignumber gasPrice))
|
||||
:gas-limit (money/to-fixed (money/bignumber gas))})}))
|
||||
from (eip55/address->checksum from)
|
||||
;;if there is a hash in the tx object that means we resending transaction
|
||||
old-tx-hash hash]
|
||||
{:db (-> db
|
||||
;;remove old transaction, because we replace it with the new one
|
||||
(update-in [:wallet :accounts from :transactions] dissoc old-tx-hash)
|
||||
(assoc-in [:wallet :accounts from :transactions new-tx-hash]
|
||||
{:timestamp (str now)
|
||||
:to to
|
||||
:from from
|
||||
:type :pending
|
||||
:hash new-tx-hash
|
||||
:data data
|
||||
:token token
|
||||
:symbol symbol
|
||||
:value (if token
|
||||
(money/unit->token amount (:decimals token))
|
||||
(money/to-fixed (money/bignumber value)))
|
||||
:gas-price (money/to-fixed (money/bignumber gasPrice))
|
||||
:gas-limit (money/to-fixed (money/bignumber gas))}))}))
|
||||
|
||||
(defn get-method-type [data]
|
||||
(cond
|
||||
|
@ -148,15 +154,17 @@
|
|||
:token token
|
||||
:symbol symbol}))))))
|
||||
|
||||
(defn parse-tx-obj [db {:keys [from to value data]}]
|
||||
(merge {:from {:address from}}
|
||||
(defn parse-tx-obj [db {:keys [from to value data cancel? hash]}]
|
||||
(merge {:from {:address from}
|
||||
:cancel? cancel?
|
||||
:hash hash}
|
||||
(if (nil? to)
|
||||
{:contact {:name (i18n/label :t/new-contract)}}
|
||||
(let [eth-value (when value (money/bignumber value))
|
||||
eth-amount (when eth-value (money/to-fixed (money/wei->ether eth-value)))
|
||||
token (get-transfer-token db to data)]
|
||||
(cond
|
||||
(and eth-amount (or (not (zero? eth-amount)) (nil? data)))
|
||||
(and eth-amount (or (not (.equals ^js (money/bignumber 0) ^js eth-amount)) (nil? data)))
|
||||
{:to to
|
||||
:contact (get-contact db to)
|
||||
:symbol :ETH
|
||||
|
@ -468,3 +476,40 @@
|
|||
:data (abi-spec/encode
|
||||
"transfer(address,uint256)"
|
||||
[to-norm amount-hex])}))}))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:signing/get-transaction-by-hash-fx
|
||||
(fn [[hash handler]]
|
||||
(json-rpc/call
|
||||
{:method "eth_getTransactionByHash"
|
||||
:params [hash]
|
||||
:on-success handler})))
|
||||
|
||||
(fx/defn cancel-transaction-pressed
|
||||
{:events [:signing.ui/cancel-transaction-pressed]}
|
||||
[_ hash]
|
||||
{:signing/get-transaction-by-hash-fx [hash #(re-frame/dispatch [:signing/cancel-transaction %])]})
|
||||
|
||||
(fx/defn increase-gas-pressed
|
||||
{:events [:signing.ui/increase-gas-pressed]}
|
||||
[_ hash]
|
||||
{:signing/get-transaction-by-hash-fx [hash #(re-frame/dispatch [:signing/increase-gas %])]})
|
||||
|
||||
(fx/defn cancel-transaction
|
||||
{:events [:signing/cancel-transaction]}
|
||||
[cofx {:keys [from nonce hash]}]
|
||||
(when (and from nonce hash)
|
||||
(sign cofx {:tx-obj {:from from
|
||||
:to from
|
||||
:nonce nonce
|
||||
:value "0x0"
|
||||
:cancel? true
|
||||
:hash hash}})))
|
||||
|
||||
(fx/defn increase-gas
|
||||
{:events [:signing/increase-gas]}
|
||||
[cofx {:keys [from nonce] :as tx}]
|
||||
(when (and from nonce)
|
||||
(sign cofx {:tx-obj (-> tx
|
||||
(select-keys [:from :to :value :input :gas :nonce :hash])
|
||||
(clojure.set/rename-keys {:input :data}))})))
|
|
@ -24,7 +24,7 @@
|
|||
(testing "qieue is empty"
|
||||
(is (= (get-in sign-first [:db :signing/queue]) '())))
|
||||
(testing "first tx object is parsed"
|
||||
(is (= (dissoc (get-in sign-first [:db :signing/tx]) :token)
|
||||
(is (= (dissoc (get-in sign-first [:db :signing/tx]) :token :hash :cancel?)
|
||||
(merge first-tx
|
||||
{:from {:address nil}
|
||||
:gas nil
|
||||
|
@ -49,7 +49,7 @@
|
|||
(testing "qieue is empty"
|
||||
(is (= (get-in first-discarded [:db :signing/queue]) '())))
|
||||
(testing "second tx object is parsed"
|
||||
(is (= (dissoc (get-in first-discarded [:db :signing/tx]) :token)
|
||||
(is (= (dissoc (get-in first-discarded [:db :signing/tx]) :token :hash :cancel?)
|
||||
(merge second-tx
|
||||
{:from {:address nil}
|
||||
:gas nil
|
||||
|
|
|
@ -103,4 +103,4 @@
|
|||
|
||||
(views/defview animated-bottom-panel [val signing-view]
|
||||
(views/letsubs [{window-height :height} [:dimensions/window]]
|
||||
[bottom-panel (when val (select-keys val [:from :contact :amount :token :approve? :message])) signing-view window-height]))
|
||||
[bottom-panel (when val (select-keys val [:from :contact :amount :token :approve? :message :cancel? :hash])) signing-view window-height]))
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
|
||||
(defn header
|
||||
[{:keys [in-progress?] :as sign}
|
||||
{:keys [contact amount approve?]}
|
||||
{:keys [contact amount approve? cancel? hash]}
|
||||
display-symbol fee fee-display-symbol]
|
||||
[react/view styles/header
|
||||
(when sign
|
||||
|
@ -78,8 +78,15 @@
|
|||
[icons/icon :main-icons/back]]])
|
||||
[react/view {:flex 1}
|
||||
(if amount
|
||||
[react/text {:style {:typography :title-bold}} (str (if approve? (i18n/label :t/authorize) (i18n/label :t/sending))
|
||||
" " amount " " display-symbol)]
|
||||
[react/text {:style {:typography :title-bold}} (str (cond approve?
|
||||
(i18n/label :t/authorize)
|
||||
cancel?
|
||||
(i18n/label :t/cancelling)
|
||||
:else
|
||||
(i18n/label :t/sending))
|
||||
(if cancel?
|
||||
(str " " (utils/get-shortened-address hash))
|
||||
(str " " amount " " display-symbol)))]
|
||||
[react/text {:style {:typography :title-bold}} (i18n/label :t/contract-interaction)])
|
||||
(if sign
|
||||
[react/nested-text {:style {:color colors/gray}
|
||||
|
@ -386,7 +393,7 @@
|
|||
:accessory-text network-name}]))
|
||||
|
||||
(views/defview sheet
|
||||
[{:keys [from contact amount token] :as tx}]
|
||||
[{:keys [from contact amount token cancel?] :as tx}]
|
||||
(views/letsubs [fee [:signing/fee]
|
||||
sign [:signing/sign]
|
||||
chain [:ethereum/chain-keyword]
|
||||
|
@ -413,9 +420,12 @@
|
|||
[contact-item (i18n/label :t/from) from]
|
||||
[separator]
|
||||
[contact-item (i18n/label :t/to) contact]
|
||||
[separator]
|
||||
[token-item token display-symbol]
|
||||
[amount-item prices wallet-currency amount amount-error display-symbol fee-display-symbol prices-loading?]
|
||||
(when-not cancel?
|
||||
[separator])
|
||||
(when-not cancel?
|
||||
[token-item token display-symbol])
|
||||
(when-not cancel?
|
||||
[amount-item prices wallet-currency amount amount-error display-symbol fee-display-symbol prices-loading?])
|
||||
[separator]
|
||||
[fee-item prices wallet-currency fee-display-symbol fee gas-error gas-error-state prices-loading?]
|
||||
(when (= :gas-is-set gas-error-state)
|
||||
|
@ -438,7 +448,7 @@
|
|||
(views/letsubs [tx [:signing/tx]]
|
||||
[bottom-panel/animated-bottom-panel
|
||||
;;we use select-keys here because we don't want to update view if other keys in map are changed
|
||||
(when tx (select-keys tx [:from :contact :amount :token :approve? :message]))
|
||||
(when tx (select-keys tx [:from :contact :amount :token :approve? :message :cancel? :hash]))
|
||||
#(if (:message %)
|
||||
[message-sheet]
|
||||
[sheet %])]))
|
||||
|
|
|
@ -39,42 +39,51 @@
|
|||
(defn render-transaction
|
||||
[{:keys [label contact address contact-accessibility-label
|
||||
address-accessibility-label currency-text amount-text
|
||||
time-formatted on-touch-fn type]}]
|
||||
[list/touchable-item on-touch-fn
|
||||
[react/view {:accessibility-label :transaction-item}
|
||||
[list/item
|
||||
(when type
|
||||
[list/item-icon (transaction-type->icon (keyword type))])
|
||||
[list/item-content
|
||||
[react/view {:style styles/amount-time}
|
||||
[react/nested-text {:style styles/tx-amount
|
||||
:ellipsize-mode "tail"
|
||||
:number-of-lines 1}
|
||||
[{:accessibility-label :amount-text}
|
||||
amount-text]
|
||||
" "
|
||||
[{:accessibility-label :currency-text}
|
||||
currency-text]]
|
||||
[react/text {:style styles/tx-time}
|
||||
time-formatted]]
|
||||
[react/view {:style styles/address-row}
|
||||
[react/text {:style styles/address-label}
|
||||
label]
|
||||
(when contact
|
||||
[react/text {:style styles/address-contact
|
||||
:accessibility-label contact-accessibility-label}
|
||||
contact])
|
||||
[quo/text {:style styles/address-hash
|
||||
:monospace true
|
||||
:color :secondary
|
||||
:ellipsize-mode "middle"
|
||||
:number-of-lines 1
|
||||
:accessibility-label address-accessibility-label}
|
||||
address]]]
|
||||
[list/item-icon {:icon :main-icons/next
|
||||
:style {:margin-top 10}
|
||||
:icon-opts (merge styles/forward
|
||||
{:accessibility-label :show-transaction-button})}]]]])
|
||||
time-formatted on-touch-fn type hash]}]
|
||||
[react/view
|
||||
[list/touchable-item on-touch-fn
|
||||
[react/view {:accessibility-label :transaction-item}
|
||||
[list/item
|
||||
(when type
|
||||
[list/item-icon (transaction-type->icon (keyword type))])
|
||||
[list/item-content
|
||||
[react/view {:style styles/amount-time}
|
||||
[react/nested-text {:style styles/tx-amount
|
||||
:ellipsize-mode "tail"
|
||||
:number-of-lines 1}
|
||||
[{:accessibility-label :amount-text}
|
||||
amount-text]
|
||||
" "
|
||||
[{:accessibility-label :currency-text}
|
||||
currency-text]]
|
||||
[react/text {:style styles/tx-time}
|
||||
time-formatted]]
|
||||
[react/view {:style styles/address-row}
|
||||
[react/text {:style styles/address-label}
|
||||
label]
|
||||
(when contact
|
||||
[react/text {:style styles/address-contact
|
||||
:accessibility-label contact-accessibility-label}
|
||||
contact])
|
||||
[quo/text {:style styles/address-hash
|
||||
:monospace true
|
||||
:color :secondary
|
||||
:ellipsize-mode "middle"
|
||||
:number-of-lines 1
|
||||
:accessibility-label address-accessibility-label}
|
||||
address]]]
|
||||
[list/item-icon {:icon :main-icons/next
|
||||
:style {:margin-top 10}
|
||||
:icon-opts (merge styles/forward
|
||||
{:accessibility-label :show-transaction-button})}]]]]
|
||||
(when (= type :pending)
|
||||
[react/view {:flex-direction :row :padding 16 :justify-content :space-between}
|
||||
[quo/button
|
||||
{:on-press #(re-frame/dispatch [:signing.ui/increase-gas-pressed hash])}
|
||||
(i18n/label :t/increase-gas)]
|
||||
[quo/button
|
||||
{:on-press #(re-frame/dispatch [:signing.ui/cancel-transaction-pressed hash])}
|
||||
(i18n/label :t/cancel)]])])
|
||||
|
||||
(defn etherscan-link [address]
|
||||
(let [link @(re-frame/subscribe [:wallet/etherscan-link address])]
|
||||
|
|
|
@ -1327,5 +1327,7 @@
|
|||
"ethereum-account": "Ethereum account",
|
||||
"ethereum-address":"Ethereum address",
|
||||
"default-assets": "Default ERC20 and ERC721",
|
||||
"increase-gas": "Increase Gas",
|
||||
"cancelling": "Cancelling",
|
||||
"refresh": "Refresh"
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue