Skip to content

Commit

Permalink
[#20035] feat: import missing key pair by scanning QR code
Browse files Browse the repository at this point in the history
  • Loading branch information
mohsen-ghafouri committed May 22, 2024
1 parent 60ef4fa commit 45c446e
Show file tree
Hide file tree
Showing 11 changed files with 160 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,16 @@ class NetworkManager(private val reactContext: ReactApplicationContext) : ReactC
callback)
}

@ReactMethod
fun inputConnectionStringForImportingKeypairsKeystores(connectionString: String, configJSON: String, callback: Callback) {
val jsonConfig = JSONObject(configJSON)
val receiverConfig = jsonConfig.getJSONObject("receiverConfig")
val keyStorePath = utils.pathCombine(utils.getNoBackupDirectory(), "/keystore")
receiverConfig.put("keystorePath", keyStorePath)

utils.executeRunnableStatusGoMethod(
{ Statusgo.inputConnectionStringForImportingKeypairsKeystores(connectionString, jsonConfig.toString()) },
callback
)
}
}
19 changes: 19 additions & 0 deletions modules/react-native-status/ios/RCTStatus/NetworkManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -124,4 +124,23 @@ @implementation NetworkManager
callback(@[result]);
}

RCT_EXPORT_METHOD(inputConnectionStringForImportingKeypairsKeystores:(NSString *)cs
configJSON:(NSString *)configJSON
callback:(RCTResponseSenderBlock)callback) {

NSData *configData = [configJSON dataUsingEncoding:NSUTF8StringEncoding];
NSError *error;
NSMutableDictionary *configDict = [NSJSONSerialization JSONObjectWithData:configData options:NSJSONReadingMutableContainers error:&error];
NSMutableDictionary *receiverConfig = configDict[@"receiverConfig"];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *rootUrl =[[fileManager URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask] lastObject];
NSURL *multiaccountKeystoreDir = [rootUrl URLByAppendingPathComponent:@"keystore"];
NSString *keystoreDir = multiaccountKeystoreDir.path;

[receiverConfig setValue:keystoreDir forKey:@"keystorePath"];
NSString *modifiedConfigJSON = [Utils jsonStringWithPrettyPrint:NO fromDictionary:configDict];
NSString *result = StatusgoInputConnectionStringForImportingKeypairsKeystores(cs, modifiedConfigJSON);
callback(@[result]);
}

@end
12 changes: 12 additions & 0 deletions src/native_module/core.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -609,3 +609,15 @@
{:fn :get-connection-string-for-exporting-keypairs-keystores
:config-json config-json})
(.getConnectionStringForExportingKeypairsKeystores ^js (network) config-json callback))

(defn input-connection-string-for-importing-keypairs-keystores
"Provides connection string to status-go for the purpose of importing keypairs and keystores on the receiver side"
[connection-string config-json callback]
(log/info "[native-module] Sending Import Keypairs Connection String"
{:fn :input-connection-string-for-importing-keypairs-keystores
:config-json config-json
:connection-string connection-string})
(.inputConnectionStringForImportingKeypairsKeystores ^js (network)
connection-string
config-json
callback))
8 changes: 7 additions & 1 deletion src/quo/components/wallet/missing_keypairs/style.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@
{:top 1})

(def title-info-container
{:padding-left 8})
{:padding-left 8
:flex 1})

(def title-row
{:display :flex
:flex-direction :row
:justify-content :space-between})

(def title-container
{:align-items :flex-start
Expand Down
20 changes: 14 additions & 6 deletions src/quo/components/wallet/missing_keypairs/view.cljs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
(ns quo.components.wallet.missing-keypairs.view
(:require
[quo.components.buttons.button.view :as button]
[quo.components.icon :as icon]
[quo.components.list-items.missing-keypair.view :as missing-keypair]
[quo.components.markdown.text :as text]
Expand All @@ -10,7 +11,7 @@
[utils.i18n :as i18n]))

(defn title-view
[{:keys [keypairs blur?]}]
[{:keys [keypairs blur? on-import-click]}]
(let [theme (quo.theme/use-theme)]
[rn/view
{:accessibility-label :title
Expand All @@ -22,11 +23,18 @@
:color colors/warning-60}]]
[rn/view
{:style style/title-info-container}
[text/text
{:weight :medium
:style {:color colors/warning-60}}
(i18n/label :t/amount-missing-keypairs
{:amount (str (count keypairs))})]
[rn/view {:style style/title-row}
[text/text
{:weight :medium
:style {:color colors/warning-60}}
(i18n/label :t/amount-missing-keypairs
{:amount (str (count keypairs))})]
[button/button
{:type :outline
:background :blur
:size 24
:on-press on-import-click}
(i18n/label :t/import)]]
[text/text
{:size :paragraph-2
:style (style/subtitle blur? theme)}
Expand Down
32 changes: 32 additions & 0 deletions src/status_im/contexts/settings/wallet/events.cljs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
(ns status-im.contexts.settings.wallet.events
(:require
[native-module.core :as native-module]
[status-im.contexts.syncing.events :as syncing-events]
[status-im.contexts.syncing.utils :as sync-utils]
[taoensso.timbre :as log]
[utils.i18n :as i18n]
Expand Down Expand Up @@ -53,3 +54,34 @@
handle-connection)))

(rf/reg-event-fx :wallet/get-key-pair-export-connection get-key-pair-export-connection)


(defn- input-connection-string-for-importing-keypairs-keystores-callback
[res]
(log/info "[local-pairing] input-connection-string-for-importing-keypairs-keystores callback"
{:response res
:event :settings/input-connection-string-for-importing-keypairs-keystores-callback})
(let [error (when (syncing-events/extract-error res)
(str "generic-error: " res))]
(when (some? error)
(rf/dispatch [:toasts/upsert
{:type :negative
:text error}]))))

(defn connection-string-for-key-pair-import
[{:keys [db]} [{:keys [sha3-pwd keypairs-key-uids connection-string]}]]
(let [key-uid (get-in db [:profile/profile :key-uid])
config-map (.stringify js/JSON
(clj->js
{:receiverConfig
{:loggedInKeyUid key-uid
:keystorePath ""
:password (security/safe-unmask-data
sha3-pwd)
:keypairsToImport keypairs-key-uids}}))]
(native-module/input-connection-string-for-importing-keypairs-keystores
connection-string
config-map
input-connection-string-for-importing-keypairs-keystores-callback)))

(rf/reg-event-fx :wallet/connection-string-for-key-pair-import connection-string-for-key-pair-import)
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
(ns status-im.contexts.settings.wallet.keypairs-and-accounts.scan-qr.view
(:require
[status-im.common.scan-qr-code.view :as scan-qr-code]
[status-im.contexts.communities.events]
[status-im.contexts.syncing.utils :as sync-utils]
[utils.debounce :as debounce]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))

(def invalid-qr-toast
{:type :negative
:theme :dark
:text (i18n/label :t/invalid-qr)})

(defn show-invalid-qr-toast
[]
(debounce/debounce-and-dispatch
[:toasts/upsert invalid-qr-toast]
300))

(defn- on-valid-connection-received
[connection-string keypairs-key-uids]
(rf/dispatch
[:standard-auth/authorize-with-password
{:blur? true
:theme :dark
:auth-button-label (i18n/label :t/confirm)
:on-auth-success (fn [password]
(rf/dispatch [:hide-bottom-sheet])
(rf/dispatch
[:wallet/connection-string-for-key-pair-import
{:connection-string connection-string
:keypairs-key-uids keypairs-key-uids
:sha3-pwd password}]))}]))

(defn on-qr-code-scanned
[scanned-text keypairs-key-uids]
(if (sync-utils/valid-connection-string? scanned-text)
(on-valid-connection-received scanned-text keypairs-key-uids)
(show-invalid-qr-toast)))

(defn view
[]
(let [keypairs (rf/sub [:get-screen-params])
keypairs-key-uids (map :key-uid keypairs)]
[scan-qr-code/view
{:title (i18n/label :t/scan-key-pairs-qr-code)
:subtitle (i18n/label :t/find-it-in-setting)
:share-button? false
:on-success-scan #(on-qr-code-scanned % keypairs-key-uids)}]))
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,11 @@
profile-picture (rf/sub [:profile/image])
customization-color (rf/sub [:profile/customization-color])
{missing-keypairs :missing
operable-keypairs :operable} (rf/sub [:wallet/settings-keypairs-accounts])]
operable-keypairs :operable} (rf/sub [:wallet/settings-keypairs-accounts])
on-import-click (rn/use-callback #(rf/dispatch [:open-modal
:screen/settings.scan-key-pair-qr
missing-keypairs])
[missing-keypairs])]
[quo/overlay
{:type :shell
:container-style (style/page-wrapper (:top insets))}
Expand All @@ -112,6 +116,7 @@
[quo/missing-keypairs
{:blur? true
:keypairs missing-keypairs
:on-import-click on-import-click
:container-style style/missing-keypairs-container-style
:on-options-press on-missing-keypair-options-press}])
[rn/flat-list
Expand Down
2 changes: 1 addition & 1 deletion src/status_im/contexts/syncing/events.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
:VerifyTransactionChainID config/verify-transaction-chain-id}}
log-config)))

(defn- extract-error
(defn extract-error
[json-str]
(-> json-str
transforms/json->clj
Expand Down
5 changes: 5 additions & 0 deletions src/status_im/navigation/screens.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
[status-im.contexts.settings.wallet.keypairs-and-accounts.encrypted-qr.view :as
encrypted-key-pair-qr]
[status-im.contexts.settings.wallet.keypairs-and-accounts.rename.view :as keypair-rename]
[status-im.contexts.settings.wallet.keypairs-and-accounts.scan-qr.view :as scan-key-pair-qr]
[status-im.contexts.settings.wallet.keypairs-and-accounts.view :as keypairs-and-accounts]
[status-im.contexts.settings.wallet.network-settings.view :as network-settings]
[status-im.contexts.settings.wallet.saved-addresses.view :as saved-addresses-settings]
Expand Down Expand Up @@ -523,6 +524,10 @@
:options options/transparent-modal-screen-options
:component keypairs-and-accounts/view}

{:name :screen/settings.scan-key-pair-qr
:options options/transparent-modal-screen-options
:component scan-key-pair-qr/view}

{:name :screen/settings.network-settings
:options options/transparent-modal-screen-options
:component network-settings/view}
Expand Down
2 changes: 2 additions & 0 deletions translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1289,6 +1289,7 @@
"scan-qr": "Scan QR",
"scan-qr-code": "Scan QR code",
"scan-with-status-app": "Scan with the Status app on another device",
"scan-key-pairs-qr-code": "Scan key pairs QR code",
"invalid-qr": "Oops! This QR doesn’t work with Status",
"search": "Search",
"search-discover-communities": "Search communities or categories",
Expand Down Expand Up @@ -2209,6 +2210,7 @@
"create-new-profile": "Create new profile",
"add-existing-status-profile": "Add existing Status profile",
"find-sync-code": "Find sync code",
"find-it-in-setting": "Find it in Settings on your other synced device",
"sign-in-by-syncing": "Sign in by syncing",
"synchronise-your-data-across-your-devices": "Synchronise your data across your devices",
"scan-sync-qr-code": "Scan QR code",
Expand Down

0 comments on commit 45c446e

Please sign in to comment.