Restructure wallet-connect namespaces (#21167)
Co-authored-by: Mohsen <maxghafori@gmail.com>
This commit is contained in:
parent
d7242f1c70
commit
9135e915ab
|
@ -6,7 +6,7 @@
|
||||||
[status-im.common.scan-qr-code.view :as scan-qr-code]
|
[status-im.common.scan-qr-code.view :as scan-qr-code]
|
||||||
[status-im.common.validation.general :as validators]
|
[status-im.common.validation.general :as validators]
|
||||||
[status-im.contexts.communities.events]
|
[status-im.contexts.communities.events]
|
||||||
[status-im.contexts.wallet.wallet-connect.utils :as wc-utils]
|
[status-im.contexts.wallet.wallet-connect.utils.uri :as wc-uri]
|
||||||
[status-im.feature-flags :as ff]
|
[status-im.feature-flags :as ff]
|
||||||
[utils.address :as utils-address]
|
[utils.address :as utils-address]
|
||||||
[utils.debounce :as debounce]
|
[utils.debounce :as debounce]
|
||||||
|
@ -100,7 +100,7 @@
|
||||||
nil
|
nil
|
||||||
|
|
||||||
(and
|
(and
|
||||||
(wc-utils/valid-uri? scanned-text)
|
(wc-uri/valid-uri? scanned-text)
|
||||||
(ff/enabled? ::ff/wallet.wallet-connect))
|
(ff/enabled? ::ff/wallet.wallet-connect))
|
||||||
(handle-wallet-connect scanned-text)
|
(handle-wallet-connect scanned-text)
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
[status-im.common.resources :as resources]
|
[status-im.common.resources :as resources]
|
||||||
[status-im.contexts.wallet.connected-dapps.disconnect-dapp.view :as disconnect-dapp]
|
[status-im.contexts.wallet.connected-dapps.disconnect-dapp.view :as disconnect-dapp]
|
||||||
[status-im.contexts.wallet.connected-dapps.style :as style]
|
[status-im.contexts.wallet.connected-dapps.style :as style]
|
||||||
[status-im.contexts.wallet.wallet-connect.core :as core]
|
[status-im.contexts.wallet.wallet-connect.utils.data-store :as data-store]
|
||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
[utils.re-frame :as rf]
|
[utils.re-frame :as rf]
|
||||||
[utils.string]))
|
[utils.string]))
|
||||||
|
@ -107,9 +107,14 @@
|
||||||
:content-container-style (style/dapps-list theme)
|
:content-container-style (style/dapps-list theme)
|
||||||
:render-fn (fn [{:keys [topic pairingTopic name url iconUrl]}]
|
:render-fn (fn [{:keys [topic pairingTopic name url iconUrl]}]
|
||||||
[quo/dapp
|
[quo/dapp
|
||||||
{:dapp {:avatar (core/compute-dapp-icon-path iconUrl
|
{:dapp {:avatar
|
||||||
url)
|
(data-store/compute-dapp-icon-path
|
||||||
:name (core/compute-dapp-name name url)
|
iconUrl
|
||||||
|
url)
|
||||||
|
:name
|
||||||
|
(data-store/compute-dapp-name
|
||||||
|
name
|
||||||
|
url)
|
||||||
:value url
|
:value url
|
||||||
:topic topic
|
:topic topic
|
||||||
:pairing-topic pairingTopic
|
:pairing-topic pairingTopic
|
||||||
|
|
|
@ -1,204 +0,0 @@
|
||||||
(ns status-im.contexts.wallet.wallet-connect.core
|
|
||||||
(:require [clojure.edn :as edn]
|
|
||||||
[clojure.set :as set]
|
|
||||||
[clojure.string :as string]
|
|
||||||
[native-module.core :as native-module]
|
|
||||||
[status-im.constants :as constants]
|
|
||||||
[status-im.contexts.wallet.common.utils.networks :as networks]
|
|
||||||
[utils.security.core :as security]
|
|
||||||
[utils.string]
|
|
||||||
[utils.transforms :as transforms]))
|
|
||||||
|
|
||||||
(def method-to-screen
|
|
||||||
{constants/wallet-connect-personal-sign-method :screen/wallet-connect.sign-message
|
|
||||||
constants/wallet-connect-eth-sign-typed-method :screen/wallet-connect.sign-message
|
|
||||||
constants/wallet-connect-eth-sign-method :screen/wallet-connect.sign-message
|
|
||||||
constants/wallet-connect-eth-sign-typed-v4-method :screen/wallet-connect.sign-message
|
|
||||||
constants/wallet-connect-eth-send-transaction-method :screen/wallet-connect.send-transaction
|
|
||||||
constants/wallet-connect-eth-sign-transaction-method :screen/wallet-connect.sign-transaction})
|
|
||||||
|
|
||||||
(defn extract-native-call-signature
|
|
||||||
[data]
|
|
||||||
(-> data transforms/json->clj :result))
|
|
||||||
|
|
||||||
(defn chain-id->eip155
|
|
||||||
[chain-id]
|
|
||||||
(str "eip155:" chain-id))
|
|
||||||
|
|
||||||
(defn eip155->chain-id
|
|
||||||
[chain-id-str]
|
|
||||||
(-> chain-id-str
|
|
||||||
(string/split #":")
|
|
||||||
last
|
|
||||||
edn/read-string))
|
|
||||||
|
|
||||||
(defn format-eip155-address
|
|
||||||
[address chain-id]
|
|
||||||
(str chain-id ":" address))
|
|
||||||
|
|
||||||
(defn get-request-method
|
|
||||||
[event]
|
|
||||||
(get-in event [:params :request :method]))
|
|
||||||
|
|
||||||
(defn get-request-params
|
|
||||||
[event]
|
|
||||||
(get-in event [:params :request :params]))
|
|
||||||
|
|
||||||
(defn get-db-current-request-event
|
|
||||||
[db]
|
|
||||||
(get-in db [:wallet-connect/current-request :event]))
|
|
||||||
|
|
||||||
(defn get-session-dapp-metadata
|
|
||||||
[proposal]
|
|
||||||
(let [metadata (get-in proposal [:params :proposer :metadata])
|
|
||||||
origin (get-in proposal [:verifyContext :verified :origin])]
|
|
||||||
(or metadata {:url origin})))
|
|
||||||
|
|
||||||
(defn get-current-request-dapp
|
|
||||||
[request sessions]
|
|
||||||
(let [dapp-url (get-in request [:event :verifyContext :verified :origin])]
|
|
||||||
(->> sessions
|
|
||||||
(filter (fn [session]
|
|
||||||
(= (utils.string/remove-trailing-slash dapp-url)
|
|
||||||
(utils.string/remove-trailing-slash (get session :url)))))
|
|
||||||
first)))
|
|
||||||
|
|
||||||
(defn get-dapp-redirect-url
|
|
||||||
[session]
|
|
||||||
(get-in session [:peer :metadata :redirect :native]))
|
|
||||||
|
|
||||||
(defn get-db-current-request-params
|
|
||||||
[db]
|
|
||||||
(-> db
|
|
||||||
get-db-current-request-event
|
|
||||||
get-request-params))
|
|
||||||
|
|
||||||
(def ^:private sign-typed-data-by-version
|
|
||||||
{:v1 native-module/sign-typed-data
|
|
||||||
:v4 native-module/sign-typed-data-v4})
|
|
||||||
|
|
||||||
(defn sign-typed-data
|
|
||||||
[version data address password]
|
|
||||||
(let [f (get sign-typed-data-by-version version)]
|
|
||||||
(->> 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 [supported-namespaces #{:eip155}
|
|
||||||
required-namespaces (get-in proposal [:params :requiredNamespaces])]
|
|
||||||
(when (every? #(contains? supported-namespaces %)
|
|
||||||
(keys required-namespaces))
|
|
||||||
(let [required-networks (get-in required-namespaces [: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)))
|
|
||||||
|
|
||||||
(defn- add-full-testnet-name
|
|
||||||
"Updates the `:full-name` key with the full testnet name if using testnet `:chain-id`.\n
|
|
||||||
e.g. `{:full-name \"Mainnet\"}` -> `{:full-name \"Mainnet Sepolia\"`}`"
|
|
||||||
[network]
|
|
||||||
(let [add-testnet-name (fn [testnet-name]
|
|
||||||
(update network :full-name #(str % " " testnet-name)))]
|
|
||||||
(condp #(contains? %1 %2) (:chain-id network)
|
|
||||||
constants/sepolia-chain-ids (add-testnet-name constants/sepolia-full-name)
|
|
||||||
constants/goerli-chain-ids (add-testnet-name constants/goerli-full-name)
|
|
||||||
network)))
|
|
||||||
|
|
||||||
(defn chain-id->network-details
|
|
||||||
[chain-id]
|
|
||||||
(-> chain-id
|
|
||||||
(networks/get-network-details)
|
|
||||||
(add-full-testnet-name)))
|
|
||||||
|
|
||||||
(defn session-networks-allowed?
|
|
||||||
[testnet-mode? {:keys [chains]}]
|
|
||||||
(let [chain-ids (set (map (fn [chain]
|
|
||||||
(-> chain
|
|
||||||
(string/split ":")
|
|
||||||
second
|
|
||||||
js/parseInt))
|
|
||||||
chains))]
|
|
||||||
(if testnet-mode?
|
|
||||||
(set/subset? chain-ids (set/union constants/sepolia-chain-ids constants/goerli-chain-ids))
|
|
||||||
(set/subset? chain-ids constants/mainnet-chain-ids))))
|
|
||||||
|
|
||||||
(defn event-should-be-handled?
|
|
||||||
[db {:keys [topic]}]
|
|
||||||
(let [testnet-mode? (get-in db [:profile/profile :test-networks-enabled?])]
|
|
||||||
(some #(and (= (:topic %) topic)
|
|
||||||
(session-networks-allowed? testnet-mode? %))
|
|
||||||
(:wallet-connect/sessions db))))
|
|
||||||
|
|
||||||
(defn sdk-session->db-session
|
|
||||||
[{:keys [topic expiry pairingTopic] :as session}]
|
|
||||||
{:topic topic
|
|
||||||
:expiry expiry
|
|
||||||
:sessionJson (transforms/clj->json session)
|
|
||||||
:pairingTopic pairingTopic
|
|
||||||
:name (get-in session [:peer :metadata :name])
|
|
||||||
:iconUrl (get-in session [:peer :metadata :icons 0])
|
|
||||||
:url (get-in session [:peer :metadata :url])
|
|
||||||
:accounts (get-in session [:namespaces :eip155 :accounts])
|
|
||||||
:chains (get-in session [:namespaces :eip155 :chains])
|
|
||||||
:disconnected false})
|
|
||||||
|
|
||||||
(defn filter-operable-accounts
|
|
||||||
[accounts]
|
|
||||||
(filter #(and (:operable? %)
|
|
||||||
(not (:watch-only? %)))
|
|
||||||
accounts))
|
|
||||||
|
|
||||||
(defn filter-sessions-for-account-addresses
|
|
||||||
[account-addresses sessions]
|
|
||||||
(filter (fn [{:keys [accounts]}]
|
|
||||||
(some (fn [account]
|
|
||||||
(some (fn [account-address]
|
|
||||||
(clojure.string/includes? account account-address))
|
|
||||||
account-addresses))
|
|
||||||
accounts))
|
|
||||||
sessions))
|
|
||||||
|
|
||||||
(defn compute-dapp-name
|
|
||||||
"Sometimes dapps have no name or an empty name. Return url as name in that case"
|
|
||||||
[name url]
|
|
||||||
(if (seq name)
|
|
||||||
name
|
|
||||||
(when (seq url)
|
|
||||||
(-> url
|
|
||||||
utils.string/remove-trailing-slash
|
|
||||||
utils.string/remove-http-prefix
|
|
||||||
string/capitalize))))
|
|
||||||
|
|
||||||
(defn compute-dapp-icon-path
|
|
||||||
"Some dapps have icons with relative paths, make paths absolute in those cases, send nil if icon is missing"
|
|
||||||
[icon-path url]
|
|
||||||
(when (and (seq icon-path)
|
|
||||||
(seq url))
|
|
||||||
(if (string/starts-with? icon-path "http")
|
|
||||||
icon-path
|
|
||||||
(str (utils.string/remove-trailing-slash url) icon-path))))
|
|
|
@ -1,27 +0,0 @@
|
||||||
(ns status-im.contexts.wallet.wallet-connect.core-test
|
|
||||||
(:require
|
|
||||||
[cljs.test :refer-macros [deftest is testing]]
|
|
||||||
[status-im.contexts.wallet.wallet-connect.core :as sut]))
|
|
||||||
|
|
||||||
(deftest get-current-request-dapp-test
|
|
||||||
(testing "returns the correct dapp based on the request's origin"
|
|
||||||
(let [request {:event {:verifyContext {:verified {:origin "https://dapp.com"}}}}
|
|
||||||
sessions [{:url "https://dapp.com"}
|
|
||||||
{:url "https://anotherdapp.com"}]]
|
|
||||||
(is (= {:url "https://dapp.com"}
|
|
||||||
(sut/get-current-request-dapp request sessions)))))
|
|
||||||
|
|
||||||
(testing "returns nil if no matching dapp is found"
|
|
||||||
(let [request {:event {:verifyContext {:verified {:origin "https://dapp.com"}}}}
|
|
||||||
sessions [{:url "https://anotherdapp.com"}]]
|
|
||||||
(is (nil? (sut/get-current-request-dapp request sessions))))))
|
|
||||||
|
|
||||||
(deftest get-dapp-redirect-url-test
|
|
||||||
(testing "returns the native redirect URL if it exists"
|
|
||||||
(let [session {:peer {:metadata {:redirect {:native "native://redirect-url"}}}}]
|
|
||||||
(is (= "native://redirect-url"
|
|
||||||
(sut/get-dapp-redirect-url session)))))
|
|
||||||
|
|
||||||
(testing "returns nil if no redirect URL is found"
|
|
||||||
(let [session {:peer {:metadata {}}}]
|
|
||||||
(is (nil? (sut/get-dapp-redirect-url session))))))
|
|
|
@ -1,358 +0,0 @@
|
||||||
(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.i18n :as i18n]
|
|
||||||
[utils.transforms :as types]))
|
|
||||||
|
|
||||||
(rf/reg-event-fx
|
|
||||||
:wallet-connect/init
|
|
||||||
(fn [{:keys [db]}]
|
|
||||||
(let [network-status (:network/status db)
|
|
||||||
web3-wallet-missing? (-> db :wallet-connect/web3-wallet boolean not)]
|
|
||||||
(if (and (= network-status :online) web3-wallet-missing?)
|
|
||||||
(do (log/info "Initialising WalletConnect SDK")
|
|
||||||
{:fx [[:effects.wallet-connect/init
|
|
||||||
{:on-success #(rf/dispatch [:wallet-connect/on-init-success %])
|
|
||||||
:on-fail #(rf/dispatch [:wallet-connect/on-init-fail %])}]]})
|
|
||||||
;; NOTE: when offline, fetching persistent sessions only
|
|
||||||
{:fx [[:dispatch [:wallet-connect/fetch-persisted-sessions]]]}))))
|
|
||||||
|
|
||||||
(rf/reg-event-fx
|
|
||||||
:wallet-connect/on-init-success
|
|
||||||
(fn [{:keys [db]} [web3-wallet]]
|
|
||||||
(log/info "WalletConnect SDK initialisation successful")
|
|
||||||
{:db (assoc db :wallet-connect/web3-wallet web3-wallet)
|
|
||||||
:fx [[:dispatch [:wallet-connect/register-event-listeners]]
|
|
||||||
[:dispatch [:wallet-connect/fetch-persisted-sessions]]]}))
|
|
||||||
|
|
||||||
(rf/reg-event-fx
|
|
||||||
:wallet-connect/reload-on-network-change
|
|
||||||
(fn [{:keys [db]} [is-connected?]]
|
|
||||||
(let [logged-in? (-> db :profile/profile boolean)]
|
|
||||||
(when (and is-connected? logged-in?)
|
|
||||||
(log/info "Re-Initialising WalletConnect SDK due to network change")
|
|
||||||
{:fx [[:dispatch [:wallet-connect/init]]]}))))
|
|
||||||
|
|
||||||
(rf/reg-event-fx
|
|
||||||
:wallet-connect/register-event-listeners
|
|
||||||
(fn [{:keys [db]}]
|
|
||||||
(let [web3-wallet (get db :wallet-connect/web3-wallet)]
|
|
||||||
{:fx [[:effects.wallet-connect/register-event-listener
|
|
||||||
[web3-wallet
|
|
||||||
constants/wallet-connect-session-proposal-event
|
|
||||||
#(rf/dispatch [:wallet-connect/on-session-proposal %])]]
|
|
||||||
[:effects.wallet-connect/register-event-listener
|
|
||||||
[web3-wallet
|
|
||||||
constants/wallet-connect-session-request-event
|
|
||||||
#(rf/dispatch [:wallet-connect/on-session-request %])]]
|
|
||||||
[:effects.wallet-connect/register-event-listener
|
|
||||||
[web3-wallet
|
|
||||||
constants/wallet-connect-session-delete-event
|
|
||||||
#(rf/dispatch [:wallet-connect/on-session-delete %])]]]})))
|
|
||||||
|
|
||||||
(rf/reg-event-fx
|
|
||||||
:wallet-connect/on-init-fail
|
|
||||||
(fn [_ [error]]
|
|
||||||
(log/error "Failed to initialize Wallet Connect"
|
|
||||||
{:error error
|
|
||||||
:event :wallet-connect/on-init-fail})))
|
|
||||||
|
|
||||||
(rf/reg-event-fx
|
|
||||||
:wallet-connect/on-session-proposal
|
|
||||||
(fn [{:keys [db]} [proposal]]
|
|
||||||
(log/info "Received Wallet Connect session proposal: " proposal)
|
|
||||||
(let [accounts (get-in db [:wallet :accounts])
|
|
||||||
current-viewing-address (get-in db [:wallet :current-viewing-account-address])
|
|
||||||
available-accounts (wallet-connect-core/filter-operable-accounts (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 (and (not-empty session-networks) required-networks-supported?)
|
|
||||||
{:db (update db
|
|
||||||
:wallet-connect/current-proposal assoc
|
|
||||||
:request proposal
|
|
||||||
:session-networks session-networks
|
|
||||||
:address (or current-viewing-address
|
|
||||||
(-> available-accounts
|
|
||||||
first
|
|
||||||
:address)))
|
|
||||||
:fx [[:dispatch
|
|
||||||
[:open-modal :screen/wallet.wallet-connect-session-proposal]]]}
|
|
||||||
{:fx [[:dispatch
|
|
||||||
[:wallet-connect/show-session-networks-unsupported-toast proposal]]
|
|
||||||
[:dispatch
|
|
||||||
[:wallet-connect/reject-session-proposal proposal]]]}))))
|
|
||||||
|
|
||||||
(rf/reg-event-fx
|
|
||||||
:wallet-connect/show-session-networks-unsupported-toast
|
|
||||||
(fn [{:keys [db]} [proposal]]
|
|
||||||
(let [{:keys [name url]} (wallet-connect-core/get-session-dapp-metadata proposal)]
|
|
||||||
{:fx [[:dispatch
|
|
||||||
[:toasts/upsert
|
|
||||||
{:type :negative
|
|
||||||
:theme (:theme db)
|
|
||||||
:text (i18n/label :t/wallet-connect-networks-not-supported
|
|
||||||
{:dapp (wallet-connect-core/compute-dapp-name name url)})}]]]})))
|
|
||||||
|
|
||||||
(rf/reg-event-fx
|
|
||||||
:wallet-connect/on-session-request
|
|
||||||
(fn [{:keys [db]} [event]]
|
|
||||||
(if (wallet-connect-core/event-should-be-handled? db event)
|
|
||||||
{:fx [[:dispatch [:wallet-connect/process-session-request event]]]}
|
|
||||||
{:fx [[:dispatch
|
|
||||||
[:wallet-connect/show-session-networks-unsupported-toast event]]
|
|
||||||
[:dispatch
|
|
||||||
[:wallet-connect/send-response
|
|
||||||
{:request event
|
|
||||||
:error (wallet-connect/get-sdk-error
|
|
||||||
constants/wallet-connect-user-rejected-chains-error-key)}]]]})))
|
|
||||||
|
|
||||||
(rf/reg-event-fx
|
|
||||||
:wallet-connect/on-session-delete
|
|
||||||
(fn [{:keys [db]} [{:keys [topic] :as event}]]
|
|
||||||
(when (wallet-connect-core/event-should-be-handled? db event)
|
|
||||||
(log/info "Received Wallet Connect session delete from the SDK: " event)
|
|
||||||
{:fx [[:dispatch [:wallet-connect/disconnect-session topic]]]})))
|
|
||||||
|
|
||||||
(rf/reg-event-fx
|
|
||||||
:wallet-connect/reset-current-session-proposal
|
|
||||||
(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]}]
|
|
||||||
{:db (dissoc db :wallet-connect/current-request)}))
|
|
||||||
|
|
||||||
(rf/reg-event-fx
|
|
||||||
:wallet-connect/disconnect-dapp
|
|
||||||
(fn [{:keys [db]} [{:keys [topic on-success on-fail]}]]
|
|
||||||
(let [web3-wallet (get db :wallet-connect/web3-wallet)
|
|
||||||
network-status (:network/status db)]
|
|
||||||
(log/info "Disconnecting dApp session" topic)
|
|
||||||
(if (= network-status :online)
|
|
||||||
{:fx [[:effects.wallet-connect/disconnect
|
|
||||||
{:web3-wallet web3-wallet
|
|
||||||
:topic topic
|
|
||||||
:reason (wallet-connect/get-sdk-error
|
|
||||||
constants/wallet-connect-user-disconnected-reason-key)
|
|
||||||
:on-fail on-fail
|
|
||||||
:on-success (fn []
|
|
||||||
(rf/dispatch [:wallet-connect/disconnect-session topic])
|
|
||||||
(when on-success
|
|
||||||
(on-success)))}]]}
|
|
||||||
{:fx [[:dispatch [:wallet-connect/no-internet-toast]]]}))))
|
|
||||||
|
|
||||||
(rf/reg-event-fx
|
|
||||||
:wallet-connect/pair
|
|
||||||
(fn [{:keys [db]} [url]]
|
|
||||||
(let [web3-wallet (get db :wallet-connect/web3-wallet)]
|
|
||||||
{:fx [[:effects.wallet-connect/pair
|
|
||||||
{:web3-wallet web3-wallet
|
|
||||||
:url url
|
|
||||||
:on-fail #(log/error "Failed to pair with dApp" {:error %})
|
|
||||||
:on-success #(log/info "dApp paired successfully")}]]})))
|
|
||||||
|
|
||||||
(rf/reg-event-fx
|
|
||||||
:wallet-connect/approve-session
|
|
||||||
(fn [{:keys [db]}]
|
|
||||||
(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))
|
|
||||||
network-status (:network/status db)
|
|
||||||
expiry (get-in current-proposal [:params :expiryTimestamp])]
|
|
||||||
(if (= network-status :online)
|
|
||||||
{:db (assoc-in db [:wallet-connect/current-proposal :response-sent?] true)
|
|
||||||
:fx [(if (wc-utils/timestamp-expired? expiry)
|
|
||||||
[:dispatch
|
|
||||||
[:toasts/upsert
|
|
||||||
{:id :wallet-connect-proposal-expired
|
|
||||||
:type :negative
|
|
||||||
:text (i18n/label :t/wallet-connect-proposal-expired)}]]
|
|
||||||
[:effects.wallet-connect/approve-session
|
|
||||||
{:web3-wallet web3-wallet
|
|
||||||
:proposal current-proposal
|
|
||||||
:networks session-networks
|
|
||||||
:accounts accounts
|
|
||||||
:on-success (fn [approved-session]
|
|
||||||
(log/info "Wallet Connect session approved")
|
|
||||||
(rf/dispatch [:wallet-connect/reset-current-session-proposal])
|
|
||||||
(rf/dispatch [:wallet-connect/persist-session
|
|
||||||
approved-session]))
|
|
||||||
:on-fail (fn [error]
|
|
||||||
(log/error "Wallet Connect session approval failed"
|
|
||||||
{:error error
|
|
||||||
:event :wallet-connect/approve-session})
|
|
||||||
(rf/dispatch
|
|
||||||
[:wallet-connect/reset-current-session-proposal]))}])
|
|
||||||
[:dispatch [:dismiss-modal :screen/wallet.wallet-connect-session-proposal]]]}
|
|
||||||
{:fx [[:dispatch [:wallet-connect/no-internet-toast]]]}))))
|
|
||||||
|
|
||||||
(rf/reg-event-fx
|
|
||||||
:wallet-connect/on-scan-connection
|
|
||||||
(fn [{:keys [db]} [scanned-text]]
|
|
||||||
(let [network-status (:network/status db)
|
|
||||||
parsed-uri (wallet-connect/parse-uri scanned-text)
|
|
||||||
version (:version parsed-uri)
|
|
||||||
valid-wc-uri? (wc-utils/valid-wc-uri? parsed-uri)
|
|
||||||
expired? (-> parsed-uri
|
|
||||||
:expiryTimestamp
|
|
||||||
wc-utils/timestamp-expired?)
|
|
||||||
version-supported? (wc-utils/version-supported? version)]
|
|
||||||
(if (or (not valid-wc-uri?)
|
|
||||||
(not version-supported?)
|
|
||||||
(= network-status :offline)
|
|
||||||
expired?)
|
|
||||||
{:fx [[:dispatch
|
|
||||||
[:toasts/upsert
|
|
||||||
{:type :negative
|
|
||||||
:theme :dark
|
|
||||||
:text (cond (= network-status :offline)
|
|
||||||
(i18n/label :t/wallet-connect-no-internet-warning)
|
|
||||||
|
|
||||||
(not valid-wc-uri?)
|
|
||||||
(i18n/label :t/wallet-connect-wrong-qr)
|
|
||||||
|
|
||||||
expired?
|
|
||||||
(i18n/label :t/wallet-connect-qr-expired)
|
|
||||||
|
|
||||||
(not version-supported?)
|
|
||||||
(i18n/label :t/wallet-connect-version-not-supported
|
|
||||||
{:version version})
|
|
||||||
|
|
||||||
:else
|
|
||||||
(i18n/label :t/something-went-wrong))}]]]}
|
|
||||||
{:fx [[:dispatch [:wallet-connect/pair scanned-text]]]}))))
|
|
||||||
|
|
||||||
;; We first load sessions from database, then we initiate a call to Wallet Connect SDK and
|
|
||||||
;; then replace the list we have stored in the database with the one that came from the SDK.
|
|
||||||
;; In addition to that, we also update the backend state by marking sessions that are not
|
|
||||||
;; active anymore by calling `:wallet-connect/disconnect-session`.
|
|
||||||
(rf/reg-event-fx
|
|
||||||
:wallet-connect/fetch-active-sessions-success
|
|
||||||
(fn [{:keys [db now]} [sessions]]
|
|
||||||
(let [persisted-sessions (:wallet-connect/sessions db)
|
|
||||||
account-addresses (->> (get-in db [:wallet :accounts])
|
|
||||||
vals
|
|
||||||
wallet-connect-core/filter-operable-accounts
|
|
||||||
(map :address))
|
|
||||||
sessions (->> (js->clj sessions :keywordize-keys true)
|
|
||||||
vals
|
|
||||||
(map wallet-connect-core/sdk-session->db-session)
|
|
||||||
(wallet-connect-core/filter-sessions-for-account-addresses
|
|
||||||
account-addresses))
|
|
||||||
session-topics (set (map :topic sessions))
|
|
||||||
expired-sessions (filter
|
|
||||||
(fn [{:keys [expiry topic]}]
|
|
||||||
(or (< expiry (/ now 1000))
|
|
||||||
(not (contains? session-topics topic))))
|
|
||||||
persisted-sessions)]
|
|
||||||
(when (seq expired-sessions)
|
|
||||||
(log/info "Updating WalletConnect persisted sessions due to expired/inactive sessions"
|
|
||||||
{:expired expired-sessions}))
|
|
||||||
{:fx (mapv (fn [{:keys [topic]}]
|
|
||||||
[:dispatch [:wallet-connect/disconnect-session topic]])
|
|
||||||
expired-sessions)
|
|
||||||
:db (assoc db :wallet-connect/sessions sessions)})))
|
|
||||||
|
|
||||||
(rf/reg-event-fx
|
|
||||||
:wallet-connect/fetch-active-sessions
|
|
||||||
(fn [{:keys [db]}]
|
|
||||||
(let [web3-wallet (get db :wallet-connect/web3-wallet)]
|
|
||||||
{:fx [[:effects.wallet-connect/fetch-active-sessions
|
|
||||||
{:web3-wallet web3-wallet
|
|
||||||
:on-fail #(log/error "Failed to get active sessions" {:error %})
|
|
||||||
:on-success #(rf/dispatch [:wallet-connect/fetch-active-sessions-success %])}]]})))
|
|
||||||
|
|
||||||
(rf/reg-event-fx
|
|
||||||
:wallet-connect/fetch-persisted-sessions-success
|
|
||||||
(fn [{:keys [db]} [sessions]]
|
|
||||||
(let [network-status (:network/status db)
|
|
||||||
sessions' (mapv (fn [{:keys [sessionJson] :as session}]
|
|
||||||
(assoc session
|
|
||||||
:accounts
|
|
||||||
(-> sessionJson
|
|
||||||
types/json->clj
|
|
||||||
:namespaces
|
|
||||||
:eip155
|
|
||||||
:accounts)))
|
|
||||||
sessions)]
|
|
||||||
{:fx [(when (= network-status :online)
|
|
||||||
[:dispatch [:wallet-connect/fetch-active-sessions]])]
|
|
||||||
:db (assoc db :wallet-connect/sessions sessions')})))
|
|
||||||
|
|
||||||
(rf/reg-event-fx
|
|
||||||
:wallet-connect/fetch-persisted-sessions-fail
|
|
||||||
(fn [_ [error]]
|
|
||||||
(log/info "Wallet Connect fetch persisted sessions failed" error)
|
|
||||||
{:fx [[:dispatch [:wallet-connect/fetch-active-sessions]]]}))
|
|
||||||
|
|
||||||
(rf/reg-event-fx
|
|
||||||
:wallet-connect/fetch-persisted-sessions
|
|
||||||
(fn [{:keys [now]} _]
|
|
||||||
(let [current-timestamp (quot now 1000)]
|
|
||||||
{:fx [[:json-rpc/call
|
|
||||||
[{:method "wallet_getWalletConnectActiveSessions"
|
|
||||||
;; NOTE: This is the activeSince timestamp to avoid expired sessions
|
|
||||||
:params [current-timestamp]
|
|
||||||
:on-success [:wallet-connect/fetch-persisted-sessions-success]
|
|
||||||
:on-error [:wallet-connect/fetch-persisted-sessions-fail]}]]]})))
|
|
||||||
|
|
||||||
(rf/reg-event-fx
|
|
||||||
:wallet-connect/persist-session
|
|
||||||
(fn [_ [session-info]]
|
|
||||||
(let [redirect-url (-> session-info
|
|
||||||
(js->clj :keywordize-keys true)
|
|
||||||
(wallet-connect-core/get-dapp-redirect-url))]
|
|
||||||
{:fx [[:json-rpc/call
|
|
||||||
[{:method "wallet_addWalletConnectSession"
|
|
||||||
:params [(js/JSON.stringify session-info)]
|
|
||||||
:on-success (fn []
|
|
||||||
(log/info "Wallet Connect session persisted")
|
|
||||||
(rf/dispatch [:wallet-connect/fetch-persisted-sessions])
|
|
||||||
(rf/dispatch [:wallet-connect/redirect-to-dapp redirect-url]))
|
|
||||||
:on-error #(log/info "Wallet Connect session persistence failed" %)}]]]})))
|
|
||||||
|
|
||||||
(rf/reg-event-fx
|
|
||||||
:wallet-connect/disconnect-session
|
|
||||||
(fn [{:keys [db]} [topic]]
|
|
||||||
(log/info "Removing session from persistance and state" topic)
|
|
||||||
{:db (update db
|
|
||||||
:wallet-connect/sessions
|
|
||||||
(fn [sessions]
|
|
||||||
(->> sessions
|
|
||||||
(remove #(= (:topic %) topic))
|
|
||||||
(into []))))
|
|
||||||
:fx [[:json-rpc/call
|
|
||||||
[{:method "wallet_disconnectWalletConnectSession"
|
|
||||||
:params [topic]
|
|
||||||
:on-success #(log/info "Wallet Connect session disconnected")
|
|
||||||
:on-error #(log/info "Wallet Connect session persistence failed" %)}]]]}))
|
|
||||||
|
|
||||||
(rf/reg-event-fx
|
|
||||||
:wallet-connect/no-internet-toast
|
|
||||||
(fn [{:keys [db]}]
|
|
||||||
{:fx [[:dispatch
|
|
||||||
[:toasts/upsert
|
|
||||||
{:type :negative
|
|
||||||
:theme (:theme db)
|
|
||||||
:text (i18n/label :t/wallet-connect-no-internet-warning)}]]]}))
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
(ns status-im.contexts.wallet.wallet-connect.events.core
|
||||||
|
(:require [re-frame.core :as rf]
|
||||||
|
[react-native.wallet-connect :as wallet-connect]
|
||||||
|
[status-im.constants :as constants]
|
||||||
|
status-im.contexts.wallet.wallet-connect.events.effects
|
||||||
|
status-im.contexts.wallet.wallet-connect.events.session-proposals
|
||||||
|
status-im.contexts.wallet.wallet-connect.events.session-requests
|
||||||
|
status-im.contexts.wallet.wallet-connect.events.session-responses
|
||||||
|
status-im.contexts.wallet.wallet-connect.events.sessions
|
||||||
|
[status-im.contexts.wallet.wallet-connect.utils.networks :as networks]
|
||||||
|
[taoensso.timbre :as log]
|
||||||
|
[utils.i18n :as i18n]))
|
||||||
|
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:wallet-connect/init
|
||||||
|
(fn [{:keys [db]}]
|
||||||
|
(let [network-status (:network/status db)
|
||||||
|
web3-wallet-missing? (-> db :wallet-connect/web3-wallet boolean not)]
|
||||||
|
(if (and (= network-status :online) web3-wallet-missing?)
|
||||||
|
(do (log/info "Initialising WalletConnect SDK")
|
||||||
|
{:fx [[:effects.wallet-connect/init
|
||||||
|
{:on-success #(rf/dispatch [:wallet-connect/on-init-success %])
|
||||||
|
:on-fail #(rf/dispatch [:wallet-connect/on-init-fail %])}]]})
|
||||||
|
;; NOTE: when offline, fetching persistent sessions only
|
||||||
|
{:fx [[:dispatch [:wallet-connect/fetch-persisted-sessions]]]}))))
|
||||||
|
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:wallet-connect/on-init-success
|
||||||
|
(fn [{:keys [db]} [web3-wallet]]
|
||||||
|
(log/info "WalletConnect SDK initialisation successful")
|
||||||
|
{:db (assoc db :wallet-connect/web3-wallet web3-wallet)
|
||||||
|
:fx [[:dispatch [:wallet-connect/register-event-listeners]]
|
||||||
|
[:dispatch [:wallet-connect/fetch-persisted-sessions]]]}))
|
||||||
|
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:wallet-connect/reload-on-network-change
|
||||||
|
(fn [{:keys [db]} [is-connected?]]
|
||||||
|
(let [logged-in? (-> db :profile/profile boolean)]
|
||||||
|
(when (and is-connected? logged-in?)
|
||||||
|
(log/info "Re-Initialising WalletConnect SDK due to network change")
|
||||||
|
{:fx [[:dispatch [:wallet-connect/init]]]}))))
|
||||||
|
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:wallet-connect/register-event-listeners
|
||||||
|
(fn [{:keys [db]}]
|
||||||
|
(let [web3-wallet (get db :wallet-connect/web3-wallet)]
|
||||||
|
{:fx [[:effects.wallet-connect/register-event-listener
|
||||||
|
[web3-wallet
|
||||||
|
constants/wallet-connect-session-proposal-event
|
||||||
|
#(rf/dispatch [:wallet-connect/on-session-proposal %])]]
|
||||||
|
[:effects.wallet-connect/register-event-listener
|
||||||
|
[web3-wallet
|
||||||
|
constants/wallet-connect-session-request-event
|
||||||
|
#(rf/dispatch [:wallet-connect/on-session-request %])]]
|
||||||
|
[:effects.wallet-connect/register-event-listener
|
||||||
|
[web3-wallet
|
||||||
|
constants/wallet-connect-session-delete-event
|
||||||
|
#(rf/dispatch [:wallet-connect/on-session-delete %])]]]})))
|
||||||
|
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:wallet-connect/on-init-fail
|
||||||
|
(fn [_ [error]]
|
||||||
|
(log/error "Failed to initialize Wallet Connect"
|
||||||
|
{:error error
|
||||||
|
:event :wallet-connect/on-init-fail})))
|
||||||
|
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:wallet-connect/on-session-request
|
||||||
|
(fn [{:keys [db]} [event]]
|
||||||
|
(if (networks/event-should-be-handled? db event)
|
||||||
|
{:fx [[:dispatch [:wallet-connect/process-session-request event]]]}
|
||||||
|
{:fx [[:dispatch
|
||||||
|
[:wallet-connect/show-session-networks-unsupported-toast event]]
|
||||||
|
[:dispatch
|
||||||
|
[:wallet-connect/send-response
|
||||||
|
{:request event
|
||||||
|
:error (wallet-connect/get-sdk-error
|
||||||
|
constants/wallet-connect-user-rejected-chains-error-key)}]]]})))
|
||||||
|
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:wallet-connect/reset-current-request
|
||||||
|
(fn [{:keys [db]}]
|
||||||
|
{:db (dissoc db :wallet-connect/current-request)}))
|
||||||
|
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:wallet-connect/no-internet-toast
|
||||||
|
(fn [{:keys [db]}]
|
||||||
|
{:fx [[:dispatch
|
||||||
|
[:toasts/upsert
|
||||||
|
{:type :negative
|
||||||
|
:theme (:theme db)
|
||||||
|
:text (i18n/label :t/wallet-connect-no-internet-warning)}]]]}))
|
|
@ -1,12 +1,12 @@
|
||||||
(ns status-im.contexts.wallet.wallet-connect.effects
|
(ns status-im.contexts.wallet.wallet-connect.events.effects
|
||||||
(:require
|
(:require
|
||||||
[promesa.core :as promesa]
|
[promesa.core :as promesa]
|
||||||
[re-frame.core :as rf]
|
[re-frame.core :as rf]
|
||||||
[react-native.wallet-connect :as wallet-connect]
|
[react-native.wallet-connect :as wallet-connect]
|
||||||
[status-im.config :as config]
|
[status-im.config :as config]
|
||||||
[status-im.constants :as constants]
|
[status-im.constants :as constants]
|
||||||
[status-im.contexts.wallet.wallet-connect.signing :as signing]
|
[status-im.contexts.wallet.wallet-connect.utils.signing :as signing]
|
||||||
[status-im.contexts.wallet.wallet-connect.transactions :as transactions]
|
[status-im.contexts.wallet.wallet-connect.utils.transactions :as transactions]
|
||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
[utils.security.core :as security]))
|
[utils.security.core :as security]))
|
||||||
|
|
|
@ -0,0 +1,141 @@
|
||||||
|
(ns status-im.contexts.wallet.wallet-connect.events.session-proposals
|
||||||
|
(:require [re-frame.core :as rf]
|
||||||
|
[react-native.wallet-connect :as wallet-connect]
|
||||||
|
[status-im.contexts.wallet.wallet-connect.utils.data-store :as
|
||||||
|
data-store]
|
||||||
|
[status-im.contexts.wallet.wallet-connect.utils.networks :as networks]
|
||||||
|
[status-im.contexts.wallet.wallet-connect.utils.sessions :as sessions]
|
||||||
|
[status-im.contexts.wallet.wallet-connect.utils.uri :as uri]
|
||||||
|
[taoensso.timbre :as log]
|
||||||
|
[utils.i18n :as i18n]))
|
||||||
|
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:wallet-connect/pair
|
||||||
|
(fn [{:keys [db]} [url]]
|
||||||
|
(let [web3-wallet (get db :wallet-connect/web3-wallet)]
|
||||||
|
{:fx [[:effects.wallet-connect/pair
|
||||||
|
{:web3-wallet web3-wallet
|
||||||
|
:url url
|
||||||
|
:on-fail #(log/error "Failed to pair with dApp" {:error %})
|
||||||
|
:on-success #(log/info "dApp paired successfully")}]]})))
|
||||||
|
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:wallet-connect/on-scan-connection
|
||||||
|
(fn [{:keys [db]} [scanned-text]]
|
||||||
|
(let [network-status (:network/status db)
|
||||||
|
parsed-uri (wallet-connect/parse-uri scanned-text)
|
||||||
|
version (:version parsed-uri)
|
||||||
|
valid-wc-uri? (uri/valid-wc-uri? parsed-uri)
|
||||||
|
expired? (-> parsed-uri
|
||||||
|
:expiryTimestamp
|
||||||
|
uri/timestamp-expired?)
|
||||||
|
version-supported? (uri/version-supported? version)]
|
||||||
|
(if (or (not valid-wc-uri?)
|
||||||
|
(not version-supported?)
|
||||||
|
(= network-status :offline)
|
||||||
|
expired?)
|
||||||
|
{:fx [[:dispatch
|
||||||
|
[:toasts/upsert
|
||||||
|
{:type :negative
|
||||||
|
:theme :dark
|
||||||
|
:text (cond (= network-status :offline)
|
||||||
|
(i18n/label :t/wallet-connect-no-internet-warning)
|
||||||
|
|
||||||
|
(not valid-wc-uri?)
|
||||||
|
(i18n/label :t/wallet-connect-wrong-qr)
|
||||||
|
|
||||||
|
expired?
|
||||||
|
(i18n/label :t/wallet-connect-qr-expired)
|
||||||
|
|
||||||
|
(not version-supported?)
|
||||||
|
(i18n/label :t/wallet-connect-version-not-supported
|
||||||
|
{:version version})
|
||||||
|
|
||||||
|
:else
|
||||||
|
(i18n/label :t/something-went-wrong))}]]]}
|
||||||
|
{:fx [[:dispatch [:wallet-connect/pair scanned-text]]]}))))
|
||||||
|
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:wallet-connect/on-session-proposal
|
||||||
|
(fn [{:keys [db]} [proposal]]
|
||||||
|
(log/info "Received Wallet Connect session proposal: " proposal)
|
||||||
|
(let [accounts (get-in db [:wallet :accounts])
|
||||||
|
current-viewing-address (get-in db [:wallet :current-viewing-account-address])
|
||||||
|
available-accounts (sessions/filter-operable-accounts (vals accounts))
|
||||||
|
networks (networks/get-networks-by-mode db)
|
||||||
|
session-networks (networks/proposal-networks-intersection proposal networks)
|
||||||
|
required-networks-supported? (networks/required-networks-supported? proposal networks)]
|
||||||
|
(if (and (not-empty session-networks) required-networks-supported?)
|
||||||
|
{:db (update db
|
||||||
|
:wallet-connect/current-proposal assoc
|
||||||
|
:request proposal
|
||||||
|
:session-networks session-networks
|
||||||
|
:address (or current-viewing-address
|
||||||
|
(-> available-accounts
|
||||||
|
first
|
||||||
|
:address)))
|
||||||
|
:fx [[:dispatch [:open-modal :screen/wallet.wallet-connect-session-proposal]]]}
|
||||||
|
{:fx [[:dispatch [:wallet-connect/show-session-networks-unsupported-toast proposal]]
|
||||||
|
[:dispatch [:wallet-connect/reject-session-proposal proposal]]]}))))
|
||||||
|
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:wallet-connect/show-session-networks-unsupported-toast
|
||||||
|
(fn [{:keys [db]} [proposal]]
|
||||||
|
(let [{:keys [name url]} (data-store/get-session-dapp-metadata proposal)]
|
||||||
|
{:fx [[:dispatch
|
||||||
|
[:toasts/upsert
|
||||||
|
{:type :negative
|
||||||
|
:theme (:theme db)
|
||||||
|
:text (i18n/label :t/wallet-connect-networks-not-supported
|
||||||
|
{:dapp (data-store/compute-dapp-name name url)})}]]]})))
|
||||||
|
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:wallet-connect/reset-current-session-proposal
|
||||||
|
(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/approve-session
|
||||||
|
(fn [{:keys [db]}]
|
||||||
|
(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 networks/chain-id->eip155)
|
||||||
|
vec)
|
||||||
|
current-address (get-in db [:wallet-connect/current-proposal :address])
|
||||||
|
accounts (-> (partial networks/format-eip155-address current-address)
|
||||||
|
(map session-networks))
|
||||||
|
network-status (:network/status db)
|
||||||
|
expiry (get-in current-proposal [:params :expiryTimestamp])]
|
||||||
|
(if (= network-status :online)
|
||||||
|
{:db (assoc-in db [:wallet-connect/current-proposal :response-sent?] true)
|
||||||
|
:fx [(if (uri/timestamp-expired? expiry)
|
||||||
|
[:dispatch
|
||||||
|
[:toasts/upsert
|
||||||
|
{:id :wallet-connect-proposal-expired
|
||||||
|
:type :negative
|
||||||
|
:text (i18n/label :t/wallet-connect-proposal-expired)}]]
|
||||||
|
[:effects.wallet-connect/approve-session
|
||||||
|
{:web3-wallet web3-wallet
|
||||||
|
:proposal current-proposal
|
||||||
|
:networks session-networks
|
||||||
|
:accounts accounts
|
||||||
|
:on-success (fn [approved-session]
|
||||||
|
(log/info "Wallet Connect session approved")
|
||||||
|
(rf/dispatch [:wallet-connect/reset-current-session-proposal])
|
||||||
|
(rf/dispatch [:wallet-connect/persist-session
|
||||||
|
approved-session]))
|
||||||
|
:on-fail (fn [error]
|
||||||
|
(log/error "Wallet Connect session approval failed"
|
||||||
|
{:error error
|
||||||
|
:event :wallet-connect/approve-session})
|
||||||
|
(rf/dispatch
|
||||||
|
[:wallet-connect/reset-current-session-proposal]))}])
|
||||||
|
[:dispatch [:dismiss-modal :screen/wallet.wallet-connect-session-proposal]]]}
|
||||||
|
{:fx [[:dispatch [:wallet-connect/no-internet-toast]]]}))))
|
|
@ -1,12 +1,14 @@
|
||||||
(ns status-im.contexts.wallet.wallet-connect.processing-events
|
(ns status-im.contexts.wallet.wallet-connect.events.session-requests
|
||||||
(:require [cljs-bean.core :as bean]
|
(:require [cljs-bean.core :as bean]
|
||||||
[clojure.string :as string]
|
[clojure.string :as string]
|
||||||
[native-module.core :as native-module]
|
[native-module.core :as native-module]
|
||||||
[re-frame.core :as rf]
|
[re-frame.core :as rf]
|
||||||
[status-im.constants :as constants]
|
[status-im.constants :as constants]
|
||||||
[status-im.contexts.wallet.wallet-connect.core :as wallet-connect-core]
|
[status-im.contexts.wallet.wallet-connect.utils.data-store :as
|
||||||
[status-im.contexts.wallet.wallet-connect.signing :as signing]
|
data-store]
|
||||||
[status-im.contexts.wallet.wallet-connect.transactions :as transactions]
|
[status-im.contexts.wallet.wallet-connect.utils.networks :as networks]
|
||||||
|
[status-im.contexts.wallet.wallet-connect.utils.signing :as signing]
|
||||||
|
[status-im.contexts.wallet.wallet-connect.utils.transactions :as transactions]
|
||||||
[taoensso.timbre :as log]
|
[taoensso.timbre :as log]
|
||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
[utils.transforms :as transforms]))
|
[utils.transforms :as transforms]))
|
||||||
|
@ -15,8 +17,8 @@
|
||||||
:wallet-connect/show-request-modal
|
:wallet-connect/show-request-modal
|
||||||
(fn [{:keys [db]}]
|
(fn [{:keys [db]}]
|
||||||
(let [event (get-in db [:wallet-connect/current-request :event])
|
(let [event (get-in db [:wallet-connect/current-request :event])
|
||||||
method (wallet-connect-core/get-request-method event)
|
method (data-store/get-request-method event)
|
||||||
screen (wallet-connect-core/method-to-screen method)]
|
screen (data-store/method-to-screen method)]
|
||||||
(if screen
|
(if screen
|
||||||
{:fx [[:dispatch [:open-modal screen]]]}
|
{:fx [[:dispatch [:open-modal screen]]]}
|
||||||
(log/error "Didn't find screen for Wallet Connect method"
|
(log/error "Didn't find screen for Wallet Connect method"
|
||||||
|
@ -25,7 +27,7 @@
|
||||||
(rf/reg-event-fx
|
(rf/reg-event-fx
|
||||||
:wallet-connect/process-session-request
|
:wallet-connect/process-session-request
|
||||||
(fn [{:keys [db]} [event]]
|
(fn [{:keys [db]} [event]]
|
||||||
(let [method (wallet-connect-core/get-request-method event)
|
(let [method (data-store/get-request-method event)
|
||||||
existing-event (get-in db [:wallet-connect/current-request :event])]
|
existing-event (get-in db [:wallet-connect/current-request :event])]
|
||||||
(log/info "Processing Wallet Connect session request" method)
|
(log/info "Processing Wallet Connect session request" method)
|
||||||
;; NOTE: make sure we don't show two requests at the same time
|
;; NOTE: make sure we don't show two requests at the same time
|
||||||
|
@ -55,7 +57,7 @@
|
||||||
(rf/reg-event-fx
|
(rf/reg-event-fx
|
||||||
:wallet-connect/process-personal-sign
|
:wallet-connect/process-personal-sign
|
||||||
(fn [{:keys [db]}]
|
(fn [{:keys [db]}]
|
||||||
(let [[raw-data address] (wallet-connect-core/get-db-current-request-params db)
|
(let [[raw-data address] (data-store/get-db-current-request-params db)
|
||||||
parsed-data (native-module/hex-to-utf8 raw-data)]
|
parsed-data (native-module/hex-to-utf8 raw-data)]
|
||||||
{:db (update-in db
|
{:db (update-in db
|
||||||
[:wallet-connect/current-request]
|
[:wallet-connect/current-request]
|
||||||
|
@ -68,7 +70,7 @@
|
||||||
(rf/reg-event-fx
|
(rf/reg-event-fx
|
||||||
:wallet-connect/process-eth-sign
|
:wallet-connect/process-eth-sign
|
||||||
(fn [{:keys [db]}]
|
(fn [{:keys [db]}]
|
||||||
(let [[address raw-data] (wallet-connect-core/get-db-current-request-params db)
|
(let [[address raw-data] (data-store/get-db-current-request-params db)
|
||||||
parsed-data (native-module/hex-to-utf8 raw-data)]
|
parsed-data (native-module/hex-to-utf8 raw-data)]
|
||||||
{:db (update-in db
|
{:db (update-in db
|
||||||
[:wallet-connect/current-request]
|
[:wallet-connect/current-request]
|
||||||
|
@ -98,11 +100,11 @@
|
||||||
(rf/reg-event-fx
|
(rf/reg-event-fx
|
||||||
:wallet-connect/process-eth-send-transaction
|
:wallet-connect/process-eth-send-transaction
|
||||||
(fn [{:keys [db]}]
|
(fn [{:keys [db]}]
|
||||||
(let [event (wallet-connect-core/get-db-current-request-event db)
|
(let [event (data-store/get-db-current-request-event db)
|
||||||
tx (-> event wallet-connect-core/get-request-params first)
|
tx (-> event data-store/get-request-params first)
|
||||||
chain-id (-> event
|
chain-id (-> event
|
||||||
(get-in [:params :chainId])
|
(get-in [:params :chainId])
|
||||||
wallet-connect-core/eip155->chain-id)]
|
networks/eip155->chain-id)]
|
||||||
{:fx [[:effects.wallet-connect/prepare-transaction
|
{:fx [[:effects.wallet-connect/prepare-transaction
|
||||||
{:tx tx
|
{:tx tx
|
||||||
:chain-id chain-id
|
:chain-id chain-id
|
||||||
|
@ -112,11 +114,11 @@
|
||||||
(rf/reg-event-fx
|
(rf/reg-event-fx
|
||||||
:wallet-connect/process-eth-sign-transaction
|
:wallet-connect/process-eth-sign-transaction
|
||||||
(fn [{:keys [db]}]
|
(fn [{:keys [db]}]
|
||||||
(let [event (wallet-connect-core/get-db-current-request-event db)
|
(let [event (data-store/get-db-current-request-event db)
|
||||||
tx (-> event wallet-connect-core/get-request-params first)
|
tx (-> event data-store/get-request-params first)
|
||||||
chain-id (-> event
|
chain-id (-> event
|
||||||
(get-in [:params :chainId])
|
(get-in [:params :chainId])
|
||||||
wallet-connect-core/eip155->chain-id)]
|
networks/eip155->chain-id)]
|
||||||
{:fx [[:effects.wallet-connect/prepare-transaction
|
{:fx [[:effects.wallet-connect/prepare-transaction
|
||||||
{:tx tx
|
{:tx tx
|
||||||
:chain-id chain-id
|
:chain-id chain-id
|
||||||
|
@ -127,11 +129,11 @@
|
||||||
:wallet-connect/process-sign-typed
|
:wallet-connect/process-sign-typed
|
||||||
(fn [{:keys [db]}]
|
(fn [{:keys [db]}]
|
||||||
(try
|
(try
|
||||||
(let [[address raw-data] (wallet-connect-core/get-db-current-request-params db)
|
(let [[address raw-data] (data-store/get-db-current-request-params db)
|
||||||
parsed-raw-data (transforms/js-parse raw-data)
|
parsed-raw-data (transforms/js-parse raw-data)
|
||||||
session-chain-id (-> (wallet-connect-core/get-db-current-request-event db)
|
session-chain-id (-> (data-store/get-db-current-request-event db)
|
||||||
(get-in [:params :chainId])
|
(get-in [:params :chainId])
|
||||||
wallet-connect-core/eip155->chain-id)
|
networks/eip155->chain-id)
|
||||||
data-chain-id (-> parsed-raw-data
|
data-chain-id (-> parsed-raw-data
|
||||||
transforms/js->clj
|
transforms/js->clj
|
||||||
signing/typed-data-chain-id)
|
signing/typed-data-chain-id)
|
||||||
|
@ -156,20 +158,20 @@
|
||||||
[:wallet-connect/on-processing-error
|
[:wallet-connect/on-processing-error
|
||||||
(ex-info "Failed to parse JSON typed data"
|
(ex-info "Failed to parse JSON typed data"
|
||||||
{:error err
|
{:error err
|
||||||
:data (wallet-connect-core/get-db-current-request-params db)})]]]}))))
|
:data (data-store/get-db-current-request-params db)})]]]}))))
|
||||||
|
|
||||||
(rf/reg-event-fx
|
(rf/reg-event-fx
|
||||||
:wallet-connect/wrong-typed-data-chain-id
|
:wallet-connect/wrong-typed-data-chain-id
|
||||||
(fn [_ [{:keys [expected-chain-id wrong-chain-id]}]]
|
(fn [_ [{:keys [expected-chain-id wrong-chain-id]}]]
|
||||||
(let [wrong-network-name (-> wrong-chain-id
|
(let [wrong-network-name (-> wrong-chain-id
|
||||||
wallet-connect-core/chain-id->network-details
|
networks/chain-id->network-details
|
||||||
:full-name)
|
:full-name)
|
||||||
expected-network-name (-> expected-chain-id
|
expected-network-name (-> expected-chain-id
|
||||||
wallet-connect-core/chain-id->network-details
|
networks/chain-id->network-details
|
||||||
:full-name)
|
:full-name)
|
||||||
toast-message (i18n/label :t/wallet-connect-typed-data-wrong-chain-id-warning
|
toast-message (i18n/label :t/wallet-connect-typed-data-wrong-chain-id-warning
|
||||||
{:wrong-chain (or wrong-network-name
|
{:wrong-chain (or wrong-network-name
|
||||||
(wallet-connect-core/chain-id->eip155
|
(networks/chain-id->eip155
|
||||||
wrong-chain-id))
|
wrong-chain-id))
|
||||||
:expected-chain expected-network-name})]
|
:expected-chain expected-network-name})]
|
||||||
{:fx [[:dispatch
|
{:fx [[:dispatch
|
||||||
|
@ -186,7 +188,7 @@
|
||||||
:wallet-connect/on-processing-error
|
:wallet-connect/on-processing-error
|
||||||
(fn [{:keys [db]} [error]]
|
(fn [{:keys [db]} [error]]
|
||||||
(let [{:keys [address event]} (get db :wallet-connect/current-request)
|
(let [{:keys [address event]} (get db :wallet-connect/current-request)
|
||||||
method (wallet-connect-core/get-request-method event)]
|
method (data-store/get-request-method event)]
|
||||||
(log/error "Failed to process Wallet Connect request"
|
(log/error "Failed to process Wallet Connect request"
|
||||||
{:error error
|
{:error error
|
||||||
:address address
|
:address address
|
|
@ -1,9 +1,10 @@
|
||||||
(ns status-im.contexts.wallet.wallet-connect.responding-events
|
(ns status-im.contexts.wallet.wallet-connect.events.session-responses
|
||||||
(:require [re-frame.core :as rf]
|
(:require [re-frame.core :as rf]
|
||||||
[react-native.wallet-connect :as wallet-connect]
|
[react-native.wallet-connect :as wallet-connect]
|
||||||
[status-im.constants :as constants]
|
[status-im.constants :as constants]
|
||||||
[status-im.contexts.wallet.wallet-connect.core :as wallet-connect-core]
|
[status-im.contexts.wallet.wallet-connect.utils.data-store :as
|
||||||
[status-im.contexts.wallet.wallet-connect.utils :as wc-utils]
|
data-store]
|
||||||
|
[status-im.contexts.wallet.wallet-connect.utils.uri :as uri]
|
||||||
[taoensso.timbre :as log]
|
[taoensso.timbre :as log]
|
||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
[utils.transforms :as transforms]))
|
[utils.transforms :as transforms]))
|
||||||
|
@ -12,10 +13,10 @@
|
||||||
:wallet-connect/respond-current-session
|
:wallet-connect/respond-current-session
|
||||||
(fn [{:keys [db]} [password]]
|
(fn [{:keys [db]} [password]]
|
||||||
(let [event (get-in db [:wallet-connect/current-request :event])
|
(let [event (get-in db [:wallet-connect/current-request :event])
|
||||||
method (wallet-connect-core/get-request-method event)
|
method (data-store/get-request-method event)
|
||||||
screen (wallet-connect-core/method-to-screen method)
|
screen (data-store/method-to-screen method)
|
||||||
expiry (get-in event [:params :request :expiryTimestamp])]
|
expiry (get-in event [:params :request :expiryTimestamp])]
|
||||||
(if (wc-utils/timestamp-expired? expiry)
|
(if (uri/timestamp-expired? expiry)
|
||||||
{:fx [[:dispatch
|
{:fx [[:dispatch
|
||||||
[:toasts/upsert
|
[:toasts/upsert
|
||||||
{:id :new-wallet-account-created
|
{:id :new-wallet-account-created
|
||||||
|
@ -99,7 +100,7 @@
|
||||||
:wallet-connect/on-sign-error
|
:wallet-connect/on-sign-error
|
||||||
(fn [{:keys [db]} [error]]
|
(fn [{:keys [db]} [error]]
|
||||||
(let [{:keys [raw-data address event]} (get db :wallet-connect/current-request)
|
(let [{:keys [raw-data address event]} (get db :wallet-connect/current-request)
|
||||||
method (wallet-connect-core/get-request-method event)]
|
method (data-store/get-request-method event)]
|
||||||
(log/error "Failed to sign Wallet Connect request"
|
(log/error "Failed to sign Wallet Connect request"
|
||||||
{:error error
|
{:error error
|
||||||
:address address
|
:address address
|
||||||
|
@ -118,7 +119,7 @@
|
||||||
(fn [{:keys [db]} [{:keys [request result error]}]]
|
(fn [{:keys [db]} [{:keys [request result error]}]]
|
||||||
(when-let [{:keys [id topic] :as event} (or request
|
(when-let [{:keys [id topic] :as event} (or request
|
||||||
(get-in db [:wallet-connect/current-request :event]))]
|
(get-in db [:wallet-connect/current-request :event]))]
|
||||||
(let [method (wallet-connect-core/get-request-method event)
|
(let [method (data-store/get-request-method event)
|
||||||
web3-wallet (get db :wallet-connect/web3-wallet)]
|
web3-wallet (get db :wallet-connect/web3-wallet)]
|
||||||
{:db (assoc-in db [:wallet-connect/current-request :response-sent?] true)
|
{:db (assoc-in db [:wallet-connect/current-request :response-sent?] true)
|
||||||
:fx [[:effects.wallet-connect/respond-session-request
|
:fx [[:effects.wallet-connect/respond-session-request
|
||||||
|
@ -142,11 +143,11 @@
|
||||||
(fn [{:keys [db]} [url]]
|
(fn [{:keys [db]} [url]]
|
||||||
(let [redirect-url (or url
|
(let [redirect-url (or url
|
||||||
(->> (get db :wallet-connect/current-request)
|
(->> (get db :wallet-connect/current-request)
|
||||||
(wallet-connect-core/get-current-request-dapp
|
(data-store/get-current-request-dapp
|
||||||
(get db :wallet-connect/sessions))
|
(get db :wallet-connect/sessions))
|
||||||
:sessionJson
|
:sessionJson
|
||||||
transforms/json->clj
|
transforms/json->clj
|
||||||
wallet-connect-core/get-dapp-redirect-url))]
|
data-store/get-dapp-redirect-url))]
|
||||||
{:fx [[:open-url redirect-url]]})))
|
{:fx [[:open-url redirect-url]]})))
|
||||||
|
|
||||||
(rf/reg-event-fx
|
(rf/reg-event-fx
|
||||||
|
@ -154,17 +155,8 @@
|
||||||
(fn [{:keys [db]} _]
|
(fn [{:keys [db]} _]
|
||||||
(let [screen (-> db
|
(let [screen (-> db
|
||||||
(get-in [:wallet-connect/current-request :event])
|
(get-in [:wallet-connect/current-request :event])
|
||||||
wallet-connect-core/get-request-method
|
data-store/get-request-method
|
||||||
wallet-connect-core/method-to-screen)]
|
data-store/method-to-screen)]
|
||||||
{:fx [[:dispatch [:dismiss-modal screen]]]})))
|
|
||||||
|
|
||||||
(rf/reg-event-fx
|
|
||||||
:wallet-connect/dismiss-request-modal
|
|
||||||
(fn [{:keys [db]} _]
|
|
||||||
(let [screen (-> db
|
|
||||||
(get-in [:wallet-connect/current-request :event])
|
|
||||||
wallet-connect-core/get-request-method
|
|
||||||
wallet-connect-core/method-to-screen)]
|
|
||||||
{:fx [[:dispatch [:dismiss-modal screen]]]})))
|
{:fx [[:dispatch [:dismiss-modal screen]]]})))
|
||||||
|
|
||||||
(rf/reg-event-fx
|
(rf/reg-event-fx
|
|
@ -1,10 +1,10 @@
|
||||||
(ns status-im.contexts.wallet.wallet-connect.responding-events-test
|
(ns status-im.contexts.wallet.wallet-connect.events.session-responses-test
|
||||||
(:require
|
(:require
|
||||||
[cljs.test :refer-macros [is]]
|
[cljs.test :refer-macros [is]]
|
||||||
matcher-combinators.test
|
matcher-combinators.test
|
||||||
[re-frame.db :as rf-db]
|
[re-frame.db :as rf-db]
|
||||||
[status-im.contexts.wallet.wallet-connect.core :as wallet-connect-core]
|
status-im.contexts.wallet.wallet-connect.events.session-responses
|
||||||
status-im.contexts.wallet.wallet-connect.responding-events
|
[status-im.contexts.wallet.wallet-connect.utils.data-store :as data-store]
|
||||||
[test-helpers.unit :as h]
|
[test-helpers.unit :as h]
|
||||||
[utils.transforms :as transforms]))
|
[utils.transforms :as transforms]))
|
||||||
|
|
||||||
|
@ -16,11 +16,11 @@
|
||||||
:sessionJson session-json}]]
|
:sessionJson session-json}]]
|
||||||
(reset! rf-db/app-db {:wallet-connect {:current-request current-request
|
(reset! rf-db/app-db {:wallet-connect {:current-request current-request
|
||||||
:sessions sessions}})
|
:sessions sessions}})
|
||||||
(with-redefs [wallet-connect-core/get-current-request-dapp
|
(with-redefs [data-store/get-current-request-dapp
|
||||||
(fn [_ _] (first sessions))
|
(fn [_ _] (first sessions))
|
||||||
transforms/json->clj
|
transforms/json->clj
|
||||||
(fn [json] (js/JSON.parse json))
|
(fn [json] (js/JSON.parse json))
|
||||||
wallet-connect-core/get-dapp-redirect-url
|
data-store/get-dapp-redirect-url
|
||||||
(fn [_] "native://redirect-url")]
|
(fn [_] "native://redirect-url")]
|
||||||
|
|
||||||
(is (match? {:fx [[:open-url "native://redirect-url"]]}
|
(is (match? {:fx [[:open-url "native://redirect-url"]]}
|
|
@ -0,0 +1,141 @@
|
||||||
|
(ns status-im.contexts.wallet.wallet-connect.events.sessions
|
||||||
|
(:require [re-frame.core :as rf]
|
||||||
|
[react-native.wallet-connect :as wallet-connect]
|
||||||
|
[status-im.constants :as constants]
|
||||||
|
[status-im.contexts.wallet.wallet-connect.utils.data-store :as
|
||||||
|
data-store]
|
||||||
|
[status-im.contexts.wallet.wallet-connect.utils.networks :as networks]
|
||||||
|
[status-im.contexts.wallet.wallet-connect.utils.sessions :as sessions]
|
||||||
|
[taoensso.timbre :as log]
|
||||||
|
[utils.transforms :as types]))
|
||||||
|
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:wallet-connect/on-session-delete
|
||||||
|
(fn [{:keys [db]} [{:keys [topic] :as event}]]
|
||||||
|
(when (networks/event-should-be-handled? db event)
|
||||||
|
(log/info "Received Wallet Connect session delete from the SDK: " event)
|
||||||
|
{:fx [[:dispatch [:wallet-connect/disconnect-persisted-session topic]]]})))
|
||||||
|
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:wallet-connect/disconnect-dapp
|
||||||
|
(fn [{:keys [db]} [{:keys [topic on-success on-fail]}]]
|
||||||
|
(let [web3-wallet (get db :wallet-connect/web3-wallet)
|
||||||
|
network-status (:network/status db)]
|
||||||
|
(log/info "Disconnecting dApp session" topic)
|
||||||
|
(if (= network-status :online)
|
||||||
|
{:fx [[:effects.wallet-connect/disconnect
|
||||||
|
{:web3-wallet web3-wallet
|
||||||
|
:topic topic
|
||||||
|
:reason (wallet-connect/get-sdk-error
|
||||||
|
constants/wallet-connect-user-disconnected-reason-key)
|
||||||
|
:on-fail on-fail
|
||||||
|
:on-success (fn []
|
||||||
|
(rf/dispatch [:wallet-connect/disconnect-persisted-session topic])
|
||||||
|
(when on-success
|
||||||
|
(on-success)))}]]}
|
||||||
|
{:fx [[:dispatch [:wallet-connect/no-internet-toast]]]}))))
|
||||||
|
|
||||||
|
;; We first load sessions from database, then we initiate a call to Wallet Connect SDK and
|
||||||
|
;; then replace the list we have stored in the database with the one that came from the SDK.
|
||||||
|
;; In addition to that, we also update the backend state by marking sessions that are not
|
||||||
|
;; active anymore by calling `:wallet-connect/disconnect-session`.
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:wallet-connect/fetch-active-sessions-success
|
||||||
|
(fn [{:keys [db now]} [sessions]]
|
||||||
|
(let [persisted-sessions (:wallet-connect/sessions db)
|
||||||
|
account-addresses (->> (get-in db [:wallet :accounts])
|
||||||
|
vals
|
||||||
|
sessions/filter-operable-accounts
|
||||||
|
(map :address))
|
||||||
|
sessions (->> (js->clj sessions :keywordize-keys true)
|
||||||
|
vals
|
||||||
|
(map sessions/sdk-session->db-session)
|
||||||
|
(sessions/filter-sessions-for-account-addresses
|
||||||
|
account-addresses))
|
||||||
|
session-topics (set (map :topic sessions))
|
||||||
|
expired-sessions (filter
|
||||||
|
(fn [{:keys [expiry topic]}]
|
||||||
|
(or (< expiry (/ now 1000))
|
||||||
|
(not (contains? session-topics topic))))
|
||||||
|
persisted-sessions)]
|
||||||
|
(when (seq expired-sessions)
|
||||||
|
(log/info "Updating WalletConnect persisted sessions due to expired/inactive sessions"
|
||||||
|
{:expired expired-sessions}))
|
||||||
|
{:fx (mapv (fn [{:keys [topic]}]
|
||||||
|
[:dispatch [:wallet-connect/disconnect-persisted-session topic]])
|
||||||
|
expired-sessions)
|
||||||
|
:db (assoc db :wallet-connect/sessions sessions)})))
|
||||||
|
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:wallet-connect/fetch-active-sessions
|
||||||
|
(fn [{:keys [db]}]
|
||||||
|
(let [web3-wallet (get db :wallet-connect/web3-wallet)]
|
||||||
|
{:fx [[:effects.wallet-connect/fetch-active-sessions
|
||||||
|
{:web3-wallet web3-wallet
|
||||||
|
:on-fail #(log/error "Failed to get active sessions" {:error %})
|
||||||
|
:on-success #(rf/dispatch [:wallet-connect/fetch-active-sessions-success %])}]]})))
|
||||||
|
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:wallet-connect/fetch-persisted-sessions-success
|
||||||
|
(fn [{:keys [db]} [sessions]]
|
||||||
|
(let [network-status (:network/status db)
|
||||||
|
sessions' (mapv (fn [{:keys [sessionJson] :as session}]
|
||||||
|
(assoc session
|
||||||
|
:accounts
|
||||||
|
(-> sessionJson
|
||||||
|
types/json->clj
|
||||||
|
:namespaces
|
||||||
|
:eip155
|
||||||
|
:accounts)))
|
||||||
|
sessions)]
|
||||||
|
{:fx [(when (= network-status :online)
|
||||||
|
[:dispatch [:wallet-connect/fetch-active-sessions]])]
|
||||||
|
:db (assoc db :wallet-connect/sessions sessions')})))
|
||||||
|
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:wallet-connect/fetch-persisted-sessions-fail
|
||||||
|
(fn [_ [error]]
|
||||||
|
(log/info "Wallet Connect fetch persisted sessions failed" error)
|
||||||
|
{:fx [[:dispatch [:wallet-connect/fetch-active-sessions]]]}))
|
||||||
|
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:wallet-connect/fetch-persisted-sessions
|
||||||
|
(fn [{:keys [now]} _]
|
||||||
|
(let [current-timestamp (quot now 1000)]
|
||||||
|
{:fx [[:json-rpc/call
|
||||||
|
[{:method "wallet_getWalletConnectActiveSessions"
|
||||||
|
;; NOTE: This is the activeSince timestamp to avoid expired sessions
|
||||||
|
:params [current-timestamp]
|
||||||
|
:on-success [:wallet-connect/fetch-persisted-sessions-success]
|
||||||
|
:on-error [:wallet-connect/fetch-persisted-sessions-fail]}]]]})))
|
||||||
|
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:wallet-connect/persist-session
|
||||||
|
(fn [_ [session-info]]
|
||||||
|
(let [redirect-url (-> session-info
|
||||||
|
(js->clj :keywordize-keys true)
|
||||||
|
(data-store/get-dapp-redirect-url))]
|
||||||
|
{:fx [[:json-rpc/call
|
||||||
|
[{:method "wallet_addWalletConnectSession"
|
||||||
|
:params [(js/JSON.stringify session-info)]
|
||||||
|
:on-success (fn []
|
||||||
|
(log/info "Wallet Connect session persisted")
|
||||||
|
(rf/dispatch [:wallet-connect/fetch-persisted-sessions])
|
||||||
|
(rf/dispatch [:wallet-connect/redirect-to-dapp redirect-url]))
|
||||||
|
:on-error #(log/info "Wallet Connect session persistence failed" %)}]]]})))
|
||||||
|
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:wallet-connect/disconnect-persisted-session
|
||||||
|
(fn [{:keys [db]} [topic]]
|
||||||
|
(log/info "Removing session from persistance and state" topic)
|
||||||
|
{:db (update db
|
||||||
|
:wallet-connect/sessions
|
||||||
|
(fn [sessions]
|
||||||
|
(->> sessions
|
||||||
|
(remove #(= (:topic %) topic))
|
||||||
|
(into []))))
|
||||||
|
:fx [[:json-rpc/call
|
||||||
|
[{:method "wallet_disconnectWalletConnectSession"
|
||||||
|
:params [topic]
|
||||||
|
:on-success #(log/info "Wallet Connect session disconnected")
|
||||||
|
:on-error #(log/info "Wallet Connect session persistence failed" %)}]]]}))
|
|
@ -2,14 +2,15 @@
|
||||||
(:require [clojure.string :as string]
|
(:require [clojure.string :as string]
|
||||||
[quo.core :as quo]
|
[quo.core :as quo]
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
[status-im.contexts.wallet.wallet-connect.core :as core]
|
[status-im.contexts.wallet.wallet-connect.modals.common.header.style :as style]
|
||||||
[status-im.contexts.wallet.wallet-connect.modals.common.header.style :as style]))
|
[status-im.contexts.wallet.wallet-connect.utils.data-store :as
|
||||||
|
data-store]))
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[{:keys [label dapp account]}]
|
[{:keys [label dapp account]}]
|
||||||
[rn/view {:style style/header-container}
|
[rn/view {:style style/header-container}
|
||||||
(let [{:keys [name iconUrl url]} dapp
|
(let [{:keys [name iconUrl url]} dapp
|
||||||
image-source (core/compute-dapp-icon-path iconUrl url)]
|
image-source (data-store/compute-dapp-icon-path iconUrl url)]
|
||||||
[rn/view {:style style/dapp-container}
|
[rn/view {:style style/dapp-container}
|
||||||
[quo/summary-tag
|
[quo/summary-tag
|
||||||
{:type :dapp
|
{:type :dapp
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
(ns status-im.contexts.wallet.wallet-connect.session-proposal.style
|
(ns status-im.contexts.wallet.wallet-connect.modals.session-proposal.style
|
||||||
(:require [quo.foundations.colors :as colors]))
|
(:require [quo.foundations.colors :as colors]))
|
||||||
|
|
||||||
(def dapp-avatar
|
(def dapp-avatar
|
|
@ -1,4 +1,4 @@
|
||||||
(ns status-im.contexts.wallet.wallet-connect.session-proposal.view
|
(ns status-im.contexts.wallet.wallet-connect.modals.session-proposal.view
|
||||||
(:require
|
(:require
|
||||||
[clojure.string :as string]
|
[clojure.string :as string]
|
||||||
[quo.core :as quo]
|
[quo.core :as quo]
|
||||||
|
@ -6,8 +6,8 @@
|
||||||
[quo.theme]
|
[quo.theme]
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
[status-im.common.floating-button-page.view :as floating-button-page]
|
[status-im.common.floating-button-page.view :as floating-button-page]
|
||||||
[status-im.contexts.wallet.wallet-connect.core :as wallet-connect-core]
|
[status-im.contexts.wallet.wallet-connect.modals.session-proposal.style :as style]
|
||||||
[status-im.contexts.wallet.wallet-connect.session-proposal.style :as style]
|
[status-im.contexts.wallet.wallet-connect.utils.data-store :as data-store]
|
||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
[utils.re-frame :as rf]
|
[utils.re-frame :as rf]
|
||||||
[utils.string]))
|
[utils.string]))
|
||||||
|
@ -17,8 +17,8 @@
|
||||||
(let [proposer (rf/sub [:wallet-connect/session-proposer])
|
(let [proposer (rf/sub [:wallet-connect/session-proposer])
|
||||||
{:keys [icons name url]} (:metadata proposer)
|
{:keys [icons name url]} (:metadata proposer)
|
||||||
first-icon (first icons)
|
first-icon (first icons)
|
||||||
dapp-name (wallet-connect-core/compute-dapp-name name url)
|
dapp-name (data-store/compute-dapp-name name url)
|
||||||
profile-picture (wallet-connect-core/compute-dapp-icon-path first-icon url)]
|
profile-picture (data-store/compute-dapp-icon-path first-icon url)]
|
||||||
[:<>
|
[:<>
|
||||||
[rn/view {:style style/dapp-avatar}
|
[rn/view {:style style/dapp-avatar}
|
||||||
[quo/user-avatar
|
[quo/user-avatar
|
|
@ -0,0 +1,75 @@
|
||||||
|
(ns status-im.contexts.wallet.wallet-connect.utils.data-store
|
||||||
|
(:require
|
||||||
|
[clojure.string :as string]
|
||||||
|
[status-im.constants :as constants]
|
||||||
|
utils.string
|
||||||
|
[utils.transforms :as transforms]))
|
||||||
|
|
||||||
|
(defn compute-dapp-name
|
||||||
|
"Sometimes dapps have no name or an empty name. Return url as name in that case"
|
||||||
|
[name url]
|
||||||
|
(if (seq name)
|
||||||
|
name
|
||||||
|
(when (seq url)
|
||||||
|
(-> url
|
||||||
|
utils.string/remove-trailing-slash
|
||||||
|
utils.string/remove-http-prefix
|
||||||
|
string/capitalize))))
|
||||||
|
|
||||||
|
(defn compute-dapp-icon-path
|
||||||
|
"Some dapps have icons with relative paths, make paths absolute in those cases, send nil if icon is missing"
|
||||||
|
[icon-path url]
|
||||||
|
(when (and (seq icon-path)
|
||||||
|
(seq url))
|
||||||
|
(if (string/starts-with? icon-path "http")
|
||||||
|
icon-path
|
||||||
|
(str (utils.string/remove-trailing-slash url) icon-path))))
|
||||||
|
|
||||||
|
(def method-to-screen
|
||||||
|
{constants/wallet-connect-personal-sign-method :screen/wallet-connect.sign-message
|
||||||
|
constants/wallet-connect-eth-sign-typed-method :screen/wallet-connect.sign-message
|
||||||
|
constants/wallet-connect-eth-sign-method :screen/wallet-connect.sign-message
|
||||||
|
constants/wallet-connect-eth-sign-typed-v4-method :screen/wallet-connect.sign-message
|
||||||
|
constants/wallet-connect-eth-send-transaction-method :screen/wallet-connect.send-transaction
|
||||||
|
constants/wallet-connect-eth-sign-transaction-method :screen/wallet-connect.sign-transaction})
|
||||||
|
|
||||||
|
(defn extract-native-call-signature
|
||||||
|
[data]
|
||||||
|
(-> data transforms/json->clj :result))
|
||||||
|
|
||||||
|
(defn get-request-method
|
||||||
|
[event]
|
||||||
|
(get-in event [:params :request :method]))
|
||||||
|
|
||||||
|
(defn get-request-params
|
||||||
|
[event]
|
||||||
|
(get-in event [:params :request :params]))
|
||||||
|
|
||||||
|
(defn get-db-current-request-event
|
||||||
|
[db]
|
||||||
|
(get-in db [:wallet-connect/current-request :event]))
|
||||||
|
|
||||||
|
(defn get-session-dapp-metadata
|
||||||
|
[proposal]
|
||||||
|
(let [metadata (get-in proposal [:params :proposer :metadata])
|
||||||
|
origin (get-in proposal [:verifyContext :verified :origin])]
|
||||||
|
(or metadata {:url origin})))
|
||||||
|
|
||||||
|
(defn get-current-request-dapp
|
||||||
|
[request sessions]
|
||||||
|
(let [dapp-url (get-in request [:event :verifyContext :verified :origin])]
|
||||||
|
(->> sessions
|
||||||
|
(filter (fn [session]
|
||||||
|
(= (utils.string/remove-trailing-slash dapp-url)
|
||||||
|
(utils.string/remove-trailing-slash (get session :url)))))
|
||||||
|
first)))
|
||||||
|
|
||||||
|
(defn get-dapp-redirect-url
|
||||||
|
[session]
|
||||||
|
(get-in session [:peer :metadata :redirect :native]))
|
||||||
|
|
||||||
|
(defn get-db-current-request-params
|
||||||
|
[db]
|
||||||
|
(-> db
|
||||||
|
get-db-current-request-event
|
||||||
|
get-request-params))
|
|
@ -0,0 +1,27 @@
|
||||||
|
(ns status-im.contexts.wallet.wallet-connect.utils.data-store-test
|
||||||
|
(:require
|
||||||
|
[cljs.test :refer-macros [deftest is testing]]
|
||||||
|
[status-im.contexts.wallet.wallet-connect.utils.data-store :as sut]))
|
||||||
|
|
||||||
|
(deftest get-current-request-dapp-test
|
||||||
|
(testing "returns the correct dapp based on the request's origin"
|
||||||
|
(let [request {:event {:verifyContext {:verified {:origin "https://dapp.com"}}}}
|
||||||
|
sessions [{:url "https://dapp.com"}
|
||||||
|
{:url "https://anotherdapp.com"}]]
|
||||||
|
(is (= {:url "https://dapp.com"}
|
||||||
|
(sut/get-current-request-dapp request sessions)))))
|
||||||
|
|
||||||
|
(testing "returns nil if no matching dapp is found"
|
||||||
|
(let [request {:event {:verifyContext {:verified {:origin "https://dapp.com"}}}}
|
||||||
|
sessions [{:url "https://anotherdapp.com"}]]
|
||||||
|
(is (nil? (sut/get-current-request-dapp request sessions))))))
|
||||||
|
|
||||||
|
(deftest get-dapp-redirect-url-test
|
||||||
|
(testing "returns the native redirect URL if it exists"
|
||||||
|
(let [session {:peer {:metadata {:redirect {:native "native://redirect-url"}}}}]
|
||||||
|
(is (= "native://redirect-url"
|
||||||
|
(sut/get-dapp-redirect-url session)))))
|
||||||
|
|
||||||
|
(testing "returns nil if no redirect URL is found"
|
||||||
|
(let [session {:peer {:metadata {}}}]
|
||||||
|
(is (nil? (sut/get-dapp-redirect-url session))))))
|
|
@ -0,0 +1,92 @@
|
||||||
|
(ns status-im.contexts.wallet.wallet-connect.utils.networks
|
||||||
|
(:require [clojure.edn :as edn]
|
||||||
|
[clojure.set :as set]
|
||||||
|
[clojure.string :as string]
|
||||||
|
[status-im.constants :as constants]
|
||||||
|
[status-im.contexts.wallet.common.utils.networks :as networks]
|
||||||
|
[utils.string]))
|
||||||
|
|
||||||
|
(defn chain-id->eip155
|
||||||
|
[chain-id]
|
||||||
|
(str "eip155:" chain-id))
|
||||||
|
|
||||||
|
(defn eip155->chain-id
|
||||||
|
[chain-id-str]
|
||||||
|
(-> chain-id-str
|
||||||
|
(string/split #":")
|
||||||
|
last
|
||||||
|
edn/read-string))
|
||||||
|
|
||||||
|
(defn format-eip155-address
|
||||||
|
[address chain-id]
|
||||||
|
(str chain-id ":" address))
|
||||||
|
|
||||||
|
(defn- add-full-testnet-name
|
||||||
|
"Updates the `:full-name` key with the full testnet name if using testnet `:chain-id`.\n
|
||||||
|
e.g. `{:full-name \"Mainnet\"}` -> `{:full-name \"Mainnet Sepolia\"`}`"
|
||||||
|
[network]
|
||||||
|
(let [add-testnet-name (fn [testnet-name]
|
||||||
|
(update network :full-name #(str % " " testnet-name)))]
|
||||||
|
(condp #(contains? %1 %2) (:chain-id network)
|
||||||
|
constants/sepolia-chain-ids (add-testnet-name constants/sepolia-full-name)
|
||||||
|
constants/goerli-chain-ids (add-testnet-name constants/goerli-full-name)
|
||||||
|
network)))
|
||||||
|
|
||||||
|
(defn chain-id->network-details
|
||||||
|
[chain-id]
|
||||||
|
(-> chain-id
|
||||||
|
(networks/get-network-details)
|
||||||
|
(add-full-testnet-name)))
|
||||||
|
|
||||||
|
(defn session-networks-allowed?
|
||||||
|
[testnet-mode? {:keys [chains]}]
|
||||||
|
(let [chain-ids (set (map (fn [chain]
|
||||||
|
(-> chain
|
||||||
|
(string/split ":")
|
||||||
|
second
|
||||||
|
js/parseInt))
|
||||||
|
chains))]
|
||||||
|
(if testnet-mode?
|
||||||
|
(set/subset? chain-ids (set/union constants/sepolia-chain-ids constants/goerli-chain-ids))
|
||||||
|
(set/subset? chain-ids constants/mainnet-chain-ids))))
|
||||||
|
|
||||||
|
(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 [supported-namespaces #{:eip155}
|
||||||
|
required-namespaces (get-in proposal [:params :requiredNamespaces])]
|
||||||
|
(when (every? #(contains? supported-namespaces %)
|
||||||
|
(keys required-namespaces))
|
||||||
|
(let [required-networks (get-in required-namespaces [: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)))
|
||||||
|
|
||||||
|
(defn event-should-be-handled?
|
||||||
|
[db {:keys [topic]}]
|
||||||
|
(let [testnet-mode? (get-in db [:profile/profile :test-networks-enabled?])]
|
||||||
|
(some #(and (= (:topic %) topic)
|
||||||
|
(session-networks-allowed? testnet-mode? %))
|
||||||
|
(:wallet-connect/sessions db))))
|
|
@ -1,4 +1,4 @@
|
||||||
(ns status-im.contexts.wallet.wallet-connect.rpc
|
(ns status-im.contexts.wallet.wallet-connect.utils.rpc
|
||||||
(:require [oops.core :as oops]
|
(:require [oops.core :as oops]
|
||||||
[promesa.core :as promesa]
|
[promesa.core :as promesa]
|
||||||
[status-im.common.json-rpc.events :as rpc-events]
|
[status-im.common.json-rpc.events :as rpc-events]
|
|
@ -0,0 +1,33 @@
|
||||||
|
(ns status-im.contexts.wallet.wallet-connect.utils.sessions
|
||||||
|
(:require
|
||||||
|
[clojure.string :as string]
|
||||||
|
[utils.transforms :as transforms]))
|
||||||
|
|
||||||
|
(defn sdk-session->db-session
|
||||||
|
[{:keys [topic expiry pairingTopic] :as session}]
|
||||||
|
{:topic topic
|
||||||
|
:expiry expiry
|
||||||
|
:sessionJson (transforms/clj->json session)
|
||||||
|
:pairingTopic pairingTopic
|
||||||
|
:name (get-in session [:peer :metadata :name])
|
||||||
|
:iconUrl (get-in session [:peer :metadata :icons 0])
|
||||||
|
:url (get-in session [:peer :metadata :url])
|
||||||
|
:accounts (get-in session [:namespaces :eip155 :accounts])
|
||||||
|
:chains (get-in session [:namespaces :eip155 :chains])
|
||||||
|
:disconnected false})
|
||||||
|
|
||||||
|
(defn filter-operable-accounts
|
||||||
|
[accounts]
|
||||||
|
(filter #(and (:operable? %)
|
||||||
|
(not (:watch-only? %)))
|
||||||
|
accounts))
|
||||||
|
|
||||||
|
(defn filter-sessions-for-account-addresses
|
||||||
|
[account-addresses sessions]
|
||||||
|
(filter (fn [{:keys [accounts]}]
|
||||||
|
(some (fn [account]
|
||||||
|
(some (fn [account-address]
|
||||||
|
(string/includes? account account-address))
|
||||||
|
account-addresses))
|
||||||
|
accounts))
|
||||||
|
sessions))
|
|
@ -1,8 +1,10 @@
|
||||||
(ns status-im.contexts.wallet.wallet-connect.signing
|
(ns status-im.contexts.wallet.wallet-connect.utils.signing
|
||||||
(:require [native-module.core :as native-module]
|
(:require [native-module.core :as native-module]
|
||||||
[promesa.core :as promesa]
|
[promesa.core :as promesa]
|
||||||
[status-im.contexts.wallet.wallet-connect.core :as core]
|
[status-im.contexts.wallet.wallet-connect.utils.data-store :as
|
||||||
[status-im.contexts.wallet.wallet-connect.rpc :as rpc]
|
data-store]
|
||||||
|
[status-im.contexts.wallet.wallet-connect.utils.networks :as networks]
|
||||||
|
[status-im.contexts.wallet.wallet-connect.utils.rpc :as rpc]
|
||||||
[utils.hex :as hex]
|
[utils.hex :as hex]
|
||||||
[utils.number :as number]
|
[utils.number :as number]
|
||||||
[utils.transforms :as transforms]))
|
[utils.transforms :as transforms]))
|
||||||
|
@ -29,7 +31,7 @@
|
||||||
:password password}
|
:password password}
|
||||||
transforms/clj->json
|
transforms/clj->json
|
||||||
native-module/sign-message
|
native-module/sign-message
|
||||||
(promesa/then core/extract-native-call-signature)))
|
(promesa/then data-store/extract-native-call-signature)))
|
||||||
|
|
||||||
(defn personal-sign
|
(defn personal-sign
|
||||||
[password address data]
|
[password address data]
|
||||||
|
@ -40,7 +42,7 @@
|
||||||
(defn eth-sign-typed-data
|
(defn eth-sign-typed-data
|
||||||
[password address data chain-id-eip155 version]
|
[password address data chain-id-eip155 version]
|
||||||
(let [legacy? (= version :v1)
|
(let [legacy? (= version :v1)
|
||||||
chain-id (core/eip155->chain-id chain-id-eip155)]
|
chain-id (networks/eip155->chain-id chain-id-eip155)]
|
||||||
(rpc/wallet-safe-sign-typed-data data
|
(rpc/wallet-safe-sign-typed-data data
|
||||||
address
|
address
|
||||||
password
|
password
|
|
@ -1,17 +1,18 @@
|
||||||
(ns status-im.contexts.wallet.wallet-connect.transactions
|
(ns status-im.contexts.wallet.wallet-connect.utils.transactions
|
||||||
(:require [cljs-bean.core :as bean]
|
(:require [cljs-bean.core :as bean]
|
||||||
[clojure.string :as string]
|
[clojure.string :as string]
|
||||||
[native-module.core :as native-module]
|
[native-module.core :as native-module]
|
||||||
[promesa.core :as promesa]
|
[promesa.core :as promesa]
|
||||||
[status-im.constants :as constants]
|
[status-im.constants :as constants]
|
||||||
[status-im.contexts.wallet.wallet-connect.core :as core]
|
[status-im.contexts.wallet.wallet-connect.utils.data-store :as
|
||||||
[status-im.contexts.wallet.wallet-connect.rpc :as rpc]
|
data-store]
|
||||||
|
[status-im.contexts.wallet.wallet-connect.utils.rpc :as rpc]
|
||||||
[utils.money :as money]
|
[utils.money :as money]
|
||||||
[utils.transforms :as transforms]))
|
[utils.transforms :as transforms]))
|
||||||
|
|
||||||
(defn transaction-request?
|
(defn transaction-request?
|
||||||
[event]
|
[event]
|
||||||
(->> (core/get-request-method event)
|
(->> (data-store/get-request-method event)
|
||||||
(contains? #{constants/wallet-connect-eth-send-transaction-method
|
(contains? #{constants/wallet-connect-eth-send-transaction-method
|
||||||
constants/wallet-connect-eth-sign-transaction-method})))
|
constants/wallet-connect-eth-sign-transaction-method})))
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
(ns status-im.contexts.wallet.wallet-connect.utils
|
(ns status-im.contexts.wallet.wallet-connect.utils.uri
|
||||||
(:require [react-native.wallet-connect :as wallet-connect]))
|
(:require [react-native.wallet-connect :as wallet-connect]))
|
||||||
|
|
||||||
(defn version-supported?
|
(defn version-supported?
|
|
@ -48,7 +48,7 @@
|
||||||
status-im.contexts.wallet.send.events
|
status-im.contexts.wallet.send.events
|
||||||
status-im.contexts.wallet.signals
|
status-im.contexts.wallet.signals
|
||||||
status-im.contexts.wallet.swap.events
|
status-im.contexts.wallet.swap.events
|
||||||
status-im.contexts.wallet.wallet-connect.events
|
status-im.contexts.wallet.wallet-connect.events.core
|
||||||
[status-im.db :as db]
|
[status-im.db :as db]
|
||||||
status-im.navigation.effects
|
status-im.navigation.effects
|
||||||
status-im.navigation.events
|
status-im.navigation.events
|
||||||
|
|
|
@ -127,10 +127,11 @@
|
||||||
[status-im.contexts.wallet.swap.swap-proposal.view :as wallet-swap-propasal]
|
[status-im.contexts.wallet.swap.swap-proposal.view :as wallet-swap-propasal]
|
||||||
[status-im.contexts.wallet.wallet-connect.modals.send-transaction.view :as
|
[status-im.contexts.wallet.wallet-connect.modals.send-transaction.view :as
|
||||||
wallet-connect-send-transaction]
|
wallet-connect-send-transaction]
|
||||||
|
[status-im.contexts.wallet.wallet-connect.modals.session-proposal.view :as
|
||||||
|
wallet-connect-session-proposal]
|
||||||
[status-im.contexts.wallet.wallet-connect.modals.sign-message.view :as wallet-connect-sign-message]
|
[status-im.contexts.wallet.wallet-connect.modals.sign-message.view :as wallet-connect-sign-message]
|
||||||
[status-im.contexts.wallet.wallet-connect.modals.sign-transaction.view :as
|
[status-im.contexts.wallet.wallet-connect.modals.sign-transaction.view :as
|
||||||
wallet-connect-sign-transaction]
|
wallet-connect-sign-transaction]
|
||||||
[status-im.contexts.wallet.wallet-connect.session-proposal.view :as wallet-connect-session-proposal]
|
|
||||||
[status-im.navigation.options :as options]
|
[status-im.navigation.options :as options]
|
||||||
[status-im.navigation.transitions :as transitions]))
|
[status-im.navigation.transitions :as transitions]))
|
||||||
|
|
||||||
|
|
|
@ -20,12 +20,12 @@
|
||||||
status-im.subs.wallet.activities
|
status-im.subs.wallet.activities
|
||||||
status-im.subs.wallet.buy
|
status-im.subs.wallet.buy
|
||||||
status-im.subs.wallet.collectibles
|
status-im.subs.wallet.collectibles
|
||||||
|
status-im.subs.wallet.dapps.core
|
||||||
status-im.subs.wallet.networks
|
status-im.subs.wallet.networks
|
||||||
status-im.subs.wallet.saved-addresses
|
status-im.subs.wallet.saved-addresses
|
||||||
status-im.subs.wallet.send
|
status-im.subs.wallet.send
|
||||||
status-im.subs.wallet.swap
|
status-im.subs.wallet.swap
|
||||||
status-im.subs.wallet.wallet
|
status-im.subs.wallet.wallet))
|
||||||
status-im.subs.wallet.wallet-connect))
|
|
||||||
|
|
||||||
(defn reg-root-key-sub
|
(defn reg-root-key-sub
|
||||||
[sub-name db-key]
|
[sub-name db-key]
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
(ns status-im.subs.wallet.dapps.core
|
||||||
|
(:require [re-frame.core :as rf]
|
||||||
|
[status-im.contexts.wallet.common.utils :as wallet-utils]
|
||||||
|
status-im.subs.wallet.dapps.proposals
|
||||||
|
status-im.subs.wallet.dapps.requests
|
||||||
|
status-im.subs.wallet.dapps.sessions
|
||||||
|
status-im.subs.wallet.dapps.transactions
|
||||||
|
[utils.string]))
|
||||||
|
|
||||||
|
(rf/reg-sub
|
||||||
|
:wallet-connect/account-details-by-address
|
||||||
|
:<- [:wallet/accounts-without-watched-accounts]
|
||||||
|
(fn [accounts [_ address]]
|
||||||
|
(let [{:keys [customization-color name emoji]} (wallet-utils/get-account-by-address accounts address)]
|
||||||
|
{:customization-color customization-color
|
||||||
|
:name name
|
||||||
|
:emoji emoji})))
|
|
@ -0,0 +1,45 @@
|
||||||
|
(ns status-im.subs.wallet.dapps.proposals
|
||||||
|
(:require [re-frame.core :as rf]
|
||||||
|
[status-im.contexts.wallet.wallet-connect.utils.data-store :as
|
||||||
|
data-store]
|
||||||
|
[utils.string]))
|
||||||
|
|
||||||
|
(rf/reg-sub
|
||||||
|
: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 :params :proposer)))
|
||||||
|
|
||||||
|
(rf/reg-sub
|
||||||
|
:wallet-connect/session-proposer-name
|
||||||
|
:<- [:wallet-connect/session-proposer]
|
||||||
|
(fn [proposer]
|
||||||
|
(let [{:keys [name url]} (-> proposer :metadata)]
|
||||||
|
(data-store/compute-dapp-name name url))))
|
||||||
|
|
||||||
|
(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]
|
||||||
|
(get-in db [:wallet-connect/current-proposal :address])))
|
|
@ -1,9 +1,9 @@
|
||||||
(ns status-im.subs.wallet.wallet-connect-test
|
(ns status-im.subs.wallet.dapps.proposals-test
|
||||||
(:require
|
(:require
|
||||||
[cljs.test :refer [is testing]]
|
[cljs.test :refer [is testing]]
|
||||||
[re-frame.db :as rf-db]
|
[re-frame.db :as rf-db]
|
||||||
status-im.subs.root
|
status-im.subs.root
|
||||||
status-im.subs.wallet.wallet-connect
|
status-im.subs.wallet.dapps.core
|
||||||
[test-helpers.unit :as h]
|
[test-helpers.unit :as h]
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
(ns status-im.subs.wallet.dapps.requests
|
||||||
|
(:require [re-frame.core :as rf]
|
||||||
|
[status-im.contexts.wallet.common.utils :as wallet-utils]
|
||||||
|
[status-im.contexts.wallet.wallet-connect.utils.data-store :as
|
||||||
|
data-store]
|
||||||
|
[status-im.contexts.wallet.wallet-connect.utils.networks :as networks]
|
||||||
|
[utils.string]))
|
||||||
|
|
||||||
|
(rf/reg-sub
|
||||||
|
:wallet-connect/current-request-address
|
||||||
|
:<- [:wallet-connect/current-request]
|
||||||
|
:-> :address)
|
||||||
|
|
||||||
|
(rf/reg-sub
|
||||||
|
:wallet-connect/current-request-display-data
|
||||||
|
:<- [:wallet-connect/current-request]
|
||||||
|
:-> :display-data)
|
||||||
|
|
||||||
|
(rf/reg-sub
|
||||||
|
:wallet-connect/current-request-account-details
|
||||||
|
:<- [:wallet-connect/current-request-address]
|
||||||
|
:<- [:wallet/accounts-without-watched-accounts]
|
||||||
|
(fn [[address accounts]]
|
||||||
|
(let [{:keys [customization-color name emoji]} (wallet-utils/get-account-by-address accounts address)]
|
||||||
|
{:customization-color customization-color
|
||||||
|
:name name
|
||||||
|
:emoji emoji})))
|
||||||
|
|
||||||
|
(rf/reg-sub
|
||||||
|
:wallet-connect/current-request-dapp
|
||||||
|
:<- [:wallet-connect/current-request]
|
||||||
|
:<- [:wallet-connect/sessions]
|
||||||
|
(fn [[request sessions]]
|
||||||
|
(data-store/get-current-request-dapp request sessions)))
|
||||||
|
|
||||||
|
(rf/reg-sub
|
||||||
|
:wallet-connect/chain-id
|
||||||
|
:<- [:wallet-connect/current-request]
|
||||||
|
(fn [request]
|
||||||
|
(-> request
|
||||||
|
(get-in [:event :params :chainId])
|
||||||
|
(networks/eip155->chain-id))))
|
||||||
|
|
||||||
|
(rf/reg-sub
|
||||||
|
:wallet-connect/current-request-network
|
||||||
|
:<- [:wallet-connect/chain-id]
|
||||||
|
networks/chain-id->network-details)
|
|
@ -0,0 +1,25 @@
|
||||||
|
(ns status-im.subs.wallet.dapps.sessions
|
||||||
|
(:require [clojure.string :as string]
|
||||||
|
[re-frame.core :as rf]
|
||||||
|
[status-im.contexts.wallet.wallet-connect.utils.networks :as networks]
|
||||||
|
[utils.string]))
|
||||||
|
|
||||||
|
(rf/reg-sub
|
||||||
|
:wallet-connect/sessions-for-current-account
|
||||||
|
:<- [:wallet-connect/sessions]
|
||||||
|
:<- [:wallet/current-viewing-account-address]
|
||||||
|
(fn [[sessions address]]
|
||||||
|
(filter
|
||||||
|
(fn [{:keys [accounts]}]
|
||||||
|
(some #(string/includes? % address) accounts))
|
||||||
|
sessions)))
|
||||||
|
|
||||||
|
(rf/reg-sub
|
||||||
|
:wallet-connect/sessions-for-current-account-and-networks
|
||||||
|
:<- [:wallet-connect/sessions-for-current-account]
|
||||||
|
:<- [:profile/test-networks-enabled?]
|
||||||
|
(fn [[sessions testnet-mode?]]
|
||||||
|
(filter
|
||||||
|
(partial networks/session-networks-allowed? testnet-mode?)
|
||||||
|
sessions)))
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
(ns status-im.subs.wallet.dapps.transactions
|
||||||
|
(:require [re-frame.core :as rf]
|
||||||
|
[status-im.contexts.wallet.common.utils :as wallet-utils]
|
||||||
|
[status-im.contexts.wallet.wallet-connect.utils.transactions :as transactions]
|
||||||
|
[utils.money :as money]
|
||||||
|
[utils.string]))
|
||||||
|
|
||||||
|
(rf/reg-sub
|
||||||
|
:wallet-connect/transaction-args
|
||||||
|
:<- [:wallet-connect/current-request]
|
||||||
|
(fn [{:keys [event transaction]}]
|
||||||
|
(when (transactions/transaction-request? event)
|
||||||
|
transaction)))
|
||||||
|
|
||||||
|
(rf/reg-sub
|
||||||
|
:wallet-connect/transaction-suggested-fees
|
||||||
|
:<- [:wallet-connect/current-request]
|
||||||
|
(fn [{:keys [event raw-data]}]
|
||||||
|
(when (transactions/transaction-request? event)
|
||||||
|
(:suggested-fees raw-data))))
|
||||||
|
|
||||||
|
(rf/reg-sub
|
||||||
|
:wallet-connect/transaction-max-fees-wei
|
||||||
|
:<- [:wallet-connect/transaction-args]
|
||||||
|
:<- [:wallet-connect/transaction-suggested-fees]
|
||||||
|
(fn [[transaction suggested-fees]]
|
||||||
|
(when transaction
|
||||||
|
(let [{:keys [gasPrice gas gasLimit maxFeePerGas]} transaction
|
||||||
|
eip-1559-chain? (:eip1559Enabled suggested-fees)
|
||||||
|
gas-limit (or gasLimit gas)
|
||||||
|
max-gas-fee (if eip-1559-chain? maxFeePerGas gasPrice)]
|
||||||
|
(money/bignumber (* max-gas-fee gas-limit))))))
|
||||||
|
|
||||||
|
(rf/reg-sub
|
||||||
|
:wallet-connect/account-eth-token
|
||||||
|
:<- [:wallet-connect/current-request-address]
|
||||||
|
:<- [:wallet/accounts]
|
||||||
|
(fn [[address accounts]]
|
||||||
|
(let [fee-token "ETH"
|
||||||
|
find-account #(when (= (:address %) address) %)
|
||||||
|
find-token #(when (= (:symbol %) fee-token) %)]
|
||||||
|
(->> accounts
|
||||||
|
(some find-account)
|
||||||
|
:tokens
|
||||||
|
(some find-token)))))
|
||||||
|
|
||||||
|
(rf/reg-sub
|
||||||
|
:wallet-connect/current-request-transaction-information
|
||||||
|
:<- [:wallet-connect/chain-id]
|
||||||
|
:<- [:wallet-connect/transaction-max-fees-wei]
|
||||||
|
:<- [:wallet-connect/transaction-args]
|
||||||
|
:<- [:wallet-connect/account-eth-token]
|
||||||
|
:<- [:profile/currency]
|
||||||
|
:<- [:profile/currency-symbol]
|
||||||
|
(fn [[chain-id max-fees-wei transaction eth-token currency currency-symbol]]
|
||||||
|
(when transaction
|
||||||
|
(let [max-fees-ether (money/wei->ether max-fees-wei)
|
||||||
|
max-fees-fiat (wallet-utils/calculate-token-fiat-value {:currency currency
|
||||||
|
:balance max-fees-ether
|
||||||
|
:token eth-token})
|
||||||
|
max-fees-fiat-formatted (-> (wallet-utils/get-standard-crypto-format eth-token max-fees-ether)
|
||||||
|
(wallet-utils/get-standard-fiat-format currency-symbol
|
||||||
|
max-fees-fiat))
|
||||||
|
balance (-> eth-token
|
||||||
|
(get-in [:balances-per-chain chain-id :raw-balance])
|
||||||
|
money/bignumber)
|
||||||
|
tx-value (money/bignumber (:value transaction))
|
||||||
|
total-transaction-value (money/add max-fees-wei tx-value)]
|
||||||
|
{:total-transaction-value total-transaction-value
|
||||||
|
:balance balance
|
||||||
|
:max-fees max-fees-wei
|
||||||
|
:max-fees-fiat-value max-fees-fiat
|
||||||
|
:max-fees-fiat-formatted max-fees-fiat-formatted
|
||||||
|
:error-state (cond
|
||||||
|
(not (money/sufficient-funds? tx-value balance))
|
||||||
|
:not-enough-assets
|
||||||
|
|
||||||
|
(not (money/sufficient-funds? total-transaction-value
|
||||||
|
balance))
|
||||||
|
:not-enough-assets-to-pay-gas-fees)}))))
|
|
@ -1,190 +0,0 @@
|
||||||
(ns status-im.subs.wallet.wallet-connect
|
|
||||||
(:require [clojure.string :as string]
|
|
||||||
[re-frame.core :as rf]
|
|
||||||
[status-im.contexts.wallet.common.utils :as wallet-utils]
|
|
||||||
[status-im.contexts.wallet.wallet-connect.core :as wallet-connect-core]
|
|
||||||
[status-im.contexts.wallet.wallet-connect.transactions :as transactions]
|
|
||||||
[utils.money :as money]
|
|
||||||
[utils.string]))
|
|
||||||
|
|
||||||
(rf/reg-sub
|
|
||||||
:wallet-connect/current-request-address
|
|
||||||
:<- [:wallet-connect/current-request]
|
|
||||||
:-> :address)
|
|
||||||
|
|
||||||
(rf/reg-sub
|
|
||||||
:wallet-connect/current-request-display-data
|
|
||||||
:<- [:wallet-connect/current-request]
|
|
||||||
:-> :display-data)
|
|
||||||
|
|
||||||
(rf/reg-sub
|
|
||||||
:wallet-connect/account-details-by-address
|
|
||||||
:<- [:wallet/accounts-without-watched-accounts]
|
|
||||||
(fn [accounts [_ address]]
|
|
||||||
(let [{:keys [customization-color name emoji]} (wallet-utils/get-account-by-address accounts address)]
|
|
||||||
{:customization-color customization-color
|
|
||||||
:name name
|
|
||||||
:emoji emoji})))
|
|
||||||
|
|
||||||
(rf/reg-sub
|
|
||||||
:wallet-connect/current-request-account-details
|
|
||||||
:<- [:wallet-connect/current-request-address]
|
|
||||||
:<- [:wallet/accounts-without-watched-accounts]
|
|
||||||
(fn [[address accounts]]
|
|
||||||
(let [{:keys [customization-color name emoji]} (wallet-utils/get-account-by-address accounts address)]
|
|
||||||
{:customization-color customization-color
|
|
||||||
:name name
|
|
||||||
:emoji emoji})))
|
|
||||||
|
|
||||||
(rf/reg-sub
|
|
||||||
:wallet-connect/current-request-dapp
|
|
||||||
:<- [:wallet-connect/current-request]
|
|
||||||
:<- [:wallet-connect/sessions]
|
|
||||||
(fn [[request sessions]]
|
|
||||||
(wallet-connect-core/get-current-request-dapp request sessions)))
|
|
||||||
|
|
||||||
(rf/reg-sub
|
|
||||||
:wallet-connect/sessions-for-current-account
|
|
||||||
:<- [:wallet-connect/sessions]
|
|
||||||
:<- [:wallet/current-viewing-account-address]
|
|
||||||
(fn [[sessions address]]
|
|
||||||
(filter
|
|
||||||
(fn [{:keys [accounts]}]
|
|
||||||
(some #(string/includes? % address) accounts))
|
|
||||||
sessions)))
|
|
||||||
|
|
||||||
(rf/reg-sub
|
|
||||||
:wallet-connect/sessions-for-current-account-and-networks
|
|
||||||
:<- [:wallet-connect/sessions-for-current-account]
|
|
||||||
:<- [:profile/test-networks-enabled?]
|
|
||||||
(fn [[sessions testnet-mode?]]
|
|
||||||
(filter
|
|
||||||
(partial wallet-connect-core/session-networks-allowed? testnet-mode?)
|
|
||||||
sessions)))
|
|
||||||
|
|
||||||
(rf/reg-sub
|
|
||||||
:wallet-connect/chain-id
|
|
||||||
:<- [:wallet-connect/current-request]
|
|
||||||
(fn [request]
|
|
||||||
(-> request
|
|
||||||
(get-in [:event :params :chainId])
|
|
||||||
(wallet-connect-core/eip155->chain-id))))
|
|
||||||
|
|
||||||
(rf/reg-sub
|
|
||||||
:wallet-connect/current-request-network
|
|
||||||
:<- [:wallet-connect/chain-id]
|
|
||||||
wallet-connect-core/chain-id->network-details)
|
|
||||||
|
|
||||||
(rf/reg-sub
|
|
||||||
:wallet-connect/transaction-args
|
|
||||||
:<- [:wallet-connect/current-request]
|
|
||||||
(fn [{:keys [event transaction]}]
|
|
||||||
(when (transactions/transaction-request? event)
|
|
||||||
transaction)))
|
|
||||||
|
|
||||||
(rf/reg-sub
|
|
||||||
:wallet-connect/transaction-suggested-fees
|
|
||||||
:<- [:wallet-connect/current-request]
|
|
||||||
(fn [{:keys [event raw-data]}]
|
|
||||||
(when (transactions/transaction-request? event)
|
|
||||||
(:suggested-fees raw-data))))
|
|
||||||
|
|
||||||
(rf/reg-sub
|
|
||||||
:wallet-connect/transaction-max-fees-wei
|
|
||||||
:<- [:wallet-connect/transaction-args]
|
|
||||||
:<- [:wallet-connect/transaction-suggested-fees]
|
|
||||||
(fn [[transaction suggested-fees]]
|
|
||||||
(when transaction
|
|
||||||
(let [{:keys [gasPrice gas gasLimit maxFeePerGas]} transaction
|
|
||||||
eip-1559-chain? (:eip1559Enabled suggested-fees)
|
|
||||||
gas-limit (or gasLimit gas)
|
|
||||||
max-gas-fee (if eip-1559-chain? maxFeePerGas gasPrice)]
|
|
||||||
(money/bignumber (* max-gas-fee gas-limit))))))
|
|
||||||
|
|
||||||
(rf/reg-sub
|
|
||||||
:wallet-connect/account-eth-token
|
|
||||||
:<- [:wallet-connect/current-request-address]
|
|
||||||
:<- [:wallet/accounts]
|
|
||||||
(fn [[address accounts]]
|
|
||||||
(let [fee-token "ETH"
|
|
||||||
find-account #(when (= (:address %) address) %)
|
|
||||||
find-token #(when (= (:symbol %) fee-token) %)]
|
|
||||||
(->> accounts
|
|
||||||
(some find-account)
|
|
||||||
:tokens
|
|
||||||
(some find-token)))))
|
|
||||||
|
|
||||||
(rf/reg-sub
|
|
||||||
:wallet-connect/current-request-transaction-information
|
|
||||||
:<- [:wallet-connect/chain-id]
|
|
||||||
:<- [:wallet-connect/transaction-max-fees-wei]
|
|
||||||
:<- [:wallet-connect/transaction-args]
|
|
||||||
:<- [:wallet-connect/account-eth-token]
|
|
||||||
:<- [:profile/currency]
|
|
||||||
:<- [:profile/currency-symbol]
|
|
||||||
(fn [[chain-id max-fees-wei transaction eth-token currency currency-symbol]]
|
|
||||||
(when transaction
|
|
||||||
(let [max-fees-ether (money/wei->ether max-fees-wei)
|
|
||||||
max-fees-fiat (wallet-utils/calculate-token-fiat-value {:currency currency
|
|
||||||
:balance max-fees-ether
|
|
||||||
:token eth-token})
|
|
||||||
max-fees-fiat-formatted (-> (wallet-utils/get-standard-crypto-format eth-token max-fees-ether)
|
|
||||||
(wallet-utils/get-standard-fiat-format currency-symbol
|
|
||||||
max-fees-fiat))
|
|
||||||
balance (-> eth-token
|
|
||||||
(get-in [:balances-per-chain chain-id :raw-balance])
|
|
||||||
money/bignumber)
|
|
||||||
tx-value (money/bignumber (:value transaction))
|
|
||||||
total-transaction-value (money/add max-fees-wei tx-value)]
|
|
||||||
{:total-transaction-value total-transaction-value
|
|
||||||
:balance balance
|
|
||||||
:max-fees max-fees-wei
|
|
||||||
:max-fees-fiat-value max-fees-fiat
|
|
||||||
:max-fees-fiat-formatted max-fees-fiat-formatted
|
|
||||||
:error-state (cond
|
|
||||||
(not (money/sufficient-funds? tx-value balance))
|
|
||||||
:not-enough-assets
|
|
||||||
|
|
||||||
(not (money/sufficient-funds? total-transaction-value
|
|
||||||
balance))
|
|
||||||
:not-enough-assets-to-pay-gas-fees)}))))
|
|
||||||
|
|
||||||
(rf/reg-sub
|
|
||||||
: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 :params :proposer)))
|
|
||||||
|
|
||||||
(rf/reg-sub
|
|
||||||
:wallet-connect/session-proposer-name
|
|
||||||
:<- [:wallet-connect/session-proposer]
|
|
||||||
(fn [proposer]
|
|
||||||
(let [{:keys [name url]} (-> proposer :metadata)]
|
|
||||||
(wallet-connect-core/compute-dapp-name name url))))
|
|
||||||
|
|
||||||
(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]
|
|
||||||
(get-in db [:wallet-connect/current-proposal :address])))
|
|
Loading…
Reference in New Issue