Wallet: loading networks (#18491)

Wallet: loading networks
This commit is contained in:
Omar Basem 2024-01-17 13:57:02 +04:00 committed by GitHub
parent 02b8d2140a
commit 19aa78cc81
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 127 additions and 149 deletions

View File

@ -219,7 +219,8 @@
(def regx-community-universal-link #"((^https?://status.app/)|(^status-app://))c/([\x00-\x7F]+)$")
(def regx-deep-link #"((^ethereum:.*)|(^status-app://[\x00-\x7F]+$))")
(def regx-ens #"^(?=.{5,255}$)([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.[a-zA-Z]{2,}$")
(def regx-address #"^0x[a-fA-F0-9]{40}$")
(def regx-multichain-address #"^(?:(?:eth:|arb1:|opt:)(?=:|))*0x[0-9a-fA-F]{40}$")
(def regx-address-contains #"(?i)0x[a-fA-F0-9]{40}")
(def regx-starts-with-uuid #"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")
(def regx-full-or-partial-address #"^0x[a-fA-F0-9]{1,40}$")

View File

@ -8,13 +8,16 @@
[status-im.config :as config]
[status-im.contexts.profile.utils :as profile.utils]
[status-im.contexts.wallet.account.tabs.about.style :as style]
[status-im.contexts.wallet.common.utils :as utils]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn about-options
[]
(let [{:keys [address] :as account} (rf/sub [:wallet/current-viewing-account])
share-title (str (:name account) " " (i18n/label :t/address))]
networks (rf/sub [:wallet/network-preference-details])
share-title (str (:name account) " " (i18n/label :t/address))
multichain-address (utils/get-multichain-address networks address)]
[quo/action-drawer
[[{:icon :i/link
:accessibility-label :view-on-eth
@ -44,7 +47,7 @@
:accessibility-label :copy-address
:label (i18n/label :t/copy-address)
:on-press (fn []
(clipboard/set-string address)
(clipboard/set-string multichain-address)
(rf/dispatch [:toasts/upsert
{:type :positive
:text (i18n/label :t/address-copied)}]))}
@ -59,15 +62,17 @@
(js/setTimeout
#(share/open
(if platform/ios?
{:activityItemSources [{:placeholderItem {:type "text"
:content address}
:item {:default {:type "text"
:content
address}}
{:activityItemSources [{:placeholderItem {:type "text"
:content
multichain-address}
:item {:default
{:type "text"
:content
multichain-address}}
:linkMetadata {:title share-title}}]}
{:title share-title
:subject share-title
:message address}))
:message multichain-address}))
600))}]]]))
(defn view

View File

@ -10,6 +10,7 @@
[react-native.platform :as platform]
[reagent.core :as reagent]
[status-im.contexts.wallet.common.sheets.account-options.style :as style]
[status-im.contexts.wallet.common.utils :as utils]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@ -31,7 +32,10 @@
(defn- options
[{:keys [theme show-account-selector? options-height]}]
(let [{:keys [name color emoji address watch-only?]} (rf/sub [:wallet/current-viewing-account])
network-preference-details (rf/sub [:wallet/network-preference-details])]
network-preference-details (rf/sub [:wallet/network-preference-details])
multichain-address (utils/get-multichain-address
network-preference-details
address)]
[rn/view
{:on-layout #(reset! options-height (oops/oget % "nativeEvent.layout.height"))
:style (when show-account-selector? style/options-container)}
@ -72,7 +76,7 @@
(rf/dispatch [:toasts/upsert
{:type :positive
:text (i18n/label :t/address-copied)}])
(clipboard/set-string address))}
(clipboard/set-string multichain-address))}
{:icon :i/share
:accessibility-label :share-account
:label (i18n/label :t/share-account)}

View File

@ -202,3 +202,15 @@
:customization-color color
:values {:crypto-value crypto-value
:fiat-value fiat-value}}))
(defn get-multichain-address
[networks address]
(str (->> networks
(map #(str (:short-name %) ":"))
(clojure.string/join ""))
address))
(defn split-prefix-and-address
[input-string]
(let [split-result (string/split input-string #"0x")]
[(first split-result) (str "0x" (second split-result))]))

View File

@ -2,4 +2,4 @@
(:require [status-im.constants :as constants]))
(defn ens-name? [s] (re-find constants/regx-ens s))
(defn eth-address? [s] (re-find constants/regx-address s))
(defn eth-address? [s] (re-find constants/regx-multichain-address s))

View File

@ -2,11 +2,10 @@
(:require
[camel-snake-kebab.core :as csk]
[camel-snake-kebab.extras :as cske]
[native-module.core :as native-module]
[status-im.constants :as constants]
[status-im.contexts.wallet.common.utils :as utils]
[status-im.contexts.wallet.send.utils :as send-utils]
[taoensso.timbre :as log]
[utils.address :as address]
[utils.money :as money]
[utils.number]
[utils.re-frame :as rf]))
@ -42,23 +41,32 @@
(update-in [:wallet :ui :send] dissoc :route)
(update-in [:wallet :ui :send] dissoc :loading-suggested-routes?))}))
(rf/reg-event-fx :wallet/select-send-account-address
(fn [{:keys [db]} [{:keys [address stack-id]}]]
{:db (-> db
(assoc-in [:wallet :ui :send :send-account-address] address)
(update-in [:wallet :ui :send] dissoc :to-address))
:fx [[:navigate-to-within-stack [:wallet-select-asset stack-id]]]}))
(rf/reg-event-fx :wallet/clean-send-address
(fn [{:keys [db]}]
{:db (update-in db [:wallet :ui :send] dissoc :recipient :to-address)}))
(rf/reg-event-fx :wallet/select-send-address
(fn [{:keys [db]} [{:keys [address token recipient stack-id]}]]
{:db (-> db
(assoc-in [:wallet :ui :send :recipient] (or recipient address))
(assoc-in [:wallet :ui :send :to-address] address))
:fx [[:navigate-to-within-stack
(if token [:wallet-send-input-amount stack-id] [:wallet-select-asset stack-id])]]}))
(let [[prefix to-address] (utils/split-prefix-and-address address)]
{:db (-> db
(assoc-in [:wallet :ui :send :recipient] (or recipient address))
(assoc-in [:wallet :ui :send :to-address] to-address)
(assoc-in [:wallet :ui :send :address-prefix] prefix))
:fx [[:navigate-to-within-stack
(if token
[:wallet-send-input-amount stack-id]
[:wallet-select-asset stack-id])]]})))
(rf/reg-event-fx :wallet/send-select-token
(fn [{:keys [db]} [{:keys [token stack-id]}]]
{:db (-> db
(update-in [:wallet :ui :send] dissoc :collectible)
(assoc-in [:wallet :ui :send :token] token))
{:db (assoc-in db [:wallet :ui :send :token] token)
:fx [[:navigate-to-within-stack [:wallet-send-input-amount stack-id]]]}))
(rf/reg-event-fx :wallet/send-select-token-drawer
@ -69,15 +77,6 @@
(fn [{:keys [db]}]
{:db (assoc-in db [:wallet :ui :send :token] nil)}))
(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)
@ -87,25 +86,18 @@
(fn [{:keys [db now]} [amount]]
(let [wallet-address (get-in db [:wallet :current-viewing-account-address])
token (get-in db [:wallet :ui :send :token])
collectible (get-in db [:wallet :ui :send :collectible])
to-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])])
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 (:decimals token)
token-id (:symbol token)
network-preferences []
gas-rates constants/gas-rate-medium
amount-in (send-utils/amount-in-hex amount (if token token-decimal 0))
amount-in (send-utils/amount-in-hex amount token-decimal)
from-address wallet-address
disabled-from-chain-ids []
disabled-to-chain-ids []
from-locked-amount {}
transaction-type (if token
constants/send-type-transfer
constants/send-type-erc-721-transfer)
request-params [transaction-type
request-params [constants/send-type-transfer
from-address
to-address
amount-in
@ -142,46 +134,21 @@
:fx [[:dispatch [:navigate-to :wallet-transaction-progress]]]})))
(defn- transaction-bridge
[{:keys [from-address from-chain-id to-address token-id token-address route data eth-transfer?]}]
(let [{:keys [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 (cond-> {:From from-address
:To (or token-address to-address)
:Gas (money/to-hex gas-amount)
:Value (when eth-transfer? amount-out)
:Nonce nil
:Input ""
:Data (or data "0x")}
eip-1559-enabled? (assoc :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)))
(not eip-1559-enabled?) (assoc :TxType "0x00"
:GasPrice (money/to-hex
(money/->wei
:gwei
gas-price))))]
[(cond-> {:BridgeName bridge-name
:ChainID from-chain-id}
(= bridge-name constants/bridge-name-erc-721-transfer)
(assoc :ERC721TransferTx
(assoc transfer-tx
:Recipient to-address
:TokenID token-id))
(= bridge-name constants/bridge-name-transfer)
(assoc :TransferTx transfer-tx))]))
[{: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"}}]))
(defn- multi-transaction-command
[{:keys [from-address to-address from-asset to-asset amount-out transfer-type]
@ -195,53 +162,27 @@
(rf/reg-event-fx :wallet/send-transaction
(fn [{:keys [db]} [sha3-pwd]]
(let [route (get-in db [:wallet :ui :send :route])
from-address (get-in db [:wallet :current-viewing-account-address])
token (get-in db [:wallet :ui :send :token])
collectible (get-in db [:wallet :ui :send :collectible])
from-chain-id (get-in 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 from-chain-id :address]))
to-address (get-in db [:wallet :ui :send :to-address])
data (when erc20-transfer?
(native-module/encode-transfer (address/normalized-hex to-address)
(:amount-out route)))
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 route) "0x0")})
(transaction-bridge {:to-address to-address
:from-address from-address
:route route
:from-chain-id from-chain-id
:token-address token-address
:token-id (when collectible
(money/to-hex (js/parseInt token-id)))
:data data
:eth-transfer? eth-transfer?})
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})
sha3-pwd]]
{:json-rpc/call [{:method "wallet_createMultiTransaction"
:params request-params
:on-success (fn [result]
(rf/dispatch [:hide-bottom-sheet])
(rf/dispatch [:wallet/add-authorized-transaction result])
(rf/dispatch [:wallet/clean-scanned-address])
(rf/dispatch [:wallet/clean-local-suggestions])
(rf/dispatch [:wallet/clean-send-address])
(rf/dispatch [:wallet/select-address-tab nil]))
(rf/dispatch [:wallet/add-authorized-transaction result]))
:on-error (fn [error]
(log/error "failed to send transaction"
{:event :wallet/send-transaction
:error error
:params request-params}))}]})))

View File

@ -53,6 +53,13 @@
(normalize-input current v)
current))
(defn- find-affordable-networks
[{:keys [balances-per-chain]} input-value]
(->> balances-per-chain
(filter (fn [[_ {:keys [balance]}]]
(>= (js/parseFloat balance) input-value)))
(map first)))
(defn- f-view-internal
[{:keys [rate limit]}]
(let [bottom (safe-area/get-bottom)
@ -142,9 +149,10 @@
:on-change-text (fn [text]
(handle-on-change text))}]
[routes/view
{:amount amount
:routes suggested-routes
:networks (:networks token)}]
{:amount amount
:routes suggested-routes
:loading-networks (find-affordable-networks token @input-value)
:networks (:networks token)}]
[quo/bottom-actions
{:actions :1-action
:button-one-label (i18n/label :t/confirm)

View File

@ -14,11 +14,13 @@
{:amount amount
:network from-network
:status status}]
[quo/network-link
{:shape :linear
:source from-network
:destination to-network
:container-style style/network-link}]
(if (= status :default)
[quo/network-link
{:shape :linear
:source from-network
:destination to-network
:container-style style/network-link}]
[rn/view {:style {:width 73}}])
[quo/network-bridge
{:amount amount
:network to-network
@ -26,12 +28,12 @@
:container-style {:right 12}}]])
(defn view
[{:keys [amount routes]}]
[{:keys [amount routes loading-networks]}]
(let [loading-suggested-routes? (rf/sub [:wallet/wallet-send-loading-suggested-routes?])
candidates (:candidates routes)]
(if (and (not loading-suggested-routes?) (not-empty candidates))
(if (or (and (not-empty loading-networks) loading-suggested-routes?) (not-empty candidates))
[rn/flat-list
{:data candidates
{:data (if loading-suggested-routes? loading-networks candidates)
:content-container-style style/routes-container
:header [rn/view {:style style/routes-header-container}
[quo/section-label
@ -40,15 +42,17 @@
[quo/section-label
{:section (i18n/label :t/to-label)
:container-style (style/section-label 64)}]]
:render-fn (fn [route]
:render-fn (fn [item]
[route-item
{:amount amount
:status :default
:from-network (utils/id->network (get-in route [:from :chain-id]))
:to-network (utils/id->network (get-in route
[:to :chain-id]))}])}]
:status (if loading-suggested-routes? :loading :default)
:from-network (if loading-suggested-routes?
(utils/id->network item)
(utils/id->network (get-in item [:from :chain-id])))
:to-network (if loading-suggested-routes?
(utils/id->network item)
(utils/id->network (get-in item
[:to :chain-id])))}])}]
[rn/view {:style style/empty-container}
(if loading-suggested-routes?
[rn/activity-indicator]
(when (not (nil? candidates))
[quo/text (i18n/label :t/no-routes-found)]))])))
(when (and (not (nil? candidates)) (not loading-suggested-routes?))
[quo/text (i18n/label :t/no-routes-found)])])))

View File

@ -38,8 +38,8 @@
(rn/dismiss-keyboard!)
(rf/dispatch [:open-modal :scan-address]))
:ens-regex constants/regx-ens
:address-regex constants/regx-address
:scanned-value (or (when recipient-plain-address? send-address) scanned-address)
:address-regex constants/regx-multichain-address
:on-detect-address #(debounce/debounce-and-dispatch
[:wallet/validate-address %]
300)
@ -48,8 +48,6 @@
[:wallet/find-ens text contacts chain-id cb]
300))
:on-change-text (fn [text]
(when-not (= scanned-address text)
(rf/dispatch [:wallet/clean-scanned-address]))
(when (empty? text)
(rf/dispatch [:wallet/clean-local-suggestions]))
(reset! input-value text))

View File

@ -43,6 +43,11 @@
:<- [:wallet/wallet-send]
:-> :to-address)
(rf/reg-sub
:wallet/wallet-send-address-prefix
:<- [:wallet/wallet-send]
:-> :address-prefix)
(rf/reg-sub
:wallet/wallet-send-route
:<- [:wallet/wallet-send]