diff --git a/modules/react-native-status/android/src/main/java/im/status/ethereum/module/StatusModule.java b/modules/react-native-status/android/src/main/java/im/status/ethereum/module/StatusModule.java index a4baf2d207..e1461a791a 100644 --- a/modules/react-native-status/android/src/main/java/im/status/ethereum/module/StatusModule.java +++ b/modules/react-native-status/android/src/main/java/im/status/ethereum/module/StatusModule.java @@ -985,6 +985,95 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL StatusThreadPoolExecutor.getInstance().execute(runnableTask); } + @ReactMethod + public void multiformatSerializePublicKey(final String multiCodecKey, final String base58btc, final Callback callback) throws JSONException { + if (!checkAvailability()) { + callback.invoke(false); + return; + } + + Runnable runnableTask = new Runnable() { + @Override + public void run() { + String res = Statusgo.multiformatSerializePublicKey(multiCodecKey,base58btc); + callback.invoke(res); + } + }; + + StatusThreadPoolExecutor.getInstance().execute(runnableTask); + } + + @ReactMethod + public void multiformatDeserializePublicKey(final String multiCodecKey, final String base58btc, final Callback callback) throws JSONException { + if (!checkAvailability()) { + callback.invoke(false); + return; + } + + Runnable runnableTask = new Runnable() { + @Override + public void run() { + String res = Statusgo.multiformatDeserializePublicKey(multiCodecKey,base58btc); + callback.invoke(res); + } + }; + + StatusThreadPoolExecutor.getInstance().execute(runnableTask); + } + + @ReactMethod + public void compressPublicKey(final String multiCodecKey, final Callback callback) throws JSONException { + if (!checkAvailability()) { + callback.invoke(false); + return; + } + + Runnable runnableTask = new Runnable() { + @Override + public void run() { + String res = Statusgo.compressPublicKey(multiCodecKey); + callback.invoke(res); + } + }; + + StatusThreadPoolExecutor.getInstance().execute(runnableTask); + } + + @ReactMethod + public void decompressPublicKey(final String multiCodecKey, final Callback callback) throws JSONException { + if (!checkAvailability()) { + callback.invoke(false); + return; + } + + Runnable runnableTask = new Runnable() { + @Override + public void run() { + String res = Statusgo.decompressPublicKey(multiCodecKey); + callback.invoke(res); + } + }; + + StatusThreadPoolExecutor.getInstance().execute(runnableTask); + } + + @ReactMethod + public void deserializeAndCompressKey(final String desktopKey, final Callback callback) throws JSONException { + if (!checkAvailability()) { + callback.invoke(false); + return; + } + + Runnable runnableTask = new Runnable() { + @Override + public void run() { + String res = Statusgo.deserializeAndCompressKey(desktopKey); + callback.invoke(res); + } + }; + + StatusThreadPoolExecutor.getInstance().execute(runnableTask); + } @ReactMethod public void hashTypedData(final String data, final Callback callback) { diff --git a/modules/react-native-status/ios/RCTStatus/RCTStatus.m b/modules/react-native-status/ios/RCTStatus/RCTStatus.m index 51e341db77..0558e10535 100644 --- a/modules/react-native-status/ios/RCTStatus/RCTStatus.m +++ b/modules/react-native-status/ios/RCTStatus/RCTStatus.m @@ -339,6 +339,38 @@ RCT_EXPORT_METHOD(inputConnectionStringForBootstrapping:(NSString *)cs callback(@[result]); } +RCT_EXPORT_METHOD(multiformatSerializePublicKey:(NSString *)multiCodecKey + base58btc:(NSString *)base58btc + callback:(RCTResponseSenderBlock)callback) { + NSString *result = StatusgoMultiformatSerializePublicKey(multiCodecKey,base58btc); + callback(@[result]); +} + +RCT_EXPORT_METHOD(multiformatDeserializePublicKey:(NSString *)multiCodecKey + base58btc:(NSString *)base58btc + callback:(RCTResponseSenderBlock)callback) { + NSString *result = StatusgoMultiformatDeserializePublicKey(multiCodecKey,base58btc); + callback(@[result]); +} + +RCT_EXPORT_METHOD(decompressPublicKey:(NSString *)multiCodecKey + callback:(RCTResponseSenderBlock)callback) { + NSString *result = StatusgoDecompressPublicKey(multiCodecKey); + callback(@[result]); +} + +RCT_EXPORT_METHOD(compressPublicKey:(NSString *)multiCodecKey + callback:(RCTResponseSenderBlock)callback) { + NSString *result = StatusgoCompressPublicKey(multiCodecKey); + callback(@[result]); +} + +RCT_EXPORT_METHOD(deserializeAndCompressKey:(NSString *)desktopKey + callback:(RCTResponseSenderBlock)callback) { + NSString *result = StatusgoDeserializeAndCompressKey(desktopKey); + callback(@[result]); +} + RCT_EXPORT_METHOD(hashTypedData:(NSString *)data callback:(RCTResponseSenderBlock)callback) { #if DEBUG diff --git a/src/status_im/constants.cljs b/src/status_im/constants.cljs index ce751e2e81..a08a5f756f 100644 --- a/src/status_im/constants.cljs +++ b/src/status_im/constants.cljs @@ -205,9 +205,26 @@ (def ^:const community-member-role-manage-users 2) (def ^:const community-member-role-moderator 3) -(def local-pairing-connection-string-identifier +(def ^:const local-pairing-connection-string-identifier "If any string begins with cs we know its a connection string. This is useful when we read QR codes we know it is a connection string if it begins with this identifier. An example of a connection string is -> cs2:5vd6J6:Jfc:27xMmHKEYwzRGXcvTtuiLZFfXscMx4Mz8d9wEHUxDj4p7:EG7Z13QScfWBJNJ5cprszzDQ5fBVsYMirXo8MaQFJvpF:3 " "cs") +(def ^:const serialization-key + "We pass this serialization key as a parameter to MultiformatSerializePublicKey + function at status-go, This key determines the output base of the serialization. + according to https://specs.status.im/spec/2#public-key-serialization we serialize + keys with base58btc encoding" + "z") + +(def ^:const deserialization-key + "We pass this deserialization key as a parameter to MultiformatDeserializePublicKey + function at status-go, This key determines the output base of the deserialization. + according to https://specs.status.im/spec/2#public-key-serialization we deserialize + keys with base16 hexadecimal encoding" + "f") + +(def ^:const multi-code-prefix + "We prefix our keys with 0xe701 prior to serialisation them" + "0xe701") diff --git a/src/status_im/native_module/core.cljs b/src/status_im/native_module/core.cljs index a7bd2cc49a..5e76cebd4d 100644 --- a/src/status_im/native_module/core.cljs +++ b/src/status_im/native_module/core.cljs @@ -5,7 +5,8 @@ [status-im.utils.platform :as platform] [status-im.utils.react-native :as react-native-utils] [status-im.utils.types :as types] - [taoensso.timbre :as log])) + [taoensso.timbre :as log] + [status-im.constants :as constants])) (defn status [] @@ -278,6 +279,55 @@ :connection-string connection-string}) (.inputConnectionStringForBootstrapping ^js (status) connection-string config-json callback)) +(defn deserialize-and-compress-key + "Provides a community id (public key) to status-go which is first deserialized + and then compressed. Example input/output : + input key = zQ3shTAten2v9CwyQD1Kc7VXAqNPDcHZAMsfbLHCZEx6nFqk9 and + output key = 0x025596a7ff87da36860a84b0908191ce60a504afc94aac93c1abd774f182967ce6" + [key callback] + (log/info "[native-module] Deserializing and then compressing public key" + {:fn :deserialize-and-compress-key + :key key}) + (.deserializeAndCompressKey ^js (status) key callback)) + + +(defn public-key->compressed-key + "Provides public key to status-go and gets back a compressed key via serialization" + [public-key callback] + (let [serialization-key constants/serialization-key + multi-code-prefix constants/multi-code-prefix + multi-code-key (str multi-code-prefix (subs public-key 2))] + (log/info "[native-module] Serializing public key" + {:fn :public-key->compressed-key + :public-key public-key + :multi-code-key multi-code-key}) + (.multiformatSerializePublicKey ^js (status) multi-code-key serialization-key callback))) + +(defn compressed-key->public-key + "Provides compressed key to status-go and gets back the uncompressed public key via deserialization" + [public-key callback] + (let [deserialization-key constants/deserialization-key] + (log/info "[native-module] Deserializing compressed key" + {:fn :compressed-key->public-key + :public-key public-key}) + (.multiformatDeserializePublicKey ^js (status) public-key deserialization-key callback))) + +(defn decompress-public-key + "Provides compressed key to status-go and gets back the uncompressed public key" + [public-key callback] + (log/info "[native-module] Decompressing public key" + {:fn :decompress-public-key + :public-key public-key}) + (.decompressPublicKey ^js (status) public-key callback)) + +(defn compress-public-key + "Provides a public key to status-go and gets back a 33bit compressed key back" + [public-key callback] + (log/info "[native-module] Compressing public key" + {:fn :compress-public-key + :public-key public-key}) + (.compressPublicKey ^js (status) public-key callback)) + (defn hash-typed-data "used for keycard" [data callback] diff --git a/src/status_im/router/core.cljs b/src/status_im/router/core.cljs index 18965404ce..2db42f8fe4 100644 --- a/src/status_im/router/core.cljs +++ b/src/status_im/router/core.cljs @@ -199,6 +199,12 @@ {:type :wallet-account :account (when account (string/lower-case account))}) +(defn community-route-type + [route-params] + (if (string/starts-with? (:community-id route-params) "z") + :desktop-community + :community)) + (defn handle-uri [chain chats uri cb] (let [{:keys [handler route-params query-params]} (match-uri uri)] @@ -229,7 +235,8 @@ (cb {:type handler :community-id (:community-id route-params)}) (= handler :community) - (cb {:type handler :community-id (:community-id route-params)}) + (cb {:type (community-route-type route-params) + :community-id (:community-id route-params)}) (= handler :community-chat) (cb {:type handler :chat-id (:chat-id route-params)}) diff --git a/src/status_im/utils/universal_links/core.cljs b/src/status_im/utils/universal_links/core.cljs index b666523c05..5df16ea621 100644 --- a/src/status_im/utils/universal_links/core.cljs +++ b/src/status_im/utils/universal_links/core.cljs @@ -14,7 +14,8 @@ [utils.re-frame :as rf] [status-im.wallet.choose-recipient.core :as choose-recipient] [status-im2.navigation.events :as navigation] - [taoensso.timbre :as log])) + [taoensso.timbre :as log] + [status-im.native-module.core :as status])) ;; TODO(yenda) investigate why `handle-universal-link` event is ;; dispatched 7 times for the same link @@ -76,7 +77,21 @@ (rf/defn handle-community [cofx {:keys [community-id]}] (log/info "universal-links: handling community" community-id) - (navigation/navigate-to-cofx cofx :community {:community-id community-id})) + (navigation/navigate-to-cofx cofx :community {:community-id community-id}) +) + +(rf/defn handle-navigation-to-desktop-community-from-mobile + {:events [:handle-navigation-to-desktop-community-from-mobile]} + [{:keys [db]} cofx deserialized-key] + (navigation/navigate-to-cofx cofx :community {:community-id deserialized-key}) +) + +(rf/defn handle-desktop-community + [cofx {:keys [community-id]}] + (status/deserialize-and-compress-key + community-id + (fn [deserialized-key] + (rf/dispatch [:handle-navigation-to-desktop-community-from-mobile cofx (str deserialized-key)])))) (rf/defn handle-community-chat [cofx {:keys [chat-id]}] @@ -145,6 +160,7 @@ :private-chat (handle-private-chat cofx data) :community-requests (handle-community-requests cofx data) :community (handle-community cofx data) + :desktop-community (handle-desktop-community cofx data) :community-chat (handle-community-chat cofx data) :contact (handle-view-profile cofx data) :browser (handle-browse cofx data) diff --git a/status-go-version.json b/status-go-version.json index 9c9fd7fb22..938093d16c 100644 --- a/status-go-version.json +++ b/status-go-version.json @@ -3,7 +3,7 @@ "_comment": "Instead use: scripts/update-status-go.sh ", "owner": "status-im", "repo": "status-go", - "version": "v0.117.1a", - "commit-sha1": "b4bdfd3df6cf5fb91ab2d0e9f3b38e8d1b9703e5", - "src-sha256": "1s50q53p1j5ysnbj88c52zb2rh1ms21pnf6bjc7wja8gzcpih2wl" + "version": "d43e06f4c27a900641cd55c2a46002e6f0909c95", + "commit-sha1": "d43e06f4c27a900641cd55c2a46002e6f0909c95", + "src-sha256": "18n5h3yx6wxb5l1nvra868dhnyl732zvpdn3mqg4zfsjxmx82np7" }