From 59ceddbaada4735e1b81a8af002619f64d91a5f5 Mon Sep 17 00:00:00 2001 From: Brian Sztamfater Date: Tue, 30 Jul 2024 11:02:11 -0300 Subject: [PATCH] fix(wallet): fix bridge transactions (#20902) * fix(wallet): fix bridge transactions Signed-off-by: Brian Sztamfater * add support for approve transactions Signed-off-by: Brian Sztamfater --------- Signed-off-by: Brian Sztamfater --- src/native_module/core.cljs | 5 + src/status_im/constants.cljs | 8 ++ src/status_im/contexts/wallet/events.cljs | 4 +- .../contexts/wallet/send/events.cljs | 106 ++++++++++++------ .../send/transaction_confirmation/view.cljs | 5 +- 5 files changed, 88 insertions(+), 40 deletions(-) diff --git a/src/native_module/core.cljs b/src/native_module/core.cljs index f89e22d1e2..cf52b643b6 100644 --- a/src/native_module/core.cljs +++ b/src/native_module/core.cljs @@ -387,6 +387,11 @@ (log/debug "[native-module] encode-transfer") (.encodeTransfer ^js (encryption) to-norm amount-hex)) +(defn encode-function-call + [method params] + (log/debug "[native-module] encode-function-call") + (.encodeFunctionCall ^js (encryption) method (types/clj->json params))) + (defn decode-parameters [bytes-string types] (log/debug "[native-module] decode-parameters") diff --git a/src/status_im/constants.cljs b/src/status_im/constants.cljs index e1d7bbe504..ba72366292 100644 --- a/src/status_im/constants.cljs +++ b/src/status_im/constants.cljs @@ -554,6 +554,14 @@ (def ^:const send-type-erc-721-transfer 6) (def ^:const send-type-erc-1155-transfer 7) +(def ^:const multi-transaction-type-send 0) +(def ^:const multi-transaction-type-approve 1) +(def ^:const multi-transaction-type-bridge 2) +(def ^:const multi-transaction-type-swap 3) +(def ^:const multi-transaction-type-unknown 255) + +(def ^:const contract-function-signature-erc20-approve "approve(address,uint256)") + (def ^:const bridge-name-transfer "Transfer") (def ^:const bridge-name-erc-721-transfer "ERC721Transfer") (def ^:const bridge-name-erc-1155-transfer "ERC1155Transfer") diff --git a/src/status_im/contexts/wallet/events.cljs b/src/status_im/contexts/wallet/events.cljs index ad1e81c7ec..37c44988cb 100644 --- a/src/status_im/contexts/wallet/events.cljs +++ b/src/status_im/contexts/wallet/events.cljs @@ -274,7 +274,7 @@ (rf/reg-event-fx :wallet/get-keypairs get-keypairs) (rf/reg-event-fx :wallet/bridge-select-token - (fn [{:keys [db]} [{:keys [token token-symbol stack-id]}]] + (fn [{:keys [db]} [{:keys [token token-symbol stack-id start-flow?]}]] (let [missing-recipient? (-> db :wallet :ui :send :to-address nil?) to-address (-> db :wallet :current-viewing-account-address)] {:db (cond-> db @@ -285,7 +285,7 @@ :fx [[:dispatch [:wallet/wizard-navigate-forward {:current-screen stack-id - :start-flow? true + :start-flow? start-flow? :flow-id :wallet-bridge-flow}]]]}))) (rf/reg-event-fx :wallet/start-bridge diff --git a/src/status_im/contexts/wallet/send/events.cljs b/src/status_im/contexts/wallet/send/events.cljs index 6750f08ac3..5d07851fdd 100644 --- a/src/status_im/contexts/wallet/send/events.cljs +++ b/src/status_im/contexts/wallet/send/events.cljs @@ -10,6 +10,7 @@ [status-im.contexts.wallet.send.utils :as send-utils] [taoensso.timbre :as log] [utils.address :as address] + [utils.hex :as utils.hex] [utils.money :as money] [utils.number] [utils.re-frame :as rf])) @@ -402,11 +403,11 @@ receiver-networks))) network-chain-ids)) from-locked-amount (update-vals from-locked-amounts to-hex) - transaction-type (case tx-type - :tx/collectible-erc-721 constants/send-type-erc-721-transfer - :tx/collectible-erc-1155 constants/send-type-erc-1155-transfer - :tx/bridge constants/send-type-bridge - constants/send-type-transfer) + send-type (case tx-type + :tx/collectible-erc-721 constants/send-type-erc-721-transfer + :tx/collectible-erc-1155 constants/send-type-erc-1155-transfer + :tx/bridge constants/send-type-bridge + constants/send-type-transfer) balances-per-chain (when token (:balances-per-chain token)) sender-token-available-networks-for-suggested-routes (when token @@ -447,7 +448,7 @@ :tx-type tx-type :receiver? true})) params [{:uuid (str (random-uuid)) - :sendType transaction-type + :sendType send-type :addrFrom from-address :addrTo to-address :amountIn amount-in @@ -583,6 +584,29 @@ :gwei gas-price)))))) +(defn- approval-path + [{:keys [route from-address to-address token-address]}] + (let [{:keys [from]} route + from-chain-id (:chain-id from) + approval-amount-required (:approval-amount-required route) + approval-amount-required-sanitized (-> approval-amount-required + (utils.hex/normalize-hex) + (native-module/hex-to-number)) + approval-contract-address (:approval-contract-address route) + data (native-module/encode-function-call + constants/contract-function-signature-erc20-approve + [approval-contract-address + approval-amount-required-sanitized]) + tx-data (transaction-data {:from-address from-address + :to-address to-address + :token-address token-address + :route route + :data data + :eth-transfer? false})] + {:BridgeName constants/bridge-name-transfer + :ChainID from-chain-id + :TransferTx tx-data})) + (defn- transaction-path [{:keys [from-address to-address token-id token-address route data eth-transfer?]}] (let [{:keys [bridge-name amount-in bonder-fees from @@ -619,7 +643,8 @@ (= bridge-name constants/bridge-name-hop) (assoc :HopTx (assoc tx-data - :ChainID to-chain-id + :ChainID from-chain-id + :ChainIDTo to-chain-id :Symbol token-id :Recipient to-address :Amount amount-in @@ -636,14 +661,14 @@ :Amount amount-in))))) (defn- multi-transaction-command - [{:keys [from-address to-address from-asset to-asset amount-out transfer-type] - :or {transfer-type constants/send-type-transfer}}] + [{:keys [from-address to-address from-asset to-asset amount-out multi-transaction-type] + :or {multi-transaction-type constants/multi-transaction-type-unknown}}] {:fromAddress from-address :toAddress to-address :fromAsset from-asset :toAsset to-asset :fromAmount amount-out - :type transfer-type}) + :type multi-transaction-type}) (rf/reg-event-fx :wallet/send-transaction (fn [{:keys [db]} [sha3-pwd]] @@ -651,11 +676,9 @@ first-route (first routes) from-address (get-in db [:wallet :current-viewing-account-address]) transaction-type (get-in db [:wallet :ui :send :tx-type]) - transaction-type-param (case transaction-type - :tx/collectible-erc-721 constants/send-type-erc-721-transfer - :tx/collectible-erc-1155 constants/send-type-erc-1155-transfer - :tx/bridge constants/send-type-bridge - constants/send-type-transfer) + 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]) @@ -670,30 +693,41 @@ 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 (mapv (fn [route] - (let [data (when erc20-transfer? - (native-module/encode-transfer - (address/normalized-hex to-address) - (:amount-in route)))] - (transaction-path {:to-address to-address - :from-address from-address - :route route - :token-address token-address - :token-id (if collectible - (money/to-hex (js/parseInt - token-id)) - token-id) - :data data - :eth-transfer? eth-transfer?}))) + 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 (transaction-path + {:to-address to-address + :from-address from-address + :route route + :token-address token-address + :token-id (if collectible + (money/to-hex + (js/parseInt token-id)) + token-id) + :data data + :eth-transfer? eth-transfer?})] + (if approval-required? + [(approval-path {:route route + :token-address token-address + :from-address from-address + :to-address to-address}) + base-path] + [base-path])))) routes) request-params [(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") - :transfer-type transaction-type-param}) + {: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") diff --git a/src/status_im/contexts/wallet/send/transaction_confirmation/view.cljs b/src/status_im/contexts/wallet/send/transaction_confirmation/view.cljs index 6ce1f42092..d66536f5bd 100644 --- a/src/status_im/contexts/wallet/send/transaction_confirmation/view.cljs +++ b/src/status_im/contexts/wallet/send/transaction_confirmation/view.cljs @@ -124,7 +124,7 @@ :customization-color (:color account)}]])])) (defn- user-summary - [{:keys [account-props theme label accessibility-label summary-type recipient account-to?]}] + [{:keys [account-props theme label accessibility-label summary-type recipient bridge-tx? account-to?]}] (let [network-values (rf/sub [:wallet/network-values account-to?]) summary-info-type (case (:recipient-type recipient) :saved-address :saved-account @@ -144,7 +144,7 @@ :networks? true :values network-values :account-props (cond-> account-props - account-to? + (and account-to? (not bridge-tx?)) (assoc :size 32 :name (:label recipient) @@ -298,5 +298,6 @@ from-account-props user-props) :recipient recipient + :bridge-tx? (= transaction-type :tx/bridge) :account-to? true :theme theme}]]]]))))