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