Implement Wallet Connect 2.0

Signed-off-by: Brian Sztamfater <brian@status.im>
This commit is contained in:
Brian Sztamfater 2021-11-15 01:42:11 -03:00
parent ece2605cb9
commit bd7da02c25
No known key found for this signature in database
GPG Key ID: 59EB921E0706B48F
37 changed files with 1752 additions and 70 deletions

View File

@ -1 +1,2 @@
import "node-libs-react-native/globals";
import "./app/index.js"; import "./app/index.js";

View File

@ -208,6 +208,8 @@ PODS:
- React - React
- react-native-blob-util (0.13.18): - react-native-blob-util (0.13.18):
- React-Core - React-Core
- react-native-blur (0.8.0):
- React
- react-native-camera-kit (8.0.4): - react-native-camera-kit (8.0.4):
- React - React
- react-native-cameraroll (4.0.4): - react-native-cameraroll (4.0.4):
@ -224,6 +226,8 @@ PODS:
- React - React
- react-native-notifications (4.1.3): - react-native-notifications (4.1.3):
- React-Core - React-Core
- react-native-randombytes (3.6.1):
- React-Core
- react-native-safe-area-context (2.0.0): - react-native-safe-area-context (2.0.0):
- React - React
- react-native-shake (3.4.0): - react-native-shake (3.4.0):
@ -422,6 +426,7 @@ DEPENDENCIES:
- React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`) - React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
- react-native-background-timer (from `../node_modules/react-native-background-timer`) - react-native-background-timer (from `../node_modules/react-native-background-timer`)
- react-native-blob-util (from `../node_modules/react-native-blob-util`) - 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-camera-kit (from `../node_modules/react-native-camera-kit`)
- "react-native-cameraroll (from `../node_modules/@react-native-community/cameraroll`)" - "react-native-cameraroll (from `../node_modules/@react-native-community/cameraroll`)"
- react-native-config (from `../node_modules/react-native-config`) - 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-mail (from `../node_modules/react-native-mail`)
- "react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)" - "react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)"
- react-native-notifications (from `../node_modules/react-native-notifications`) - 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-safe-area-context (from `../node_modules/react-native-safe-area-context`)
- react-native-shake (from `../node_modules/react-native-shake`) - react-native-shake (from `../node_modules/react-native-shake`)
- "react-native-slider (from `../node_modules/@react-native-community/slider`)" - "react-native-slider (from `../node_modules/@react-native-community/slider`)"
@ -525,6 +531,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-background-timer" :path: "../node_modules/react-native-background-timer"
react-native-blob-util: react-native-blob-util:
:path: "../node_modules/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: react-native-camera-kit:
:path: "../node_modules/react-native-camera-kit" :path: "../node_modules/react-native-camera-kit"
react-native-cameraroll: react-native-cameraroll:
@ -539,6 +547,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/@react-native-community/netinfo" :path: "../node_modules/@react-native-community/netinfo"
react-native-notifications: react-native-notifications:
:path: "../node_modules/react-native-notifications" :path: "../node_modules/react-native-notifications"
react-native-randombytes:
:path: "../node_modules/react-native-randombytes"
react-native-safe-area-context: react-native-safe-area-context:
:path: "../node_modules/react-native-safe-area-context" :path: "../node_modules/react-native-safe-area-context"
react-native-shake: react-native-shake:
@ -653,6 +663,7 @@ SPEC CHECKSUMS:
React-jsinspector: 58aef7155bc9a9683f5b60b35eccea8722a4f53a React-jsinspector: 58aef7155bc9a9683f5b60b35eccea8722a4f53a
react-native-background-timer: 1f7d560647b40e6a60b01c452ba29c54bf581fc4 react-native-background-timer: 1f7d560647b40e6a60b01c452ba29c54bf581fc4
react-native-blob-util: 600972b1782380a5a7d5db61a3817ea32349dae9 react-native-blob-util: 600972b1782380a5a7d5db61a3817ea32349dae9
react-native-blur: cad4d93b364f91e7b7931b3fa935455487e5c33c
react-native-camera-kit: 498a6d111a904834e0824e9073cfadef7303235f react-native-camera-kit: 498a6d111a904834e0824e9073cfadef7303235f
react-native-cameraroll: 88f4e62d9ecd0e1f253abe4f685474f2ea14bfa2 react-native-cameraroll: 88f4e62d9ecd0e1f253abe4f685474f2ea14bfa2
react-native-config: c98128a72bc2c3a1ca72caec0b021f0fa944aa29 react-native-config: c98128a72bc2c3a1ca72caec0b021f0fa944aa29
@ -660,6 +671,7 @@ SPEC CHECKSUMS:
react-native-mail: 8fdcd3aef007c33a6877a18eb4cf7447a1d4ce4a react-native-mail: 8fdcd3aef007c33a6877a18eb4cf7447a1d4ce4a
react-native-netinfo: ddaca8bbb9e6e914b1a23787ccb879bc642931c9 react-native-netinfo: ddaca8bbb9e6e914b1a23787ccb879bc642931c9
react-native-notifications: 805108822ceff3440644d5701944f0cda35f5b4b react-native-notifications: 805108822ceff3440644d5701944f0cda35f5b4b
react-native-randombytes: 421f1c7d48c0af8dbcd471b0324393ebf8fe7846
react-native-safe-area-context: 60f654e00b6cc416573f6d5dbfce3839958eb57a react-native-safe-area-context: 60f654e00b6cc416573f6d5dbfce3839958eb57a
react-native-shake: de052eaa3eadc4a326b8ddd7ac80c06e8d84528c react-native-shake: de052eaa3eadc4a326b8ddd7ac80c06e8d84528c
react-native-slider: 12bd76d3d568c9c5500825db54123d44b48e4ad4 react-native-slider: 12bd76d3d568c9c5500825db54123d44b48e4ad4

View File

@ -13,4 +13,7 @@ module.exports = {
}, },
}), }),
}, },
resolver: {
extraNodeModules: require('node-libs-react-native'),
},
}; };

View File

@ -13,6 +13,7 @@
"dependencies": { "dependencies": {
"@react-native-community/async-storage": "^1.11.0", "@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/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/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/clipboard": "^1.2.2",
"@react-native-community/hooks": "^2.5.1", "@react-native-community/hooks": "^2.5.1",
@ -20,6 +21,7 @@
"@react-native-community/netinfo": "^4.4.0", "@react-native-community/netinfo": "^4.4.0",
"@react-native-community/push-notification-ios": "^1.4.1", "@react-native-community/push-notification-ios": "^1.4.1",
"@react-native-community/slider": "^3.0.0", "@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", "bignumber.js": "git+https://github.com/status-im/bignumber.js.git#v4.0.2-status",
"buffer": "^5.4.2", "buffer": "^5.4.2",
"chance": "^1.1.0", "chance": "^1.1.0",
@ -30,6 +32,7 @@
"hermes-engine": "0.5.2-rc1", "hermes-engine": "0.5.2-rc1",
"hi-base32": "^0.5.0", "hi-base32": "^0.5.0",
"i18n-js": "^3.3.0", "i18n-js": "^3.3.0",
"node-libs-react-native": "^1.2.1",
"qrcode": "^1.4.1", "qrcode": "^1.4.1",
"react": "16.13.1", "react": "16.13.1",
"react-dom": "^16.4.2", "react-dom": "^16.4.2",
@ -56,6 +59,7 @@
"react-native-navigation": "^7.13.0", "react-native-navigation": "^7.13.0",
"react-native-notifications": "^4.1.3", "react-native-notifications": "^4.1.3",
"react-native-permissions": "^2.1.5", "react-native-permissions": "^2.1.5",
"react-native-randombytes": "^3.6.1",
"react-native-reanimated": "^2.1.0", "react-native-reanimated": "^2.1.0",
"react-native-redash": "^16.0.11", "react-native-redash": "^16.0.11",
"react-native-safe-area-context": "^2.0.0", "react-native-safe-area-context": "^2.0.0",

View File

@ -22,5 +22,10 @@ module.exports = {
ios: null, ios: null,
}, },
}, },
'@react-native-community/blur': {
platforms: {
android: null,
},
},
}, },
}; };

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 539 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 338 B

After

Width:  |  Height:  |  Size: 249 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 467 B

After

Width:  |  Height:  |  Size: 323 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 467 B

View File

@ -213,6 +213,16 @@
(def react-native-notifications (def react-native-notifications
#js {:Notifications #js {}}) #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 ;; Update i18n_resources.cljs
(defn mock [module] (defn mock [module]
(case module (case module
@ -243,12 +253,14 @@
"react-native-linear-gradient" react-native-gradien "react-native-linear-gradient" react-native-gradien
"react-native-navigation" react-native-navigation "react-native-navigation" react-native-navigation
"@react-native-community/push-notification-ios" push-notification-ios "@react-native-community/push-notification-ios" push-notification-ios
"@react-native-community/blur" react-native-blur
"react-native-camera-kit" react-native-camera-kit "react-native-camera-kit" react-native-camera-kit
"rn-emoji-keyboard" rn-emoji-keyboard "rn-emoji-keyboard" rn-emoji-keyboard
"react-native-notifications" react-native-notifications "react-native-notifications" react-native-notifications
"react-native-draggable-flatlist" react-native-draggable-flatlist "react-native-draggable-flatlist" react-native-draggable-flatlist
"./fleets.js" default-fleets "./fleets.js" default-fleets
"./chats.js" default-chats "./chats.js" default-chats
"@walletconnect/client" wallet-connect-client
"../translations/ar.json" (js/JSON.parse (slurp "./translations/ar.json")) "../translations/ar.json" (js/JSON.parse (slurp "./translations/ar.json"))
"../translations/de.json" (js/JSON.parse (slurp "./translations/de.json")) "../translations/de.json" (js/JSON.parse (slurp "./translations/de.json"))
"../translations/en.json" (js/JSON.parse (slurp "./translations/en.json")) "../translations/en.json" (js/JSON.parse (slurp "./translations/en.json"))

View File

@ -57,6 +57,8 @@
(defn pressable-hooks [props] (defn pressable-hooks [props]
(let [{background-color :bgColor (let [{background-color :bgColor
border-radius :borderRadius border-radius :borderRadius
border-color :borderColor
border-width :borderWidth
type :type type :type
disabled :disabled disabled :disabled
on-press :onPress on-press :onPress
@ -121,7 +123,9 @@
[animated/view {:style (merge absolute-fill [animated/view {:style (merge absolute-fill
background background
{:background-color background-color {: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}] (into [animated/view {:style foreground}]
(react/get-children children))]]]]))) (react/get-children children))]]]])))

View File

@ -28,27 +28,31 @@
(defn themes [theme] (defn themes [theme]
(case theme (case theme
:main {:icon-color (:icon-04 @colors/theme) :main {:icon-color (:icon-04 @colors/theme)
:background-color (:interactive-02 @colors/theme) :background-color (:interactive-02 @colors/theme)
:text-color (:text-04 @colors/theme)} :text-color (:text-04 @colors/theme)}
:icon {:icon-color (:icon-01 @colors/theme) :icon {:icon-color (:icon-01 @colors/theme)
:background-color (:interactive-02 @colors/theme) :background-color (:interactive-02 @colors/theme)
:text-color (:text-01 @colors/theme)} :text-color (:text-01 @colors/theme)}
:negative {:icon-color (:negative-01 @colors/theme) :negative {:icon-color (:negative-01 @colors/theme)
:background-color (:negative-02 @colors/theme) :background-color (:negative-02 @colors/theme)
:text-color (:negative-01 @colors/theme)} :text-color (:negative-01 @colors/theme)}
:positive {:icon-color (:positive-01 @colors/theme) :positive {:icon-color (:positive-01 @colors/theme)
:background-color (:positive-02 @colors/theme) :background-color (:positive-02 @colors/theme)
:text-color (:positive-01 @colors/theme)} :text-color (:positive-01 @colors/theme)}
:accent {:icon-color (:icon-05 @colors/theme) :accent {:icon-color (:icon-05 @colors/theme)
:background-color (:interactive-01 @colors/theme) :background-color (:interactive-01 @colors/theme)
:text-color (:text-05 @colors/theme)} :text-color (:text-05 @colors/theme)}
:secondary {:icon-color (:icon-02 @colors/theme) :secondary {:icon-color (:icon-02 @colors/theme)
:background-color (:interactive-02 @colors/theme) :background-color (:interactive-02 @colors/theme)
:text-color (:text-02 @colors/theme)} :text-color (:text-02 @colors/theme)}
:disabled {:icon-color (:icon-02 @colors/theme) :disabled {:icon-color (:icon-02 @colors/theme)
:background-color (:ui-01 @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 (defn button [{:keys [on-press disabled type theme before after
haptic-feedback haptic-type on-long-press on-press-start haptic-feedback haptic-type on-long-press on-press-start
@ -62,7 +66,7 @@
(let [theme' (cond (let [theme' (cond
disabled :disabled disabled :disabled
:else theme) :else theme)
{:keys [icon-color background-color text-color]} {:keys [icon-color background-color text-color border-color]}
(themes theme') (themes theme')
optional-haptic (fn [] optional-haptic (fn []
@ -73,6 +77,9 @@
:type type :type type
:disabled disabled :disabled disabled
:accessibility-label accessibility-label} :accessibility-label accessibility-label}
(when border-color
{:border-color border-color
:border-width 1})
(when on-press (when on-press
{:on-press (fn [] {:on-press (fn []
(optional-haptic) (optional-haptic)

View File

@ -20,6 +20,7 @@
(def light-theme (def light-theme
{:positive-01 "rgba(68,208,88,1)" ; Primary Positive, text, icons color {: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-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-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 :negative-02 "rgba(255,45,85,0.1))" ; Secondary Negative, Supporting color for errors illustrations
:warning-01 "rgba(255, 202, 15, 1)" :warning-01 "rgba(255, 202, 15, 1)"
@ -46,11 +47,13 @@
:backdrop "rgba(0,0,0,0.4)" ; Backdrop for modals and bottom sheet :backdrop "rgba(0,0,0,0.4)" ; Backdrop for modals and bottom sheet
:border-01 "rgba(238,242,245,1)" :border-01 "rgba(238,242,245,1)"
:border-02 "rgba(67, 96, 223, 0.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 (def dark-theme
{:positive-01 "rgba(68,208,88,1)" {:positive-01 "rgba(68,208,88,1)"
:positive-02 "rgba(78,188,96,0.1)" :positive-02 "rgba(78,188,96,0.1)"
:positive-03 "rgba(78,188,96,1)"
:negative-01 "rgba(252,95,95,1)" :negative-01 "rgba(252,95,95,1)"
:negative-02 "rgba(252,95,95,0.1)" :negative-02 "rgba(252,95,95,0.1)"
:warning-01 "rgba(255, 202, 15, 1)" :warning-01 "rgba(255, 202, 15, 1)"
@ -77,7 +80,8 @@
:backdrop "rgba(0,0,0,0.4)" :backdrop "rgba(0,0,0,0.4)"
:border-01 "rgba(37,37,40,1)" :border-01 "rgba(37,37,40,1)"
:border-02 "rgba(97,119,229,0.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)) (def theme (reagent/atom light-theme))

View File

@ -61,7 +61,8 @@
status-im.wallet.custom-tokens.core status-im.wallet.custom-tokens.core
[status-im.navigation.core :as navigation.core] [status-im.navigation.core :as navigation.core]
[status-im.multiaccounts.login.core :as login.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 (re-frame/reg-fx
:dismiss-keyboard :dismiss-keyboard

View File

@ -42,7 +42,8 @@
[status-im.ui.components.react :as react] [status-im.ui.components.react :as react]
[status-im.utils.platform :as platform] [status-im.utils.platform :as platform]
[status-im.ethereum.tokens :as tokens] [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 (re-frame/reg-fx
::initialize-communities-enabled ::initialize-communities-enabled
@ -82,6 +83,20 @@
(fn [] (fn []
(status/start-local-notifications))) (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] (defn rpc->accounts [accounts]
(reduce (fn [acc {:keys [chat type wallet] :as account}] (reduce (fn [acc {:keys [chat type wallet] :as account}]
(if chat (if chat
@ -343,6 +358,10 @@
[cofx] [cofx]
{::initialize-transactions-management-enabled nil}) {::initialize-transactions-management-enabled nil})
(fx/defn initialize-wallet-connect
[cofx]
{::initialize-wallet-connect nil})
(fx/defn get-node-config-callback (fx/defn get-node-config-callback
{:events [::get-node-config-callback]} {:events [::get-node-config-callback]}
[{:keys [db] :as cofx} node-config-json] [{:keys [db] :as cofx} node-config-json]
@ -377,6 +396,7 @@
(acquisition/login) (acquisition/login)
(initialize-appearance) (initialize-appearance)
(initialize-communities-enabled) (initialize-communities-enabled)
(initialize-wallet-connect)
(get-node-config) (get-node-config)
(communities/fetch) (communities/fetch)
(logging/set-log-level (:log-level multiaccount)) (logging/set-log-level (:log-level multiaccount))

View File

@ -86,3 +86,20 @@
[_] [_]
{:hide-select-acc-sheet nil}) {: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})

View File

@ -159,7 +159,7 @@
(.events Navigation) (.events Navigation)
(fn [^js evn] (fn [^js evn]
(let [view-id (keyword (.-componentName 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)) (.-componentName evn))
(re-frame/dispatch [::view-disappeared view-id]) (re-frame/dispatch [::view-disappeared view-id])
(doseq [[_ {:keys [ref value]}] @quo.text-input/text-input-refs] (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 :show-bottom-sheet (fn [] (show-overlay "bottom-sheet")))
(re-frame/reg-fx :hide-bottom-sheet (fn [] (dissmiss-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 ;; SIGNING
(defonce signing-sheet-reg (defonce signing-sheet-reg

View File

@ -78,16 +78,20 @@
(navigation/change-tab :wallet) (navigation/change-tab :wallet)
(navigation/pop-to-root-tab :wallet-stack))) (navigation/pop-to-root-tab :wallet-stack)))
(fx/defn handle-wallet-connect [cofx data]
{:dispatch [:wallet-connect/pair data]})
(fx/defn match-scan (fx/defn match-scan
{:events [::match-scanned-value]} {:events [::match-scanned-value]}
[cofx {:keys [type] :as data}] [cofx {:keys [type] :as data}]
(case type (case type
:public-chat (handle-public-chat cofx data) :public-chat (handle-public-chat cofx data)
:group-chat (handle-group-chat cofx data) :group-chat (handle-group-chat cofx data)
:private-chat (handle-private-chat cofx data) :private-chat (handle-private-chat cofx data)
:contact (handle-view-profile cofx data) :contact (handle-view-profile cofx data)
:browser (handle-browse cofx data) :browser (handle-browse cofx data)
:eip681 (handle-eip681 cofx data) :eip681 (handle-eip681 cofx data)
:wallet-connect (handle-wallet-connect cofx data)
{:dispatch [:navigate-back] {:dispatch [:navigate-back]
:utils/show-popup {:title (i18n/label :t/unable-to-read-this-code) :utils/show-popup {:title (i18n/label :t/unable-to-read-this-code)
:on-dismiss #(re-frame/dispatch [:pop-to-root-tab :chat-stack])}})) :on-dismiss #(re-frame/dispatch [:pop-to-root-tab :chat-stack])}}))

View File

@ -12,12 +12,15 @@
[status-im.utils.db :as utils.db] [status-im.utils.db :as utils.db]
[status-im.utils.http :as http] [status-im.utils.http :as http]
[status-im.chat.models :as chat.models] [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 ethereum-scheme "ethereum:")
(def uri-schemes ["status-im://" "status-im:"]) (def uri-schemes ["status-im://" "status-im:"])
(def wallet-connect-scheme "wc:")
(def web-prefixes ["https://" "http://" "https://www." "http://wwww."]) (def web-prefixes ["https://" "http://" "https://www." "http://wwww."])
(def web2-domain "join.status.im") (def web2-domain "join.status.im")
@ -226,6 +229,9 @@
(http/url? uri) (http/url? uri)
(cb (match-browser-string uri)) (cb (match-browser-string uri))
(wallet-connect/url? uri)
(cb {:type :wallet-connect :data uri})
:else :else
(cb {:type :undefined (cb {:type :undefined
:data uri})))) :data uri}))))

View File

@ -268,6 +268,14 @@
(reg-root-key-sub :backup/performing-backup :backup/performing-backup) (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 (re-frame/reg-sub
:communities :communities
:<- [:raw-communities] :<- [:raw-communities]
@ -640,9 +648,11 @@
:bottom-sheet :bottom-sheet
:<- [:bottom-sheet/show?] :<- [:bottom-sheet/show?]
:<- [:bottom-sheet/view] :<- [:bottom-sheet/view]
(fn [[show? view]] :<- [:bottom-sheet/options]
(fn [[show? view options]]
{:show? show? {:show? show?
:view view})) :view view
:options options}))
(re-frame/reg-sub (re-frame/reg-sub
:is-contact-selected? :is-contact-selected?

View File

@ -43,7 +43,7 @@
:duration 500 :duration 500
:useNativeDriver true})]))) :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) (let [bottom-anim-value (anim/create-value window-height)
alpha-value (anim/create-value 0) alpha-value (anim/create-value 0)
clear-timeout (atom nil) clear-timeout (atom nil)
@ -97,8 +97,12 @@
:ignore-offset true} :ignore-offset true}
[react/view {:flex 1} [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}]) [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 [react/animated-view {:style {:position :absolute
:transform [{:translateY bottom-anim-value}] :transform [{:translateY bottom-anim-value}]
:bottom 0 :left 0 :right 0}} :bottom 0 :left 0 :right 0}}
@ -108,6 +112,6 @@
#(do (on-close) #(do (on-close)
nil)))}))) 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]] (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)]))

View File

@ -13,7 +13,8 @@
["@react-native-community/clipboard" :default Clipboard] ["@react-native-community/clipboard" :default Clipboard]
["react-native-linear-gradient" :default LinearGradient] ["react-native-linear-gradient" :default LinearGradient]
["react-native-navigation" :refer (Navigation)] ["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])) (:require-macros [status-im.utils.views :as views]))
(def native-modules (.-NativeModules react-native)) (def native-modules (.-NativeModules react-native))
@ -39,6 +40,8 @@
(def linear-gradient (reagent/adapt-react-class LinearGradient)) (def linear-gradient (reagent/adapt-react-class LinearGradient))
(def blur-view (reagent/adapt-react-class (.-BlurView blur)))
(defn valid-source? [source] (defn valid-source? [source]
(or (not (map? source)) (or (not (map? source))
(not (contains? source :uri)) (not (contains? source :uri))

View File

@ -13,7 +13,8 @@
transactions-management-enabled? transactions-management-enabled?
wakuv2-flag wakuv2-flag
current-fleet current-fleet
webview-debug]}] webview-debug
wallet-connect-enabled?]}]
(keep (keep
identity identity
[{:size :small [{:size :small
@ -112,7 +113,16 @@
#(re-frame/dispatch #(re-frame/dispatch
[:multiaccounts.ui/waku-bloom-filter-mode-switched (not waku-bloom-filter-mode)]) [:multiaccounts.ui/waku-bloom-filter-mode-switched (not waku-bloom-filter-mode)])
:accessory :switch :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] (defn- flat-list-data [options]
(normal-mode-settings-data options)) (normal-mode-settings-data options))
@ -130,7 +140,8 @@
communities-enabled? [:communities/enabled?] communities-enabled? [:communities/enabled?]
transactions-management-enabled? [:wallet/transactions-management-enabled?] transactions-management-enabled? [:wallet/transactions-management-enabled?]
current-log-level [:log-level/current-log-level] 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 [list/flat-list
{:data (flat-list-data {:data (flat-list-data
{:network-name network-name {:network-name network-name
@ -141,6 +152,7 @@
:dev-mode? false :dev-mode? false
:wakuv2-flag wakuv2-flag :wakuv2-flag wakuv2-flag
:waku-bloom-filter-mode waku-bloom-filter-mode :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)) :key-fn (fn [_ i] (str i))
:render-fn render-item}])) :render-fn render-item}]))

View File

@ -9,7 +9,7 @@
[quo.core :as quo])) [quo.core :as quo]))
(defn bottom-sheet [] (defn bottom-sheet []
(let [{:keys [show? view]} @(re-frame/subscribe [:bottom-sheet]) (let [{:keys [show? view options]} @(re-frame/subscribe [:bottom-sheet])
{:keys [content] {:keys [content]
:as opts} :as opts}
(cond-> {:visible? show? (cond-> {:visible? show?
@ -40,4 +40,4 @@
(merge key-storage/migrate-account-password))] (merge key-storage/migrate-account-password))]
[quo/bottom-sheet opts [quo/bottom-sheet opts
(when content (when content
[content])])) [content (when options options)])]))

View File

@ -71,7 +71,7 @@
:size :small} :size :small}
name] name]
[icons/icon [icons/icon
:main-icons/chevron-down :main-icons/chevron-right
{:color colors/gray {:color colors/gray
:width 16 :width 16
:height 22}]]) :height 22}]])

View File

@ -13,7 +13,8 @@
[quo.design-system.colors :as colors] [quo.design-system.colors :as colors]
[status-im.utils.config :as config] [status-im.utils.config :as config]
[status-im.keycard.test-menu :as keycard.test-menu] [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 [] (defn get-screens []
(reduce (reduce
@ -112,7 +113,7 @@
(def signing-comp (def signing-comp
(reagent/reactify-component (reagent/reactify-component
(fn [] (fn []
^{:key (str "signing-seet" @reloader/cnt)} ^{:key (str "signing-sheet" @reloader/cnt)}
[react/safe-area-provider [react/safe-area-provider
[inactive] [inactive]
[signing/signing] [signing/signing]
@ -128,3 +129,33 @@
[wallet.send.views/select-account] [wallet.send.views/select-account]
(when js/goog.DEBUG (when js/goog.DEBUG
[reloader/reload-view])]))) [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])])))

View File

@ -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})

View File

@ -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]))

View File

@ -167,3 +167,12 @@
"giphy.com" "giphy.com"
"gph.is" "gph.is"
"media.giphy.com"}) "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")

View File

@ -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:"))

View File

@ -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)))

View File

@ -1738,5 +1738,15 @@
"current-average": "Current average", "current-average": "Current average",
"current-base": "Current base", "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.", "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"
} }

862
yarn.lock

File diff suppressed because it is too large Load Diff