* 🔳 QR on success not being called - IDK why, trying things out * 🙃 Stupid of me - My handler was not being called because I wrote the code in a different QR scanner * ✅ Approval screen taking shape * 🧹 Lint fix * 🎛️ Wallet connect session screen shows up - Hard coded the first account - The data item component doesn't support networks or accounts yet - The quo category component cannot show a data-item yet - Connected accept and decline button * 🧰 Fix review issues * 🔨 Fix lint * 🔧 Rename event and move dispatch * 🔧 Fix lint * 🎏 Add ff for wc scanner - Bring back missing event
This commit is contained in:
parent
901dddc603
commit
379ba87c16
|
@ -1,7 +1,8 @@
|
|||
(ns react-native.wallet-connect
|
||||
(:require
|
||||
["@walletconnect/core" :refer [Core]]
|
||||
["@walletconnect/utils" :refer [buildApprovedNamespaces getSdkError]]
|
||||
["@walletconnect/utils" :refer
|
||||
[buildApprovedNamespaces getSdkError parseUri]]
|
||||
["@walletconnect/web3wallet" :refer [Web3Wallet]]))
|
||||
|
||||
(defn- wallet-connect-core
|
||||
|
@ -24,3 +25,9 @@
|
|||
(defn get-sdk-error
|
||||
[error-key]
|
||||
(getSdkError error-key))
|
||||
|
||||
(defn parse-uri
|
||||
[uri]
|
||||
(-> uri
|
||||
parseUri
|
||||
(js->clj :keywordize-keys true)))
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
(goog-define ALCHEMY_OPTIMISM_MAINNET_TOKEN "")
|
||||
(goog-define ALCHEMY_OPTIMISM_GOERLI_TOKEN "")
|
||||
(goog-define ALCHEMY_OPTIMISM_SEPOLIA_TOKEN "")
|
||||
(goog-define WALLET_CONNECT_PROJECT_ID "")
|
||||
(goog-define WALLET_CONNECT_PROJECT_ID "87815d72a81d739d2a7ce15c2cfdefb3")
|
||||
|
||||
(def mainnet-rpc-url (str "https://eth-archival.rpc.grove.city/v1/" POKT_TOKEN))
|
||||
(def goerli-rpc-url (str "https://goerli-archival.gateway.pokt.network/v1/lb/" POKT_TOKEN))
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
(ns status-im.contexts.shell.qr-reader.view
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[react-native.core :as rn]
|
||||
[react-native.hooks :as hooks]
|
||||
[status-im.common.router :as router]
|
||||
[status-im.common.scan-qr-code.view :as scan-qr-code]
|
||||
[status-im.common.validation.general :as validators]
|
||||
[status-im.contexts.communities.events]
|
||||
[status-im.contexts.wallet.common.validation :as wallet-validation]
|
||||
[utils.debounce :as debounce]
|
||||
[utils.ethereum.eip.eip681 :as eip681]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.url :as url]))
|
||||
(:require [clojure.string :as string]
|
||||
[react-native.core :as rn]
|
||||
[react-native.hooks :as hooks]
|
||||
[status-im.common.router :as router]
|
||||
[status-im.common.scan-qr-code.view :as scan-qr-code]
|
||||
[status-im.common.validation.general :as validators]
|
||||
[status-im.contexts.communities.events]
|
||||
[status-im.contexts.wallet.common.validation :as wallet-validation]
|
||||
[status-im.contexts.wallet.wallet-connect.utils :as wc-utils]
|
||||
[status-im.feature-flags :as ff]
|
||||
[utils.debounce :as debounce]
|
||||
[utils.ethereum.eip.eip681 :as eip681]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.url :as url]))
|
||||
|
||||
(def invalid-qr-toast
|
||||
{:type :negative
|
||||
|
@ -42,10 +43,6 @@
|
|||
[_]
|
||||
false)
|
||||
|
||||
(defn wallet-connect-code?
|
||||
[scanned-text]
|
||||
(string/starts-with? scanned-text "wc:"))
|
||||
|
||||
(defn url?
|
||||
[scanned-text]
|
||||
(url/url? scanned-text))
|
||||
|
@ -68,6 +65,12 @@
|
|||
[:toasts/upsert invalid-qr-toast]
|
||||
300))
|
||||
|
||||
(defn- handle-wallet-connect
|
||||
[scanned-text]
|
||||
(debounce/debounce-and-dispatch
|
||||
[:wallet-connect/on-scan-connection scanned-text]
|
||||
300))
|
||||
|
||||
(defn on-qr-code-scanned
|
||||
[scanned-text]
|
||||
(cond
|
||||
|
@ -100,9 +103,10 @@
|
|||
;; TODO: https://github.com/status-im/status-mobile/issues/18744
|
||||
nil
|
||||
|
||||
(wallet-connect-code? scanned-text)
|
||||
;; WalletConnect is not working yet, this flow should be updated once WalletConnect is ready
|
||||
nil
|
||||
(and
|
||||
(wc-utils/valid-uri? scanned-text)
|
||||
(ff/enabled? ::ff/wallet.wallet-connect))
|
||||
(handle-wallet-connect scanned-text)
|
||||
|
||||
(url? scanned-text)
|
||||
(debounce/debounce-and-dispatch [:browser.ui/open-url scanned-text] 300)
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
(ns status-im.contexts.wallet.common.scan-account.view
|
||||
(:require [clojure.string :as string]
|
||||
[status-im.common.scan-qr-code.view :as scan-qr-code]
|
||||
[status-im.constants :as constants]
|
||||
[utils.debounce :as debounce]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[status-im.common.scan-qr-code.view :as scan-qr-code]
|
||||
[status-im.constants :as constants]
|
||||
[utils.debounce :as debounce]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(def ^:private supported-networks #{:eth :arb1 :oeth})
|
||||
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
(ns status-im.contexts.wallet.wallet-connect.events
|
||||
(:require [re-frame.core :as rf]
|
||||
[react-native.wallet-connect :as wallet-connect]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.wallet-connect.core :as wallet-connect-core]
|
||||
status-im.contexts.wallet.wallet-connect.effects
|
||||
status-im.contexts.wallet.wallet-connect.processing-events
|
||||
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.ethereum.chain :as chain]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/init
|
||||
|
@ -51,7 +54,9 @@
|
|||
: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)}))
|
||||
{:db (assoc db :wallet-connect/current-proposal proposal)
|
||||
:fx [[:dispatch
|
||||
[:open-modal :screen/wallet.wallet-connect-session-proposal]]]}))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/on-session-request
|
||||
|
@ -153,3 +158,32 @@
|
|||
:event :wallet-connect/approve-session})
|
||||
(rf/dispatch
|
||||
[:wallet-connect/reset-current-session-proposal]))}]]})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/on-scan-connection
|
||||
(fn [_ [scanned-text]]
|
||||
(let [parsed-uri (wallet-connect/parse-uri scanned-text)
|
||||
version (:version parsed-uri)
|
||||
expired? (-> parsed-uri
|
||||
:expiryTimestamp
|
||||
wc-utils/timestamp-expired?)
|
||||
version-supported? (wc-utils/version-supported? version)]
|
||||
(cond
|
||||
expired?
|
||||
{:fx [[:dispatch
|
||||
[:toasts/upsert
|
||||
{:type :negative
|
||||
:theme :dark
|
||||
:text (i18n/label :t/wallet-connect-qr-expired)}]]]}
|
||||
|
||||
(not version-supported?)
|
||||
{:fx [[:dispatch
|
||||
[:toasts/upsert
|
||||
{:type :negative
|
||||
:theme :dark
|
||||
:text (i18n/label :t/wallet-connect-version-not-supported
|
||||
{:version version})}]]]}
|
||||
|
||||
:else
|
||||
{:fx [[:dispatch [:wallet-connect/pair scanned-text]]
|
||||
[:dispatch [:dismiss-modal :screen/wallet.wallet-connect-session-proposal]]]}))))
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
(ns status-im.contexts.wallet.wallet-connect.session-proposal.style
|
||||
(:require [quo.foundations.colors :as colors]))
|
||||
|
||||
(def dapp-avatar
|
||||
{:padding-horizontal 20
|
||||
:padding-top 12})
|
||||
|
||||
(def approval-note-container
|
||||
{:margin-horizontal 20
|
||||
:padding 12
|
||||
:border-radius 16
|
||||
:border-width 1
|
||||
:border-color colors/neutral-10
|
||||
:background-color colors/neutral-2_5})
|
||||
|
||||
(def approval-note-title
|
||||
{:color colors/neutral-50
|
||||
:margin-bottom 8})
|
||||
|
||||
(def approval-note-li
|
||||
{:flex 1
|
||||
:flex-direction :row
|
||||
:align-items :center})
|
||||
|
||||
(def approval-li-spacer
|
||||
{:width 8})
|
||||
|
||||
(def detail-item
|
||||
{:margin-bottom 20
|
||||
:margin-horizontal 20
|
||||
:padding 12})
|
|
@ -0,0 +1,119 @@
|
|||
(ns status-im.contexts.wallet.wallet-connect.session-proposal.view
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[status-im.common.floating-button-page.view :as floating-button-page]
|
||||
[status-im.contexts.wallet.wallet-connect.session-proposal.style :as style]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- dapp-metadata
|
||||
[]
|
||||
(let [proposer (rf/sub [:wallet-connect/session-proposer])
|
||||
{:keys [icons name url]} (:metadata proposer)]
|
||||
[:<>
|
||||
[rn/view {:style style/dapp-avatar}
|
||||
[quo/user-avatar
|
||||
{:profile-picture (first icons)
|
||||
:size :big}]]
|
||||
[quo/page-top
|
||||
{:title name
|
||||
:description :context-tag
|
||||
:context-tag {:type :icon
|
||||
:size 32
|
||||
:icon :i/link
|
||||
:context url}}]]))
|
||||
|
||||
(defn- approval-note
|
||||
[]
|
||||
(let [dapp-name (rf/sub [:wallet-connect/session-proposer-name])
|
||||
labels [(i18n/label :t/check-your-account-balance-and-activity)
|
||||
(i18n/label :t/request-txns-and-message-signing)]]
|
||||
[rn/view {:style style/approval-note-container}
|
||||
[quo/text {:style style/approval-note-title}
|
||||
(i18n/label :t/dapp-will-be-able-to {:dapp-name dapp-name})]
|
||||
(map-indexed
|
||||
(fn [idx label]
|
||||
^{:key (str idx label)}
|
||||
[rn/view {:style style/approval-note-li}
|
||||
[quo/icon :i/bullet
|
||||
{:color colors/neutral-50}]
|
||||
[rn/view {:style style/approval-li-spacer}]
|
||||
[quo/text label]])
|
||||
labels)]))
|
||||
|
||||
(defn- accounts-data-item
|
||||
[]
|
||||
;; TODO. This account is currently hard coded in
|
||||
;; `status-im.contexts.wallet.wallet-connect.events`. Should be selectable and changeable
|
||||
(let [accounts (rf/sub [:wallet/accounts-without-watched-accounts])
|
||||
name (-> accounts first :name)]
|
||||
[quo/data-item
|
||||
{:container-style style/detail-item
|
||||
:blur? false
|
||||
:description :default
|
||||
:icon-right? true
|
||||
:right-icon :i/chevron-right
|
||||
:icon-color colors/neutral-10
|
||||
:card? false
|
||||
:label :preview
|
||||
;; TODO. The quo component for data item doesn't support showing accounts yet
|
||||
:status :default
|
||||
:size :small
|
||||
:title (i18n/label :t/account-title)
|
||||
:subtitle name}]))
|
||||
|
||||
(defn- networks-data-item
|
||||
[]
|
||||
[quo/data-item
|
||||
{:container-style style/detail-item
|
||||
:blur? false
|
||||
:description :default
|
||||
:icon-right? true
|
||||
:card? true
|
||||
:label :none
|
||||
:status :default
|
||||
:size :small
|
||||
:title (i18n/label :t/networks)
|
||||
;; TODO. The quo component for data-item does not support showing networks yet
|
||||
:subtitle "Networks will show up here"}])
|
||||
|
||||
(defn- footer
|
||||
[]
|
||||
(let [customization-color (rf/sub [:profile/customization-color])]
|
||||
[quo/bottom-actions
|
||||
{:actions :two-actions
|
||||
:button-two-label (i18n/label :t/decline)
|
||||
:button-two-props {:type :grey
|
||||
:accessibility-label :wc-deny-connection
|
||||
:on-press #(do (rf/dispatch [:navigate-back])
|
||||
(rf/dispatch
|
||||
[:wallet-connect/reset-current-session]))}
|
||||
:button-one-label (i18n/label :t/connect)
|
||||
:button-one-props {:customization-color customization-color
|
||||
:type :primary
|
||||
:accessibility-label :wc-connect
|
||||
:on-press #(rf/dispatch [:wallet-connect/approve-session])}}]))
|
||||
|
||||
(defn- header
|
||||
[]
|
||||
[quo/page-nav
|
||||
{:type :no-title
|
||||
:background :blur
|
||||
:icon-name :i/close
|
||||
:on-press (rn/use-callback #(rf/dispatch [:navigate-back]))
|
||||
:accessibility-label :wc-session-proposal-top-bar}])
|
||||
|
||||
(defn view
|
||||
[]
|
||||
[floating-button-page/view
|
||||
{:footer-container-padding 0
|
||||
:header [header]
|
||||
:footer [footer]}
|
||||
[rn/view
|
||||
[dapp-metadata]
|
||||
[accounts-data-item]
|
||||
[networks-data-item]
|
||||
[approval-note]]])
|
|
@ -0,0 +1,29 @@
|
|||
(ns status-im.contexts.wallet.wallet-connect.utils
|
||||
(:require [react-native.wallet-connect :as wallet-connect]))
|
||||
|
||||
(defn version-supported?
|
||||
[version]
|
||||
(= version 2))
|
||||
|
||||
(defn- current-timestamp
|
||||
[]
|
||||
(quot (.getTime (js/Date.)) 1000))
|
||||
|
||||
(defn timestamp-expired?
|
||||
[expiry-timestamp]
|
||||
(> (current-timestamp) expiry-timestamp))
|
||||
|
||||
(defn valid-wc-uri?
|
||||
[parsed-uri]
|
||||
(let [{:keys [topic version expiryTimestamp]} parsed-uri]
|
||||
(and (seq topic)
|
||||
(number? version)
|
||||
(number? expiryTimestamp))))
|
||||
|
||||
(defn valid-uri?
|
||||
"Check if the uri is in the wallet-connect format.
|
||||
At this stage, the uri might be expired or from an unsupported version"
|
||||
[s]
|
||||
(-> s
|
||||
wallet-connect/parse-uri
|
||||
valid-wc-uri?))
|
|
@ -109,6 +109,7 @@
|
|||
[status-im.contexts.wallet.send.transaction-confirmation.view :as wallet-transaction-confirmation]
|
||||
[status-im.contexts.wallet.send.transaction-progress.view :as wallet-transaction-progress]
|
||||
[status-im.contexts.wallet.swap.select-asset-to-pay.view :as wallet-swap-select-asset-to-pay]
|
||||
[status-im.contexts.wallet.wallet-connect.session-proposal.view :as wallet-connect-session-proposal]
|
||||
[status-im.contexts.wallet.wallet-connect.sign-message.view :as wallet-connect-sign-message]
|
||||
[status-im.navigation.options :as options]
|
||||
[status-im.navigation.transitions :as transitions]))
|
||||
|
@ -392,6 +393,10 @@
|
|||
:options {:insets {:top? true}}
|
||||
:component wallet-connected-dapps/view}
|
||||
|
||||
{:name :screen/wallet.wallet-connect-session-proposal
|
||||
:options {:sheet? true}
|
||||
:component wallet-connect-session-proposal/view}
|
||||
|
||||
{:name :screen/wallet.edit-account
|
||||
:component wallet-edit-account/view}
|
||||
|
||||
|
|
|
@ -30,3 +30,15 @@
|
|||
{:customization-color customization-color
|
||||
:name name
|
||||
:emoji emoji})))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet-connect/session-proposer
|
||||
:<- [:wallet-connect/current-proposal]
|
||||
(fn [proposal]
|
||||
(-> proposal :params :proposer)))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet-connect/session-proposer-name
|
||||
:<- [:wallet-connect/session-proposer]
|
||||
(fn [proposer]
|
||||
(-> proposer :metadata :name)))
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
(ns status-im.subs.wallet.wallet-connect-test
|
||||
(:require
|
||||
[cljs.test :refer [is testing]]
|
||||
[re-frame.db :as rf-db]
|
||||
status-im.subs.root
|
||||
status-im.subs.wallet.wallet-connect
|
||||
[test-helpers.unit :as h]
|
||||
[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}}})
|
||||
|
||||
(h/deftest-sub :wallet-connect/session-proposer
|
||||
[sub-name]
|
||||
(testing "Return the session proposer public key and metadata"
|
||||
(swap! rf-db/app-db
|
||||
assoc
|
||||
:wallet-connect/current-proposal
|
||||
sample-session)
|
||||
|
||||
(let [proposer (rf/sub [sub-name])]
|
||||
(is (= (-> proposer :publicKey)
|
||||
(-> sample-session :params :proposer :publicKey)))
|
||||
|
||||
(is (= (-> proposer :metadata :url)
|
||||
(-> sample-session :params :proposer :metadata :url))))))
|
||||
|
||||
(h/deftest-sub :wallet-connect/session-proposer-name
|
||||
[sub-name]
|
||||
(testing "Return only the name of the session proposer"
|
||||
(swap! rf-db/app-db
|
||||
assoc
|
||||
:wallet-connect/current-proposal
|
||||
sample-session)
|
||||
|
||||
(is (= (-> sample-session :params :proposer :metadata :name)
|
||||
(rf/sub [sub-name])))))
|
|
@ -1049,6 +1049,7 @@
|
|||
"language-and-currency": "Language and currency",
|
||||
"opening-buy-crypto": "Opening {{site}}...",
|
||||
"network": "Network",
|
||||
"networks": "Networks",
|
||||
"network-chain": "Network chain",
|
||||
"network-fee": "Network fee",
|
||||
"network-id": "Network ID",
|
||||
|
@ -2682,5 +2683,10 @@
|
|||
"you-cannot-add-your-own-account-as-a-saved-address": "You cannot add your own account as a saved address",
|
||||
"this-address-is-already-saved": "This address is already saved",
|
||||
"this-ens-name-is-not-registered-yet": "This ENS name is not registered yet",
|
||||
"address-saved": "Address saved"
|
||||
"address-saved": "Address saved",
|
||||
"dapp-will-be-able-to": "{{dapp-name}} will be able to:",
|
||||
"check-your-account-balance-and-activity": "Check your account balance and activity",
|
||||
"request-txns-and-message-signing": "Request transactions and message signing",
|
||||
"wallet-connect-qr-expired": "WalletConnect QR has expired",
|
||||
"wallet-connect-version-not-supported": "WalletConnect version {{version}} is not supported"
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue