🎛️ Account switcher UI for Wallet Connect sessions (#20573)

* 🎛️ Account switcher UI for Wallet Connect sessions

* 😢 Remove repl workflow

* 🔀 Merge current-proposal request and account

*  Remove redundant test

* 🐛 Lint fix

---------

Co-authored-by: Lungu Cristian <lungucristian95@gmail.com>
This commit is contained in:
Shivek Khurana 2024-07-02 18:48:48 +05:30 committed by GitHub
parent b650591e58
commit b021b1e20a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 142 additions and 61 deletions

View File

@ -53,10 +53,22 @@
(rf/reg-event-fx
:wallet-connect/on-session-proposal
(fn [{:keys [db]} [proposal]]
(log/info "Received Wallet Connect session proposal: " {:id (:id proposal)})
{:db (assoc db :wallet-connect/current-proposal proposal)
:fx [[:dispatch
[:open-modal :screen/wallet.wallet-connect-session-proposal]]]}))
(let [accounts (get-in db [:wallet :accounts])
without-watched (remove :watch-only? (vals accounts))]
(log/info "Received Wallet Connect session proposal: " {:id (:id proposal)})
{:db (assoc db
;; NOTE: for now using the first account, but should be using the account selected
;; by the user on the connection screen. The default would depend on where the
;; connection started from:
;; - global scanner -> first account in list
;; - wallet account dapps -> account that is selected
:wallet-connect/current-proposal
{:request proposal
:address (-> without-watched
first
:address)})
:fx [[:dispatch
[:open-modal :screen/wallet.wallet-connect-session-proposal]]]})))
(rf/reg-event-fx
:wallet-connect/on-session-request
@ -69,6 +81,11 @@
(fn [{:keys [db]}]
{:db (dissoc db :wallet-connect/current-proposal)}))
(rf/reg-event-fx
:wallet-connect/set-current-proposal-address
(fn [{:keys [db]} [address]]
{:db (assoc-in db [:wallet-connect/current-proposal :address] address)}))
(rf/reg-event-fx
:wallet-connect/reset-current-request
(fn [{:keys [db]}]
@ -119,39 +136,34 @@
(rf/reg-event-fx
:wallet-connect/approve-session
(fn [{:keys [db]}]
(let [web3-wallet (get db :wallet-connect/web3-wallet)
current-proposal (get db :wallet-connect/current-proposal)
accounts (get-in db [:wallet :accounts])
supported-chain-ids (->> db
chain/chain-ids
(map wallet-connect-core/chain-id->eip155)
vec)
;; NOTE: for now using the first account, but should be using the account selected by the
;; user on the connection screen. The default would depend on where the connection started
;; from:
;; - global scanner -> first account in list
;; - wallet account dapps -> account that is selected
address (-> accounts keys first)
accounts (-> (partial wallet-connect-core/format-eip155-address address)
(map supported-chain-ids))
supported-namespaces (clj->js {:eip155
{:chains supported-chain-ids
:methods constants/wallet-connect-supported-methods
:events constants/wallet-connect-supported-events
:accounts accounts}})]
(let [web3-wallet (get db :wallet-connect/web3-wallet)
current-proposal-request (get-in db [:wallet-connect/current-proposal :request])
supported-chain-ids (->> db
chain/chain-ids
(map wallet-connect-core/chain-id->eip155)
vec)
current-address (get-in db [:wallet-connect/current-proposal :address])
accounts (-> (partial wallet-connect-core/format-eip155-address current-address)
(map supported-chain-ids))
supported-namespaces (clj->js {:eip155
{:chains supported-chain-ids
:methods constants/wallet-connect-supported-methods
:events constants/wallet-connect-supported-events
:accounts accounts}})]
{:fx [[:effects.wallet-connect/approve-session
{:web3-wallet web3-wallet
:proposal current-proposal
:proposal current-proposal-request
:supported-namespaces supported-namespaces
:on-success (fn []
(log/info "Wallet Connect session approved")
(let [metadata (-> current-proposal :params :proposer :metadata)]
(let [metadata
(-> current-proposal-request :params :proposer :metadata)]
(rf/dispatch [:wallet-connect/reset-current-session-proposal])
(rf/dispatch [:wallet-connect/persist-session
{:id (:id current-proposal)
{:id (:id current-proposal-request)
:dapp-name (:name metadata)
:dapp-url (:url metadata)
:session-info current-proposal}])))
:session-info current-proposal-request}])))
:on-fail (fn [error]
(log/error "Wallet Connect session approval failed"
{:error error

View File

@ -24,3 +24,10 @@
(def approval-li-spacer
{:width 8})
(def account-switcher-title
{:padding-horizontal 20})
(def account-switcher-list
{:margin-top 8
:padding-horizontal 8})

View File

@ -51,36 +51,79 @@
{:source (quo.resources/get-network :optimism)}
{:source (quo.resources/get-network :arbitrum)}])
(defn- set-current-proposal-address
[acc]
(fn []
(rf/dispatch [:wallet-connect/set-current-proposal-address (:address acc)])
(rf/dispatch [:hide-bottom-sheet])))
(defn- accounts-list
[]
(let [accounts (rf/sub [:wallet/accounts-without-watched-accounts])
selected-address (rf/sub [:wallet-connect/current-proposal-address])]
[rn/view {:style style/account-switcher-list}
(for [account accounts]
^{:key (-> account :address str)}
[quo/account-item
{:type :default
:state (if (and selected-address
(= (account :address)
selected-address))
:selected
:default)
:account-props account
:on-press (set-current-proposal-address account)}])]))
(defn- account-switcher-sheet
[]
[:<>
[rn/view {:style style/account-switcher-title}
[quo/text
{:size :heading-2
:weight :semi-bold
:accessibility-label "select-account-title"}
(i18n/label :t/select-account)]]
[accounts-list]])
(defn- show-account-switcher-bottom-sheet
[]
(rf/dispatch
[:show-bottom-sheet
{:content account-switcher-sheet}]))
(defn- connection-category
[]
(let [{:keys [name emoji customization-color]} (first (rf/sub
[:wallet/accounts-without-watched-accounts]))
data-item-common-props {:blur? false
:description :default
:card? false
:label :preview
:status :default
:size :default}
account-data-item-props (assoc data-item-common-props
:right-content {:type :accounts
:size :size-32
:data [{:emoji emoji
:customization-color
customization-color}]}
:on-press #(js/alert "Not yet implemented")
:title (i18n/label :t/account-title)
:subtitle name
:icon-right? true
:right-icon :i/chevron-right
:icon-color colors/neutral-10)
networks-data-item-props (assoc data-item-common-props
:right-content {:type :network
:data
(get-placeholder-networks)}
:title (i18n/label :t/networks)
;; TODO. The quo component for data-item
;; does not support showing networks yet
:subtitle "Networks placeholder")]
(let [address (rf/sub [:wallet-connect/current-proposal-address])
{:keys
[name
customization-color
emoji]} (rf/sub [:wallet-connect/account-details-by-address address])
data-item-common-props {:blur? false
:description :default
:card? false
:label :preview
:status :default
:size :default}
account-data-item-props (assoc data-item-common-props
:right-content {:type :accounts
:size :size-32
:data [{:emoji emoji
:customization-color
customization-color}]}
:on-press show-account-switcher-bottom-sheet
:title (i18n/label :t/account-title)
:subtitle name
:icon-right? true
:right-icon :i/chevron-right
:icon-color colors/neutral-10)
networks-data-item-props (assoc data-item-common-props
:right-content {:type :network
:data
(get-placeholder-networks)}
:title (i18n/label :t/networks)
;; TODO. The quo component for data-item
;; does not support showing networks yet
:subtitle "Networks placeholder")]
[quo/category
{:blur? false
:list-type :data-item

View File

@ -111,10 +111,15 @@
:wallet-connect/session-proposer
:<- [:wallet-connect/current-proposal]
(fn [proposal]
(-> proposal :params :proposer)))
(-> proposal :request :params :proposer)))
(rf/reg-sub
:wallet-connect/session-proposer-name
:<- [:wallet-connect/session-proposer]
(fn [proposer]
(-> proposer :metadata :name)))
(rf/reg-sub
:wallet-connect/current-proposal-address
(fn [db]
(get-in db [:wallet-connect/current-proposal :address])))

View File

@ -45,8 +45,8 @@
[sub-name]
(testing "Return the session proposer public key and metadata"
(swap! rf-db/app-db
assoc
:wallet-connect/current-proposal
assoc-in
[:wallet-connect/current-proposal :request]
sample-session)
(let [proposer (rf/sub [sub-name])]
@ -60,9 +60,23 @@
[sub-name]
(testing "Return only the name of the session proposer"
(swap! rf-db/app-db
assoc
:wallet-connect/current-proposal
assoc-in
[:wallet-connect/current-proposal :request]
sample-session)
(is (= (-> sample-session :params :proposer :metadata :name)
(rf/sub [sub-name])))))
(h/deftest-sub :wallet-connect/current-proposal-address
[sub-name]
(testing "Return the current proposal account address"
(let [address "0x1234567890abcdef"]
(swap! rf-db/app-db assoc-in [:wallet-connect/current-proposal :address] address)
(is (= address (rf/sub [sub-name]))))
(testing "Return nil when there is no current proposal account"
(swap! rf-db/app-db assoc-in [:wallet-connect/current-proposal :address] nil)
(is (nil? (rf/sub [sub-name]))))))