Implement Wallet Connect 2.0
Signed-off-by: Brian Sztamfater <brian@status.im>
|
@ -208,6 +208,8 @@ PODS:
|
|||
- React
|
||||
- react-native-blob-util (0.13.18):
|
||||
- React-Core
|
||||
- react-native-blur (0.8.0):
|
||||
- React
|
||||
- react-native-camera-kit (8.0.4):
|
||||
- React
|
||||
- react-native-cameraroll (4.0.4):
|
||||
|
@ -224,6 +226,8 @@ PODS:
|
|||
- React
|
||||
- react-native-notifications (4.1.3):
|
||||
- React-Core
|
||||
- react-native-randombytes (3.6.1):
|
||||
- React-Core
|
||||
- react-native-safe-area-context (2.0.0):
|
||||
- React
|
||||
- react-native-shake (3.4.0):
|
||||
|
@ -422,6 +426,7 @@ DEPENDENCIES:
|
|||
- React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
|
||||
- react-native-background-timer (from `../node_modules/react-native-background-timer`)
|
||||
- react-native-blob-util (from `../node_modules/react-native-blob-util`)
|
||||
- "react-native-blur (from `../node_modules/@react-native-community/blur`)"
|
||||
- react-native-camera-kit (from `../node_modules/react-native-camera-kit`)
|
||||
- "react-native-cameraroll (from `../node_modules/@react-native-community/cameraroll`)"
|
||||
- react-native-config (from `../node_modules/react-native-config`)
|
||||
|
@ -429,6 +434,7 @@ DEPENDENCIES:
|
|||
- react-native-mail (from `../node_modules/react-native-mail`)
|
||||
- "react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)"
|
||||
- react-native-notifications (from `../node_modules/react-native-notifications`)
|
||||
- react-native-randombytes (from `../node_modules/react-native-randombytes`)
|
||||
- react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
|
||||
- react-native-shake (from `../node_modules/react-native-shake`)
|
||||
- "react-native-slider (from `../node_modules/@react-native-community/slider`)"
|
||||
|
@ -525,6 +531,8 @@ EXTERNAL SOURCES:
|
|||
:path: "../node_modules/react-native-background-timer"
|
||||
react-native-blob-util:
|
||||
:path: "../node_modules/react-native-blob-util"
|
||||
react-native-blur:
|
||||
:path: "../node_modules/@react-native-community/blur"
|
||||
react-native-camera-kit:
|
||||
:path: "../node_modules/react-native-camera-kit"
|
||||
react-native-cameraroll:
|
||||
|
@ -539,6 +547,8 @@ EXTERNAL SOURCES:
|
|||
:path: "../node_modules/@react-native-community/netinfo"
|
||||
react-native-notifications:
|
||||
:path: "../node_modules/react-native-notifications"
|
||||
react-native-randombytes:
|
||||
:path: "../node_modules/react-native-randombytes"
|
||||
react-native-safe-area-context:
|
||||
:path: "../node_modules/react-native-safe-area-context"
|
||||
react-native-shake:
|
||||
|
@ -653,6 +663,7 @@ SPEC CHECKSUMS:
|
|||
React-jsinspector: 58aef7155bc9a9683f5b60b35eccea8722a4f53a
|
||||
react-native-background-timer: 1f7d560647b40e6a60b01c452ba29c54bf581fc4
|
||||
react-native-blob-util: 600972b1782380a5a7d5db61a3817ea32349dae9
|
||||
react-native-blur: cad4d93b364f91e7b7931b3fa935455487e5c33c
|
||||
react-native-camera-kit: 498a6d111a904834e0824e9073cfadef7303235f
|
||||
react-native-cameraroll: 88f4e62d9ecd0e1f253abe4f685474f2ea14bfa2
|
||||
react-native-config: c98128a72bc2c3a1ca72caec0b021f0fa944aa29
|
||||
|
@ -660,6 +671,7 @@ SPEC CHECKSUMS:
|
|||
react-native-mail: 8fdcd3aef007c33a6877a18eb4cf7447a1d4ce4a
|
||||
react-native-netinfo: ddaca8bbb9e6e914b1a23787ccb879bc642931c9
|
||||
react-native-notifications: 805108822ceff3440644d5701944f0cda35f5b4b
|
||||
react-native-randombytes: 421f1c7d48c0af8dbcd471b0324393ebf8fe7846
|
||||
react-native-safe-area-context: 60f654e00b6cc416573f6d5dbfce3839958eb57a
|
||||
react-native-shake: de052eaa3eadc4a326b8ddd7ac80c06e8d84528c
|
||||
react-native-slider: 12bd76d3d568c9c5500825db54123d44b48e4ad4
|
||||
|
|
|
@ -13,4 +13,7 @@ module.exports = {
|
|||
},
|
||||
}),
|
||||
},
|
||||
resolver: {
|
||||
extraNodeModules: require('node-libs-react-native'),
|
||||
},
|
||||
};
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
"dependencies": {
|
||||
"@react-native-community/async-storage": "^1.11.0",
|
||||
"@react-native-community/audio-toolkit": "git+https://github.com/tbenr/react-native-audio-toolkit.git#v2.0.3-status-v6",
|
||||
"@react-native-community/blur": "^3.6.0",
|
||||
"@react-native-community/cameraroll": "git+https://github.com/status-im/react-native-cameraroll.git#v4.0.4-status.0",
|
||||
"@react-native-community/clipboard": "^1.2.2",
|
||||
"@react-native-community/hooks": "^2.5.1",
|
||||
|
@ -20,6 +21,7 @@
|
|||
"@react-native-community/netinfo": "^4.4.0",
|
||||
"@react-native-community/push-notification-ios": "^1.4.1",
|
||||
"@react-native-community/slider": "^3.0.0",
|
||||
"@walletconnect/client": "^2.0.0-beta.23",
|
||||
"bignumber.js": "git+https://github.com/status-im/bignumber.js.git#v4.0.2-status",
|
||||
"buffer": "^5.4.2",
|
||||
"chance": "^1.1.0",
|
||||
|
@ -30,6 +32,7 @@
|
|||
"hermes-engine": "0.5.2-rc1",
|
||||
"hi-base32": "^0.5.0",
|
||||
"i18n-js": "^3.3.0",
|
||||
"node-libs-react-native": "^1.2.1",
|
||||
"qrcode": "^1.4.1",
|
||||
"react": "16.13.1",
|
||||
"react-dom": "^16.4.2",
|
||||
|
@ -56,6 +59,7 @@
|
|||
"react-native-navigation": "^7.13.0",
|
||||
"react-native-notifications": "^4.1.3",
|
||||
"react-native-permissions": "^2.1.5",
|
||||
"react-native-randombytes": "^3.6.1",
|
||||
"react-native-reanimated": "^2.1.0",
|
||||
"react-native-redash": "^16.0.11",
|
||||
"react-native-safe-area-context": "^2.0.0",
|
||||
|
|
|
@ -22,5 +22,10 @@ module.exports = {
|
|||
ios: null,
|
||||
},
|
||||
},
|
||||
'@react-native-community/blur': {
|
||||
platforms: {
|
||||
android: null,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
After Width: | Height: | Size: 469 B |
After Width: | Height: | Size: 637 B |
After Width: | Height: | Size: 386 B |
After Width: | Height: | Size: 539 B |
Before Width: | Height: | Size: 338 B After Width: | Height: | Size: 249 B |
Before Width: | Height: | Size: 467 B After Width: | Height: | Size: 323 B |
After Width: | Height: | Size: 338 B |
After Width: | Height: | Size: 467 B |
|
@ -213,6 +213,16 @@
|
|||
(def react-native-notifications
|
||||
#js {:Notifications #js {}})
|
||||
|
||||
(def react-native-blur
|
||||
(clj->js {:BlurView {}}))
|
||||
|
||||
(def wallet-connect-client #js {:default #js {}
|
||||
:CLIENT_EVENTS #js {:session #js {:request nil
|
||||
:created nil
|
||||
:deleted nil
|
||||
:proposal nil
|
||||
:updated nil}}})
|
||||
|
||||
;; Update i18n_resources.cljs
|
||||
(defn mock [module]
|
||||
(case module
|
||||
|
@ -243,12 +253,14 @@
|
|||
"react-native-linear-gradient" react-native-gradien
|
||||
"react-native-navigation" react-native-navigation
|
||||
"@react-native-community/push-notification-ios" push-notification-ios
|
||||
"@react-native-community/blur" react-native-blur
|
||||
"react-native-camera-kit" react-native-camera-kit
|
||||
"rn-emoji-keyboard" rn-emoji-keyboard
|
||||
"react-native-notifications" react-native-notifications
|
||||
"react-native-draggable-flatlist" react-native-draggable-flatlist
|
||||
"./fleets.js" default-fleets
|
||||
"./chats.js" default-chats
|
||||
"@walletconnect/client" wallet-connect-client
|
||||
"../translations/ar.json" (js/JSON.parse (slurp "./translations/ar.json"))
|
||||
"../translations/de.json" (js/JSON.parse (slurp "./translations/de.json"))
|
||||
"../translations/en.json" (js/JSON.parse (slurp "./translations/en.json"))
|
||||
|
|
|
@ -57,6 +57,8 @@
|
|||
(defn pressable-hooks [props]
|
||||
(let [{background-color :bgColor
|
||||
border-radius :borderRadius
|
||||
border-color :borderColor
|
||||
border-width :borderWidth
|
||||
type :type
|
||||
disabled :disabled
|
||||
on-press :onPress
|
||||
|
@ -121,7 +123,9 @@
|
|||
[animated/view {:style (merge absolute-fill
|
||||
background
|
||||
{:background-color background-color
|
||||
:border-radius border-radius})}]
|
||||
:border-radius border-radius
|
||||
:border-color border-color
|
||||
:border-width border-width})}]
|
||||
(into [animated/view {:style foreground}]
|
||||
(react/get-children children))]]]])))
|
||||
|
||||
|
|
|
@ -48,7 +48,11 @@
|
|||
:text-color (:text-02 @colors/theme)}
|
||||
:disabled {:icon-color (:icon-02 @colors/theme)
|
||||
:background-color (:ui-01 @colors/theme)
|
||||
:text-color (:text-02 @colors/theme)}))
|
||||
:text-color (:text-02 @colors/theme)}
|
||||
:monocromatic {:icon-color (:icon-01 @colors/theme)
|
||||
:background-color (:ui-background @colors/theme)
|
||||
:text-color (:text-01 @colors/theme)
|
||||
:border-color (:ui-01 @colors/theme)}))
|
||||
|
||||
(defn button [{:keys [on-press disabled type theme before after
|
||||
haptic-feedback haptic-type on-long-press on-press-start
|
||||
|
@ -62,7 +66,7 @@
|
|||
(let [theme' (cond
|
||||
disabled :disabled
|
||||
:else theme)
|
||||
{:keys [icon-color background-color text-color]}
|
||||
{:keys [icon-color background-color text-color border-color]}
|
||||
(themes theme')
|
||||
|
||||
optional-haptic (fn []
|
||||
|
@ -73,6 +77,9 @@
|
|||
:type type
|
||||
:disabled disabled
|
||||
:accessibility-label accessibility-label}
|
||||
(when border-color
|
||||
{:border-color border-color
|
||||
:border-width 1})
|
||||
(when on-press
|
||||
{:on-press (fn []
|
||||
(optional-haptic)
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
(def light-theme
|
||||
{:positive-01 "rgba(68,208,88,1)" ; Primary Positive, text, icons color
|
||||
:positive-02 "rgba(78,188,96,0.1)" ; Secondary Positive, Supporting color for success illustrations
|
||||
:positive-03 "rgba(78,188,96,1)" ; Lighter Positive, Supporting color for success illustrations
|
||||
:negative-01 "rgba(255,45,85,1)" ; Primary Negative, text, icons color
|
||||
:negative-02 "rgba(255,45,85,0.1))" ; Secondary Negative, Supporting color for errors illustrations
|
||||
:warning-01 "rgba(255, 202, 15, 1)"
|
||||
|
@ -46,11 +47,13 @@
|
|||
:backdrop "rgba(0,0,0,0.4)" ; Backdrop for modals and bottom sheet
|
||||
:border-01 "rgba(238,242,245,1)"
|
||||
:border-02 "rgba(67, 96, 223, 0.1)"
|
||||
:highlight "rgba(67,96,223,0.4)"})
|
||||
:highlight "rgba(67,96,223,0.4)"
|
||||
:blurred-bg "rgba(255,255,255,0.3)"})
|
||||
|
||||
(def dark-theme
|
||||
{:positive-01 "rgba(68,208,88,1)"
|
||||
:positive-02 "rgba(78,188,96,0.1)"
|
||||
:positive-03 "rgba(78,188,96,1)"
|
||||
:negative-01 "rgba(252,95,95,1)"
|
||||
:negative-02 "rgba(252,95,95,0.1)"
|
||||
:warning-01 "rgba(255, 202, 15, 1)"
|
||||
|
@ -77,7 +80,8 @@
|
|||
:backdrop "rgba(0,0,0,0.4)"
|
||||
:border-01 "rgba(37,37,40,1)"
|
||||
:border-02 "rgba(97,119,229,0.1)"
|
||||
:highlight "rgba(67,96,223,0.4)"})
|
||||
:highlight "rgba(67,96,223,0.4)"
|
||||
:blurred-bg "rgba(0,0,0,0.3)"})
|
||||
|
||||
(def theme (reagent/atom light-theme))
|
||||
|
||||
|
|
|
@ -61,7 +61,8 @@
|
|||
status-im.wallet.custom-tokens.core
|
||||
[status-im.navigation.core :as navigation.core]
|
||||
[status-im.multiaccounts.login.core :as login.core]
|
||||
[status-im.signing.core :as signing]))
|
||||
[status-im.signing.core :as signing]
|
||||
status-im.wallet-connect.core))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:dismiss-keyboard
|
||||
|
|
|
@ -42,7 +42,8 @@
|
|||
[status-im.ui.components.react :as react]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.ethereum.tokens :as tokens]
|
||||
[clojure.string :as string]))
|
||||
[clojure.string :as string]
|
||||
[status-im.utils.wallet-connect :as wallet-connect]))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::initialize-communities-enabled
|
||||
|
@ -82,6 +83,20 @@
|
|||
(fn []
|
||||
(status/start-local-notifications)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::initialize-wallet-connect
|
||||
(fn []
|
||||
(wallet-connect/init
|
||||
#(re-frame/dispatch [:wallet-connect/client-init %])
|
||||
#(log/error "[wallet-connect]" %))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::initialize-wallet-connect
|
||||
(fn []
|
||||
(async-storage/get-item
|
||||
:wallet-connect-enabled?
|
||||
#(re-frame/dispatch [:multiaccounts.ui/switch-wallet-connect-enabled %]))))
|
||||
|
||||
(defn rpc->accounts [accounts]
|
||||
(reduce (fn [acc {:keys [chat type wallet] :as account}]
|
||||
(if chat
|
||||
|
@ -343,6 +358,10 @@
|
|||
[cofx]
|
||||
{::initialize-transactions-management-enabled nil})
|
||||
|
||||
(fx/defn initialize-wallet-connect
|
||||
[cofx]
|
||||
{::initialize-wallet-connect nil})
|
||||
|
||||
(fx/defn get-node-config-callback
|
||||
{:events [::get-node-config-callback]}
|
||||
[{:keys [db] :as cofx} node-config-json]
|
||||
|
@ -377,6 +396,7 @@
|
|||
(acquisition/login)
|
||||
(initialize-appearance)
|
||||
(initialize-communities-enabled)
|
||||
(initialize-wallet-connect)
|
||||
(get-node-config)
|
||||
(communities/fetch)
|
||||
(logging/set-log-level (:log-level multiaccount))
|
||||
|
|
|
@ -86,3 +86,20 @@
|
|||
[_]
|
||||
{:hide-select-acc-sheet nil})
|
||||
|
||||
(fx/defn hide-wallet-connect-sheet
|
||||
{:events [:hide-wallet-connect-sheet]}
|
||||
[_]
|
||||
{:hide-wallet-connect-sheet nil})
|
||||
|
||||
(fx/defn hide-wallet-connect-success-sheet
|
||||
{:events [:hide-wallet-connect-success-sheet]}
|
||||
[_]
|
||||
{:hide-wallet-connect-success-sheet nil})
|
||||
|
||||
(fx/defn hide-wallet-connect-app-management-sheet
|
||||
{:events [:hide-wallet-connect-app-management-sheet]}
|
||||
[{:keys [db]}]
|
||||
{:db (-> db
|
||||
(assoc db :wallet-connect/showing-app-management-sheet? false)
|
||||
(dissoc :wallet-connect/session-managed))
|
||||
:hide-wallet-connect-app-management-sheet nil})
|
||||
|
|
|
@ -159,7 +159,7 @@
|
|||
(.events Navigation)
|
||||
(fn [^js evn]
|
||||
(let [view-id (keyword (.-componentName evn))]
|
||||
(when-not (#{"popover" "bottom-sheet" "signing-sheet" "visibility-status-popover"}
|
||||
(when-not (#{"popover" "bottom-sheet" "signing-sheet" "visibility-status-popover" "wallet-connect-sheet" "wallet-connect-success-sheet" "wallet-connect-app-management-sheet"}
|
||||
(.-componentName evn))
|
||||
(re-frame/dispatch [::view-disappeared view-id])
|
||||
(doseq [[_ {:keys [ref value]}] @quo.text-input/text-input-refs]
|
||||
|
@ -338,6 +338,33 @@
|
|||
(re-frame/reg-fx :show-bottom-sheet (fn [] (show-overlay "bottom-sheet")))
|
||||
(re-frame/reg-fx :hide-bottom-sheet (fn [] (dissmiss-overlay "bottom-sheet")))
|
||||
|
||||
;; WALLET CONNECT
|
||||
|
||||
(defonce wallet-connect-sheet-reg
|
||||
(.registerComponent Navigation
|
||||
"wallet-connect-sheet"
|
||||
(fn [] (gestureHandlerRootHOC views/wallet-connect-comp))
|
||||
(fn [] views/wallet-connect-comp)))
|
||||
|
||||
(defonce wallet-connect-success-sheet-reg
|
||||
(.registerComponent Navigation
|
||||
"wallet-connect-success-sheet"
|
||||
(fn [] (gestureHandlerRootHOC views/wallet-connect-success-comp))
|
||||
(fn [] views/wallet-connect-success-comp)))
|
||||
|
||||
(defonce wallet-connect-app-management-sheet-reg
|
||||
(.registerComponent Navigation
|
||||
"wallet-connect-app-management-sheet"
|
||||
(fn [] (gestureHandlerRootHOC views/wallet-connect-app-management-comp))
|
||||
(fn [] views/wallet-connect-app-management-comp)))
|
||||
|
||||
(re-frame/reg-fx :show-wallet-connect-sheet (fn [] (show-overlay "wallet-connect-sheet")))
|
||||
(re-frame/reg-fx :hide-wallet-connect-sheet (fn [] (dissmiss-overlay "wallet-connect-sheet")))
|
||||
(re-frame/reg-fx :show-wallet-connect-success-sheet (fn [] (show-overlay "wallet-connect-success-sheet")))
|
||||
(re-frame/reg-fx :hide-wallet-connect-success-sheet (fn [] (dissmiss-overlay "wallet-connect-success-sheet")))
|
||||
(re-frame/reg-fx :show-wallet-connect-app-management-sheet (fn [] (show-overlay "wallet-connect-app-management-sheet")))
|
||||
(re-frame/reg-fx :hide-wallet-connect-app-management-sheet (fn [] (dissmiss-overlay "wallet-connect-app-management-sheet")))
|
||||
|
||||
;; SIGNING
|
||||
|
||||
(defonce signing-sheet-reg
|
||||
|
|
|
@ -78,6 +78,9 @@
|
|||
(navigation/change-tab :wallet)
|
||||
(navigation/pop-to-root-tab :wallet-stack)))
|
||||
|
||||
(fx/defn handle-wallet-connect [cofx data]
|
||||
{:dispatch [:wallet-connect/pair data]})
|
||||
|
||||
(fx/defn match-scan
|
||||
{:events [::match-scanned-value]}
|
||||
[cofx {:keys [type] :as data}]
|
||||
|
@ -88,6 +91,7 @@
|
|||
:contact (handle-view-profile cofx data)
|
||||
:browser (handle-browse cofx data)
|
||||
:eip681 (handle-eip681 cofx data)
|
||||
:wallet-connect (handle-wallet-connect cofx data)
|
||||
{:dispatch [:navigate-back]
|
||||
:utils/show-popup {:title (i18n/label :t/unable-to-read-this-code)
|
||||
:on-dismiss #(re-frame/dispatch [:pop-to-root-tab :chat-stack])}}))
|
||||
|
|
|
@ -12,12 +12,15 @@
|
|||
[status-im.utils.db :as utils.db]
|
||||
[status-im.utils.http :as http]
|
||||
[status-im.chat.models :as chat.models]
|
||||
[status-im.ethereum.stateofus :as stateofus]))
|
||||
[status-im.ethereum.stateofus :as stateofus]
|
||||
[status-im.utils.wallet-connect :as wallet-connect]))
|
||||
|
||||
(def ethereum-scheme "ethereum:")
|
||||
|
||||
(def uri-schemes ["status-im://" "status-im:"])
|
||||
|
||||
(def wallet-connect-scheme "wc:")
|
||||
|
||||
(def web-prefixes ["https://" "http://" "https://www." "http://wwww."])
|
||||
|
||||
(def web2-domain "join.status.im")
|
||||
|
@ -226,6 +229,9 @@
|
|||
(http/url? uri)
|
||||
(cb (match-browser-string uri))
|
||||
|
||||
(wallet-connect/url? uri)
|
||||
(cb {:type :wallet-connect :data uri})
|
||||
|
||||
:else
|
||||
(cb {:type :undefined
|
||||
:data uri}))))
|
||||
|
|
|
@ -268,6 +268,14 @@
|
|||
|
||||
(reg-root-key-sub :backup/performing-backup :backup/performing-backup)
|
||||
|
||||
;; wallet connect
|
||||
(reg-root-key-sub :wallet-connect/proposal-metadata :wallet-connect/proposal-metadata)
|
||||
(reg-root-key-sub :wallet-connect/enabled? :wallet-connect/enabled?)
|
||||
(reg-root-key-sub :wallet-connect/session-connected :wallet-connect/session-connected)
|
||||
(reg-root-key-sub :wallet-connect/showing-app-management-sheet? :wallet-connect/showing-app-management-sheet?)
|
||||
(reg-root-key-sub :wallet-connect/sessions :wallet-connect/sessions)
|
||||
(reg-root-key-sub :wallet-connect/session-managed :wallet-connect/session-managed)
|
||||
|
||||
(re-frame/reg-sub
|
||||
:communities
|
||||
:<- [:raw-communities]
|
||||
|
@ -640,9 +648,11 @@
|
|||
:bottom-sheet
|
||||
:<- [:bottom-sheet/show?]
|
||||
:<- [:bottom-sheet/view]
|
||||
(fn [[show? view]]
|
||||
:<- [:bottom-sheet/options]
|
||||
(fn [[show? view options]]
|
||||
{:show? show?
|
||||
:view view}))
|
||||
:view view
|
||||
:options options}))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:is-contact-selected?
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
:duration 500
|
||||
:useNativeDriver true})])))
|
||||
|
||||
(defn bottom-panel [_ render window-height on-close]
|
||||
(defn bottom-panel [_ render window-height on-close on-touch-outside show-overlay?]
|
||||
(let [bottom-anim-value (anim/create-value window-height)
|
||||
alpha-value (anim/create-value 0)
|
||||
clear-timeout (atom nil)
|
||||
|
@ -97,8 +97,12 @@
|
|||
:ignore-offset true}
|
||||
|
||||
[react/view {:flex 1}
|
||||
(when platform/ios?
|
||||
(when (and platform/ios? show-overlay?)
|
||||
[react/animated-view {:flex 1 :background-color colors/black-persist :opacity alpha-value}])
|
||||
(when on-touch-outside
|
||||
[react/touchable-opacity {:active-opacity 0
|
||||
:on-press on-touch-outside
|
||||
:style {:flex 1}}])
|
||||
[react/animated-view {:style {:position :absolute
|
||||
:transform [{:translateY bottom-anim-value}]
|
||||
:bottom 0 :left 0 :right 0}}
|
||||
|
@ -108,6 +112,6 @@
|
|||
#(do (on-close)
|
||||
nil)))})))
|
||||
|
||||
(views/defview animated-bottom-panel [val signing-view on-close]
|
||||
(views/defview animated-bottom-panel [val view on-close on-touch-outside show-overlay?]
|
||||
(views/letsubs [{window-height :height} [:dimensions/window]]
|
||||
[bottom-panel (when val (select-keys val [:from :contact :amount :token :approve? :message :cancel? :hash])) signing-view window-height on-close]))
|
||||
[bottom-panel (when val (select-keys val [:from :contact :amount :token :approve? :message :cancel? :hash :name :url :icons :description :topic :relay :self :peer :permissions :state])) view window-height on-close on-touch-outside (if-not (nil? show-overlay?) show-overlay? true)]))
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
["@react-native-community/clipboard" :default Clipboard]
|
||||
["react-native-linear-gradient" :default LinearGradient]
|
||||
["react-native-navigation" :refer (Navigation)]
|
||||
["react-native-fast-image" :as FastImage])
|
||||
["react-native-fast-image" :as FastImage]
|
||||
["@react-native-community/blur" :as blur])
|
||||
(:require-macros [status-im.utils.views :as views]))
|
||||
|
||||
(def native-modules (.-NativeModules react-native))
|
||||
|
@ -39,6 +40,8 @@
|
|||
|
||||
(def linear-gradient (reagent/adapt-react-class LinearGradient))
|
||||
|
||||
(def blur-view (reagent/adapt-react-class (.-BlurView blur)))
|
||||
|
||||
(defn valid-source? [source]
|
||||
(or (not (map? source))
|
||||
(not (contains? source :uri))
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
transactions-management-enabled?
|
||||
wakuv2-flag
|
||||
current-fleet
|
||||
webview-debug]}]
|
||||
webview-debug
|
||||
wallet-connect-enabled?]}]
|
||||
(keep
|
||||
identity
|
||||
[{:size :small
|
||||
|
@ -112,7 +113,16 @@
|
|||
#(re-frame/dispatch
|
||||
[:multiaccounts.ui/waku-bloom-filter-mode-switched (not waku-bloom-filter-mode)])
|
||||
:accessory :switch
|
||||
:active waku-bloom-filter-mode}]))
|
||||
:active waku-bloom-filter-mode}
|
||||
{:size :small
|
||||
:title (i18n/label :t/wallet-connect-2.0)
|
||||
:accessibility-label :wallet-connect-settings-switch
|
||||
:container-margin-bottom 8
|
||||
:on-press
|
||||
#(re-frame/dispatch
|
||||
[:multiaccounts.ui/switch-wallet-connect-enabled (not wallet-connect-enabled?)])
|
||||
:accessory :switch
|
||||
:active wallet-connect-enabled?}]))
|
||||
|
||||
(defn- flat-list-data [options]
|
||||
(normal-mode-settings-data options))
|
||||
|
@ -130,7 +140,8 @@
|
|||
communities-enabled? [:communities/enabled?]
|
||||
transactions-management-enabled? [:wallet/transactions-management-enabled?]
|
||||
current-log-level [:log-level/current-log-level]
|
||||
current-fleet [:fleets/current-fleet]]
|
||||
current-fleet [:fleets/current-fleet]
|
||||
wallet-connect-enabled? [:wallet-connect/enabled?]]
|
||||
[list/flat-list
|
||||
{:data (flat-list-data
|
||||
{:network-name network-name
|
||||
|
@ -141,6 +152,7 @@
|
|||
:dev-mode? false
|
||||
:wakuv2-flag wakuv2-flag
|
||||
:waku-bloom-filter-mode waku-bloom-filter-mode
|
||||
:webview-debug webview-debug})
|
||||
:webview-debug webview-debug
|
||||
:wallet-connect-enabled? wallet-connect-enabled?})
|
||||
:key-fn (fn [_ i] (str i))
|
||||
:render-fn render-item}]))
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
[quo.core :as quo]))
|
||||
|
||||
(defn bottom-sheet []
|
||||
(let [{:keys [show? view]} @(re-frame/subscribe [:bottom-sheet])
|
||||
(let [{:keys [show? view options]} @(re-frame/subscribe [:bottom-sheet])
|
||||
{:keys [content]
|
||||
:as opts}
|
||||
(cond-> {:visible? show?
|
||||
|
@ -40,4 +40,4 @@
|
|||
(merge key-storage/migrate-account-password))]
|
||||
[quo/bottom-sheet opts
|
||||
(when content
|
||||
[content])]))
|
||||
[content (when options options)])]))
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
:size :small}
|
||||
name]
|
||||
[icons/icon
|
||||
:main-icons/chevron-down
|
||||
:main-icons/chevron-right
|
||||
{:color colors/gray
|
||||
:width 16
|
||||
:height 22}]])
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
[quo.design-system.colors :as colors]
|
||||
[status-im.utils.config :as config]
|
||||
[status-im.keycard.test-menu :as keycard.test-menu]
|
||||
[status-im.utils.platform :as platform]))
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.ui.screens.wallet-connect.session-proposal.views :as wallet-connect]))
|
||||
|
||||
(defn get-screens []
|
||||
(reduce
|
||||
|
@ -112,7 +113,7 @@
|
|||
(def signing-comp
|
||||
(reagent/reactify-component
|
||||
(fn []
|
||||
^{:key (str "signing-seet" @reloader/cnt)}
|
||||
^{:key (str "signing-sheet" @reloader/cnt)}
|
||||
[react/safe-area-provider
|
||||
[inactive]
|
||||
[signing/signing]
|
||||
|
@ -128,3 +129,33 @@
|
|||
[wallet.send.views/select-account]
|
||||
(when js/goog.DEBUG
|
||||
[reloader/reload-view])])))
|
||||
|
||||
(def wallet-connect-comp
|
||||
(reagent/reactify-component
|
||||
(fn []
|
||||
^{:key (str "wallet-connect-sheet" @reloader/cnt)}
|
||||
[react/safe-area-provider
|
||||
[inactive]
|
||||
[wallet-connect/wallet-connect-proposal-sheet]
|
||||
(when js/goog.DEBUG
|
||||
[reloader/reload-view])])))
|
||||
|
||||
(def wallet-connect-success-comp
|
||||
(reagent/reactify-component
|
||||
(fn []
|
||||
^{:key (str "wallet-connect-success-sheet" @reloader/cnt)}
|
||||
[react/safe-area-provider
|
||||
[inactive]
|
||||
[wallet-connect/wallet-connect-success-sheet-view]
|
||||
(when js/goog.DEBUG
|
||||
[reloader/reload-view])])))
|
||||
|
||||
(def wallet-connect-app-management-comp
|
||||
(reagent/reactify-component
|
||||
(fn []
|
||||
^{:key (str "wallet-connect-app-management-sheet" @reloader/cnt)}
|
||||
[react/safe-area-provider
|
||||
[inactive]
|
||||
[wallet-connect/wallet-connect-app-management-sheet-view]
|
||||
(when js/goog.DEBUG
|
||||
[reloader/reload-view])])))
|
|
@ -0,0 +1,144 @@
|
|||
(ns status-im.ui.screens.wallet-connect.session-proposal.styles
|
||||
(:require [quo.design-system.colors :as colors]))
|
||||
|
||||
(defn toolbar-container [background-color]
|
||||
{:height 36
|
||||
:border-radius 18
|
||||
:background-color background-color
|
||||
:align-items :center
|
||||
:flex-direction :row
|
||||
:padding-left 13
|
||||
:padding-right 6})
|
||||
|
||||
(def toolbar-text
|
||||
{:flex-grow 1
|
||||
:margin-right 3})
|
||||
|
||||
(defn dapp-logo []
|
||||
{:width 120
|
||||
:height 120
|
||||
:resize-mode :cover
|
||||
:margin-top 31
|
||||
:border-radius 16
|
||||
:border-width 2
|
||||
:border-color (:interactive-02 @colors/theme)
|
||||
:padding 5})
|
||||
|
||||
(def sheet-body-container
|
||||
{:flex 1
|
||||
:align-items :center})
|
||||
|
||||
(defn acc-sheet []
|
||||
{:background-color (:ui-background @colors/theme)
|
||||
:border-top-right-radius 16
|
||||
:border-top-left-radius 16
|
||||
:padding-bottom 1})
|
||||
|
||||
(defn proposal-sheet-container []
|
||||
{:background-color (:ui-background @colors/theme)
|
||||
:width "100%"
|
||||
:align-items :center
|
||||
:padding-top 0
|
||||
:padding-bottom 50
|
||||
:border-top-right-radius 16
|
||||
:border-top-left-radius 16})
|
||||
|
||||
(defn proposal-sheet-header []
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:justify-content :center
|
||||
:height 56
|
||||
:width "100%"
|
||||
:border-color colors/gray-lighter
|
||||
:border-bottom-width 1})
|
||||
|
||||
(def proposal-title-container
|
||||
{:align-items :center
|
||||
:margin-top 21})
|
||||
|
||||
(def message-title
|
||||
{:margin-top 10
|
||||
:margin-bottom 14
|
||||
:margin-horizontal 72.5
|
||||
:text-align :center})
|
||||
|
||||
(defn proposal-buttons-container []
|
||||
{:width "100%"
|
||||
:height 76
|
||||
:border-color colors/gray-lighter
|
||||
:border-top-width 1
|
||||
:flex 1
|
||||
:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:align-items :center
|
||||
:padding-horizontal 16})
|
||||
|
||||
(defn success-button-container []
|
||||
{:width "100%"
|
||||
:height 76
|
||||
:border-color colors/gray-lighter
|
||||
:border-top-width 1
|
||||
:flex-direction :row
|
||||
:justify-content :flex-end
|
||||
:align-items :center
|
||||
:padding-horizontal 16})
|
||||
|
||||
(defn account-container [color account-selected?]
|
||||
{:height 34
|
||||
:background-color color
|
||||
:border-radius 17
|
||||
:padding-horizontal 10
|
||||
:justify-content :center
|
||||
:margin-right 4
|
||||
:opacity (if account-selected? 1 0.5)})
|
||||
|
||||
(def account-selector-container
|
||||
{:height 80
|
||||
:width "100%"
|
||||
:justify-content :center
|
||||
:padding-horizontal 16})
|
||||
|
||||
(def account-selector-wrapper
|
||||
{:margin-top 40
|
||||
:width "100%"})
|
||||
|
||||
(def account-selector-list
|
||||
{:height 40
|
||||
:width "100%"
|
||||
:margin-top 10})
|
||||
|
||||
(def single-account-container
|
||||
{:width "100%"
|
||||
:align-items :center
|
||||
:padding-top 8})
|
||||
|
||||
(defn blur-view []
|
||||
{:position :absolute
|
||||
:top 60
|
||||
:left 0
|
||||
:right 0
|
||||
:bottom 0
|
||||
:background-color (:blurred-bg @colors/theme)})
|
||||
|
||||
(def shadow
|
||||
{:width "100%"
|
||||
:height 50
|
||||
:opacity 0.3})
|
||||
|
||||
(defn management-sheet-header []
|
||||
{:width "100%"
|
||||
:flex-direction :row
|
||||
:padding 16
|
||||
:align-items :center
|
||||
:border-bottom-width 1
|
||||
:border-bottom-color colors/gray-lighter})
|
||||
|
||||
(def management-icon
|
||||
{:width 40
|
||||
:height 40
|
||||
:border-radius 20
|
||||
:margin-right 16})
|
||||
|
||||
(def app-info-container
|
||||
{:flex-direction :column
|
||||
:flex 1})
|
|
@ -0,0 +1,205 @@
|
|||
(ns status-im.ui.screens.wallet-connect.session-proposal.views
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.utils.security]
|
||||
[quo.design-system.colors :as colors]
|
||||
[quo.core :as quo]
|
||||
[status-im.ui.components.icons.icons :as icons]
|
||||
[status-im.ui.components.bottom-panel.views :as bottom-panel]
|
||||
[status-im.ui.screens.wallet-connect.session-proposal.styles :as styles]
|
||||
[status-im.ui.components.list.views :as list]
|
||||
[reagent.core :as reagent]
|
||||
[clojure.string :as string]
|
||||
[quo.platform :as platform]))
|
||||
|
||||
(def chevron-icon-container-width 24)
|
||||
|
||||
(def chevron-icon-container-height 24)
|
||||
|
||||
(defn toolbar-selection [{:keys [text background-color on-press]}]
|
||||
[react/touchable-opacity {:on-press on-press}
|
||||
[react/view (styles/toolbar-container background-color)
|
||||
[quo/text {:color :inverse
|
||||
:weight :medium
|
||||
:style styles/toolbar-text}
|
||||
text]
|
||||
[icons/icon
|
||||
:main-icons/chevron-down
|
||||
{:color (:text-05 @colors/theme)
|
||||
:width chevron-icon-container-width
|
||||
:height chevron-icon-container-height}]]])
|
||||
|
||||
(def show-account-selector? (reagent/atom false))
|
||||
|
||||
(defn render-account [{:keys [address name color] :as account} _ _ {:keys [selected-account on-select]}]
|
||||
(let [account-selected? (= (:address @selected-account) address)]
|
||||
[react/touchable-without-feedback {:on-press #(do
|
||||
(reset! selected-account (merge {} account))
|
||||
(when on-select (on-select)))}
|
||||
[react/view (styles/account-container color account-selected?)
|
||||
[quo/text {:color :inverse
|
||||
:weight (if account-selected? :medium :regular)}
|
||||
name]]]))
|
||||
|
||||
(defn account-selector [accounts selected-account-atom on-select]
|
||||
[react/view styles/account-selector-container
|
||||
[quo/text {:size :small} (i18n/label :t/select-account)]
|
||||
[list/flat-list {:data accounts
|
||||
:key-fn :address
|
||||
:render-fn render-account
|
||||
:render-data {:selected-account selected-account-atom
|
||||
:on-select on-select}
|
||||
:horizontal true
|
||||
:shows-horizontal-scroll-indicator false
|
||||
:extra-data @selected-account-atom
|
||||
:style styles/account-selector-list}]])
|
||||
|
||||
(defn account-picker [accounts selected-account-atom {:keys [on-press on-select]}]
|
||||
(if (> (count accounts) 1)
|
||||
[react/view {:style styles/account-selector-wrapper}
|
||||
[account-selector accounts selected-account-atom on-select]]
|
||||
[react/touchable-opacity {:style styles/single-account-container}
|
||||
[toolbar-selection {:text (:name @selected-account-atom)
|
||||
:background-color (:color @selected-account-atom)
|
||||
:on-press on-press}]]))
|
||||
|
||||
(defview success-sheet-view [{:keys [topic]}]
|
||||
(letsubs [visible-accounts [:visible-accounts-without-watch-only]
|
||||
dapps-account [:dapps-account]
|
||||
sessions [:wallet-connect/sessions]
|
||||
managed-session [:wallet-connect/session-managed]]
|
||||
(let [{:keys [peer state] :as session} (first (filter #(= (:topic %) topic) sessions))
|
||||
{:keys [accounts]} state
|
||||
{:keys [metadata]} peer
|
||||
{:keys [name icons]} metadata
|
||||
icon-uri (when (and icons (> (count icons) 0)) (first icons))
|
||||
address (last (string/split (first accounts) #":"))
|
||||
account (first (filter #(= (:address %) address) visible-accounts))
|
||||
selected-account-atom (reagent/atom account)]
|
||||
[react/view (styles/proposal-sheet-container)
|
||||
[react/view (styles/proposal-sheet-header)
|
||||
[quo/text {:weight :bold
|
||||
:size :large}
|
||||
(i18n/label :t/connection-request)]]
|
||||
[react/image {:style (styles/dapp-logo)
|
||||
:source {:uri icon-uri}}]
|
||||
[react/view styles/sheet-body-container
|
||||
[react/view styles/proposal-title-container
|
||||
[quo/text {:weight :bold
|
||||
:size :large}
|
||||
name]
|
||||
[quo/text {:weight :regular
|
||||
:size :large}
|
||||
(i18n/label :t/connected)]]]
|
||||
[account-picker
|
||||
(vector dapps-account)
|
||||
selected-account-atom
|
||||
{:on-press #(do
|
||||
(re-frame/dispatch [:wallet-connect/manage-app session])
|
||||
(reset! show-account-selector? true))}]
|
||||
[quo/text {:weight :regular
|
||||
:color :secondary
|
||||
:style styles/message-title}
|
||||
(i18n/label :t/manage-connections)]
|
||||
[react/view (styles/success-button-container)
|
||||
[quo/button
|
||||
{:theme :accent
|
||||
:on-press #(do
|
||||
(reset! show-account-selector? false)
|
||||
(re-frame/dispatch [:hide-wallet-connect-success-sheet]))}
|
||||
(i18n/label :t/close)]]
|
||||
(when managed-session
|
||||
(if platform/ios?
|
||||
[react/blur-view {:style (styles/blur-view)
|
||||
:blurAmount 2
|
||||
:blurType (if (colors/dark?) :dark :light)}]
|
||||
[react/view (styles/blur-view)]))])))
|
||||
|
||||
(defview app-management-sheet-view [{:keys [topic]}]
|
||||
(letsubs [sessions [:wallet-connect/sessions]
|
||||
visible-accounts [:visible-accounts-without-watch-only]]
|
||||
(let [{:keys [peer state]} (first (filter #(= (:topic %) topic) sessions))
|
||||
{:keys [accounts]} state
|
||||
{:keys [metadata]} peer
|
||||
{:keys [name icons url]} metadata
|
||||
icon-uri (when (and icons (> (count icons) 0)) (first icons))
|
||||
account-address (last (string/split (first accounts) #":"))
|
||||
selected-account-atom (reagent/atom (first (filter #(= (:address %) account-address) visible-accounts)))]
|
||||
[react/view {:style (merge (styles/acc-sheet) {:background-color "rgba(0,0,0,0)"})}
|
||||
[react/linear-gradient {:colors ["rgba(0,0,0,0)" "rgba(0,0,0,0.3)"]
|
||||
:start {:x 0 :y 0} :end {:x 0 :y 1}
|
||||
:style styles/shadow}]
|
||||
[react/view (styles/proposal-sheet-container)
|
||||
[react/view (styles/management-sheet-header)
|
||||
[react/image {:style styles/management-icon
|
||||
:source {:uri icon-uri}}]
|
||||
[react/view styles/app-info-container
|
||||
[quo/text {:weight :medium} name]
|
||||
[quo/text {:color :secondary
|
||||
:number-of-lines 1
|
||||
:elipsize-mode :tail} url]]
|
||||
[quo/button
|
||||
{:type :secondary
|
||||
:theme :secondary
|
||||
:on-press #(re-frame/dispatch [:wallet-connect/disconnect topic])}
|
||||
(i18n/label :t/disconnect)]]
|
||||
[account-selector
|
||||
visible-accounts
|
||||
selected-account-atom
|
||||
#(re-frame/dispatch [:wallet-connect/change-session-account topic @selected-account-atom])]]])))
|
||||
|
||||
(defview session-proposal-sheet [{:keys [name icons]}]
|
||||
(letsubs [visible-accounts [:visible-accounts-without-watch-only]
|
||||
dapps-account [:dapps-account]]
|
||||
(let [icon-uri (when (and icons (> (count icons) 0)) (first icons))
|
||||
selected-account-atom (reagent/atom dapps-account)]
|
||||
[react/view (styles/proposal-sheet-container)
|
||||
[react/view (styles/proposal-sheet-header)
|
||||
[quo/text {:weight :bold
|
||||
:size :large}
|
||||
(i18n/label :t/connection-request)]]
|
||||
[react/image {:style (styles/dapp-logo)
|
||||
:source {:uri icon-uri}}]
|
||||
[react/view styles/sheet-body-container
|
||||
[react/view styles/proposal-title-container
|
||||
[quo/text {:weight :bold
|
||||
:size :large}
|
||||
(str name " ")]
|
||||
[quo/text {:weight :regular
|
||||
:size :large}
|
||||
(i18n/label :t/wallet-connect-proposal-title)]]]
|
||||
[account-picker visible-accounts selected-account-atom]
|
||||
[react/view (merge (styles/proposal-buttons-container) (when (= (count visible-accounts) 1) {:margin-top 12}))
|
||||
[quo/button
|
||||
{:type :secondary
|
||||
:on-press #(re-frame/dispatch [:wallet-connect/reject-proposal])}
|
||||
(i18n/label :t/reject)]
|
||||
[quo/button
|
||||
{:theme :accent
|
||||
:on-press #(re-frame/dispatch [:wallet-connect/approve-proposal @selected-account-atom])}
|
||||
(i18n/label :t/connect)]]])))
|
||||
|
||||
(defview wallet-connect-proposal-sheet []
|
||||
(letsubs [proposal-metadata [:wallet-connect/proposal-metadata]]
|
||||
[bottom-panel/animated-bottom-panel
|
||||
proposal-metadata
|
||||
session-proposal-sheet
|
||||
#(re-frame/dispatch [:hide-wallet-connect-sheet])]))
|
||||
|
||||
(defview wallet-connect-success-sheet-view []
|
||||
(letsubs [session [:wallet-connect/session-connected]]
|
||||
[bottom-panel/animated-bottom-panel
|
||||
session
|
||||
success-sheet-view
|
||||
#(re-frame/dispatch [:hide-wallet-connect-success-sheet])]))
|
||||
|
||||
(defview wallet-connect-app-management-sheet-view []
|
||||
(letsubs [session [:wallet-connect/session-managed]]
|
||||
[bottom-panel/animated-bottom-panel
|
||||
session
|
||||
app-management-sheet-view
|
||||
#(re-frame/dispatch [:hide-wallet-connect-app-management-sheet])
|
||||
#(re-frame/dispatch [:hide-wallet-connect-app-management-sheet])
|
||||
false]))
|
|
@ -167,3 +167,12 @@
|
|||
"giphy.com"
|
||||
"gph.is"
|
||||
"media.giphy.com"})
|
||||
|
||||
(def default-relay-provider "https://relay.walletconnect.com")
|
||||
|
||||
(def default-wallet-connect-metadata {:name "Status Wallet"
|
||||
:description "Status is a secure messaging app, crypto wallet, and Web3 browser built with state of the art technology."
|
||||
:url "#"
|
||||
:icons ["https://statusnetwork.com/img/press-kit-status-logo.svg"]})
|
||||
|
||||
(def wallet-connect-project-id "87815d72a81d739d2a7ce15c2cfdefb3")
|
|
@ -0,0 +1,28 @@
|
|||
(ns status-im.utils.wallet-connect
|
||||
(:require ["@walletconnect/client" :refer [CLIENT_EVENTS] :default WalletConnectClient]
|
||||
["@react-native-community/async-storage" :default AsyncStorage]
|
||||
[clojure.string :as string]
|
||||
[status-im.utils.config :as config]))
|
||||
|
||||
(defn init [on-success on-error]
|
||||
(-> ^js WalletConnectClient
|
||||
(.init (clj->js {:controller true
|
||||
:projectId config/wallet-connect-project-id
|
||||
:logger "debug"
|
||||
:metadata config/default-wallet-connect-metadata
|
||||
:storageOptions {:asyncStorage ^js AsyncStorage}}))
|
||||
(.then on-success)
|
||||
(.catch on-error)))
|
||||
|
||||
(defn session-request-event [] (.-request (.-session CLIENT_EVENTS)))
|
||||
|
||||
(defn session-created-event [] (.-created (.-session CLIENT_EVENTS)))
|
||||
|
||||
(defn session-deleted-event [] (.-deleted (.-session CLIENT_EVENTS)))
|
||||
|
||||
(defn session-proposal-event [] (.-proposal (.-session CLIENT_EVENTS)))
|
||||
|
||||
(defn session-updated-event [] (.-updated (.-session CLIENT_EVENTS)))
|
||||
|
||||
(defn url? [url]
|
||||
(string/starts-with? url "wc:"))
|
|
@ -0,0 +1,273 @@
|
|||
(ns status-im.wallet-connect.core
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.signing.core :as signing]
|
||||
[status-im.utils.wallet-connect :as wallet-connect]
|
||||
[status-im.browser.core :as browser]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.async-storage.core :as async-storage]
|
||||
[status-im.utils.config :as config]
|
||||
[status-im.utils.types :as types]))
|
||||
|
||||
(fx/defn switch-wallet-connect-enabled
|
||||
{:events [:multiaccounts.ui/switch-wallet-connect-enabled]}
|
||||
[{:keys [db]} enabled?]
|
||||
(merge
|
||||
{::async-storage/set! {:wallet-connect-enabled? enabled?}
|
||||
:db (cond-> db
|
||||
(not enabled?)
|
||||
(dissoc :wallet-connect/client)
|
||||
:always
|
||||
(assoc :wallet-connect/enabled? enabled?))}
|
||||
(when enabled? {:wc-2-init nil})))
|
||||
|
||||
(fx/defn proposal-handler
|
||||
{:events [:wallet-connect/proposal]}
|
||||
[{:keys [db] :as cofx} request-event]
|
||||
(let [proposal (types/js->clj request-event)
|
||||
proposer (:proposer proposal)
|
||||
metadata (:metadata proposer)]
|
||||
{:db (assoc db :wallet-connect/proposal proposal :wallet-connect/proposal-metadata metadata)
|
||||
:show-wallet-connect-sheet nil}))
|
||||
|
||||
(fx/defn session-connected
|
||||
{:events [:wallet-connect/created]}
|
||||
[{:keys [db]} session]
|
||||
(let [session (types/js->clj session)
|
||||
client (get db :wallet-connect/client)]
|
||||
(log/debug "[wallet connect] session created - " session)
|
||||
{:show-wallet-connect-success-sheet nil
|
||||
:db (assoc db :wallet-connect/session-connected session :wallet-connect/sessions (types/js->clj (.-values (.-session client))))}))
|
||||
|
||||
(fx/defn manage-app
|
||||
{:events [:wallet-connect/manage-app]}
|
||||
[{:keys [db]} session]
|
||||
(let [session (types/js->clj session)]
|
||||
{:db (assoc db :wallet-connect/session-managed session :wallet-connect/showing-app-management-sheet? true)
|
||||
:show-wallet-connect-app-management-sheet nil}))
|
||||
|
||||
(fx/defn request-handler
|
||||
{:events [:wallet-connect/request]}
|
||||
[{:keys [db] :as cofx} request-event]
|
||||
(let [request (types/js->clj request-event)
|
||||
params (:request request)
|
||||
pending-requests (or (:wallet-connect/pending-requests db) [])
|
||||
new-pending-requests (conj pending-requests request)
|
||||
client (get db :wallet-connect/client)
|
||||
topic (:topic request)]
|
||||
{:db (assoc db :wallet-connect/pending-requests new-pending-requests)
|
||||
:dispatch [:wallet-connect/request-received request]}))
|
||||
|
||||
(fx/defn request-handler-test
|
||||
{:events [:wallet-connect/request-test]}
|
||||
[{:keys [db] :as cofx}]
|
||||
{:show-wallet-connect-sheet nil})
|
||||
|
||||
(defn subscribe-to-events [wallet-connect-client]
|
||||
(.on wallet-connect-client (wallet-connect/session-request-event) #(re-frame/dispatch [:wallet-connect/request %]))
|
||||
(.on wallet-connect-client (wallet-connect/session-created-event) #(re-frame/dispatch [:wallet-connect/created %]))
|
||||
(.on wallet-connect-client (wallet-connect/session-deleted-event) #(re-frame/dispatch [:wallet-connect/update-sessions]))
|
||||
(.on wallet-connect-client (wallet-connect/session-updated-event) #(re-frame/dispatch [:wallet-connect/update-sessions]))
|
||||
(.on wallet-connect-client (wallet-connect/session-proposal-event) #(re-frame/dispatch [:wallet-connect/proposal %])))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wc-2-init
|
||||
(fn []
|
||||
(wallet-connect/init
|
||||
#(re-frame/dispatch [:wallet-connect/client-init %])
|
||||
#(log/error "[wallet-connect]" %))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wc-2-subscribe-to-events
|
||||
(fn [client]
|
||||
(subscribe-to-events client)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wc-2-client-approve-proposal
|
||||
(fn [[client proposal response]]
|
||||
(-> ^js client
|
||||
(.approve (clj->js {:proposal proposal :response response}))
|
||||
(.then #(log/debug "[wallet-connect] session proposal approved"))
|
||||
(.catch #(log/error "[wallet-connect] session proposal approval error:" %)))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wc-2-client-reject-proposal
|
||||
(fn [[client proposal]]
|
||||
(-> ^js client
|
||||
(.reject (clj->js {:proposal proposal}))
|
||||
(.then #(log/debug "[wallet-connect] session proposal rejected"))
|
||||
(.catch #(log/error "[wallet-connect] " %)))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wc-2-client-disconnect
|
||||
(fn [[client topic]]
|
||||
(-> ^js client
|
||||
(.disconnect (clj->js {:topic topic}))
|
||||
(.then #(log/debug "[wallet-connect] session disconnected - topic " topic))
|
||||
(.catch #(log/error "[wallet-connect] " %)))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wc-2-change-session
|
||||
(fn [[client topic accounts]]
|
||||
(-> ^js client
|
||||
(.update (clj->js {:topic topic
|
||||
:state {:accounts accounts}}))
|
||||
(.then #(log/debug "[wallet-connect] session topic " topic " changed to account " (first accounts)))
|
||||
(.catch #(log/error "[wallet-connect] " %)))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wc-2-change-session
|
||||
(fn [[client topic accounts]]
|
||||
(-> ^js client
|
||||
(.update (clj->js {:topic topic
|
||||
:state {:accounts accounts}}))
|
||||
(.then #(log/debug "[wallet-connect] session topic " topic " changed to account " (first accounts)))
|
||||
(.catch #(log/error "[wallet-connect] " %)))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wc-2-pair
|
||||
(fn [[client uri]]
|
||||
(.pair client (clj->js {:uri uri}))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:wc-2-respond
|
||||
(fn [[client response]]
|
||||
(.respond client (clj->js response))))
|
||||
|
||||
(fx/defn approve-proposal
|
||||
{:events [:wallet-connect/approve-proposal]}
|
||||
[{:keys [db]} account]
|
||||
(let [client (get db :wallet-connect/client)
|
||||
proposal (get db :wallet-connect/proposal)
|
||||
topic (:topic proposal)
|
||||
permissions (:permissions proposal)
|
||||
blockchain (:blockchain permissions)
|
||||
proposal-chain-ids (map #(last (string/split % #":")) (:chains blockchain))
|
||||
available-chain-ids (map #(get-in % [:config :NetworkId]) (vals (get db :networks/networks)))
|
||||
supported-chain-ids (filter (fn [chain-id] #(boolean (some #{chain-id} available-chain-ids))) proposal-chain-ids)
|
||||
address (:address account)
|
||||
accounts (map #(str "eip155:" % ":" (ethereum/normalized-hex address)) supported-chain-ids)
|
||||
;; TODO: Check for unsupported
|
||||
metadata (get db :wallet-connect/proposal-metadata)
|
||||
response {:state {:accounts accounts}
|
||||
:metadata config/default-wallet-connect-metadata}]
|
||||
{:hide-wallet-connect-sheet nil
|
||||
:wc-2-client-approve-proposal [client proposal response]}))
|
||||
|
||||
(fx/defn reject-proposal
|
||||
{:events [:wallet-connect/reject-proposal]}
|
||||
[{:keys [db]} account]
|
||||
(let [client (get db :wallet-connect/client)
|
||||
proposal (get db :wallet-connect/proposal)]
|
||||
{:hide-wallet-connect-sheet nil
|
||||
:wc-2-client-reject-proposal client}))
|
||||
|
||||
(fx/defn change-session-account
|
||||
{:events [:wallet-connect/change-session-account]}
|
||||
[{:keys [db]} topic account]
|
||||
(let [client (get db :wallet-connect/client)
|
||||
sessions (get db :wallet-connect/sessions)
|
||||
session (first (filter #(= (:topic %) topic) sessions))
|
||||
permissions (:permissions session)
|
||||
blockchain (:blockchain permissions)
|
||||
proposal-chain-ids (map #(last (string/split % #":")) (:chains blockchain))
|
||||
address (:address account)
|
||||
available-chain-ids (map #(get-in % [:config :NetworkId]) (vals (get db :networks/networks)))
|
||||
supported-chain-ids (filter (fn [chain-id] #(boolean (some #{chain-id} available-chain-ids))) proposal-chain-ids)
|
||||
accounts (map #(str "eip155:" % ":" (ethereum/normalized-hex address)) supported-chain-ids)]
|
||||
{:db (assoc db :wallet-connect/showing-app-management-sheet? false)
|
||||
:hide-wallet-connect-app-management-sheet nil
|
||||
:wc-2-change-session [client topic accounts]}))
|
||||
|
||||
(fx/defn disconnect-session
|
||||
{:events [:wallet-connect/disconnect]}
|
||||
[{:keys [db]} topic]
|
||||
(let [client (get db :wallet-connect/client)]
|
||||
{:hide-wallet-connect-app-management-sheet nil
|
||||
:hide-wallet-connect-success-sheet nil
|
||||
:wc-2-client-disconnect [client topic]
|
||||
:db (-> db
|
||||
(assoc :wallet-connect/sessions (types/js->clj (.-values (.-session client))))
|
||||
(dissoc :wallet-connect/session-managed))}))
|
||||
|
||||
(fx/defn pair-session
|
||||
{:events [:wallet-connect/pair]}
|
||||
[{:keys [db]} {:keys [data]}]
|
||||
(let [client (get db :wallet-connect/client)
|
||||
wallet-connect-enabled? (get db :wallet-connect/enabled?)]
|
||||
(merge
|
||||
{:dispatch [:navigate-back]}
|
||||
(when wallet-connect-enabled?
|
||||
{:db (assoc db :wallet-connect/scanned-uri data)
|
||||
:wc-2-pair [client data]}))))
|
||||
|
||||
(fx/defn wallet-connect-client-initate
|
||||
{:events [:wallet-connect/client-init]}
|
||||
[{:keys [db] :as cofx} client]
|
||||
{:db (assoc db :wallet-connect/client client :wallet-connect/sessions (types/js->clj (.-values (.-session client))))
|
||||
:wc-2-subscribe-to-events client})
|
||||
|
||||
(fx/defn update-sessions
|
||||
{:events [:wallet-connect/update-sessions]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [client (get db :wallet-connect/client)]
|
||||
{:db (-> db
|
||||
(assoc :wallet-connect/sessions (types/js->clj (.-values (.-session client))))
|
||||
(dissoc :wallet-connect/session-managed))}))
|
||||
|
||||
(fx/defn wallet-connect-complete-transaction
|
||||
{:events [:wallet-connect.dapp/transaction-on-result]}
|
||||
[{:keys [db]} message-id topic result]
|
||||
(let [client (get db :wallet-connect/client)
|
||||
response {:topic topic
|
||||
:response {:jsonrpc "2.0"
|
||||
:id message-id
|
||||
:result result}}]
|
||||
{:db (assoc db :wallet-connect/response response)
|
||||
:wc-2-respond [client response]}))
|
||||
|
||||
(fx/defn wallet-connect-send-async
|
||||
[cofx {:keys [method params id] :as payload} message-id topic]
|
||||
(let [message? (browser/web3-sign-message? method)
|
||||
dapps-address (get-in cofx [:db :multiaccount :dapps-address])
|
||||
accounts (get-in cofx [:db :multiaccount/visible-accounts])
|
||||
typed? (and (not= constants/web3-personal-sign method) (not= constants/web3-eth-sign method))]
|
||||
(if (or message? (= constants/web3-send-transaction method))
|
||||
(let [[address data] (cond (and (= method constants/web3-keycard-sign-typed-data)
|
||||
(not (vector? params)))
|
||||
;; We don't use signer argument for keycard sign-typed-data
|
||||
["0x0" params]
|
||||
message? (browser/normalize-sign-message-params params typed?)
|
||||
:else [nil nil])]
|
||||
(when (or (not message?) (and address data))
|
||||
(signing/sign cofx (merge
|
||||
(if message?
|
||||
{:message {:address address
|
||||
:data data
|
||||
:v4 (= constants/web3-sign-typed-data-v4 method)
|
||||
:typed? typed?
|
||||
:pinless? (= method constants/web3-keycard-sign-typed-data)
|
||||
:from address}}
|
||||
{:tx-obj (-> params
|
||||
first
|
||||
(update :from #(or % dapps-address))
|
||||
(dissoc :gasPrice))})
|
||||
{:on-result [:wallet-connect.dapp/transaction-on-result message-id topic]
|
||||
:on-error [:wallet-connect.dapp/transaction-on-error message-id topic]}))))
|
||||
(when (#{"eth_accounts" "eth_coinbase"} method)
|
||||
(wallet-connect-complete-transaction cofx message-id topic (if (= method "eth_coinbase") dapps-address [dapps-address]))))))
|
||||
|
||||
(fx/defn wallet-connect-send-async-read-only
|
||||
[{:keys [db] :as cofx} {:keys [method] :as payload} message-id topic]
|
||||
(wallet-connect-send-async cofx payload message-id topic))
|
||||
|
||||
(fx/defn process-request
|
||||
{:events [:wallet-connect/request-received]}
|
||||
[{:keys [db] :as cofx} session-request]
|
||||
(let [pending-requests (get db :wallet-connect/pending-requests)
|
||||
{:keys [topic request]} session-request
|
||||
{:keys [id]} request]
|
||||
(wallet-connect-send-async-read-only cofx request id topic)))
|
|
@ -1738,5 +1738,15 @@
|
|||
"current-average": "Current average",
|
||||
"current-base": "Current base",
|
||||
"maximum-fee-desc": "Maximum overall price for the transaction. If the current block base fee exceeds this, your transaction will be included in a following block with a lower base fee.",
|
||||
"insufficient-balance-to-cover-fee": "not enough balance to cover transaction fee"
|
||||
"insufficient-balance-to-cover-fee": "not enough balance to cover transaction fee",
|
||||
"wallet-connect-proposal-title": "Would like to connect with your wallet",
|
||||
"wallet-connect-proposal-description": "By connecting you allow {{name}} to retrieve your account address and enable Web3",
|
||||
"wallet-connect-app-connected": "is connected",
|
||||
"wallet-connect-go-back": "Go back to your browser or dapp",
|
||||
"wallet-connect-2.0": "Wallet Connect 2.0",
|
||||
"reject": "Reject",
|
||||
"manage-connections": "Manage connections from within Application Connections",
|
||||
"wallet-manage-app-connections": "Manage app connections",
|
||||
"connection-request": "Connection Request",
|
||||
"disconnect": "Disconnect"
|
||||
}
|
||||
|
|