[#10199] fix No message when sending funds in 1-1 chat with keycard

This commit is contained in:
Roman Volosovskyi 2020-04-02 12:50:35 +03:00
parent 0cc7ec92bd
commit 8b4bc0290a
No known key found for this signature in database
GPG Key ID: 0238A4B5ECEE70DE
7 changed files with 147 additions and 56 deletions

View File

@ -175,13 +175,14 @@
(defn on-error-retry (defn on-error-retry
[call-method {:keys [method number-of-retries delay on-error] :as arg}] [call-method {:keys [method number-of-retries delay on-error] :as arg}]
(if (pos? number-of-retries) (if (pos? number-of-retries)
(fn [] (fn [error]
(let [updated-delay (if delay (let [updated-delay (if delay
(min 2000 (* 2 delay)) (min 2000 (* 2 delay))
50)] 50)]
(log/debug "[on-error-retry]" method (log/debug "[on-error-retry]" method
"number-of-retries" number-of-retries "number-of-retries" number-of-retries
"delay" delay) "delay" delay
"error" error)
(utils/set-timeout #(call-method (-> arg (utils/set-timeout #(call-method (-> arg
(update :number-of-retries dec) (update :number-of-retries dec)
(assoc :delay updated-delay))) (assoc :delay updated-delay)))

View File

@ -402,7 +402,7 @@
(re-frame/dispatch [:hardwallet.callback/on-get-keys-error (re-frame/dispatch [:hardwallet.callback/on-get-keys-error
(error-object->map response)]))}))) (error-object->map response)]))})))
(defn sign [args] (defn sign [{:keys [on-success on-failure] :as args}]
(log/info "[keycard] sign" args) (log/info "[keycard] sign" args)
(keycard/sign (keycard/sign
card card
@ -411,12 +411,15 @@
{:on-success {:on-success
(fn [response] (fn [response]
(log/info "[keycard response succ] sign" (js->clj response :keywordize-keys true)) (log/info "[keycard response succ] sign" (js->clj response :keywordize-keys true))
(re-frame/dispatch [:hardwallet.callback/on-sign-success (if on-success
response])) (on-success response)
(re-frame/dispatch [:hardwallet.callback/on-sign-success response])))
:on-failure :on-failure
(fn [response] (fn [response]
(log/info "[keycard response fail] sign" (log/info "[keycard response fail] sign"
(error-object->map response)) (error-object->map response))
(re-frame/dispatch (if on-failure
[:hardwallet.callback/on-sign-error (on-failure response)
(error-object->map response)]))}))) (re-frame/dispatch
[:hardwallet.callback/on-sign-error
(error-object->map response)])))})))

View File

@ -31,6 +31,49 @@
(when-not keycard-match? (when-not keycard-match?
(common/show-wrong-keycard-alert card-connected?)))))) (common/show-wrong-keycard-alert card-connected?))))))
(fx/defn sign-message
{:events [:hardwallet/sign-message]}
[{:keys [db] :as cofx} params result]
(let [{:keys [result error]} (types/json->clj result)
on-success #(re-frame/dispatch [:hardwallet/on-sign-message-success params %])
hash (ethereum/naked-address result)
card-connected? (get-in db [:hardwallet :card-connected?])
pairing (common/get-pairing db)
multiaccount-keycard-instance-uid (get-in db [:multiaccount :keycard-instance-uid])
instance-uid (get-in db [:hardwallet :application-info :instance-uid])
keycard-match? (= multiaccount-keycard-instance-uid instance-uid)
pin (common/vector->string (get-in db [:hardwallet :pin :sign]))]
(if (and card-connected?
keycard-match?)
{:db (-> db
(assoc-in [:hardwallet :card-read-in-progress?] true)
(assoc-in [:hardwallet :pin :status] :verifying))
:hardwallet/sign {:hash (ethereum/naked-address hash)
:pairing pairing
:pin pin
:on-success on-success}}
(fx/merge cofx
{:db (assoc-in db [:signing/sign :keycard-step] :signing)}
(common/set-on-card-connected :hardwallet/sign)
(when-not keycard-match?
(common/show-wrong-keycard-alert card-connected?))))))
(fx/defn on-sign-message-success
{:events [:hardwallet/on-sign-message-success]}
[{:keys [db] :as cofx} {:keys [tx-hash message-id chat-id value contract]} signature]
(fx/merge
cofx
{:dispatch
(if message-id
[:sign/send-accept-transaction-message message-id tx-hash signature]
[:sign/send-transaction-message chat-id value contract tx-hash signature])
:db (-> db
(assoc-in [:hardwallet :pin :sign] [])
(assoc-in [:hardwallet :pin :status] nil))}
(common/clear-on-card-connected)
(common/get-application-info (common/get-pairing db) nil)
(common/hide-connection-sheet)))
(fx/defn prepare-to-sign (fx/defn prepare-to-sign
{:events [:hardwallet/prepare-to-sign]} {:events [:hardwallet/prepare-to-sign]}
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
@ -60,16 +103,22 @@
[{:keys [db] :as cofx} signature] [{:keys [db] :as cofx} signature]
(log/debug "[hardwallet] sign success: " signature) (log/debug "[hardwallet] sign success: " signature)
(let [transaction (get-in db [:hardwallet :transaction]) (let [transaction (get-in db [:hardwallet :transaction])
tx-obj (select-keys transaction [:from :to :value :gas :gasPrice])] tx-obj (select-keys transaction [:from :to :value :gas :gasPrice :command? :chat-id :message-id])
command? (:command? transaction)]
(fx/merge cofx (fx/merge cofx
{:db (-> db {:db (-> db
(assoc-in [:hardwallet :pin :sign] [])
(assoc-in [:hardwallet :pin :status] nil)
(assoc-in [:hardwallet :hash] nil) (assoc-in [:hardwallet :hash] nil)
(assoc-in [:hardwallet :transaction] nil))} (assoc-in [:hardwallet :transaction] nil))}
(common/clear-on-card-connected) (when-not command?
(common/get-application-info (common/get-pairing db) nil) (fn [{:keys [db] :as cofx}]
(common/hide-connection-sheet) (fx/merge
cofx
{:db (-> db
(assoc-in [:hardwallet :pin :sign] [])
(assoc-in [:hardwallet :pin :status] nil))}
(common/clear-on-card-connected)
(common/get-application-info (common/get-pairing db) nil)
(common/hide-connection-sheet))))
(if transaction (if transaction
(send-transaction-with-signature {:transaction (types/clj->json transaction) (send-transaction-with-signature {:transaction (types/clj->json transaction)
:signature signature :signature signature

View File

@ -13,11 +13,15 @@
[status-im.native-module.core :as status] [status-im.native-module.core :as status]
[status-im.utils.fx :as fx] [status-im.utils.fx :as fx]
[status-im.hardwallet.common :as hardwallet.common] [status-im.hardwallet.common :as hardwallet.common]
[status-im.hardwallet.sign :as hardwallet.sign]
[status-im.signing.keycard :as signing.keycard]
[status-im.utils.hex :as utils.hex] [status-im.utils.hex :as utils.hex]
[status-im.utils.money :as money] [status-im.utils.money :as money]
[status-im.utils.security :as security] [status-im.utils.security :as security]
[status-im.utils.types :as types] [status-im.utils.types :as types]
[status-im.utils.utils :as utils])) [status-im.utils.utils :as utils]
[taoensso.timbre :as log]
[re-frame.core :as re-frame.core]))
(re-frame/reg-fx (re-frame/reg-fx
:signing/send-transaction-fx :signing/send-transaction-fx
@ -211,20 +215,22 @@
(show-sign cofx)))) (show-sign cofx))))
(fx/defn send-transaction-message (fx/defn send-transaction-message
{:events [::send-transaction-message]} {:events [:sign/send-transaction-message]}
[cofx chat-id value contract transaction-hash signature] [cofx chat-id value contract transaction-hash signature]
{::json-rpc/call [{:method (json-rpc/call-ext-method (waku/enabled? cofx) "sendTransaction") {::json-rpc/call [{:method (json-rpc/call-ext-method (waku/enabled? cofx) "sendTransaction")
:params [chat-id value contract transaction-hash :params [chat-id value contract transaction-hash
(:result (types/json->clj signature))] (or (:result (types/json->clj signature))
(ethereum/normalized-hex signature))]
:on-success :on-success
#(re-frame/dispatch [:transport/message-sent % 1])}]}) #(re-frame/dispatch [:transport/message-sent % 1])}]})
(fx/defn send-accept-request-transaction-message (fx/defn send-accept-request-transaction-message
{:events [::send-accept-transaction-message]} {:events [:sign/send-accept-transaction-message]}
[cofx message-id transaction-hash signature] [cofx message-id transaction-hash signature]
{::json-rpc/call [{:method (json-rpc/call-ext-method (waku/enabled? cofx) "acceptRequestTransaction") {::json-rpc/call [{:method (json-rpc/call-ext-method (waku/enabled? cofx) "acceptRequestTransaction")
:params [transaction-hash message-id :params [transaction-hash message-id
(:result (types/json->clj signature))] (or (:result (types/json->clj signature))
(ethereum/normalized-hex signature))]
:on-success :on-success
#(re-frame/dispatch [:transport/message-sent % 1])}]}) #(re-frame/dispatch [:transport/message-sent % 1])}]})
@ -242,22 +248,38 @@
(fx/defn command-transaction-result (fx/defn command-transaction-result
[{:keys [db] :as cofx} transaction-hash hashed-password [{:keys [db] :as cofx} transaction-hash hashed-password
{:keys [message-id chat-id from] :as tx-obj}] {:keys [message-id chat-id from] :as tx-obj}]
(let [{:keys [on-result symbol amount contract value]} (get db :signing/tx)] (let [{:keys [on-result symbol amount contract value]} (get db :signing/tx)
data (str (get-in db [:multiaccount :public-key])
(subs transaction-hash 2))]
(fx/merge (fx/merge
cofx cofx
{:db (dissoc db :signing/tx :signing/in-progress? :signing/sign) {:db (dissoc db :signing/tx :signing/in-progress? :signing/sign)}
:signing.fx/sign-message (if (hardwallet.common/keycard-multiaccount? db)
{:params {:data (str (get-in db [:multiaccount :public-key]) (signing.keycard/hash-message
(subs transaction-hash 2)) {:data data
:password hashed-password :on-completed
:account from} (fn [hash]
:on-completed (re-frame.core/dispatch
#(re-frame/dispatch [:hardwallet/sign-message
(if message-id {:tx-hash transaction-hash
[::send-accept-transaction-message message-id transaction-hash %] :message-id message-id
[::send-transaction-message :chat-id chat-id
chat-id value contract transaction-hash %]))} :value value
:signing/show-transaction-result nil} :contract contract}
hash]))})
(fn [_]
{:signing.fx/sign-message
{:params {:data data
:password hashed-password
:account from}
:on-completed
(fn [res]
(re-frame/dispatch
(if message-id
[:sign/send-accept-transaction-message message-id transaction-hash res]
[:sign/send-transaction-message
chat-id value contract transaction-hash res])))}
:signing/show-transaction-result nil}))
(prepare-unconfirmed-transaction transaction-hash tx-obj symbol amount) (prepare-unconfirmed-transaction transaction-hash tx-obj symbol amount)
(check-queue) (check-queue)
#(when on-result #(when on-result
@ -293,6 +315,7 @@
[cofx response tx-obj hashed-password] [cofx response tx-obj hashed-password]
(let [cofx-in-progress-false (assoc-in cofx [:db :signing/sign :in-progress?] false) (let [cofx-in-progress-false (assoc-in cofx [:db :signing/sign :in-progress?] false)
{:keys [result error]} (types/json->clj response)] {:keys [result error]} (types/json->clj response)]
(log/debug "transaction-completed" error tx-obj)
(if error (if error
(transaction-error cofx-in-progress-false error) (transaction-error cofx-in-progress-false error)
(if (:command? tx-obj) (if (:command? tx-obj)
@ -317,13 +340,14 @@
(defn normalize-tx-obj [db tx] (defn normalize-tx-obj [db tx]
(update-in tx [:tx-obj :from] #(eip55/address->checksum (or % (ethereum/default-address db))))) (update-in tx [:tx-obj :from] #(eip55/address->checksum (or % (ethereum/default-address db)))))
(fx/defn sign [{:keys [db] :as cofx} tx] (fx/defn sign
"Signing transaction or message, shows signing sheet "Signing transaction or message, shows signing sheet
tx tx
{:tx-obj - transaction object to send https://github.com/ethereum/wiki/wiki/JavaScript-API#parameters-25 {:tx-obj - transaction object to send https://github.com/ethereum/wiki/wiki/JavaScript-API#parameters-25
:message {:address :data :typed? } - message data to sign :message {:address :data :typed? } - message data to sign
:on-result - re-frame event vector :on-result - re-frame event vector
:on-error - re-frame event vector}" :on-error - re-frame event vector}"
[{:keys [db] :as cofx} tx]
(fx/merge cofx (fx/merge cofx
{:db (update db :signing/queue conj (normalize-tx-obj db tx))} {:db (update db :signing/queue conj (normalize-tx-obj db tx))}
(check-queue))) (check-queue)))

View File

@ -4,7 +4,8 @@
[status-im.native-module.core :as status] [status-im.native-module.core :as status]
[status-im.utils.types :as types] [status-im.utils.types :as types]
[status-im.ethereum.abi-spec :as abi-spec] [status-im.ethereum.abi-spec :as abi-spec]
[status-im.ethereum.core :as ethereum])) [status-im.ethereum.core :as ethereum]
[taoensso.timbre :as log]))
(re-frame/reg-fx (re-frame/reg-fx
::hash-transaction ::hash-transaction
@ -23,24 +24,31 @@
(defn prepare-transaction (defn prepare-transaction
[{:keys [gas gasPrice data nonce tx-obj]}] [{:keys [gas gasPrice data nonce tx-obj]}]
(let [{:keys [from to value]} tx-obj] (let [{:keys [from to value chat-id message-id command?]} tx-obj]
(cond-> {:from from (cond-> {:from from
:to to :to to
:value value :value value
:gas (str "0x" (abi-spec/number-to-hex gas)) :gas (str "0x" (abi-spec/number-to-hex gas))
:gasPrice (str "0x" (abi-spec/number-to-hex gasPrice))} :gasPrice (str "0x" (abi-spec/number-to-hex gasPrice))
:chat-id chat-id
:message-id message-id
:command? command?}
data data
(assoc :data data) (assoc :data data)
nonce nonce
(assoc :nonce nonce)))) (assoc :nonce nonce))))
(fx/defn hash-message (fx/defn hash-message
[_ {:keys [data typed?]}] [_ {:keys [data typed? on-completed]}]
(if typed? (if typed?
{::hash-typed-data {:data data {::hash-typed-data
:on-completed #(re-frame/dispatch [:signing.keycard.callback/hash-message-completed %])}} {:data data
{::hash-message {:message data :on-completed
:on-completed #(re-frame/dispatch [:signing.keycard.callback/hash-message-completed %])}})) (or on-completed #(re-frame/dispatch [:signing.keycard.callback/hash-message-completed %]))}}
{::hash-message
{:message data
:on-completed
(or on-completed #(re-frame/dispatch [:signing.keycard.callback/hash-message-completed %]))}}))
(fx/defn hash-message-completed (fx/defn hash-message-completed
{:events [:signing.keycard.callback/hash-message-completed]} {:events [:signing.keycard.callback/hash-message-completed]}
@ -51,15 +59,20 @@
(fx/defn hash-transaction (fx/defn hash-transaction
[{:keys [db]}] [{:keys [db]}]
{::hash-transaction {:transaction (prepare-transaction (:signing/tx db)) (let [tx (prepare-transaction (:signing/tx db))]
:on-completed #(re-frame/dispatch [:signing.keycard.callback/hash-transaction-completed %])}}) (log/debug "hash-transaction" tx)
{::hash-transaction
{:transaction tx
:on-completed #(re-frame/dispatch
[:signing.keycard.callback/hash-transaction-completed tx %])}}))
(fx/defn hash-transaction-completed (fx/defn hash-transaction-completed
{:events [:signing.keycard.callback/hash-transaction-completed]} {:events [:signing.keycard.callback/hash-transaction-completed]}
[{:keys [db]} result] [{:keys [db]} original-tx result]
(let [{:keys [transaction hash]} (:result (types/json->clj result))] (let [{:keys [transaction hash]} (:result (types/json->clj result))]
{:db (-> db {:db (-> db
(assoc-in [:hardwallet :transaction] transaction) (assoc-in [:hardwallet :transaction]
(merge original-tx transaction))
(assoc-in [:hardwallet :hash] hash))})) (assoc-in [:hardwallet :hash] hash))}))
(fx/defn sign-with-keycard (fx/defn sign-with-keycard

View File

@ -254,4 +254,4 @@
message]) message])
#(re-frame/dispatch #(re-frame/dispatch
[::commands/decline-request-address-for-transaction [::commands/decline-request-address-for-transaction
message-id])]))]]])) message-id])]))]]]))

View File

@ -437,15 +437,14 @@
(fx/defn accept-request-transaction-button-clicked-from-command (fx/defn accept-request-transaction-button-clicked-from-command
{:events [:wallet.ui/accept-request-transaction-button-clicked-from-command]} {:events [:wallet.ui/accept-request-transaction-button-clicked-from-command]}
[{:keys [db] :as cofx} chat-id {:keys [address value from id contract] :as request-parameters}] [{:keys [db]} chat-id {:keys [value contract] :as request-parameters}]
(let [identity (:current-chat-id db) (let [identity (:current-chat-id db)
all-tokens (:wallet/all-tokens db) all-tokens (:wallet/all-tokens db)
current-network-string (:networks/current-network db) current-network-string (:networks/current-network db)
prices (:prices db)
all-networks (:networks/networks db) all-networks (:networks/networks db)
current-network (get all-networks current-network-string) current-network (get all-networks current-network-string)
chain (ethereum/network->chain-keyword current-network) chain (ethereum/network->chain-keyword current-network)
{:keys [symbol icon decimals] :as token} {:keys [symbol decimals]}
(if (seq contract) (if (seq contract)
(get (get all-tokens chain) contract) (get (get all-tokens chain) contract)
(tokens/native-currency chain)) (tokens/native-currency chain))
@ -465,8 +464,8 @@
(fx/defn sign-transaction-button-clicked-from-request (fx/defn sign-transaction-button-clicked-from-request
{:events [:wallet.ui/sign-transaction-button-clicked-from-request]} {:events [:wallet.ui/sign-transaction-button-clicked-from-request]}
[{:keys [db] :as cofx} {:keys [to amount from token gas gasPrice]}] [{:keys [db] :as cofx} {:keys [amount from token]}]
(let [{:keys [request-parameters]} (:wallet/prepare-transaction db) (let [{:keys [request-parameters chat-id]} (:wallet/prepare-transaction db)
{:keys [symbol address]} token {:keys [symbol address]} token
amount-hex (str "0x" (abi-spec/number-to-hex amount)) amount-hex (str "0x" (abi-spec/number-to-hex amount))
to-norm (:address request-parameters) to-norm (:address request-parameters)
@ -480,12 +479,14 @@
{:to to-norm {:to to-norm
:from from-address :from from-address
:message-id (:id request-parameters) :message-id (:id request-parameters)
:chat-id chat-id
:command? true :command? true
:value amount-hex} :value amount-hex}
{:to (ethereum/normalized-hex address) {:to (ethereum/normalized-hex address)
:from from-address :from from-address
:command? true :command? true
:message-id (:id request-parameters) :message-id (:id request-parameters)
:chat-id chat-id
:data (abi-spec/encode :data (abi-spec/encode
"transfer(address,uint256)" "transfer(address,uint256)"
[to-norm amount-hex])})}))))) [to-norm amount-hex])})})))))