From 268b07fddc976e7d09cee56277bfd7103a982445 Mon Sep 17 00:00:00 2001 From: Goran Jovic Date: Sun, 3 Jun 2018 12:25:14 +0200 Subject: [PATCH] feature #4065 - gas and gas price can be changed for dapp transactions Signed-off-by: Pedro Pombeiro --- .../status/ethereum/module/StatusModule.java | 25 +++++++-- .../ios/RCTStatus/RCTStatus.m | 23 ++++++-- src/status_im/native_module/core.cljs | 7 ++- src/status_im/native_module/impl/module.cljs | 20 ++++--- .../impl/non_status_go_module.cljs | 3 +- src/status_im/native_module/module.cljs | 3 +- .../ui/screens/wallet/send/events.cljs | 47 ++++++++++++----- .../ui/screens/wallet/send/subs.cljs | 4 +- .../ui/screens/wallet/send/views.cljs | 52 +++++++++++-------- 9 files changed, 131 insertions(+), 53 deletions(-) diff --git a/modules/react-native-status/android/src/main/java/im/status/ethereum/module/StatusModule.java b/modules/react-native-status/android/src/main/java/im/status/ethereum/module/StatusModule.java index 93df40fc9d..594a3f7032 100644 --- a/modules/react-native-status/android/src/main/java/im/status/ethereum/module/StatusModule.java +++ b/modules/react-native-status/android/src/main/java/im/status/ethereum/module/StatusModule.java @@ -503,8 +503,8 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL } @ReactMethod - public void approveSignRequests(final String hashes, final String password, final Callback callback) { - Log.d(TAG, "approveSignRequests"); + public void approveSignRequest(final String id, final String password, final Callback callback) { + Log.d(TAG, "approveSignRequest"); if (!checkAvailability()) { callback.invoke(false); return; @@ -513,7 +513,26 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL Runnable r = new Runnable() { @Override public void run() { - String res = Statusgo.ApproveSignRequests(hashes, password); + String res = Statusgo.ApproveSignRequest(id, password); + callback.invoke(res); + } + }; + + StatusThreadPoolExecutor.getInstance().execute(r); + } + + @ReactMethod + public void approveSignRequestWithArgs(final String id, final String password, final String gas, final String gasPrice, final Callback callback) { + Log.d(TAG, "approveSignRequestWithArgs"); + if (!checkAvailability()) { + callback.invoke(false); + return; + } + + Runnable r = new Runnable() { + @Override + public void run() { + String res = Statusgo.ApproveSignRequestWithArgs(id, password, Long.parseLong(gas), Long.parseLong(gasPrice)); callback.invoke(res); } }; diff --git a/modules/react-native-status/ios/RCTStatus/RCTStatus.m b/modules/react-native-status/ios/RCTStatus/RCTStatus.m index 2e5129770c..8e2203fa22 100644 --- a/modules/react-native-status/ios/RCTStatus/RCTStatus.m +++ b/modules/react-native-status/ios/RCTStatus/RCTStatus.m @@ -309,15 +309,30 @@ RCT_EXPORT_METHOD(login:(NSString *)address } //////////////////////////////////////////////////////////////////// -#pragma mark - Approve Sign Requests +#pragma mark - Approve Sign Request //////////////////////////////////////////////////////////////////// approveSignRequests -RCT_EXPORT_METHOD(approveSignRequests:(NSString *)hashes +RCT_EXPORT_METHOD(approveSignRequest:(NSString *)id password:(NSString *)password callback:(RCTResponseSenderBlock)callback) { #if DEBUG - NSLog(@"ApproveSignRequests() method called"); + NSLog(@"ApproveSignRequest() method called"); #endif - char * result = ApproveSignRequests((char *) [hashes UTF8String], (char *) [password UTF8String]); + char * result = ApproveSignRequest((char *) [id UTF8String], (char *) [password UTF8String]); + callback(@[[NSString stringWithUTF8String: result]]); +} + +//////////////////////////////////////////////////////////////////// +#pragma mark - Approve Sign Request With Args +//////////////////////////////////////////////////////////////////// approveSignRequestWithArgs +RCT_EXPORT_METHOD(approveSignRequestWithArgs:(NSString *)id + password:(NSString *)password + gas:(NSString *)gas + gasPrice:(NSString *)gasPrice + callback:(RCTResponseSenderBlock)callback) { +#if DEBUG + NSLog(@"ApproveSignRequestWithArgs() method called"); +#endif + char * result = ApproveSignRequestWithArgs((char *) [id UTF8String], (char *) [password UTF8String], (long long) [gas longLongValue], (long long) [gasPrice longLongValue]); callback(@[[NSString stringWithUTF8String: result]]); } diff --git a/src/status_im/native_module/core.cljs b/src/status_im/native_module/core.cljs index 9b80819baf..c1b09ee8fe 100644 --- a/src/status_im/native_module/core.cljs +++ b/src/status_im/native_module/core.cljs @@ -40,8 +40,11 @@ (defn login [address password callback] (module-interface/-login rns-module address password callback)) -(defn approve-sign-requests [hashes password callback] - (module-interface/-approve-sign-requests rns-module hashes password callback)) +(defn approve-sign-request [id password callback] + (module-interface/-approve-sign-request rns-module id password callback)) + +(defn approve-sign-request-with-args [id password gas gas-price callback] + (module-interface/-approve-sign-request-with-args rns-module id password gas gas-price callback)) (defn discard-sign-request [id] (module-interface/-discard-sign-request rns-module id)) diff --git a/src/status_im/native_module/impl/module.cljs b/src/status_im/native_module/impl/module.cljs index 403035963a..d1939f98f2 100644 --- a/src/status_im/native_module/impl/module.cljs +++ b/src/status_im/native_module/impl/module.cljs @@ -117,11 +117,17 @@ (when status (call-module #(.login status address password on-result)))) -(defn approve-sign-requests - [hashes password callback] - (log/debug :approve-sign-requests (boolean status) hashes) +(defn approve-sign-request + [id password callback] + (log/debug :approve-sign-request (boolean status) id) (when status - (call-module #(.approveSignRequests status (types/clj->json hashes) password callback)))) + (call-module #(.approveSignRequest status id password callback)))) + +(defn approve-sign-request-with-args + [id password gas gas-price callback] + (log/debug :approve-sign-request-with-args (boolean status) id gas gas-price) + (when status + (call-module #(.approveSignRequestWithArgs status id password gas gas-price callback)))) (defn discard-sign-request [id] @@ -260,8 +266,10 @@ (recover-account passphrase password callback)) (-login [this address password callback] (login address password callback)) - (-approve-sign-requests [this hashes password callback] - (approve-sign-requests hashes password callback)) + (-approve-sign-request [this id password callback] + (approve-sign-request id password callback)) + (-approve-sign-request-with-args [this id password gas gas-price callback] + (approve-sign-request-with-args id password gas gas-price callback)) (-discard-sign-request [this id] (discard-sign-request id)) (-parse-jail [this chat-id file callback] diff --git a/src/status_im/native_module/impl/non_status_go_module.cljs b/src/status_im/native_module/impl/non_status_go_module.cljs index 54d1568d60..3e2766a9bf 100644 --- a/src/status_im/native_module/impl/non_status_go_module.cljs +++ b/src/status_im/native_module/impl/non_status_go_module.cljs @@ -24,7 +24,8 @@ (if (not= password wrong-password) (callback "{\"error\":\"\"}") (callback "{\"error\":\"cannot retrieve a valid key for a given account: could not decrypt key with given passphrase\"}"))) - (-approve-sign-requests [this hashes password callback]) + (-approve-sign-request [this id password callback]) + (-approve-sign-request-with-args [this id password gas gas-price callback]) (-discard-sign-request [this id]) (-parse-jail [this chat-id file callback] (when (= chat-id constants/console-chat-id) diff --git a/src/status_im/native_module/module.cljs b/src/status_im/native_module/module.cljs index 0ccfd94e59..999783bd1e 100644 --- a/src/status_im/native_module/module.cljs +++ b/src/status_im/native_module/module.cljs @@ -8,7 +8,8 @@ (-create-account [this password callback]) (-recover-account [this passphrase password callback]) (-login [this address password callback]) - (-approve-sign-requests [this hashes password callback]) + (-approve-sign-request [this id password callback]) + (-approve-sign-request-with-args [this id password gas gas-price callback]) (-discard-sign-request [this id]) (-parse-jail [this chat-id file callback]) (-call-jail [this params]) diff --git a/src/status_im/ui/screens/wallet/send/events.cljs b/src/status_im/ui/screens/wallet/send/events.cljs index 58b3780d71..7a9163b4ea 100644 --- a/src/status_im/ui/screens/wallet/send/events.cljs +++ b/src/status_im/ui/screens/wallet/send/events.cljs @@ -15,15 +15,28 @@ [status-im.utils.types :as types] [status-im.utils.utils :as utils] [status-im.constants :as constants] - [status-im.transport.utils :as transport.utils])) + [status-im.transport.utils :as transport.utils] + [taoensso.timbre :as log])) ;;;; FX (re-frame/reg-fx ::accept-transaction (fn [{:keys [masked-password id on-completed]}] + ;; unmasking the password as late as possible to avoid being exposed from app-db + (status/approve-sign-request id + (security/unmask masked-password) + on-completed))) + +(re-frame/reg-fx + ::accept-transaction-with-changed-gas + (fn [{:keys [masked-password id on-completed gas gas-price]}] ;; unmasking the password as late as possible to avoid being exposed from app-db - (status/approve-sign-requests (list id) (security/unmask masked-password) on-completed))) + (status/approve-sign-request-with-args id + (security/unmask masked-password) + (money/to-fixed gas) + (money/to-fixed gas-price) + on-completed))) (defn- send-ethers [{:keys [web3 from to value gas gas-price]}] (.sendTransaction (.-eth web3) @@ -67,7 +80,7 @@ (or (and to (utils.hex/valid-hex? to)) (and data (not= data "0x")))) (defn dispatch-transaction-completed [result & [modal?]] - (re-frame/dispatch [::transaction-completed {:id (name (key result)) :response (second result)} modal?])) + (re-frame/dispatch [::transaction-completed {:id (:id result) :response result} modal?])) ;;;; Handlers (defn set-and-validate-amount-db [db amount symbol decimals] @@ -105,9 +118,8 @@ :password nil}) (defn on-transactions-completed [raw-results] - (let [results (:results (types/json->clj raw-results))] - (doseq [result results] - (dispatch-transaction-completed result)))) + (let [result (types/json->clj raw-results)] + (dispatch-transaction-completed result))) (handlers/register-handler-fx :sign-later-from-chat @@ -231,7 +243,7 @@ (handlers/register-handler-fx ::transaction-completed - (fn [{db :db now :now} [_ {:keys [id response]} modal?]] + (fn [{db :db now :now} [_ {:keys [id response] :as params} modal?]] (let [{:keys [hash error]} response {:keys [method]} (get-in db [:wallet :send-transaction]) db' (assoc-in db [:wallet :send-transaction :in-progress?] false)] @@ -252,9 +264,8 @@ {:dispatch [:navigate-to :wallet-transaction-sent]})))))) (defn on-transactions-modal-completed [raw-results] - (let [results (:results (types/json->clj raw-results))] - (doseq [result results] - (dispatch-transaction-completed result true)))) + (let [result (types/json->clj raw-results)] + (dispatch-transaction-completed result true))) (handlers/register-handler-fx :wallet/sign-transaction @@ -280,9 +291,8 @@ :symbol symbol :method method :network network}})))) - (handlers/register-handler-fx - :wallet/sign-transaction-modal + :wallet/sign-message-modal (fn [{db :db} _] (let [{:keys [id password]} (get-in db [:wallet :send-transaction])] {:db (assoc-in db [:wallet :send-transaction :in-progress?] true) @@ -290,6 +300,19 @@ :masked-password password :on-completed on-transactions-modal-completed}}))) +(handlers/register-handler-fx + :wallet/sign-transaction-modal + (fn [{db :db} _] + ;;TODO(goranjovic) - unify send-transaction and unsigned-transaction + (let [{:keys [id password] :as send-transaction} (get-in db [:wallet :send-transaction]) + {:keys [gas gas-price]} [:wallet.send/unsigned-transaction]] + {:db (assoc-in db [:wallet :send-transaction :in-progress?] true) + ::accept-transaction-with-changed-gas {:id id + :masked-password password + :gas (or gas (:gas send-transaction)) + :gas-price (or gas-price (:gas-price send-transaction)) + :on-completed on-transactions-modal-completed}}))) + (defn discard-transaction [{:keys [db]}] (let [{:keys [id]} (get-in db [:wallet :send-transaction])] diff --git a/src/status_im/ui/screens/wallet/send/subs.cljs b/src/status_im/ui/screens/wallet/send/subs.cljs index 4ffd18e789..8081971f75 100644 --- a/src/status_im/ui/screens/wallet/send/subs.cljs +++ b/src/status_im/ui/screens/wallet/send/subs.cljs @@ -51,8 +51,8 @@ (:id send-transaction))] (merge send-transaction unsigned-transaction - {:gas (or (:gas unsigned-transaction) (:gas send-transaction)) - :gas-price (or (:gas-price unsigned-transaction) (:gas-price send-transaction))})))) + {:gas (or (:gas send-transaction) (:gas unsigned-transaction)) + :gas-price (or (:gas-price send-transaction) (:gas-price unsigned-transaction))})))) (re-frame/reg-sub :wallet/edit :<- [:wallet] diff --git a/src/status_im/ui/screens/wallet/send/views.cljs b/src/status_im/ui/screens/wallet/send/views.cljs index fe4c4f2492..a5610de6a5 100644 --- a/src/status_im/ui/screens/wallet/send/views.cljs +++ b/src/status_im/ui/screens/wallet/send/views.cljs @@ -92,30 +92,39 @@ (i18n/label :t/transactions-sign-transaction) [vector-icons/icon :icons/forward {:color (if immediate-sign-enabled? :white :gray)}]]])) -(defn handler [discard?] - (if discard? - #(re-frame/dispatch [:wallet/discard-transaction-navigate-back]) - act/default-handler)) - -(defn- toolbar [discard? action title] - [toolbar/toolbar {:style wallet.styles/toolbar} - [toolbar/nav-button (action (handler discard?))] - [toolbar/content-title {:color :white} title]]) - (defn- max-fee [gas gas-price] (when (and gas gas-price) (money/wei->ether (.times gas gas-price)))) +(defn return-to-transaction [dapp-transaction?] + (if dapp-transaction? + (re-frame/dispatch [:navigate-to-modal :wallet-send-transaction-modal]) + (act/default-handler))) + +(defn handler [discard? dapp-transaction?] + (if discard? + #(re-frame/dispatch [:wallet/discard-transaction-navigate-back]) + #(return-to-transaction dapp-transaction?))) + +(defn- toolbar [discard? dapp-transaction? action title] + [toolbar/toolbar {:style wallet.styles/toolbar} + [toolbar/nav-button (action (handler discard? dapp-transaction?))] + [toolbar/content-title {:color :white} title]]) + (defview transaction-fee [] - (letsubs [{:keys [amount symbol] :as transaction} [:wallet.send/transaction] - network [:get-current-account-network] + (letsubs [send-transaction [:wallet.send/transaction] + unsigned-transaction [:wallet.send/unsigned-transaction] + network [:get-current-account-network] {gas-edit :gas gas-price-edit :gas-price} [:wallet/edit]] - (let [gas (or (:value gas-edit) (:gas transaction)) + (let [modal? (:id send-transaction) + ;;TODO(goranjovic) - unify unsigned and regular transaction subs + {:keys [amount symbol] :as transaction} (if modal? unsigned-transaction send-transaction) + gas (or (:value gas-edit) (:gas transaction)) gas-price (or (:value gas-price-edit) (:gas-price transaction)) {:keys [decimals]} (tokens/asset-for (ethereum/network->chain-keyword network) symbol)] - [wallet.components/simple-screen {:status-toolbar-type :modal-wallet} - [toolbar true act/close-white + [wallet.components/simple-screen {:status-bar-type :modal-wallet} + [toolbar false modal? act/close-white (i18n/label :t/wallet-transaction-fee)] [react/view components.styles/flex [react/view {:flex-direction :row} @@ -170,7 +179,7 @@ :accessibility-label :reset-to-default-button} (i18n/label :t/reset-default)] [button/button {:on-press #(do (re-frame/dispatch [:wallet.send/set-gas-details gas gas-price]) - (act/default-handler)) + (return-to-transaction modal?)) :accessibility-label :done-button :disabled? (or (:invalid? gas-edit) (:invalid? gas-price-edit))} @@ -178,8 +187,7 @@ (defn- advanced-cartouche [{:keys [gas gas-price]} modal?] [react/view - [wallet.components/cartouche {:disabled? modal? - :on-press #(do (re-frame/dispatch [:wallet.send/clear-gas]) + [wallet.components/cartouche {:on-press #(do (re-frame/dispatch [:wallet.send/clear-gas]) (re-frame/dispatch [:navigate-to-modal :wallet-transaction-fee]))} (i18n/label :t/wallet-transaction-fee) [react/view {:style styles/advanced-options-text-wrapper @@ -209,7 +217,7 @@ timeout (atom nil)] [wallet.components/simple-screen {:avoid-keyboard? (not modal?) :status-bar-type (if modal? :modal-wallet :wallet)} - [toolbar from-chat? (if modal? act/close-white act/back-white) + [toolbar from-chat? false (if modal? act/close-white act/back-white) (i18n/label :t/send-transaction)] [react/view components.styles/flex [common/network-info {:text-color :white}] @@ -264,14 +272,14 @@ [react/view wallet.styles/wallet-modal-container [react/view components.styles/flex [status-bar/status-bar {:type :modal-wallet}] - [toolbar false act/close-white + [toolbar false false act/close-white (i18n/label :t/send-transaction)] [react/text {:style styles/empty-text} (i18n/label :t/unsigned-transaction-expired)]]]))) (defview sign-message-modal [] (letsubs [{:keys [data in-progress?]} [:wallet.send/unsigned-transaction]] [wallet.components/simple-screen {:status-bar-type :modal-wallet} - [toolbar true act/close-white + [toolbar true false act/close-white (i18n/label :t/sign-message)] [react/view components.styles/flex [react/scroll-view @@ -285,7 +293,7 @@ nil]]]] [signing-buttons #(re-frame/dispatch [:wallet/discard-transaction-navigate-back]) - #(re-frame/dispatch [:wallet/sign-transaction-modal]) + #(re-frame/dispatch [:wallet/sign-message-modal]) :t/transactions-sign] [sign-panel true] (when in-progress?