Update sending transaction end point (#21480) (#21541)

* Update sending transaction end point

* Transaction approval

* Fixes

* Fixes

* Fixes

* Fix for issue 3

* Fixes for 2, 4, 7

* Update

* Fixes

* Fixes
This commit is contained in:
Alexander 2024-11-28 14:08:35 +01:00 committed by GitHub
parent 5f8d5fd57e
commit de2b5fb935
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 488 additions and 443 deletions

View File

@ -45,6 +45,12 @@
"wallet.suggested.routes" "wallet.suggested.routes"
{:fx [[:dispatch [:wallet/handle-suggested-routes (transforms/js->clj event-js)]]]} {:fx [[:dispatch [:wallet/handle-suggested-routes (transforms/js->clj event-js)]]]}
"wallet.router.sign-transactions"
{:fx [[:dispatch [:wallet/sign-transactions-signal-received (transforms/js->clj event-js)]]]}
"wallet.router.transactions-sent"
{:fx [[:dispatch [:wallet/transactions-sent-signal-received (transforms/js->clj event-js)]]]}
"envelope.sent" "envelope.sent"
(messages.transport/update-envelopes-status (messages.transport/update-envelopes-status
cofx cofx

View File

@ -116,6 +116,7 @@
:on-close #(rf/dispatch [:standard-auth/reset-login-password]) :on-close #(rf/dispatch [:standard-auth/reset-login-password])
:content (fn [] :content (fn []
[keycard.pin/auth {:on-complete on-complete}])}]]]}) [keycard.pin/auth {:on-complete on-complete}])}]]]})
(rf/reg-event-fx :standard-auth/authorize-with-keycard authorize-with-keycard) (rf/reg-event-fx :standard-auth/authorize-with-keycard authorize-with-keycard)
(defn authorize-with-password (defn authorize-with-password

View File

@ -565,6 +565,18 @@
(:less-than-five-minutes constants/wallet-transaction-estimation) "3-5" (:less-than-five-minutes constants/wallet-transaction-estimation) "3-5"
">5")) ">5"))
(defn transactions->hash-to-transaction-map
[transactions]
(reduce
(fn [acc {to-chain :toChain tx-hash :hash}]
(assoc acc
tx-hash
{:status :pending
:id tx-hash
:chain-id to-chain}))
{}
transactions))
(defn get-accounts-with-token-balance (defn get-accounts-with-token-balance
[accounts token] [accounts token]
(let [operable-account (filter :operable? (vals accounts)) (let [operable-account (filter :operable? (vals accounts))

View File

@ -5,6 +5,7 @@
[promesa.core :as promesa] [promesa.core :as promesa]
[status-im.common.json-rpc.events :as json-rpc] [status-im.common.json-rpc.events :as json-rpc]
[status-im.contexts.profile.recover.effects :as profile.recover.effects] [status-im.contexts.profile.recover.effects :as profile.recover.effects]
[status-im.contexts.wallet.rpc :as wallet-rpc]
[taoensso.timbre :as log] [taoensso.timbre :as log]
[utils.re-frame :as rf] [utils.re-frame :as rf]
[utils.security.core :as security] [utils.security.core :as security]
@ -103,3 +104,22 @@
(-> (verify-private-key-for-keypair keypair-key-uid private-key) (-> (verify-private-key-for-keypair keypair-key-uid private-key)
(promesa/then (partial rf/call-continuation on-success)) (promesa/then (partial rf/call-continuation on-success))
(promesa/catch (partial rf/call-continuation on-error))))) (promesa/catch (partial rf/call-continuation on-error)))))
(defn sign-transaction-hashes
[hashes address password]
(-> (promesa/all
(for [h hashes]
(promesa/let [signature (wallet-rpc/sign-message h address password)]
{:message h
:signature signature})))
(promesa/catch (fn [err]
(throw (ex-info "Failed to sign transaction hashes"
{:error err
:code :error/sign-transaction-hashes}))))))
(rf/reg-fx
:effects.wallet/sign-transaction-hashes
(fn [{:keys [hashes address password on-success on-error]}]
(-> (sign-transaction-hashes hashes address password)
(promesa/then on-success)
(promesa/catch on-error))))

View File

@ -701,3 +701,36 @@
(let [full-status (cske/transform-keys message transforms/->kebab-case-keyword)] (let [full-status (cske/transform-keys message transforms/->kebab-case-keyword)]
{:db (assoc-in db [:wallet :blockchain] full-status)}))) {:db (assoc-in db [:wallet :blockchain] full-status)})))
(rf/reg-event-fx
:wallet/sign-transactions-signal-received
(fn [{:keys [db]} [{send-details :sendDetails :as data}]]
(let [type (if (or (= (:fromToken send-details)
(:toToken send-details))
(string/blank? (:toToken send-details)))
:send
:swap)
callback-fx (get-in db [:wallet :ui type :sign-transactions-callback-fx])
error-response (:errorResponse send-details)]
{:fx [(when (and callback-fx (not error-response))
callback-fx)]
:db (-> db
(assoc-in [:wallet :ui type :sign-transactions-callback-fx] nil)
(assoc-in [:wallet :ui type :error-response] error-response)
(assoc-in [:wallet :ui type :transaction-for-signing] data))})))
(rf/reg-event-fx
:wallet/transactions-sent-signal-received
(fn [{:keys [db]}
[{sent-transactions :sentTransactions
send-details :sendDetails}]]
(let [swap? (get-in db [:wallet :ui :swap])]
{:fx [[:dispatch
(if-let [error-response (:errorResponse send-details)]
[(if swap?
:wallet.swap/transaction-failure
:wallet/transaction-failure)
error-response]
[(if swap?
:wallet.swap/transaction-success
:wallet/transaction-success)
sent-transactions])]]})))

View File

@ -0,0 +1,59 @@
(ns status-im.contexts.wallet.rpc
(:require [oops.core :as oops]
[promesa.core :as promesa]
[status-im.common.json-rpc.events :as rpc-events]
[status-im.constants :as constants]
[utils.hex]
[utils.transforms :as transforms]))
(defn build-transaction
[chain-id tx]
(promesa/let [res (rpc-events/call-async "wallet_buildTransaction" true chain-id tx)]
{:message-to-sign (oops/oget res :messageToSign)
:tx-args (oops/oget res :txArgs)}))
(defn build-raw-transaction
[chain-id tx-args signature]
(-> (rpc-events/call-async "wallet_buildRawTransaction"
true
chain-id
(transforms/js-stringify tx-args 0)
signature)
(promesa/then #(oops/oget % "rawTx"))))
(defn hash-message-eip-191
[message]
(rpc-events/call-async "wallet_hashMessageEIP191" true message))
(defn safe-sign-typed-data
[data address password chain-id legacy?]
(rpc-events/call-async "wallet_safeSignTypedDataForDApps"
true
data
address
password
chain-id
legacy?))
(defn get-suggested-fees
[chain-id]
(-> (rpc-events/call-async "wallet_getSuggestedFees" true chain-id)
(promesa/then transforms/js->clj)))
(defn send-transaction-with-signature
[chain-id tx-args signature]
(rpc-events/call-async "wallet_sendTransactionWithSignature"
true
chain-id
constants/transaction-pending-type-wallet-connect-transfer
(transforms/js-stringify tx-args 0)
signature))
(defn sign-message
[message address password]
(-> (rpc-events/call-async "wallet_signMessage"
true
message
address
password)
(promesa/then utils.hex/normalize-hex)))

View File

@ -1,7 +1,6 @@
(ns status-im.contexts.wallet.send.events (ns status-im.contexts.wallet.send.events
(:require (:require
[clojure.string :as string] [clojure.string :as string]
[native-module.core :as native-module]
[status-im.constants :as constants] [status-im.constants :as constants]
[status-im.contexts.wallet.collectible.utils :as collectible.utils] [status-im.contexts.wallet.collectible.utils :as collectible.utils]
[status-im.contexts.wallet.common.utils :as utils] [status-im.contexts.wallet.common.utils :as utils]
@ -9,11 +8,10 @@
[status-im.contexts.wallet.data-store :as data-store] [status-im.contexts.wallet.data-store :as data-store]
[status-im.contexts.wallet.send.utils :as send-utils] [status-im.contexts.wallet.send.utils :as send-utils]
[taoensso.timbre :as log] [taoensso.timbre :as log]
[utils.address :as address]
[utils.hex :as utils.hex]
[utils.money :as utils.money] [utils.money :as utils.money]
[utils.number] [utils.number]
[utils.re-frame :as rf])) [utils.re-frame :as rf]
[utils.security.core :as security]))
(rf/reg-event-fx :wallet/clean-send-data (rf/reg-event-fx :wallet/clean-send-data
(fn [{:keys [db]}] (fn [{:keys [db]}]
@ -327,22 +325,30 @@
(rf/reg-event-fx (rf/reg-event-fx
:wallet/set-token-amount-to-send :wallet/set-token-amount-to-send
(fn [{:keys [db]} [{:keys [amount stack-id start-flow?]}]] (fn [{:keys [db]} [{:keys [amount stack-id start-flow?]}]]
{:db (assoc-in db [:wallet :ui :send :amount] amount) (let [last-request-uuid (get-in db [:wallet :ui :send :last-request-uuid])]
:fx [[:dispatch {:db (-> db
(assoc-in [:wallet :ui :send :amount] amount)
(update-in [:wallet :ui :send] dissoc :transaction-for-signing))
:fx [[:dispatch [:wallet/build-transactions-from-route {:request-uuid last-request-uuid}]]
[:dispatch
[:wallet/wizard-navigate-forward [:wallet/wizard-navigate-forward
{:current-screen stack-id {:current-screen stack-id
:start-flow? start-flow? :start-flow? start-flow?
:flow-id :wallet-send-flow}]]]})) :flow-id :wallet-send-flow}]]]})))
(rf/reg-event-fx (rf/reg-event-fx
:wallet/set-token-amount-to-bridge :wallet/set-token-amount-to-bridge
(fn [{:keys [db]} [{:keys [amount stack-id start-flow?]}]] (fn [{:keys [db]} [{:keys [amount stack-id start-flow?]}]]
{:db (assoc-in db [:wallet :ui :send :amount] amount) (let [last-request-uuid (get-in db [:wallet :ui :send :last-request-uuid])]
:fx [[:dispatch {:db (-> db
(assoc-in [:wallet :ui :send :amount] amount)
(update-in [:wallet :ui :send] dissoc :transaction-for-signing))
:fx [[:dispatch [:wallet/build-transactions-from-route {:request-uuid last-request-uuid}]]
[:dispatch
[:wallet/wizard-navigate-forward [:wallet/wizard-navigate-forward
{:current-screen stack-id {:current-screen stack-id
:start-flow? start-flow? :start-flow? start-flow?
:flow-id :wallet-bridge-flow}]]]})) :flow-id :wallet-bridge-flow}]]]})))
(rf/reg-event-fx (rf/reg-event-fx
:wallet/clean-bridge-to-selection :wallet/clean-bridge-to-selection
@ -458,7 +464,8 @@
:token-networks-ids token-networks-ids :token-networks-ids token-networks-ids
:tx-type tx-type :tx-type tx-type
:receiver? true})) :receiver? true}))
params [{:uuid (str (random-uuid)) request-uuid (str (random-uuid))
params [{:uuid request-uuid
:sendType send-type :sendType send-type
:addrFrom from-address :addrFrom from-address
:addrTo to-address :addrTo to-address
@ -477,7 +484,8 @@
{:db (update-in db {:db (update-in db
[:wallet :ui :send] [:wallet :ui :send]
#(-> % #(-> %
(assoc :amount amount (assoc :last-request-uuid request-uuid
:amount amount
:loading-suggested-routes? true :loading-suggested-routes? true
:sender-network-values sender-network-values :sender-network-values sender-network-values
:receiver-network-values receiver-network-values) :receiver-network-values receiver-network-values)
@ -565,27 +573,39 @@
:else [:wallet/suggested-routes-success (fix-routes data) :else [:wallet/suggested-routes-success (fix-routes data)
enough-assets?])]]}))))) enough-assets?])]]})))))
(rf/reg-event-fx :wallet/add-authorized-transaction (rf/reg-event-fx
(fn [{:keys [db]} [transaction]] :wallet/transaction-success
(let [transaction-batch-id (:id transaction) (fn [{:keys [db]} [sent-transactions]]
transaction-hashes (:hashes transaction) (let [wallet-transactions (get-in db [:wallet :transactions] {})
transaction-ids (flatten (vals transaction-hashes)) transactions (utils/transactions->hash-to-transaction-map sent-transactions)
transaction-details (send-utils/map-multitransaction-by-ids transaction-batch-id transaction-ids (->> transactions
transaction-hashes)] vals
(map :hash))]
{:db (-> db {:db (-> db
(assoc-in [:wallet :ui :send :just-completed-transaction?] true) (assoc-in [:wallet :ui :send :just-completed-transaction?] true)
(assoc-in [:wallet :transactions] transaction-details) (assoc-in [:wallet :ui :send :transaction-ids] transaction-ids)
(assoc-in [:wallet :ui :send :transaction-ids] transaction-ids)) (assoc-in [:wallet :transactions] (merge wallet-transactions transactions)))
:fx [;; Remove wallet/stop-and-clean-suggested-routes event when we move to new transaction :fx [[:dispatch [:wallet/end-transaction-flow]]
;; submission process as the routes as stopped by status-go [:dispatch-later
[:dispatch [{:ms 2000
[:wallet/stop-and-clean-suggested-routes]] :dispatch [:wallet/stop-and-clean-suggested-routes]}]]
[:dispatch
[:wallet/end-transaction-flow]]
[:dispatch-later [:dispatch-later
[{:ms 2000 [{:ms 2000
:dispatch [:wallet/clean-just-completed-transaction]}]]]}))) :dispatch [:wallet/clean-just-completed-transaction]}]]]})))
(rf/reg-event-fx
:wallet/transaction-failure
(fn [_ [{:keys [details]}]]
{:fx [[:dispatch [:wallet/end-transaction-flow]]
[:dispatch-later
[{:ms 2000
:dispatch [:wallet/stop-and-clean-suggested-routes]}]]
[:dispatch
[:toasts/upsert
{:id :send-transaction-failure
:type :negative
:text (or details "An error occured")}]]]}))
(rf/reg-event-fx :wallet/clean-just-completed-transaction (rf/reg-event-fx :wallet/clean-just-completed-transaction
(fn [{:keys [db]}] (fn [{:keys [db]}]
{:db (update-in db [:wallet :ui :send] dissoc :just-completed-transaction?)})) {:db (update-in db [:wallet :ui :send] dissoc :just-completed-transaction?)}))
@ -609,100 +629,65 @@
[{:ms 20 [{:ms 20
:dispatch [:wallet/clean-up-transaction-flow]}]]]}))) :dispatch [:wallet/clean-up-transaction-flow]}]]]})))
(rf/reg-event-fx :wallet/send-transaction (rf/reg-event-fx
(fn [{:keys [db]} [sha3-pwd]] :wallet/build-transactions-from-route
(let [routes (get-in db [:wallet :ui :send :route]) (fn [_ [{:keys [request-uuid slippage] :or {slippage constants/default-slippage}}]]
first-route (first routes) {:json-rpc/call [{:method "wallet_buildTransactionsFromRoute"
from-address (get-in db [:wallet :current-viewing-account-address]) :params [{:uuid request-uuid
transaction-type (get-in db [:wallet :ui :send :tx-type]) :slippagePercentage slippage}]
multi-transaction-type (if (= :tx/bridge transaction-type)
constants/multi-transaction-type-bridge
constants/multi-transaction-type-send)
token (get-in db [:wallet :ui :send :token])
collectible (get-in db [:wallet :ui :send :collectible])
first-route-from-chain-id (get-in first-route [:from :chain-id])
token-id (if token
(:symbol token)
(get-in collectible [:id :token-id]))
erc20-transfer? (and token (not= token-id "ETH"))
eth-transfer? (and token (not erc20-transfer?))
token-address (cond collectible
(get-in collectible
[:id :contract-id :address])
erc20-transfer?
(get-in token [:balances-per-chain first-route-from-chain-id :address]))
to-address (get-in db [:wallet :ui :send :to-address])
transaction-paths (into []
(mapcat
(fn [route]
(let [approval-required? (:approval-required route)
data (when erc20-transfer?
(native-module/encode-transfer
(address/normalized-hex to-address)
(:amount-in route)))
base-path (utils/transaction-path
{:to-address to-address
:from-address from-address
:route route
:token-address token-address
:token-id-from (if collectible
(utils.hex/number-to-hex
token-id)
token-id)
:data data
:eth-transfer? eth-transfer?})]
(if approval-required?
[(utils/approval-path {:route route
:token-address token-address
:from-address from-address
:to-address to-address})
base-path]
[base-path]))))
routes)
request-params
[(utils/multi-transaction-command
{:from-address from-address
:to-address to-address
:from-asset token-id
:to-asset token-id
:amount-out (if eth-transfer? (:amount-out first-route) "0x0")
:multi-transaction-type multi-transaction-type})
transaction-paths
sha3-pwd]]
(log/info "multi transaction called")
{:json-rpc/call [{:method "wallet_createMultiTransaction"
:params request-params
:on-success (fn [result]
(when result
(rf/dispatch [:wallet/add-authorized-transaction result])
(rf/dispatch [:hide-bottom-sheet])))
:on-error (fn [error] :on-error (fn [error]
(log/error "failed to send transaction" (log/error "failed to build transactions from route"
{:event :wallet/send-transaction {:event :wallet/build-transactions-from-route
:error error
:params request-params})
(rf/dispatch [:toasts/upsert
{:id :send-transaction-error
:type :negative
:text (:message error)}]))}]})))
(rf/reg-event-fx :wallet/proceed-with-transactions-signatures
(fn [_ [signatures]]
{:json-rpc/call [{:method "wallet_proceedWithTransactionsSignatures"
:params [signatures]
:on-success (fn [result]
(when result
(rf/dispatch [:wallet/add-authorized-transaction result])
(rf/dispatch [:hide-bottom-sheet])))
:on-error (fn [error]
(log/error "failed to proceed-with-transactions-signatures"
{:event :wallet/proceed-with-transactions-signatures
:error error}) :error error})
(rf/dispatch [:toasts/upsert (rf/dispatch [:toasts/upsert
{:id :send-transaction-error {:id :build-transactions-from-route-error
:type :negative :type :negative
:text (:message error)}]))}]})) :text (:message error)}]))}]}))
(rf/reg-event-fx
:wallet/prepare-signatures-for-transactions
(fn [{:keys [db]} [type sha3-pwd]]
(let [transaction-for-signing (get-in db [:wallet :ui type :transaction-for-signing])]
{:fx [[:effects.wallet/sign-transaction-hashes
{:hashes (get-in transaction-for-signing [:signingDetails :hashes])
:address (get-in transaction-for-signing [:signingDetails :address])
:password (security/safe-unmask-data sha3-pwd)
:on-success (fn [signatures]
(rf/dispatch [:wallet/send-router-transactions-with-signatures type
signatures]))
:on-error (fn [error]
(log/error "failed to prepare signatures for transactions"
{:event :wallet/prepare-signatures-for-transactions
:error error})
(rf/dispatch [:toasts/upsert
{:id :prepare-signatures-for-transactions-error
:type :negative
:text (:message error)}]))}]]})))
(rf/reg-event-fx
:wallet/send-router-transactions-with-signatures
(fn [{:keys [db]} [type signatures]]
(let [transaction-for-signing (get-in db [:wallet :ui type :transaction-for-signing])
signatures-map (reduce (fn [acc {:keys [message signature]}]
(assoc acc
message
(send-utils/signature-rsv signature)))
{}
signatures)]
{:json-rpc/call [{:method "wallet_sendRouterTransactionsWithSignatures"
:params [{:uuid (get-in transaction-for-signing [:sendDetails :uuid])
:signatures signatures-map}]
:on-success (fn []
(rf/dispatch [:hide-bottom-sheet]))
:on-error (fn [error]
(log/error "failed to send router transactions with signatures"
{:event :wallet/send-router-transactions-with-signatures
:error error})
(rf/dispatch [:toasts/upsert
{:id :send-router-transactions-with-signatures-error
:type :negative
:text (:message error)}]))}]})))
(rf/reg-event-fx (rf/reg-event-fx
:wallet/select-from-account :wallet/select-from-account
(fn [{db :db} [{:keys [address stack-id network-details start-flow?]}]] (fn [{db :db} [{:keys [address stack-id network-details start-flow?]}]]

View File

@ -575,29 +575,6 @@
:from-locked-amounts {}}}}}) :from-locked-amounts {}}}}})
(is (match? expected-db (:db (dispatch [event-id suggested-routes timestamp])))))) (is (match? expected-db (:db (dispatch [event-id suggested-routes timestamp]))))))
(h/deftest-event :wallet/add-authorized-transaction
[event-id dispatch]
(let [hashes {:chain-1 ["tx-1" "tx-2" "tx-3"]
:chain-2 ["tx-4" "tx-5"]
:chain-3 ["tx-6" "tx-7" "tx-8" "tx-9"]}
transaction-id "txid-1"
expected-result {:db {:wallet {:ui {:send {:transaction-ids ["tx-1" "tx-2" "tx-3"
"tx-4" "tx-5" "tx-6"
"tx-7" "tx-8" "tx-9"]}}
:transactions (send-utils/map-multitransaction-by-ids
transaction-id
hashes)}}
:fx [[:dispatch
[:wallet/stop-and-clean-suggested-routes]]
[:dispatch [:wallet/end-transaction-flow]]
[:dispatch-later
[{:ms 2000
:dispatch [:wallet/clean-just-completed-transaction]}]]]}]
(is (match? expected-result
(dispatch [event-id
{:id transaction-id
:hashes hashes}])))))
(h/deftest-event :wallet/select-from-account (h/deftest-event :wallet/select-from-account
[event-id dispatch] [event-id dispatch]
(let [stack-id :screen/stack (let [stack-id :screen/stack

View File

@ -13,8 +13,7 @@
[status-im.contexts.wallet.send.utils :as send-utils] [status-im.contexts.wallet.send.utils :as send-utils]
[status-im.feature-flags :as ff] [status-im.feature-flags :as ff]
[utils.i18n :as i18n] [utils.i18n :as i18n]
[utils.re-frame :as rf] [utils.re-frame :as rf]))
[utils.security.core :as security]))
(defn- transaction-title (defn- transaction-title
[{:keys [token-display-name amount account route to-network image-url transaction-type [{:keys [token-display-name amount account route to-network image-url transaction-type
@ -238,6 +237,7 @@
bridge-to-chain-id])) bridge-to-chain-id]))
loading-suggested-routes? (rf/sub loading-suggested-routes? (rf/sub
[:wallet/wallet-send-loading-suggested-routes?]) [:wallet/wallet-send-loading-suggested-routes?])
transaction-for-signing (rf/sub [:wallet/wallet-send-transaction-for-signing])
from-account-props {:customization-color account-color from-account-props {:customization-color account-color
:size 32 :size 32
:emoji (:emoji account) :emoji (:emoji account)
@ -268,16 +268,20 @@
:transaction-type transaction-type}] :transaction-type transaction-type}]
(when (and (not loading-suggested-routes?) route (seq route)) (when (and (not loading-suggested-routes?) route (seq route))
[standard-auth/slide-button [standard-auth/slide-button
{:keycard-supported? true {:keycard-supported? (get-in transaction-for-signing
[:signingDetails :signOnKeycard])
:size :size-48 :size :size-48
:track-text (if (= transaction-type :tx/bridge) :track-text (if (= transaction-type :tx/bridge)
(i18n/label :t/slide-to-bridge) (i18n/label :t/slide-to-bridge)
(i18n/label :t/slide-to-send)) (i18n/label :t/slide-to-send))
:container-style {:z-index 2} :container-style {:z-index 2}
:disabled? (not transaction-for-signing)
:customization-color account-color :customization-color account-color
:on-auth-success #(rf/dispatch :on-auth-success
[:wallet/send-transaction (fn [data]
(security/safe-unmask-data %)]) (rf/dispatch
[:wallet/prepare-signatures-for-transactions
:send data]))
:auth-button-label (i18n/label :t/confirm)}])] :auth-button-label (i18n/label :t/confirm)}])]
:gradient-cover? true :gradient-cover? true
:customization-color (:color account)} :customization-color (:color account)}

View File

@ -303,3 +303,9 @@
(defn bridge-disabled? (defn bridge-disabled?
[token-symbol] [token-symbol]
(not (constants/bridge-assets token-symbol))) (not (constants/bridge-assets token-symbol)))
(defn signature-rsv
[signature]
{:r (subs signature 0 64)
:s (subs signature 64 128)
:v (subs signature 128 130)})

View File

@ -1,14 +1,11 @@
(ns status-im.contexts.wallet.swap.events (ns status-im.contexts.wallet.swap.events
(:require [native-module.core :as native-module] (:require [re-frame.core :as rf]
[re-frame.core :as rf]
[status-im.constants :as constants] [status-im.constants :as constants]
[status-im.contexts.wallet.common.utils :as utils] [status-im.contexts.wallet.common.utils :as utils]
[status-im.contexts.wallet.send.utils :as send-utils] [status-im.contexts.wallet.send.utils :as send-utils]
[status-im.contexts.wallet.sheets.network-selection.view :as network-selection] [status-im.contexts.wallet.sheets.network-selection.view :as network-selection]
[status-im.contexts.wallet.swap.utils :as swap-utils] [status-im.contexts.wallet.swap.utils :as swap-utils]
[taoensso.timbre :as log] [taoensso.timbre :as log]
[utils.address :as address]
[utils.debounce :as debounce]
[utils.i18n :as i18n] [utils.i18n :as i18n]
[utils.money :as money] [utils.money :as money]
[utils.number :as number])) [utils.number :as number]))
@ -151,10 +148,9 @@
:disabledFromChainIDs disabled-from-chain-ids :disabledFromChainIDs disabled-from-chain-ids
:disabledToChainIDs disabled-to-chain-ids :disabledToChainIDs disabled-to-chain-ids
:gasFeeMode gas-rates :gasFeeMode gas-rates
:fromLockedAmount from-locked-amount} :fromLockedAmount from-locked-amount
amount-in (assoc :amountIn amount-in-hex) :amountOut (or amount-out-hex "0x0")}
amount-out (assoc :amountOut amount-out-hex))]] amount-in (assoc :amountIn amount-in-hex))]]
(when-let [amount (or amount-in amount-out)] (when-let [amount (or amount-in amount-out)]
{:db (update-in db {:db (update-in db
[:wallet :ui :swap] [:wallet :ui :swap]
@ -270,150 +266,21 @@
(fn [{:keys [db]}] (fn [{:keys [db]}]
{:db (update-in db [:wallet :ui] dissoc :swap)})) {:db (update-in db [:wallet :ui] dissoc :swap)}))
(rf/reg-event-fx :wallet/swap-transaction
(fn [{:keys [db]} [sha3-pwd]]
(let [wallet-address (get-in db
[:wallet
:current-viewing-account-address])
{:keys [asset-to-pay asset-to-receive
swap-proposal network amount
approval-transaction-id
max-slippage]} (get-in db [:wallet :ui :swap])
transactions (get-in db [:wallet :transactions])
approval-transaction (when approval-transaction-id
(get transactions approval-transaction-id))
already-approved? (and approval-transaction
(= (:status approval-transaction)
:confirmed))
approval-required? (and (:approval-required swap-proposal)
(not already-approved?))
multi-transaction-type constants/multi-transaction-type-swap
swap-chain-id (:chain-id network)
token-id-from (:symbol asset-to-pay)
token-id-to (:symbol asset-to-receive)
erc20-transfer? (and asset-to-pay (not= token-id-from "ETH"))
eth-transfer? (and asset-to-pay (not erc20-transfer?))
token-address (when erc20-transfer?
(get-in asset-to-pay
[:balances-per-chain swap-chain-id
:address]))
data (when erc20-transfer?
(native-module/encode-transfer
(address/normalized-hex wallet-address)
(:amount-in swap-proposal)))
transaction-paths (if approval-required?
[(utils/approval-path
{:route swap-proposal
:token-address token-address
:from-address wallet-address
:to-address wallet-address})]
[(utils/transaction-path
{:to-address wallet-address
:from-address wallet-address
:route swap-proposal
:token-address token-address
:token-id-from token-id-from
:token-id-to token-id-to
:data data
:slippage-percentage max-slippage
:eth-transfer? eth-transfer?})])
request-params [(utils/multi-transaction-command
{:from-address wallet-address
:to-address wallet-address
:from-asset token-id-from
:to-asset (if approval-required?
token-id-from
token-id-to)
:amount-out (if eth-transfer?
(:amount-out swap-proposal)
"0x0")
:multi-transaction-type
multi-transaction-type})
transaction-paths
sha3-pwd]]
(log/info "multi transaction called")
{:json-rpc/call [{:method "wallet_createMultiTransaction"
:params request-params
:on-success (fn [result]
(when result
(let [receive-token-decimals (:decimals asset-to-receive)
amount-out (:amount-out swap-proposal)
receive-amount
(when amount-out
(-> amount-out
(number/hex->whole receive-token-decimals)
(money/to-fixed receive-token-decimals)))]
(rf/dispatch [:centralized-metrics/track
(if approval-required?
:metric/swap-approval-execution-start
:metric/swap-transaction-execution-start)
(cond-> {:network swap-chain-id
:pay_token token-id-from}
(not approval-required?)
(assoc :receive_token token-id-to))])
(rf/dispatch [:wallet.swap/add-authorized-transaction
(cond-> {:transaction result
:approval-transaction?
approval-required?}
(not approval-required?)
(assoc :swap-data
{:pay-token-symbol token-id-from
:pay-amount amount
:receive-token-symbol token-id-to
:receive-amount receive-amount
:swap-chain-id swap-chain-id}))])
(rf/dispatch [:hide-bottom-sheet])
(rf/dispatch [:dismiss-modal
(if approval-required?
:screen/wallet.swap-set-spending-cap
:screen/wallet.swap-confirmation)])
(when-not approval-required?
(rf/dispatch [:wallet/end-swap-flow])
(debounce/debounce-and-dispatch
[:toasts/upsert
{:id :swap-transaction-pending
:icon :i/info
:type :neutral
:text (i18n/label :t/swapping-to
{:pay-amount amount
:pay-token-symbol token-id-from
:receive-token-symbol token-id-to
:receive-amount receive-amount})}]
500)))))
:on-error (fn [error]
(rf/dispatch [:centralized-metrics/track
(if approval-required?
:metric/swap-approval-execution-failed
:metric/swap-transaction-execution-failed)
(cond-> {:network swap-chain-id
:error error
:pay_token token-id-from}
(not approval-required?)
(assoc :receive_token token-id-to))])
(log/error "failed swap transaction"
{:event :wallet/swap-transaction
:error error
:params request-params})
(rf/dispatch [:toasts/upsert
{:id :swap-transaction-error
:type :negative
:text (:message error)}]))}]})))
(rf/reg-event-fx :wallet.swap/add-authorized-transaction (rf/reg-event-fx :wallet.swap/add-authorized-transaction
(fn [{:keys [db]} [{:keys [transaction swap-data approval-transaction?]}]] (fn [{:keys [db]} [{:keys [sent-transactions swap-data approval-transaction?]}]]
(let [transactions (get-in db [:wallet :transactions] {}) (let [wallet-transactions (get-in db [:wallet :transactions] {})
transaction-batch-id (:id transaction) transactions (utils/transactions->hash-to-transaction-map sent-transactions)
transaction-hashes (:hashes transaction) transaction-ids (->> transactions
transaction-ids (flatten (vals transaction-hashes)) vals
(map :hash))
transaction-id (first transaction-ids) transaction-id (first transaction-ids)
transaction-details (cond-> (send-utils/map-multitransaction-by-ids transaction-batch-id transaction-details (cond-> transactions
transaction-hashes)
:always (assoc-in [transaction-id :tx-type] :swap) :always (assoc-in [transaction-id :tx-type] :swap)
swap-data (assoc-in [transaction-id :swap-data] swap-data)) swap-data (assoc-in [transaction-id :swap-data] swap-data))
swap-transaction-ids (get-in db [:wallet :swap-transaction-ids])] swap-transaction-ids (get-in db [:wallet :swap-transaction-ids])]
{:db (cond-> db {:db (cond-> db
:always (assoc-in [:wallet :transactions] :always (assoc-in [:wallet :transactions]
(merge transactions transaction-details)) (merge wallet-transactions transaction-details))
:always (assoc-in [:wallet :ui :swap :transaction-ids] transaction-ids) :always (assoc-in [:wallet :ui :swap :transaction-ids] transaction-ids)
approval-transaction? (assoc-in [:wallet :ui :swap :approval-transaction-id] approval-transaction? (assoc-in [:wallet :ui :swap :approval-transaction-id]
transaction-id) transaction-id)
@ -463,7 +330,8 @@
(not transaction-confirmed?) (not transaction-confirmed?)
(assoc :db (update-in db [:wallet :ui :swap] dissoc :approval-transaction-id))))))) (assoc :db (update-in db [:wallet :ui :swap] dissoc :approval-transaction-id)))))))
(rf/reg-event-fx :wallet.swap/swap-transaction-update (rf/reg-event-fx
:wallet.swap/swap-transaction-update
(fn [{:keys [db]} [{:keys [tx-hash status]}]] (fn [{:keys [db]} [{:keys [tx-hash status]}]]
(let [{:keys [pay-amount pay-token-symbol (let [{:keys [pay-amount pay-token-symbol
receive-amount receive-token-symbol receive-amount receive-token-symbol
@ -494,7 +362,8 @@
:receive-amount receive-amount}) :receive-amount receive-amount})
(i18n/label :t/swap-failed))}]]]})))) (i18n/label :t/swap-failed))}]]]}))))
(rf/reg-event-fx :wallet.swap/flip-assets (rf/reg-event-fx
:wallet.swap/flip-assets
(fn [{:keys [db]}] (fn [{:keys [db]}]
(let [{:keys [asset-to-pay asset-to-receive (let [{:keys [asset-to-pay asset-to-receive
swap-proposal amount network]} (get-in db [:wallet :ui :swap]) swap-proposal amount network]} (get-in db [:wallet :ui :swap])
@ -528,14 +397,169 @@
:previous_token (:symbol asset-to-receive) :previous_token (:symbol asset-to-receive)
:new_token (:symbol asset-to-pay)}]]]}))) :new_token (:symbol asset-to-pay)}]]]})))
(rf/reg-event-fx :wallet/end-swap-flow (rf/reg-event-fx
:wallet.swap/set-sign-transactions-callback-fx
(fn [{:keys [db]} [callback-fx]]
{:db (assoc-in db [:wallet :ui :swap :sign-transactions-callback-fx] callback-fx)}))
(rf/reg-event-fx
:wallet.swap/approve
(fn [{:keys [db]}] (fn [{:keys [db]}]
(let [launch-screen (get-in db [:wallet :ui :swap :launch-screen]) (let [last-request-uuid (get-in db [:wallet :ui :swap :last-request-uuid])
address (get-in db [:wallet :current-viewing-account-address])] max-slippage (get-in db [:wallet :ui :swap :max-slippage])]
{:fx [(when (= launch-screen :wallet-stack) {:fx [[:dispatch
[:dispatch [:wallet/navigate-to-account-within-stack address]]) [:wallet/build-transactions-from-route
{:request-uuid last-request-uuid
:slippage max-slippage}]]
[:dispatch
[:wallet.swap/set-sign-transactions-callback-fx
[:dispatch [:open-modal :screen/wallet.swap-set-spending-cap]]]]]})))
(rf/reg-event-fx
:wallet.swap/review-swap
(fn [{:keys [db]}]
(let [last-request-uuid (get-in db [:wallet :ui :swap :last-request-uuid])
max-slippage (get-in db [:wallet :ui :swap :max-slippage])]
{:db (-> db
(update-in [:wallet :ui :swap] dissoc :transaction-for-signing))
:fx [[:dispatch
[:wallet/build-transactions-from-route
{:request-uuid last-request-uuid
:slippage max-slippage}]]
[:dispatch
[:navigate-to-within-stack
[:screen/wallet.swap-confirmation
:screen/wallet.setup-swap]]]]})))
(defn transaction-approval-required?
[transactions {:keys [swap-proposal approval-transaction-id]}]
(let [approval-transaction (when approval-transaction-id
(get transactions approval-transaction-id))
already-approved? (and approval-transaction
(= (:status approval-transaction)
:confirmed))]
(and (:approval-required swap-proposal)
(not already-approved?))))
(rf/reg-event-fx
:wallet.swap/mark-as-pending
(fn [{:keys [db]} [transaction-id]]
{:db (-> db
(assoc-in [:wallet :transactions transaction-id :status] :pending)
(assoc-in [:wallet :ui :swap :approval-transaction-id] transaction-id))}))
(rf/reg-event-fx
:wallet.swap/transaction-success
(fn [{:keys [db]} [sent-transactions]]
(let [transactions (get-in db [:wallet :transactions])
{:keys [swap-proposal
asset-to-pay
asset-to-receive
network
amount]
:as swap} (get-in db [:wallet :ui :swap])
swap-chain-id (:chain-id network)
token-id-from (:symbol asset-to-pay)
token-id-to (:symbol asset-to-receive)
receive-token-decimals (:decimals asset-to-receive)
amount-out (:amount-out swap-proposal)
receive-amount (when amount-out
(-> amount-out
(number/hex->whole receive-token-decimals)
(money/to-fixed receive-token-decimals)))
approval-required? (transaction-approval-required? transactions swap)]
{:fx [[:dispatch
[:centralized-metrics/track
(if approval-required?
:metric/swap-approval-execution-start
:metric/swap-transaction-execution-start)
(cond-> {:network swap-chain-id
:pay_token token-id-from}
(not approval-required?)
(assoc :receive_token token-id-to))]]
[:dispatch
[:wallet.swap/add-authorized-transaction
(cond-> {:sent-transactions sent-transactions
:approval-transaction? approval-required?}
(not approval-required?)
(assoc :swap-data
{:pay-token-symbol token-id-from
:pay-amount amount
:receive-token-symbol token-id-to
:receive-amount receive-amount
:swap-chain-id swap-chain-id}))]]
(when approval-required?
;; dismiss the spending cap dialog if the transaction needs to be approved
[:dispatch [:dismiss-modal :screen/wallet.swap-set-spending-cap]])
(when approval-required?
[:dispatch [:wallet.swap/mark-as-pending (-> sent-transactions first :hash)]])
(when-not approval-required?
;; just end the whole transaction flow if no approval needed
[:dispatch [:wallet.swap/end-transaction-flow]])
(when-not approval-required?
[:dispatch-later
{:ms 500
:dispatch [:toasts/upsert
{:id :swap-transaction-pending
:icon :i/info
:type :neutral
:text (i18n/label :t/swapping-to
{:pay-amount amount
:pay-token-symbol token-id-from
:receive-token-symbol token-id-to
:receive-amount receive-amount})}]}])]})))
(rf/reg-event-fx
:wallet.swap/transaction-failure
(fn [{:keys [db]} [{:keys [details] :as error}]]
(let [transactions (get-in db [:wallet :transactions])
{:keys [asset-to-pay
asset-to-receive
network]
:as swap} (get-in db [:wallet :ui :swap])
swap-chain-id (:chain-id network)
token-id-from (:symbol asset-to-pay)
token-id-to (:symbol asset-to-receive)
approval-required? (transaction-approval-required? transactions swap)]
{:fx [[:centralized-metrics/track
(if approval-required?
:metric/swap-approval-execution-failed
:metric/swap-transaction-execution-failed)
(cond-> {:network swap-chain-id
:error error
:pay_token token-id-from}
(not approval-required?)
(assoc :receive_token token-id-to))]
[:dispatch [:wallet.swap/end-transaction-flow]]
[:dispatch
[:toasts/upsert
{:id :send-transaction-error
:type :negative
:text (or details "An error occured")}]]]})))
(rf/reg-event-fx
:wallet.swap/clean-up-transaction-flow
(fn [{:keys [db]}]
(let [transactions (get-in db [:wallet :transactions])
swap (get-in db [:wallet :ui :swap])
approval-required? (transaction-approval-required? transactions swap)]
{:db (update-in db [:wallet :ui] dissoc :swap)
:fx [[:dispatch
[:dismiss-modal
(if approval-required?
:screen/wallet.swap-set-spending-cap
:screen/wallet.swap-confirmation)]]]})))
(rf/reg-event-fx
:wallet.swap/end-transaction-flow
(fn [{:keys [db]}]
(let [address (get-in db [:wallet :current-viewing-account-address])]
{:fx [[:dispatch [:wallet/navigate-to-account-within-stack address]]
[:dispatch [:wallet/fetch-activities-for-current-account]] [:dispatch [:wallet/fetch-activities-for-current-account]]
[:dispatch [:wallet/select-account-tab :activity]]]}))) [:dispatch [:wallet/select-account-tab :activity]]
[:dispatch-later
[{:ms 20
:dispatch [:wallet.swap/clean-up-transaction-flow]}]]]})))
(rf/reg-event-fx :wallet.swap/start-from-account (rf/reg-event-fx :wallet.swap/start-from-account
(fn [{:keys [db]} [account]] (fn [{:keys [db]} [account]]

View File

@ -12,8 +12,7 @@
[status-im.contexts.wallet.swap.set-spending-cap.style :as style] [status-im.contexts.wallet.swap.set-spending-cap.style :as style]
[utils.address :as address-utils] [utils.address :as address-utils]
[utils.i18n :as i18n] [utils.i18n :as i18n]
[utils.re-frame :as rf] [utils.re-frame :as rf]))
[utils.security.core :as security]))
(defn- swap-title (defn- swap-title
[] []
@ -221,9 +220,8 @@
(let [loading-swap-proposal? (rf/sub [:wallet/swap-loading-swap-proposal?]) (let [loading-swap-proposal? (rf/sub [:wallet/swap-loading-swap-proposal?])
swap-proposal (rf/sub [:wallet/swap-proposal-without-fees]) swap-proposal (rf/sub [:wallet/swap-proposal-without-fees])
account (rf/sub [:wallet/current-viewing-account]) account (rf/sub [:wallet/current-viewing-account])
on-auth-success (rn/use-callback #(rf/dispatch on-auth-success (rn/use-callback
[:wallet/swap-transaction #(rf/dispatch [:wallet/prepare-signatures-for-transactions :swap %]))]
(security/safe-unmask-data %)]))]
[standard-auth/slide-button [standard-auth/slide-button
{:size :size-48 {:size :size-48
:track-text (i18n/label :t/slide-to-sign) :track-text (i18n/label :t/slide-to-sign)

View File

@ -95,8 +95,10 @@
:subtitle (str max-slippage "%") :subtitle (str max-slippage "%")
:subtitle-icon :i/edit :subtitle-icon :i/edit
:size :small :size :small
:on-press #(rf/dispatch [:show-bottom-sheet :on-press (fn []
{:content slippage-settings/view}])}]])) (when-not loading-swap-proposal?
(rf/dispatch [:show-bottom-sheet
{:content slippage-settings/view}])))}]]))
(defn- pay-token-input (defn- pay-token-input
[{:keys [input-state on-max-press on-input-focus on-token-press on-approve-press input-focused?]}] [{:keys [input-state on-max-press on-input-focus on-token-press on-approve-press input-focused?]}]
@ -195,7 +197,8 @@
:approve) :approve)
:token-value approval-label-token-value :token-value approval-label-token-value
:button-props (merge {:on-press on-approve-press} :button-props (merge {:on-press on-approve-press}
(when error-response (when (or loading-swap-proposal?
error-response)
{:disabled? true})) {:disabled? true}))
:customization-color account-color :customization-color account-color
:token-symbol pay-token-symbol}}])) :token-symbol pay-token-symbol}}]))
@ -361,9 +364,7 @@
(not pay-input-error?)) (not pay-input-error?))
on-review-swap-press (rn/use-callback on-review-swap-press (rn/use-callback
(fn [] (fn []
(rf/dispatch [:navigate-to-within-stack (rf/dispatch [:wallet.swap/review-swap])))
[:screen/wallet.swap-confirmation
:screen/wallet.setup-swap]])))
on-press (rn/use-callback on-press (rn/use-callback
(fn [c] (fn [c]
(let (let
@ -492,7 +493,7 @@
:on-max-press on-max-press :on-max-press on-max-press
:input-focused? pay-input-focused? :input-focused? pay-input-focused?
:on-token-press #(rf/dispatch [:show-bottom-sheet {:content pay-token-bottom-sheet}]) :on-token-press #(rf/dispatch [:show-bottom-sheet {:content pay-token-bottom-sheet}])
:on-approve-press #(rf/dispatch [:open-modal :screen/wallet.swap-set-spending-cap]) :on-approve-press #(rf/dispatch [:wallet.swap/approve])
:on-input-focus (fn [] :on-input-focus (fn []
(when platform/android? (rf/dispatch [:dismiss-keyboard])) (when platform/android? (rf/dispatch [:dismiss-keyboard]))
(set-pay-input-focused? true))}] (set-pay-input-focused? true))}]

View File

@ -12,8 +12,7 @@
[status-im.contexts.wallet.swap.swap-confirmation.style :as style] [status-im.contexts.wallet.swap.swap-confirmation.style :as style]
[utils.address :as address-utils] [utils.address :as address-utils]
[utils.i18n :as i18n] [utils.i18n :as i18n]
[utils.re-frame :as rf] [utils.re-frame :as rf]))
[utils.security.core :as security]))
(defn- on-close-action (defn- on-close-action
[] []
@ -166,21 +165,22 @@
(defn- slide-button (defn- slide-button
[] []
(let [loading-swap-proposal? (rf/sub [:wallet/swap-loading-swap-proposal?]) (let [loading-swap-proposal? (rf/sub [:wallet/swap-loading-swap-proposal?])
transaction-for-signing (rf/sub [:wallet/swap-transaction-for-signing])
swap-proposal (rf/sub [:wallet/swap-proposal-without-fees]) swap-proposal (rf/sub [:wallet/swap-proposal-without-fees])
account (rf/sub [:wallet/current-viewing-account]) account (rf/sub [:wallet/current-viewing-account])
account-color (:color account) account-color (:color account)]
on-auth-success (rn/use-callback (fn [data]
(rf/dispatch [:wallet/stop-get-swap-proposal])
(rf/dispatch [:wallet/swap-transaction
(security/safe-unmask-data data)])))]
[standard-auth/slide-button [standard-auth/slide-button
{:size :size-48 {:size :size-48
:track-text (i18n/label :t/slide-to-swap) :track-text (i18n/label :t/slide-to-swap)
:container-style {:z-index 2} :container-style {:z-index 2}
:customization-color account-color :customization-color account-color
:disabled? (or loading-swap-proposal? (not swap-proposal)) :disabled? (or loading-swap-proposal?
(not swap-proposal)
(not transaction-for-signing))
:auth-button-label (i18n/label :t/confirm) :auth-button-label (i18n/label :t/confirm)
:on-auth-success on-auth-success}])) :on-auth-success (fn [data]
(rf/dispatch [:wallet/stop-get-swap-proposal])
(rf/dispatch [:wallet/prepare-signatures-for-transactions :swap data]))}]))
(defn footer (defn footer
[] []

View File

@ -1,4 +0,0 @@
(ns status-im.contexts.wallet.swap.swap-proposal.style)
(def container
{:flex 1})

View File

@ -1,27 +0,0 @@
(ns status-im.contexts.wallet.swap.swap-proposal.view
(:require
[quo.core :as quo]
[react-native.core :as rn]
[status-im.contexts.wallet.sheets.slippage-settings.view :as slippage-settings]
[status-im.contexts.wallet.swap.swap-proposal.style :as style]
[utils.re-frame :as rf]))
(defn view
[]
(let [max-slippage (rf/sub [:wallet/swap-max-slippage])]
[rn/view {:style style/container}
[quo/button
{:on-press #(rf/dispatch [:show-bottom-sheet
{:content slippage-settings/view}])}
(str "Edit Slippage: " max-slippage "%")]
[quo/button
{:on-press #(rf/dispatch [:navigate-to-within-stack
[:screen/wallet.swap-confirmation :screen/wallet.swap-propasal]])}
"Swap confirmation"]
[quo/button
{:on-press #(rf/dispatch [:open-modal :screen/wallet.swap-set-spending-cap])}
"Set spending cap"]
[quo/button
{:on-press #(rf/dispatch [:navigate-to-within-stack
[:screen/wallet.setup-swap :screen/wallet.swap-propasal]])}
"Setup swap"]]))

View File

@ -1,63 +1,8 @@
(ns status-im.contexts.wallet.wallet-connect.utils.rpc (ns status-im.contexts.wallet.wallet-connect.utils.rpc
(:require [oops.core :as oops] (:require [promesa.core :as promesa]
[promesa.core :as promesa]
[status-im.common.json-rpc.events :as rpc-events] [status-im.common.json-rpc.events :as rpc-events]
[status-im.constants :as constants]
[utils.hex :as hex]
[utils.transforms :as transforms])) [utils.transforms :as transforms]))
(defn wallet-build-transaction
[chain-id tx]
(promesa/let [res (rpc-events/call-async :wallet_buildTransaction true chain-id tx)]
{:message-to-sign (oops/oget res :messageToSign)
:tx-args (oops/oget res :txArgs)}))
(defn wallet-build-raw-transaction
[chain-id tx-args signature]
(-> (rpc-events/call-async "wallet_buildRawTransaction"
true
chain-id
(transforms/js-stringify tx-args 0)
signature)
(promesa/then #(oops/oget % "rawTx"))))
(defn wallet-send-transaction-with-signature
[chain-id tx-args signature]
(rpc-events/call-async "wallet_sendTransactionWithSignature"
true
chain-id
constants/transaction-pending-type-wallet-connect-transfer
(transforms/js-stringify tx-args 0)
signature))
(defn wallet-sign-message
[message address password]
(-> (rpc-events/call-async "wallet_signMessage"
true
message
address
password)
(promesa/then hex/normalize-hex)))
(defn wallet-hash-message-eip-191
[message]
(rpc-events/call-async "wallet_hashMessageEIP191" true message))
(defn wallet-safe-sign-typed-data
[data address password chain-id legacy?]
(rpc-events/call-async "wallet_safeSignTypedDataForDApps"
true
data
address
password
chain-id
legacy?))
(defn wallet-get-suggested-fees
[chain-id]
(-> (rpc-events/call-async "wallet_getSuggestedFees" true chain-id)
(promesa/then transforms/js->clj)))
(defn wallet-disconnect-persisted-session (defn wallet-disconnect-persisted-session
[topic] [topic]
(rpc-events/call-async "wallet_disconnectWalletConnectSession" true topic)) (rpc-events/call-async "wallet_disconnectWalletConnectSession" true topic))

View File

@ -2,9 +2,9 @@
(:require (:require
[native-module.core :as native-module] [native-module.core :as native-module]
[promesa.core :as promesa] [promesa.core :as promesa]
[status-im.contexts.wallet.rpc :as wallet-rpc]
[status-im.contexts.wallet.wallet-connect.utils.data-store :as [status-im.contexts.wallet.wallet-connect.utils.data-store :as
data-store] data-store]
[status-im.contexts.wallet.wallet-connect.utils.rpc :as rpc]
[utils.hex :as hex] [utils.hex :as hex]
[utils.transforms :as transforms])) [utils.transforms :as transforms]))
@ -19,6 +19,6 @@
(defn personal-sign (defn personal-sign
[password address data] [password address data]
(-> (rpc/wallet-hash-message-eip-191 data) (-> (wallet-rpc/hash-message-eip-191 data)
(promesa/then #(rpc/wallet-sign-message % address password)) (promesa/then #(wallet-rpc/sign-message % address password))
(promesa/then hex/prefix-hex))) (promesa/then hex/prefix-hex)))

View File

@ -4,9 +4,10 @@
[native-module.core :as native-module] [native-module.core :as native-module]
[promesa.core :as promesa] [promesa.core :as promesa]
[status-im.constants :as constants] [status-im.constants :as constants]
[status-im.contexts.wallet.rpc :as wallet-rpc]
[status-im.contexts.wallet.wallet-connect.utils.data-store :as [status-im.contexts.wallet.wallet-connect.utils.data-store :as
data-store] data-store]
[status-im.contexts.wallet.wallet-connect.utils.rpc :as rpc] [status-im.contexts.wallet.wallet-connect.utils.rpc :as wallet-connect-rpc]
[utils.money :as money] [utils.money :as money]
[utils.transforms :as transforms])) [utils.transforms :as transforms]))
@ -119,14 +120,15 @@
"Formats and builds the incoming transaction, adding the missing properties and returning the final "Formats and builds the incoming transaction, adding the missing properties and returning the final
transaction, along with the transaction hash and the suggested fees" transaction, along with the transaction hash and the suggested fees"
[tx chain-id tx-priority] [tx chain-id tx-priority]
(promesa/let [suggested-fees (rpc/wallet-get-suggested-fees chain-id) (promesa/let [suggested-fees (wallet-rpc/get-suggested-fees chain-id)
{:keys [tx-args message-to-sign]} (->> {:keys [tx-args message-to-sign]} (->>
(prepare-transaction-fees tx (prepare-transaction-fees tx
tx-priority tx-priority
suggested-fees) suggested-fees)
prepare-transaction-for-rpc prepare-transaction-for-rpc
(rpc/wallet-build-transaction chain-id)) (wallet-rpc/build-transaction
estimated-time (rpc/wallet-get-transaction-estimated-time chain-id))
estimated-time (wallet-connect-rpc/wallet-get-transaction-estimated-time
chain-id chain-id
(:maxPriorityFeePerGas suggested-fees))] (:maxPriorityFeePerGas suggested-fees))]
{:tx-args tx-args {:tx-args tx-args
@ -137,15 +139,15 @@
(defn sign-transaction (defn sign-transaction
[password address tx-hash tx-args chain-id] [password address tx-hash tx-args chain-id]
(promesa/let (promesa/let
[signature (rpc/wallet-sign-message tx-hash address password) [signature (wallet-rpc/sign-message tx-hash address password)
raw-tx (rpc/wallet-build-raw-transaction chain-id tx-args signature)] raw-tx (wallet-rpc/build-raw-transaction chain-id tx-args signature)]
raw-tx)) raw-tx))
(defn send-transaction (defn send-transaction
[password address tx-hash tx-args chain-id] [password address tx-hash tx-args chain-id]
(promesa/let (promesa/let
[signature (rpc/wallet-sign-message tx-hash address password) [signature (wallet-rpc/sign-message tx-hash address password)
tx (rpc/wallet-send-transaction-with-signature chain-id tx (wallet-rpc/send-transaction-with-signature chain-id
tx-args tx-args
signature)] signature)]
tx)) tx))

View File

@ -1,8 +1,8 @@
(ns status-im.contexts.wallet.wallet-connect.utils.typed-data (ns status-im.contexts.wallet.wallet-connect.utils.typed-data
(:require [clojure.string :as string] (:require [clojure.string :as string]
[status-im.constants :as constants] [status-im.constants :as constants]
[status-im.contexts.wallet.rpc :as wallet-rpc]
[status-im.contexts.wallet.wallet-connect.utils.networks :as networks] [status-im.contexts.wallet.wallet-connect.utils.networks :as networks]
[status-im.contexts.wallet.wallet-connect.utils.rpc :as rpc]
[utils.number :as number])) [utils.number :as number]))
(declare flatten-data) (declare flatten-data)
@ -88,7 +88,7 @@
[password address data chain-id-eip155 version] [password address data chain-id-eip155 version]
(let [legacy? (= version :v1) (let [legacy? (= version :v1)
chain-id (networks/eip155->chain-id chain-id-eip155)] chain-id (networks/eip155->chain-id chain-id-eip155)]
(rpc/wallet-safe-sign-typed-data data (wallet-rpc/safe-sign-typed-data data
address address
password password
chain-id chain-id

View File

@ -141,7 +141,6 @@
[status-im.contexts.wallet.swap.set-spending-cap.view :as wallet-swap-set-spending-cap] [status-im.contexts.wallet.swap.set-spending-cap.view :as wallet-swap-set-spending-cap]
[status-im.contexts.wallet.swap.setup-swap.view :as wallet-swap-setup-swap] [status-im.contexts.wallet.swap.setup-swap.view :as wallet-swap-setup-swap]
[status-im.contexts.wallet.swap.swap-confirmation.view :as wallet-swap-confirmation] [status-im.contexts.wallet.swap.swap-confirmation.view :as wallet-swap-confirmation]
[status-im.contexts.wallet.swap.swap-proposal.view :as wallet-swap-propasal]
[status-im.contexts.wallet.wallet-connect.modals.send-transaction.view :as [status-im.contexts.wallet.wallet-connect.modals.send-transaction.view :as
wallet-connect-send-transaction] wallet-connect-send-transaction]
[status-im.contexts.wallet.wallet-connect.modals.session-proposal.view :as [status-im.contexts.wallet.wallet-connect.modals.session-proposal.view :as
@ -651,12 +650,6 @@
:insets {:bottom? true}} :insets {:bottom? true}}
:component wallet-swap-setup-swap/view} :component wallet-swap-setup-swap/view}
{:name :screen/wallet.swap-propasal
:metrics {:track? true
:alias-id :wallet-swap.swap-proposal}
:options {:insets {:top? true}}
:component wallet-swap-propasal/view}
{:name :screen/wallet.swap-set-spending-cap {:name :screen/wallet.swap-set-spending-cap
:metrics {:track? true :metrics {:track? true
:alias-id :wallet-swap.set-spending-cap} :alias-id :wallet-swap.set-spending-cap}

View File

@ -143,6 +143,11 @@
:<- [:wallet/swap] :<- [:wallet/swap]
:-> :loading-swap-proposal?) :-> :loading-swap-proposal?)
(rf/reg-sub
:wallet/swap-transaction-for-signing
:<- [:wallet/swap]
:-> :transaction-for-signing)
(rf/reg-sub (rf/reg-sub
:wallet/swap-proposal-amount-out :wallet/swap-proposal-amount-out
:<- [:wallet/swap-proposal] :<- [:wallet/swap-proposal]

View File

@ -220,6 +220,11 @@
:<- [:wallet/wallet-send] :<- [:wallet/wallet-send]
:-> :loading-suggested-routes?) :-> :loading-suggested-routes?)
(rf/reg-sub
:wallet/wallet-send-transaction-for-signing
:<- [:wallet/wallet-send]
:-> :transaction-for-signing)
(rf/reg-sub (rf/reg-sub
:wallet/wallet-send-suggested-routes :wallet/wallet-send-suggested-routes
:<- [:wallet/wallet-send] :<- [:wallet/wallet-send]