From eec0cf5e313d1b2cfd521da191efe33100ae540a Mon Sep 17 00:00:00 2001 From: Brian Sztamfater Date: Tue, 2 Jan 2024 13:17:57 -0300 Subject: [PATCH] feat: prepare events for sending collectible Signed-off-by: Brian Sztamfater --- .../components/wallet/summary_info/view.cljs | 8 +- src/status_im/constants.cljs | 2 + .../preview/quo/wallet/summary_info.cljs | 6 +- .../wallet/common/collectibles_tab/view.cljs | 4 +- .../contexts/wallet/send/events.cljs | 116 +++++++++---- .../wallet/send/select_asset/view.cljs | 7 +- .../send/transaction_confirmation/view.cljs | 160 ++++++++++-------- 7 files changed, 186 insertions(+), 117 deletions(-) diff --git a/src/quo/components/wallet/summary_info/view.cljs b/src/quo/components/wallet/summary_info/view.cljs index 654ba65db3..d40463cac6 100644 --- a/src/quo/components/wallet/summary_info/view.cljs +++ b/src/quo/components/wallet/summary_info/view.cljs @@ -33,22 +33,22 @@ [rn/view {:style style/networks-container :accessibility-label :networks} - (when (pos? ethereum) + (when (and ethereum (pos? (:amount ethereum))) [network-amount {:network :ethereum - :amount (str ethereum " ETH") + :amount (str (:amount ethereum) " " (or (:token-symbol ethereum) "ETH")) :divider? (or show-arbitrum? show-optimism?) :theme theme}]) (when show-optimism? [network-amount {:network :optimism - :amount (str optimism " OPT") + :amount (str (:amount optimism) " " (or (:token-symbol optimism) "OPT")) :divider? show-arbitrum? :theme theme}]) (when show-arbitrum? [network-amount {:network :arbitrum - :amount (str arbitrum " ARB") + :amount (str (:amount arbitrum) " " (or (:token-symbol arbitrum) "ARB")) :theme theme}])])) (defn- view-internal diff --git a/src/status_im/constants.cljs b/src/status_im/constants.cljs index 881c554d8b..1be038c6db 100644 --- a/src/status_im/constants.cljs +++ b/src/status_im/constants.cljs @@ -437,3 +437,5 @@ (def ^:const send-type-stickers-buy 4) (def ^:const send-type-bridge 5) (def ^:const send-type-erc-721-transfer 6) + +(def ^:const bridge-name-erc-721-transfer "ERC721Transfer") diff --git a/src/status_im/contexts/preview/quo/wallet/summary_info.cljs b/src/status_im/contexts/preview/quo/wallet/summary_info.cljs index 7fbf8e827a..231245b3c7 100644 --- a/src/status_im/contexts/preview/quo/wallet/summary_info.cljs +++ b/src/status_im/contexts/preview/quo/wallet/summary_info.cljs @@ -20,9 +20,9 @@ [] (let [state (reagent/atom {:type :status-account :networks? true - :values {:ethereum 150 - :optimism 50 - :arbitrum 25}}) + :values {:ethereum {:amount 150} + :optimism {:amount 50} + :arbitrum {:amount 25}}}) status-account-props {:customization-color :purple :size 32 :emoji "🍑" diff --git a/src/status_im/contexts/wallet/common/collectibles_tab/view.cljs b/src/status_im/contexts/wallet/common/collectibles_tab/view.cljs index f80eabec50..8a3f5b6acb 100644 --- a/src/status_im/contexts/wallet/common/collectibles_tab/view.cljs +++ b/src/status_im/contexts/wallet/common/collectibles_tab/view.cljs @@ -30,9 +30,9 @@ :style {:flex 1} :content-container-style {:align-items :center} :num-columns 2 - :render-fn (fn [{:keys [preview-url id]}] + :render-fn (fn [{:keys [preview-url] :as collectible}] [quo/collectible {:images [preview-url] - :on-press #(on-collectible-press id)}])}]))) + :on-press #(on-collectible-press collectible)}])}]))) (def view (quo.theme/with-theme view-internal)) diff --git a/src/status_im/contexts/wallet/send/events.cljs b/src/status_im/contexts/wallet/send/events.cljs index 3b7c1b1a56..44925f6c38 100644 --- a/src/status_im/contexts/wallet/send/events.cljs +++ b/src/status_im/contexts/wallet/send/events.cljs @@ -51,9 +51,20 @@ (rf/reg-event-fx :wallet/send-select-token (fn [{:keys [db]} [{:keys [token stack-id]}]] - {:db (assoc-in db [:wallet :ui :send :token] token) + {:db (-> db + (update-in [:wallet :ui :send] dissoc :collectible) + (assoc-in [:wallet :ui :send :token] token)) :fx [[:navigate-to-within-stack [:wallet-send-input-amount stack-id]]]})) +(rf/reg-event-fx :wallet/send-select-collectible + (fn [{:keys [db]} [{:keys [collectible stack-id]}]] + {:db (-> db + (update-in [:wallet :ui :send] dissoc :token) + (assoc-in [:wallet :ui :send :collectible] collectible) + (assoc-in [:wallet :ui :send :amount] 1)) + :fx [[:dispatch [:wallet/get-suggested-routes 1]] + [:navigate-to-within-stack [:wallet-transaction-confirmation stack-id]]]})) + (rf/reg-event-fx :wallet/send-select-amount (fn [{:keys [db]} [{:keys [amount stack-id]}]] {:db (assoc-in db [:wallet :ui :send :amount] amount) @@ -63,17 +74,26 @@ (fn [{:keys [db now]} [amount]] (let [wallet-address (get-in db [:wallet :current-viewing-account-address]) token (get-in db [:wallet :ui :send :token]) - to-address (get-in db [:wallet :ui :send :to-address]) - token-decimal (:decimals token) - token-id (:symbol token) - network-preferences [] + collectible (get-in db [:wallet :ui :send :collectible]) + account-address (get-in db [:wallet :ui :send :send-account-address]) + to-address (or account-address (get-in db [:wallet :ui :send :to-address])) + token-decimal (when token (:decimals token)) + token-id (if token + (:symbol token) + (str (get-in collectible [:id :contract-id :address]) + ":" + (get-in collectible [:id :token-id]))) + network-preferences (if token [] [(get-in collectible [:id :contract-id :chain-id])]) gas-rates constants/gas-rate-medium - amount-in (send-utils/amount-in-hex amount token-decimal) + amount-in (send-utils/amount-in-hex amount (if token token-decimal 0)) from-address wallet-address disabled-from-chain-ids [] disabled-to-chain-ids [] from-locked-amount {} - request-params [constants/send-type-transfer + transaction-type (if token + constants/send-type-transfer + constants/send-type-erc-721-transfer) + request-params [transaction-type from-address to-address amount-in @@ -110,21 +130,43 @@ :fx [[:dispatch [:navigate-to :wallet-transaction-progress]]]}))) (defn- transaction-bridge - [{:keys [from-address to-address route]}] - (let [{:keys [from bridge-name amount-out gas-amount gas-fees]} route - {:keys [gas-price max-fee-per-gas-medium max-priority-fee-per-gas]} gas-fees] - [{:BridgeName bridge-name - :ChainID (:chain-id from) - :TransferTx {:From from-address - :To to-address - :Gas (money/to-hex gas-amount) - :GasPrice (money/to-hex (money/->wei :gwei gas-price)) - :Value amount-out - :Nonce nil - :MaxFeePerGas (money/to-hex (money/->wei :gwei max-fee-per-gas-medium)) - :MaxPriorityFeePerGas (money/to-hex (money/->wei :gwei max-priority-fee-per-gas)) - :Input "" - :Data "0x"}}])) + [{:keys [from-address to-address token-id token-address route]}] + (let [{:keys [from bridge-name amount-out gas-amount + gas-fees]} route + eip-1559-enabled? (:eip-1559-enabled gas-fees) + {:keys [gas-price max-fee-per-gas-medium + max-priority-fee-per-gas]} gas-fees + transfer-tx (merge + (if eip-1559-enabled? + {:TxType "0x02" + :MaxFeePerGas (money/to-hex + (money/->wei + :gwei + max-fee-per-gas-medium)) + :MaxPriorityFeePerGas (money/to-hex + (money/->wei + :gwei + max-priority-fee-per-gas))} + {:TxType "0x00" + :GasPrice (money/to-hex (money/->wei :gwei + gas-price))}) + {:From from-address + :To (or token-address to-address) + :Gas (money/to-hex gas-amount) + :Value amount-out + :Nonce nil + :Input "" + :Data "0x"})] + [(merge + {:BridgeName bridge-name + :ChainID (:chain-id from)} + (if (= bridge-name constants/bridge-name-erc-721-transfer) + {:ERC721TransferTx + (merge + {:Recipient to-address + :TokenID token-id} + transfer-tx)} + {:TransferTx transfer-tx}))])) (defn- multi-transaction-command [{:keys [from-address to-address from-asset to-asset amount-out transfer-type] @@ -140,17 +182,27 @@ (fn [{:keys [db]} [sha3-pwd]] (let [route (get-in db [:wallet :ui :send :route]) from-address (get-in db [:wallet :current-viewing-account-address]) - to-address (get-in db [:wallet :ui :send :to-address]) token (get-in db [:wallet :ui :send :token]) - token-id (:symbol token) - request-params [(multi-transaction-command {:from-address from-address - :to-address to-address - :from-asset token-id - :to-asset token-id - :amount-out (:amount-out route)}) - (transaction-bridge {:to-address to-address - :from-address from-address - :route route}) + collectible (get-in db [:wallet :ui :send :collectible]) + token-address (when collectible + (get-in collectible + [:id :contract-id :address])) + to-address (get-in db [:wallet :ui :send :to-address]) + token-id (if token + (:symbol token) + (get-in collectible [:id :token-id])) + request-params [(multi-transaction-command + {:from-address from-address + :to-address to-address + :from-asset token-id + :to-asset token-id + :amount-out (:amount-out route)}) + (transaction-bridge {:to-address to-address + :from-address from-address + :route route + :token-address token-address + :token-id (when collectible + (money/to-hex (js/parseInt token-id)))}) sha3-pwd]] {:json-rpc/call [{:method "wallet_createMultiTransaction" :params request-params diff --git a/src/status_im/contexts/wallet/send/select_asset/view.cljs b/src/status_im/contexts/wallet/send/select_asset/view.cljs index ae299dff7a..c871740f47 100644 --- a/src/status_im/contexts/wallet/send/select_asset/view.cljs +++ b/src/status_im/contexts/wallet/send/select_asset/view.cljs @@ -61,10 +61,9 @@ [collectibles-tab/view {:collectibles collectibles :filtered? search-performed? - :on-collectible-press (fn [collectible-id] - (js/alert (str "Collectible to send: \n" - collectible-id - "\nNavigation not implemented yet")))}])) + :on-collectible-press #(rf/dispatch [:wallet/send-select-collectible + {:collectible % + :stack-id :wallet-select-asset}])}])) (defn- tab-view [search-text selected-tab on-change-text] 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 fd7f852486..4bd9ae9950 100644 --- a/src/status_im/contexts/wallet/send/transaction_confirmation/view.cljs +++ b/src/status_im/contexts/wallet/send/transaction_confirmation/view.cljs @@ -1,5 +1,6 @@ (ns status-im.contexts.wallet.send.transaction-confirmation.view (:require + [clojure.string :as string] [legacy.status-im.utils.utils :as utils] [quo.core :as quo] [quo.theme :as quo.theme] @@ -9,10 +10,11 @@ [status-im.common.standard-authentication.core :as standard-auth] [status-im.contexts.wallet.send.transaction-confirmation.style :as style] [utils.i18n :as i18n] - [utils.re-frame :as rf])) + [utils.re-frame :as rf] + [utils.security.core :as security])) (defn- transaction-title - [{:keys [token-symbol amount account to-address]}] + [{:keys [token-symbol amount account to-address image-url collectible?]}] [rn/view {:style style/content-container} [rn/view {:style {:flex-direction :row}} [quo/text @@ -22,10 +24,10 @@ :accessibility-label :send-label} (i18n/label :t/send)] [quo/summary-tag - {:token token-symbol + {:token (if collectible? "" token-symbol) :label (str amount " " token-symbol) - :type :token - :image-source :eth}]] + :type (if collectible? :collectible :token) + :image-source (if collectible? image-url :eth)}]] [rn/view {:style {:flex-direction :row :margin-top 4}} @@ -54,7 +56,7 @@ :label (utils/get-shortened-address to-address)}]]]) (defn- user-summary - [{:keys [amount account-props theme label accessibility-label summary-type]}] + [{:keys [amount token-symbol account-props theme label accessibility-label summary-type]}] [rn/view {:style {:padding-horizontal 20 :padding-bottom 16}} @@ -67,7 +69,8 @@ [quo/summary-info {:type summary-type :networks? true - :values {:ethereum amount} + :values {:ethereum {:amount amount + :token-symbol token-symbol}} :account-props account-props}]]) (defn- transaction-details @@ -124,72 +127,85 @@ (let [on-close #(rf/dispatch [:navigate-back-within-stack :wallet-select-asset]) send-transaction-data (rf/sub [:wallet/wallet-send]) token (:token send-transaction-data) - token-symbol (:symbol token) - amount (:amount send-transaction-data) - route (:route send-transaction-data) - estimated-time-min (:estimated-time route) - max-fees "-" - to-address (:to-address send-transaction-data) - account (rf/sub [:wallet/current-viewing-account]) - account-color (:color account) - from-account-props {:customization-color account-color - :size 32 - :emoji (:emoji account) - :type :default - :name (:name account) - :address (utils/get-shortened-address (:address account))} - user-props {:full-name to-address - :address (utils/get-shortened-address to-address)}] - (prn route) + collectible (:collectible send-transaction-data) + collection-data (:collection-data collectible) + collectible-data (:collectible-data collectible) + collectible-id (get-in collectible [:id :token-id]) + token-symbol (if collectible + (first (remove string/blank? + [(:name collectible-data) + (str (:name collection-data) " #" collectible-id)])) + (:symbol token)) + image-url (when collectible (:image-url collectible-data)) + amount (:amount send-transaction-data)] (fn [{:keys [theme]}] - [rn/view {:style {:flex 1}} - [floating-button-page/view - {:header [quo/page-nav - {:icon-name :i/arrow-left - :on-press on-close - :margin-top (safe-area/get-top) - :background :blur - :accessibility-label :top-bar - :right-side [{:icon-name :i/advanced - :on-press #(js/alert - "to be implemented") - :accessibility-label :advanced-options}]}] - :footer [standard-auth/slide-button - {:size :size-48 - :track-text (i18n/label :t/slide-to-send) - :container-style {:z-index 2} - :customization-color account-color - :on-auth-success #(rf/dispatch [:wallet/send-transaction %]) - :auth-button-label (i18n/label :t/confirm)}] - :gradient-cover? true - :customization-color (:color account)} - [rn/view - [transaction-title - {:token-symbol token-symbol - :amount amount - :account account - :to-address to-address}] - [user-summary - {:amount amount - :summary-type :status-account - :accessibility-label :summary-from-label - :label (i18n/label :t/from-capitalized) - :account-props from-account-props - :theme theme}] - [user-summary - {:amount amount - :summary-type :account - :accessibility-label :summary-to-label - :label (i18n/label :t/to-capitalized) - :account-props user-props - :theme theme}] - [transaction-details - {:estimated-time-min estimated-time-min - :max-fees max-fees - :token token - :amount amount - :to-address to-address - :theme theme}]]]]))) + (let [route (:route send-transaction-data) + estimated-time-min (:estimated-time route) + max-fees "-" + to-address (:to-address send-transaction-data) + account (rf/sub [:wallet/current-viewing-account]) + account-color (:color account) + from-account-props {:customization-color account-color + :size 32 + :emoji (:emoji account) + :type :default + :name (:name account) + :address (utils/get-shortened-address (:address account))} + user-props {:full-name to-address + :address (utils/get-shortened-address to-address)}] + [rn/view {:style {:flex 1}} + [floating-button-page/view + {:header [quo/page-nav + {:icon-name :i/arrow-left + :on-press on-close + :margin-top (safe-area/get-top) + :background :blur + :accessibility-label :top-bar + :right-side [{:icon-name :i/advanced + :on-press #(js/alert + "to be implemented") + :accessibility-label :advanced-options}]}] + :footer [standard-auth/slide-button + {:size :size-48 + :track-text (i18n/label :t/slide-to-send) + :container-style {:z-index 2} + :customization-color account-color + :on-auth-success #(rf/dispatch [:wallet/send-transaction + (security/safe-unmask-data %)]) + :auth-button-label (i18n/label :t/confirm)}] + :gradient-cover? true + :customization-color (:color account)} + [rn/view + [transaction-title + {:token-symbol token-symbol + :amount amount + :account account + :to-address to-address + :image-url image-url + :collectible? (some? collectible)}] + [user-summary + {:amount amount + :token-symbol token-symbol + :summary-type :status-account + :accessibility-label :summary-from-label + :label (i18n/label :t/from-capitalized) + :account-props from-account-props + :theme theme}] + [user-summary + {:amount amount + :token-symbol token-symbol + :summary-type :account + :accessibility-label :summary-to-label + :label (i18n/label :t/to-capitalized) + :account-props user-props + :theme theme}] + [transaction-details + {:estimated-time-min estimated-time-min + :max-fees max-fees + :token token + :amount amount + :to-address to-address + :theme theme}]]]])))) (def view (quo.theme/with-theme view-internal))