Wallet Connect session establish networks (#20576)

* feat: showing supported networks in wc connection

* feat: added :large size for quo/data-item

* feat: added required networks check
This commit is contained in:
Lungu Cristian 2024-07-02 16:39:33 +02:00 committed by GitHub
parent b021b1e20a
commit ac4ffd83db
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 207 additions and 114 deletions

View File

@ -6,8 +6,14 @@
[{:keys [size card? blur? actionable? theme]}]
{:flex-direction :row
:justify-content :space-between
:padding-vertical (when (= size :default) 8)
:padding-horizontal (when (= size :default) 12)
:padding-vertical (case size
:default 8
:large 12
nil)
:padding-horizontal (case size
:default 12
:large 16
nil)
:border-radius 16
:border-width (when (and card? (not= size :small)) 1)
:background-color (if blur?
@ -24,15 +30,27 @@
(defn loading-container
[size blur? theme]
{:width (if (= size :default) 132 72)
:height (if (= size :default) 16 10)
{:width (case size
:large 132
:small 72
132)
:height (case size
:large 16
:small 10
16)
:background-color (if blur?
colors/white-opa-5
(colors/theme-colors colors/neutral-5
colors/neutral-90
theme))
:border-radius (if (= size :default) 6 3)
:margin-vertical (if (= size :default) 4 3)})
:border-radius (case size
:large 6
:small 3
6)
:margin-vertical (case size
:large 4
:small 3
4)})
(def subtitle-container
{:flex-direction :row

View File

@ -55,7 +55,8 @@
{:type :select
:key :size
:options [{:key :default}
{:key :small}]}])
{:key :small}
{:key :large}]}])
(defn view
[]

View File

@ -45,6 +45,10 @@
[db]
(get-in db [:wallet-connect/current-request :event]))
(defn get-session-dapp-metadata
[proposal]
(get-in proposal [:params :proposer :metadata]))
(defn get-db-current-request-params
[db]
(-> db
@ -61,3 +65,32 @@
(->> password
security/safe-unmask-data
(f data address))))
(defn get-proposal-networks
[proposal]
(let [required-namespaces (get-in proposal [:params :requiredNamespaces])
optional-namespaces (get-in proposal [:params :optionalNamespaces])]
(->> [required-namespaces optional-namespaces]
(map #(get-in % [:eip155 :chains]))
(apply concat)
(into #{}))))
(defn proposal-networks-intersection
[proposal supported-networks]
(let [proposed-networks (get-proposal-networks proposal)]
(->> supported-networks
(filter #(->> %
chain-id->eip155
(contains? proposed-networks))))))
(defn required-networks-supported?
[proposal supported-networks]
(let [required-networks (get-in proposal [:params :requiredNamespaces :eip155 :chains])
supported-eip155 (set (map chain-id->eip155 supported-networks))]
(every? #(contains? supported-eip155 %) required-networks)))
(defn get-networks-by-mode
[db]
(let [test-mode? (get-in db [:profile/profile :test-networks-enabled?])
networks (get-in db [:wallet :networks (if test-mode? :test :prod)])]
(mapv #(-> % :chain-id) networks)))

View File

@ -8,7 +8,6 @@
status-im.contexts.wallet.wallet-connect.responding-events
[status-im.contexts.wallet.wallet-connect.utils :as wc-utils]
[taoensso.timbre :as log]
[utils.ethereum.chain :as chain]
[utils.i18n :as i18n]))
(rf/reg-event-fx
@ -53,22 +52,37 @@
(rf/reg-event-fx
:wallet-connect/on-session-proposal
(fn [{:keys [db]} [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]]]})))
(log/info "Received Wallet Connect session proposal: " {:id (:id proposal)})
(let [accounts (get-in db [:wallet :accounts])
without-watched (remove :watch-only? (vals accounts))
networks (wallet-connect-core/get-networks-by-mode db)
session-networks (wallet-connect-core/proposal-networks-intersection proposal
networks)
required-networks-supported? (wallet-connect-core/required-networks-supported? proposal
networks)]
(if required-networks-supported?
{:db (update db
:wallet-connect/current-proposal assoc
:request proposal
:session-networks session-networks
:address (-> without-watched
first
:address)
)
:fx [[:dispatch
[:open-modal :screen/wallet.wallet-connect-session-proposal]]]}
{:fx [[:dispatch
[:wallet-connect/session-networks-unsupported proposal]]]}))))
(rf/reg-event-fx
:wallet-connect/session-networks-unsupported
(fn [_ [proposal]]
(let [{:keys [name]} (wallet-connect-core/get-session-dapp-metadata proposal)]
{:fx [[:dispatch
[:toasts/upsert
{:type :negative
:theme :dark
:text (i18n/label :t/wallet-connect-networks-not-supported {:dapp name})}]]]})))
(rf/reg-event-fx
:wallet-connect/on-session-request
@ -136,34 +150,33 @@
(rf/reg-event-fx
:wallet-connect/approve-session
(fn [{:keys [db]}]
(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}})]
(let [web3-wallet (get db :wallet-connect/web3-wallet)
current-proposal (get-in db [:wallet-connect/current-proposal :request])
session-networks (->> (get-in db [:wallet-connect/current-proposal :session-networks])
(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 session-networks))
supported-namespaces (clj->js {:eip155
{:chains session-networks
: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-request
:proposal current-proposal
:supported-namespaces supported-namespaces
:on-success (fn []
(log/info "Wallet Connect session approved")
(let [metadata
(-> current-proposal-request :params :proposer :metadata)]
(let [metadata (wallet-connect-core/get-session-dapp-metadata
current-proposal)]
(rf/dispatch [:wallet-connect/reset-current-session-proposal])
(rf/dispatch [:wallet-connect/persist-session
{:id (:id current-proposal-request)
{:id (:id current-proposal)
:dapp-name (:name metadata)
:dapp-url (:url metadata)
:session-info current-proposal-request}])))
:session-info current-proposal}])))
:on-fail (fn [error]
(log/error "Wallet Connect session approval failed"
{:error error

View File

@ -1,8 +1,8 @@
(ns status-im.contexts.wallet.wallet-connect.session-proposal.view
(:require
[clojure.string :as string]
[quo.core :as quo]
[quo.foundations.colors :as colors]
[quo.foundations.resources :as quo.resources]
[quo.theme]
[react-native.core :as rn]
[status-im.common.floating-button-page.view :as floating-button-page]
@ -45,11 +45,9 @@
[quo/text label]])
labels)]))
(defn- get-placeholder-networks
[]
[{:source (quo.resources/get-network :ethereum)}
{:source (quo.resources/get-network :optimism)}
{:source (quo.resources/get-network :arbitrum)}])
(defn- format-network-name
[network]
(-> network :network-name name string/capitalize))
(defn- set-current-proposal-address
[acc]
@ -93,37 +91,41 @@
(defn- connection-category
[]
(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")]
(let [{:keys [session-networks
all-networks-in-session?]} (rf/sub
[:wallet-connect/session-proposal-network-details])
address (rf/sub [:wallet-connect/current-proposal-address])
{:keys [name customization-color emoji]} (rf/sub [:wallet-connect/account-details-by-address
address])
network-names (->> session-networks
(map format-network-name)
(string/join ", "))
network-images (mapv :source session-networks)
data-item-common-props {:blur? false
:description :default
:card? false
:label :preview
:status :default
:size :large}
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 network-images}
:title (i18n/label :t/networks)
:subtitle (if all-networks-in-session?
(i18n/label :t/all-networks)
network-names))]
[quo/category
{:blur? false
:list-type :data-item

View File

@ -108,10 +108,20 @@
:else nil)})))))
(rf/reg-sub
:wallet-connect/session-proposer
:wallet-connect/current-proposal-request
:<- [:wallet-connect/current-proposal]
:-> :request)
(rf/reg-sub
:wallet-connect/session-proposal-networks
:<- [:wallet-connect/current-proposal]
:-> :session-networks)
(rf/reg-sub
:wallet-connect/session-proposer
:<- [:wallet-connect/current-proposal-request]
(fn [proposal]
(-> proposal :request :params :proposer)))
(-> proposal :params :proposer)))
(rf/reg-sub
:wallet-connect/session-proposer-name
@ -119,6 +129,18 @@
(fn [proposer]
(-> proposer :metadata :name)))
(rf/reg-sub
:wallet-connect/session-proposal-network-details
:<- [:wallet-connect/session-proposal-networks]
:<- [:wallet/network-details]
(fn [[session-networks network-details]]
(let [supported-networks (map :chain-id network-details)
session-networks (filterv #(contains? (set session-networks) (:chain-id %))
network-details)
all-networks-in-session? (= (count supported-networks) (count session-networks))]
{:session-networks session-networks
:all-networks-in-session? all-networks-in-session?})))
(rf/reg-sub
:wallet-connect/current-proposal-address
(fn [db]

View File

@ -8,38 +8,39 @@
[utils.re-frame :as rf]))
(def sample-session
{:id 1716798889093634
:params
{:id 1716798889093634
:pairingTopic "9b18e1348817a548bbc97f9b4a09278f4fdf7c984e4a61ddf461bd1f57710d33"
:expiryTimestamp 1716799189
:requiredNamespaces {}
:optionalNamespaces {:eip155
{:chains ["eip155:1" "eip155:42161" "eip155:137" "eip155:43114" "eip155:56"
"eip155:10" "eip155:100"
"eip155:324" "eip155:7777777" "eip155:8453" "eip155:42220"
"eip155:1313161554" "eip155:11155111" "eip155:11155420"]
:methods ["personal_sign" "eth_accounts" "eth_requestAccounts"
"eth_sendRawTransaction" "eth_sendTransaction"
"eth_sign" "eth_signTransaction" "eth_signTypedData"
"eth_signTypedData_v3" "eth_signTypedData_v4"
"wallet_addEthereumChain" "wallet_getCallsStatus"
"wallet_getCapabilities" "wallet_getPermissions"
"wallet_registerOnboarding" "wallet_requestPermissions"
"wallet_scanQRCode" "wallet_sendCalls"
"wallet_showCallsStatus" "wallet_switchEthereumChain"
"wallet_watchAsset"]
:events ["chainChanged" "accountsChanged"]}}
:relays [{:protocol "irn"}]
:proposer {:publicKey "cddea055b8974d93380e6c7e72110145506c06524047866f8034f3db0990137a"
:metadata {:name "Web3Modal"
:description "Web3Modal Laboratory"
:url "https://lab.web3modal.com"
:icons ["https://avatars.githubusercontent.com/u/37784886"]}}}
:verifyContext {:verified {:verifyUrl "https://verify.walletconnect.com"
:validation "VALID"
:origin "https://lab.web3modal.com"
:isScam false}}})
{:session-proposal
{:id 1716798889093634
:params
{:id 1716798889093634
:pairingTopic "9b18e1348817a548bbc97f9b4a09278f4fdf7c984e4a61ddf461bd1f57710d33"
:expiryTimestamp 1716799189
:requiredNamespaces {}
:optionalNamespaces {:eip155
{:chains ["eip155:1" "eip155:42161" "eip155:137" "eip155:43114" "eip155:56"
"eip155:10" "eip155:100"
"eip155:324" "eip155:7777777" "eip155:8453" "eip155:42220"
"eip155:1313161554" "eip155:11155111" "eip155:11155420"]
:methods ["personal_sign" "eth_accounts" "eth_requestAccounts"
"eth_sendRawTransaction" "eth_sendTransaction"
"eth_sign" "eth_signTransaction" "eth_signTypedData"
"eth_signTypedData_v3" "eth_signTypedData_v4"
"wallet_addEthereumChain" "wallet_getCallsStatus"
"wallet_getCapabilities" "wallet_getPermissions"
"wallet_registerOnboarding" "wallet_requestPermissions"
"wallet_scanQRCode" "wallet_sendCalls"
"wallet_showCallsStatus" "wallet_switchEthereumChain"
"wallet_watchAsset"]
:events ["chainChanged" "accountsChanged"]}}
:relays [{:protocol "irn"}]
:proposer {:publicKey "cddea055b8974d93380e6c7e72110145506c06524047866f8034f3db0990137a"
:metadata {:name "Web3Modal"
:description "Web3Modal Laboratory"
:url "https://lab.web3modal.com"
:icons ["https://avatars.githubusercontent.com/u/37784886"]}}}
:verifyContext {:verified {:verifyUrl "https://verify.walletconnect.com"
:validation "VALID"
:origin "https://lab.web3modal.com"
:isScam false}}}})
(h/deftest-sub :wallet-connect/session-proposer
[sub-name]
@ -54,6 +55,7 @@
(-> sample-session :params :proposer :publicKey)))
(is (= (-> proposer :metadata :url)
(-> sample-session :params :proposer :metadata :url))))))
(h/deftest-sub :wallet-connect/session-proposer-name

View File

@ -214,6 +214,7 @@
"airdrop-addresses": "Address for airdrops",
"join-as": "Join as {{role}}",
"all-addresses": "All addresses",
"all-networks": "All networks",
"for-airdrops": "For airdrops",
"members-label": "Members",
"open-membership": "Open membership",
@ -2043,6 +2044,7 @@
"wallet-connect-sign-message-warning": "Sign messages only if you trust the dApp",
"wallet-connect-send-transaction-warning": "Send transactions only if you trust the dApp",
"wallet-connect-sign-transaction-warning": "Sign transactions only if you trust the dApp",
"wallet-connect-networks-not-supported": "{{dapp}} requires an unsupported network.",
"reject": "Reject",
"manage-connections": "Manage connections from within Application Connections",
"contact-request-was-ignored": "Contact request ignored",