Skip to content

Commit

Permalink
[#8026] [Wallet] Sign transaction module
Browse files Browse the repository at this point in the history
  • Loading branch information
flexsurfer committed Jun 12, 2019
1 parent eb4ba4c commit 7de2941
Show file tree
Hide file tree
Showing 43 changed files with 1,073 additions and 1,439 deletions.
7 changes: 0 additions & 7 deletions components/src/status_im/ui/components/react.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -301,20 +301,13 @@
(case current-view
(:wallet
:wallet-send-transaction
:wallet-transaction-sent
:wallet-request-transaction
:wallet-send-transaction-chat
:wallet-send-assets
:wallet-request-assets
:choose-recipient
:recent-recipients
:wallet-send-transaction-modal
:wallet-transaction-sent-modal
:wallet-send-transaction-request
:wallet-transaction-fee
:wallet-sign-message-modal
:contact-code
:wallet-onboarding-setup
:wallet-modal
:wallet-onboarding-setup-modal
:wallet-settings-hook)
Expand Down
63 changes: 50 additions & 13 deletions src/status_im/browser/core.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
[status-im.utils.random :as random]
[status-im.utils.types :as types]
[status-im.utils.universal-links.core :as universal-links]
[taoensso.timbre :as log]))
[taoensso.timbre :as log]
[status-im.signing.core :as signing]))

(fx/defn initialize-browsers
[{:keys [db all-stored-browsers]}]
Expand Down Expand Up @@ -274,19 +275,55 @@
(navigation/navigate-to-cofx :browser nil)
(resolve-url nil))))

(fx/defn web3-error-callback
{:events [:browser.dapp/transaction-on-error]}
[{{:keys [webview-bridge]} :db} message-id message]
{:browser/send-to-bridge
{:message {:type constants/web3-send-async-callback
:messageId message-id
:error message}
:webview webview-bridge}})

(fx/defn dapp-complete-transaction
{:events [:browser.dapp/transaction-on-result]}
[{{:keys [webview-bridge]} :db} message-id id result]
;;TODO check and test id
{:browser/send-to-bridge
{:message {:type constants/web3-send-async-callback
:messageId message-id
:result {:jsonrpc "2.0"
:id (int id)
:result result}}
:webview webview-bridge}})

(defn normalize-sign-message-params
"NOTE (andrey) we need this function, because params may be mixed up"
[params]
(let [[first-param second-param] params]
(cond
(ethereum/address? first-param)
[first-param second-param]
(ethereum/address? second-param)
[second-param first-param])))

(fx/defn web3-send-async
[{:keys [db]} {:keys [method] :as payload} message-id]
(if (or (= constants/web3-send-transaction method)
(constants/web3-sign-message? method))
{:db (update-in db [:wallet :transactions-queue] conj {:message-id message-id :payload payload})
;;TODO(yenda): refactor check-dapps-transactions-queue to remove this dispatch
:dispatch [:check-dapps-transactions-queue]}
{:browser/call-rpc [payload
#(re-frame/dispatch [:browser.callback/call-rpc
{:type constants/web3-send-async-callback
:messageId message-id
:error %1
:result %2}])]}))
[cofx {:keys [method params id] :as payload} message-id]
(let [message? (constants/web3-sign-message? method)]
(if (or message? (= constants/web3-send-transaction method))
(let [[address data] (when message? (normalize-sign-message-params params))]
(when (or (not message?) (and address data))
(signing/sign cofx (merge
(if message?
{:message {:address address :data data :typed? (not= constants/web3-personal-sign method)}}
{:tx-obj (first params)})
{:on-result [:browser.dapp/transaction-on-result message-id id]
:on-error [:browser.dapp/transaction-on-error message-id]}))))
{:browser/call-rpc [payload
#(re-frame/dispatch [:browser.callback/call-rpc
{:type constants/web3-send-async-callback
:messageId message-id
:error %1
:result %2}])]})))

(fx/defn send-to-bridge
[cofx message]
Expand Down
62 changes: 20 additions & 42 deletions src/status_im/chat/commands/impl/transactions.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
:as
transactions-styles]
[status-im.chat.commands.protocol :as protocol]
[status-im.contact.db :as db.contact]
[status-im.data-store.messages :as messages-store]
[status-im.ethereum.core :as ethereum]
[status-im.ethereum.tokens :as tokens]
Expand All @@ -18,16 +17,13 @@
[status-im.ui.components.list.views :as list]
[status-im.ui.components.react :as react]
[status-im.ui.components.svgimage :as svgimage]
[status-im.ui.screens.navigation :as navigation]
[status-im.ui.screens.wallet.choose-recipient.events
:as
choose-recipient.events]
[status-im.ui.screens.wallet.utils :as wallet.utils]
[status-im.utils.datetime :as datetime]
[status-im.utils.fx :as fx]
[status-im.utils.money :as money]
[status-im.utils.platform :as platform]
[status-im.wallet.db :as wallet.db])
[status-im.wallet.db :as wallet.db]
[status-im.signing.core :as signing]
[status-im.ethereum.abi-spec :as abi-spec])
(:require-macros [status-im.utils.views :refer [defview letsubs]]))

;; common `send/request` functionality
Expand Down Expand Up @@ -287,8 +283,8 @@
(description [_] (i18n/label :t/send-command-payment))
(parameters [_] personal-send-request-params)
(validate [_ parameters cofx]
;; Only superficial/formatting validation, "real validation" will be performed
;; by the wallet, where we yield control in the next step
;; Only superficial/formatting validation, "real validation" will be performed
;; by the wallet, where we yield control in the next step
(personal-send-request-validation parameters cofx))
(on-send [_ {:keys [chat-id] :as send-message} {:keys [db]}]
(when-let [responding-to (get-in db [:chats chat-id :metadata :responding-to-command])]
Expand All @@ -304,39 +300,21 @@
(send-preview command-message))
protocol/Yielding
(yield-control [_ {{{amount :amount asset :asset} :params} :content} {:keys [db] :as cofx}]
;; Prefill wallet and navigate there
(let [recipient-contact (or
(get-in db [:contacts/contacts (:current-chat-id db)])
(db.contact/public-key->new-contact (:current-chat-id db)))

sender-account (:account/account db)
chain (keyword (:chain db))
symbol-param (keyword asset)
all-tokens (:wallet/all-tokens db)
{:keys [symbol decimals]} (tokens/asset-for all-tokens chain symbol-param)
{:keys [value error]} (wallet.db/parse-amount amount decimals)
next-view-id (if (:wallet-set-up-passed? sender-account)
:wallet-send-modal-stack
:wallet-send-modal-stack-with-onboarding)]
(fx/merge cofx
{:db (-> db
(assoc-in [:navigation/screen-params :wallet-send-modal-stack :modal?] true)
(update-in [:wallet :send-transaction]
assoc
:amount (money/formatted->internal value symbol decimals)
:amount-text amount
:amount-error error)
(choose-recipient.events/fill-request-details
(transaction-details recipient-contact symbol) false)
(update-in [:wallet :send-transaction]
dissoc :id :password :wrong-password?))
;; TODO(janherich) - refactor wallet send events, updating gas price
;; is generic thing which shouldn't be defined in wallet.send, then
;; we can include the utility helper without running into circ-dep problem
:wallet/update-gas-price
{:success-event :wallet/update-gas-price-success
:edit? false}}
(navigation/navigate-to-cofx next-view-id {}))))
(let [{:keys [symbol decimals address]} (tokens/asset-for (:wallet/all-tokens db) (keyword (:chain db)) (keyword asset))
{:keys [value]} (wallet.db/parse-amount amount decimals)
current-chat-id (:current-chat-id db)
amount-hex (str "0x" (abi-spec/number-to-hex (money/formatted->internal value symbol decimals)))
to (ethereum/public-key->address current-chat-id)
to-norm (ethereum/normalized-address (if (= symbol :ETH) to address))
tx-obj (if (= symbol :ETH)
{:to to-norm
:value amount-hex}
{:to to-norm
:data (abi-spec/encode "transfer(address,uint256)" [to amount-hex])})]
(signing/sign cofx {:tx-obj tx-obj
:on-result [:chat/send-transaction-result current-chat-id {:address to-norm
:asset (name symbol)
:amount amount}]})))
protocol/EnhancedParameters
(enhance-send-parameters [_ parameters cofx]
(-> parameters
Expand Down
5 changes: 5 additions & 0 deletions src/status_im/chat/models/input.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,11 @@
(command-not-complete-fx input-text current-chat-id cofx))
(plain-text-message-fx input-text current-chat-id cofx))))

(fx/defn send-transaction-result
{:events [:chat/send-transaction-result]}
[cofx chat-id params result]
(commands.sending/send cofx chat-id (get-in cofx [:db :id->command ["send" #{:personal-chats}]]) (assoc params :tx-hash result)))

;; effects

(re-frame/reg-fx
Expand Down
4 changes: 4 additions & 0 deletions src/status_im/constants.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,10 @@
;; (ethereum/sha3 "Transfer(address,address,uint256)")
(def ^:const event-transfer-hash "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef")

(def ^:const method-id-transfer "0xa9059cbb")
(def ^:const method-id-approve "0x095ea7b3")
(def ^:const method-id-approve-and-call "0xcae9ca51")

(def regx-emoji #"^((?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85\uDFC2-\uDFC4\uDFC7\uDFCA-\uDFCC]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66-\uDC69\uDC6E\uDC70-\uDC78\uDC7C\uDC81-\uDC83\uDC85-\uDC87\uDCAA\uDD74\uDD75\uDD7A\uDD90\uDD95\uDD96\uDE45-\uDE47\uDE4B-\uDE4F\uDEA3\uDEB4-\uDEB6\uDEC0\uDECC]|\uD83E[\uDD18-\uDD1C\uDD1E\uDD1F\uDD26\uDD30-\uDD39\uDD3D\uDD3E\uDDD1-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])?|(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDEEB\uDEEC\uDEF4-\uDEF8]|\uD83E[\uDD10-\uDD3A\uDD3C-\uDD3E\uDD40-\uDD45\uDD47-\uDD4C\uDD50-\uDD6B\uDD80-\uDD97\uDDC0\uDDD0-\uDDE6])|(?:[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u2660\u2663\u2665\u2666\u2668\u267B\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD7A\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA4\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED2\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3-\uDEF8]|\uD83E[\uDD10-\uDD3A\uDD3C-\uDD3E\uDD40-\uDD45\uDD47-\uDD4C\uDD50-\uDD6B\uDD80-\uDD97\uDDC0\uDDD0-\uDDE6])\uFE0F|[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF])+$")
(def regx-rtl-characters #"[^\u0591-\u06EF\u06FA-\u07FF\u200F\u202B\u202E\uFB1D-\uFDFD\uFE70-\uFEFC]*?[\u0591-\u06EF\u06FA-\u07FF\u200F\u202B\u202E\uFB1D-\uFDFD\uFE70-\uFEFC]")
(def regx-url #"(?i)(?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9\-]+[.][a-z]{1,4}/?)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:\'\".,<>?«»“”‘’]){0,}")
Expand Down
2 changes: 1 addition & 1 deletion src/status_im/ethereum/json_rpc.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"eth_getBalance"
{:on-result money/bignumber}
"eth_estimateGas"
{:on-result money/bignumber}
{:on-result #(money/bignumber (int (* % 1.2)))}
"eth_gasPrice"
{:on-result money/bignumber}
"eth_getBlockByHash"
Expand Down
27 changes: 5 additions & 22 deletions src/status_im/events.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -2102,28 +2102,6 @@
(fn [cofx [_ hash]]
(wallet/open-transaction-details cofx hash)))

(handlers/register-handler-fx
:wallet/show-sign-transaction
(fn [cofx [_ {:keys [id method]} from-chat?]]
(wallet/open-send-transaction-modal cofx id method from-chat?)))

(handlers/register-handler-fx
:wallet/update-gas-price-success
(fn [cofx [_ price edit?]]
(wallet/update-gas-price cofx price edit?)))

(handlers/register-handler-fx
:TODO.remove/update-estimated-gas
(fn [{:keys [db]} [_ obj]]
{:wallet/update-estimated-gas
{:obj obj
:success-event :wallet/update-estimated-gas-success}}))

(handlers/register-handler-fx
:wallet/update-estimated-gas-success
(fn [cofx [_ gas]]
(wallet/update-estimated-gas-price cofx gas)))

(handlers/register-handler-fx
:wallet.setup.ui/navigate-back-pressed
(fn [{:keys [db] :as cofx}]
Expand All @@ -2135,3 +2113,8 @@
:shake-event
(fn [cofx _]
(logging/show-logs-dialog cofx)))

(re-frame/reg-fx
:dismiss-keyboard
(fn []
(react/dismiss-keyboard!)))
57 changes: 11 additions & 46 deletions src/status_im/extensions/capacities/ethereum.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,17 @@
[status-im.ethereum.abi-spec :as abi-spec]
[status-im.ethereum.core :as ethereum]
[status-im.ethereum.ens :as ens]
[status-im.i18n :as i18n]
[status-im.native-module.core :as status]
[status-im.ui.screens.navigation :as navigation]
[status-im.utils.fx :as fx]
[status-im.utils.handlers :as handlers]
[status-im.utils.hex :as hex]
[status-im.utils.money :as money]
[status-im.utils.types :as types]
[status-im.wallet.core :as wallet]))
[status-im.signing.core :as signing]))

(handlers/register-handler-fx
:extensions/wallet-ui-on-success
(fn [cofx [_ on-success _ result _]]
(fx/merge cofx
(when on-success (on-success {:value result}))
(navigation/navigate-back))))
(fn [_ [_ on-success result]]
(when on-success (on-success {:value result}))))

(handlers/register-handler-fx
:extensions/wallet-ui-on-failure
Expand All @@ -42,35 +37,11 @@
#(f db (assoc arguments address-keyword %))))
(f db arguments))))

(defn prepare-extension-transaction [params contacts on-success on-failure]
(let [{:keys [to value data gas gasPrice nonce]} params
contact (get contacts (hex/normalize-hex to))]
(cond-> {:id "extension-id"
:to-name (or (when (nil? to)
(i18n/label :t/new-contract))
contact)
:symbol :ETH
:method constants/web3-send-transaction
:to to
:amount (money/bignumber (or value 0))
:gas (cond
gas
(money/bignumber gas)
(and value (empty? data))
(money/bignumber 21000))
:gas-price (when gasPrice
(money/bignumber gasPrice))
:data data
:on-result [:extensions/wallet-ui-on-success on-success]
:on-error [:extensions/wallet-ui-on-failure on-failure]}
nonce
(assoc :nonce nonce))))

(defn- execute-send-transaction [db {:keys [method params on-success on-failure] :as arguments}]
(let [tx-object (assoc (select-keys arguments [:to :gas :gas-price :value :nonce])
:data (when (and method params) (abi-spec/encode method params)))
transaction (prepare-extension-transaction tx-object (:contacts/contacts db) on-success on-failure)]
(wallet/open-modal-wallet-for-transaction db transaction tx-object)))
(signing/sign {:db db} {:tx-obj (assoc (select-keys arguments [:to :gas :gas-price :value :nonce])
:data (when (and method params) (abi-spec/encode method params)))
:on-result [:extensions/wallet-ui-on-success on-success]
:on-error [:extensions/wallet-ui-on-failure on-failure]}))

(handlers/register-handler-fx
:extensions/ethereum-send-transaction
Expand Down Expand Up @@ -381,22 +352,16 @@
(when on-failure
(on-failure {:value (str "'" name "' is not a valid name")})))))

;; EXTENSION SIGN -> SIGN MESSAGE
(handlers/register-handler-fx
:extensions/ethereum-sign
(fn [{db :db :as cofx} [_ _ {:keys [message data id on-success on-failure]}]]
(if (and message data)
(when on-failure
(on-failure {:error "only one of :message and :data can be used"}))
(fx/merge cofx
{:db (assoc-in db [:wallet :send-transaction]
{:id id
:from (ethereum/current-address db)
:data (or data (ethereum/utf8-to-hex message))
:on-result [:extensions/wallet-ui-on-success on-success]
:on-error [:extensions/wallet-ui-on-failure on-failure]
:method constants/web3-personal-sign})}
(navigation/navigate-to-cofx :wallet-sign-message-modal nil)))))
(signing/sign cofx {:message {:address (ethereum/current-address db)
:data (or data (ethereum/utf8-to-hex message))}
:on-result [:extensions/wallet-ui-on-success on-success]
:on-error [:extensions/wallet-ui-on-failure on-failure]}))))

(handlers/register-handler-fx
:extensions/ethereum-create-address
Expand Down
Loading

0 comments on commit 7de2941

Please sign in to comment.