parent
4cdbfb6cc6
commit
389a730eff
|
@ -75,4 +75,17 @@ class NetworkManager(private val reactContext: ReactApplicationContext) : ReactC
|
||||||
utils.executeRunnableStatusGoMethod({ Statusgo.recover(rpcParams) }, callback)
|
utils.executeRunnableStatusGoMethod({ Statusgo.recover(rpcParams) }, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ReactMethod
|
||||||
|
fun getConnectionStringForExportingKeypairsKeystores(configJSON: String, callback: Callback) {
|
||||||
|
val jsonConfig = JSONObject(configJSON)
|
||||||
|
val senderConfig = jsonConfig.getJSONObject("senderConfig")
|
||||||
|
val keyUID = senderConfig.getString("loggedInKeyUid")
|
||||||
|
val keyStorePath = utils.getKeyStorePath(keyUID)
|
||||||
|
senderConfig.put("keystorePath", keyStorePath)
|
||||||
|
|
||||||
|
utils.executeRunnableStatusGoMethod(
|
||||||
|
{ Statusgo.getConnectionStringForExportingKeypairsKeystores(jsonConfig.toString()) },
|
||||||
|
callback)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,4 +106,22 @@ RCT_EXPORT_METHOD(recover:(NSString *)message
|
||||||
callback(@[result]);
|
callback(@[result]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RCT_EXPORT_METHOD(getConnectionStringForExportingKeypairsKeystores:(NSString *)configJSON
|
||||||
|
callback:(RCTResponseSenderBlock)callback) {
|
||||||
|
|
||||||
|
NSData *configData = [configJSON dataUsingEncoding:NSUTF8StringEncoding];
|
||||||
|
NSError *error;
|
||||||
|
NSMutableDictionary *configDict = [NSJSONSerialization JSONObjectWithData:configData options:NSJSONReadingMutableContainers error:&error];
|
||||||
|
NSMutableDictionary *senderConfig = configDict[@"senderConfig"];
|
||||||
|
NSString *keyUID = senderConfig[@"loggedInKeyUid"];
|
||||||
|
NSURL *multiaccountKeystoreDir = [Utils getKeyStoreDirForKeyUID:keyUID];
|
||||||
|
NSString *keystoreDir = multiaccountKeystoreDir.path;
|
||||||
|
|
||||||
|
[senderConfig setValue:keystoreDir forKey:@"keystorePath"];
|
||||||
|
NSString *modifiedConfigJSON = [Utils jsonStringWithPrettyPrint:NO fromDictionary:configDict];
|
||||||
|
|
||||||
|
NSString *result = StatusgoGetConnectionStringForExportingKeypairsKeystores(modifiedConfigJSON);
|
||||||
|
callback(@[result]);
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -601,3 +601,11 @@
|
||||||
(.createAccountFromMnemonicAndDeriveAccountsForPaths ^js (account-manager)
|
(.createAccountFromMnemonicAndDeriveAccountsForPaths ^js (account-manager)
|
||||||
(types/clj->json mnemonic)
|
(types/clj->json mnemonic)
|
||||||
#(callback (types/json->clj %))))
|
#(callback (types/json->clj %))))
|
||||||
|
|
||||||
|
(defn get-connection-string-for-exporting-keypairs-keystores
|
||||||
|
"Generates connection string form status-go for the purpose of exporting keypairs and keystores on sender side"
|
||||||
|
[config-json callback]
|
||||||
|
(log/info "[native-module] Fetching Export Keypairs Connection String"
|
||||||
|
{:fn :get-connection-string-for-exporting-keypairs-keystores
|
||||||
|
:config-json config-json})
|
||||||
|
(.getConnectionStringForExportingKeypairsKeystores ^js (network) config-json callback))
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
(ns status-im.contexts.settings.wallet.events
|
(ns status-im.contexts.settings.wallet.events
|
||||||
(:require
|
(:require
|
||||||
|
[native-module.core :as native-module]
|
||||||
|
[status-im.contexts.syncing.utils :as sync-utils]
|
||||||
[taoensso.timbre :as log]
|
[taoensso.timbre :as log]
|
||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]
|
||||||
|
[utils.security.core :as security]
|
||||||
|
[utils.transforms :as transforms]))
|
||||||
|
|
||||||
(rf/reg-event-fx
|
(rf/reg-event-fx
|
||||||
:wallet/rename-keypair-success
|
:wallet/rename-keypair-success
|
||||||
|
@ -30,3 +34,22 @@
|
||||||
:on-error #(log/info "failed to rename keypair " %)}]]]})
|
:on-error #(log/info "failed to rename keypair " %)}]]]})
|
||||||
|
|
||||||
(rf/reg-event-fx :wallet/rename-keypair rename-keypair)
|
(rf/reg-event-fx :wallet/rename-keypair rename-keypair)
|
||||||
|
|
||||||
|
(defn get-key-pair-export-connection
|
||||||
|
[{:keys [db]} [{:keys [sha3-pwd keypair-key-uid callback]}]]
|
||||||
|
(let [key-uid (get-in db [:profile/profile :key-uid])
|
||||||
|
config-map (transforms/clj->json {:senderConfig {:loggedInKeyUid key-uid
|
||||||
|
:keystorePath ""
|
||||||
|
:keypairsToExport [keypair-key-uid]
|
||||||
|
:password (security/safe-unmask-data
|
||||||
|
sha3-pwd)}
|
||||||
|
:serverConfig {:timeout 0}})
|
||||||
|
handle-connection (fn [response]
|
||||||
|
(when (sync-utils/valid-connection-string? response)
|
||||||
|
(callback response)
|
||||||
|
(rf/dispatch [:hide-bottom-sheet])))]
|
||||||
|
(native-module/get-connection-string-for-exporting-keypairs-keystores
|
||||||
|
config-map
|
||||||
|
handle-connection)))
|
||||||
|
|
||||||
|
(rf/reg-event-fx :wallet/get-key-pair-export-connection get-key-pair-export-connection)
|
||||||
|
|
|
@ -7,13 +7,23 @@
|
||||||
[data]
|
[data]
|
||||||
(rf/dispatch [:open-modal :screen/settings.rename-keypair data]))
|
(rf/dispatch [:open-modal :screen/settings.rename-keypair data]))
|
||||||
|
|
||||||
|
(defn on-show-qr
|
||||||
|
[data]
|
||||||
|
(rf/dispatch [:open-modal :screen/settings.encrypted-key-pair-qr data]))
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[props data]
|
[props data]
|
||||||
|
(let [has-paired-device (rf/sub [:pairing/has-paired-devices])]
|
||||||
[:<>
|
[:<>
|
||||||
[quo/drawer-top props]
|
[quo/drawer-top props]
|
||||||
[quo/action-drawer
|
[quo/action-drawer
|
||||||
[(when (= (:type props) :keypair)
|
[(when has-paired-device
|
||||||
|
[{:icon :i/qr-code
|
||||||
|
:accessibility-label :show-key-pr-qr
|
||||||
|
:label (i18n/label :t/show-encrypted-qr-of-key-pairs)
|
||||||
|
:on-press #(on-show-qr data)}])
|
||||||
|
(when (= (:type props) :keypair)
|
||||||
[{:icon :i/edit
|
[{:icon :i/edit
|
||||||
:accessibility-label :rename-key-pair
|
:accessibility-label :rename-key-pair
|
||||||
:label (i18n/label :t/rename-key-pair)
|
:label (i18n/label :t/rename-key-pair)
|
||||||
:on-press #(on-rename-request data)}])]]])
|
:on-press #(on-rename-request data)}])]]]))
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
(ns status-im.contexts.settings.wallet.keypairs-and-accounts.encrypted-qr.countdown.view
|
||||||
|
(:require
|
||||||
|
[quo.core :as quo]
|
||||||
|
[quo.foundations.colors :as colors]
|
||||||
|
[react-native.core :as rn]
|
||||||
|
[react-native.hooks :as hooks]
|
||||||
|
[utils.datetime :as datetime]
|
||||||
|
[utils.i18n :as i18n]))
|
||||||
|
|
||||||
|
(def code-valid-for-ms 120000)
|
||||||
|
(def one-min-ms 60000)
|
||||||
|
|
||||||
|
(defn current-ms
|
||||||
|
[]
|
||||||
|
(* 1000 (js/Math.ceil (/ (datetime/timestamp) 1000))))
|
||||||
|
|
||||||
|
(defn view
|
||||||
|
[on-clear]
|
||||||
|
(let [[valid-for-ms set-valid-for-ms] (rn/use-state code-valid-for-ms)
|
||||||
|
[timestamp set-timestamp] (rn/use-state current-ms)
|
||||||
|
clock (rn/use-callback (fn []
|
||||||
|
(let [remaining (- code-valid-for-ms
|
||||||
|
(- (current-ms)
|
||||||
|
timestamp))]
|
||||||
|
(when (pos? remaining)
|
||||||
|
(set-valid-for-ms remaining))
|
||||||
|
(when (zero? remaining)
|
||||||
|
(set-timestamp (current-ms))
|
||||||
|
(set-valid-for-ms code-valid-for-ms)
|
||||||
|
(on-clear))))
|
||||||
|
[code-valid-for-ms])]
|
||||||
|
(hooks/use-interval clock on-clear 1000)
|
||||||
|
[quo/text
|
||||||
|
{:size :paragraph-2
|
||||||
|
:style {:color (if (< valid-for-ms one-min-ms)
|
||||||
|
colors/danger-60
|
||||||
|
colors/white-opa-40)}}
|
||||||
|
(i18n/label :t/valid-for-time {:valid-for (datetime/ms-to-duration valid-for-ms)})]))
|
|
@ -0,0 +1,46 @@
|
||||||
|
(ns status-im.contexts.settings.wallet.keypairs-and-accounts.encrypted-qr.style
|
||||||
|
(:require
|
||||||
|
[quo.foundations.colors :as colors]
|
||||||
|
[react-native.safe-area :as safe-area]))
|
||||||
|
|
||||||
|
(defn container-main
|
||||||
|
[]
|
||||||
|
{:background-color colors/neutral-95
|
||||||
|
:padding-top (safe-area/get-top)
|
||||||
|
:flex 1})
|
||||||
|
|
||||||
|
(def page-container
|
||||||
|
{:margin-top 14
|
||||||
|
:margin-horizontal 20})
|
||||||
|
|
||||||
|
(def title-container
|
||||||
|
{:flex-direction :row
|
||||||
|
:align-items :center
|
||||||
|
:justify-content :space-between})
|
||||||
|
|
||||||
|
(def standard-auth
|
||||||
|
{:margin-top 12
|
||||||
|
:flex 1})
|
||||||
|
|
||||||
|
(def qr-container
|
||||||
|
{:margin-top 12
|
||||||
|
:background-color colors/white-opa-5
|
||||||
|
:border-radius 20
|
||||||
|
:flex 1
|
||||||
|
:padding 12})
|
||||||
|
|
||||||
|
(def sub-text-container
|
||||||
|
{:margin-bottom 8
|
||||||
|
:justify-content :space-between
|
||||||
|
:align-items :center
|
||||||
|
:flex-direction :row})
|
||||||
|
|
||||||
|
(def valid-cs-container
|
||||||
|
{:flex 1
|
||||||
|
:margin 12})
|
||||||
|
|
||||||
|
(def warning-text
|
||||||
|
{:margin-horizontal 16
|
||||||
|
:margin-top 20
|
||||||
|
:text-align :center
|
||||||
|
:color colors/white-opa-70})
|
|
@ -0,0 +1,98 @@
|
||||||
|
(ns status-im.contexts.settings.wallet.keypairs-and-accounts.encrypted-qr.view
|
||||||
|
(:require
|
||||||
|
[quo.core :as quo]
|
||||||
|
[quo.foundations.colors :as colors]
|
||||||
|
[react-native.clipboard :as clipboard]
|
||||||
|
[react-native.core :as rn]
|
||||||
|
[status-im.common.qr-codes.view :as qr-codes]
|
||||||
|
[status-im.common.resources :as resources]
|
||||||
|
[status-im.common.standard-authentication.core :as standard-auth]
|
||||||
|
[status-im.contexts.settings.wallet.keypairs-and-accounts.encrypted-qr.countdown.view :as countdown]
|
||||||
|
[status-im.contexts.settings.wallet.keypairs-and-accounts.encrypted-qr.style :as style]
|
||||||
|
[status-im.contexts.syncing.utils :as sync-utils]
|
||||||
|
[utils.i18n :as i18n]
|
||||||
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
|
(defn navigate-back [] (rf/dispatch [:navigate-back]))
|
||||||
|
|
||||||
|
(defn view
|
||||||
|
[]
|
||||||
|
(let [{:keys [key-uid]} (rf/sub [:get-screen-params])
|
||||||
|
{:keys [customization-color]} (rf/sub [:profile/profile-with-image])
|
||||||
|
[code set-code] (rn/use-state nil)
|
||||||
|
valid-connection-string? (rn/use-memo #(sync-utils/valid-connection-string? code) [code])
|
||||||
|
validate-and-set-code (rn/use-callback (fn [connection-string]
|
||||||
|
(when (sync-utils/valid-connection-string?
|
||||||
|
connection-string)
|
||||||
|
(set-code connection-string))))
|
||||||
|
cleanup-clock (rn/use-callback #(set-code nil))
|
||||||
|
on-auth-success (rn/use-callback (fn [entered-password]
|
||||||
|
(rf/dispatch
|
||||||
|
[:wallet/get-key-pair-export-connection
|
||||||
|
{:sha3-pwd entered-password
|
||||||
|
:keypair-key-uid key-uid
|
||||||
|
:callback validate-and-set-code}]))
|
||||||
|
[key-uid])]
|
||||||
|
[rn/view {:style (style/container-main)}
|
||||||
|
[rn/scroll-view
|
||||||
|
[quo/page-nav
|
||||||
|
{:type :no-title
|
||||||
|
:icon-name :i/close
|
||||||
|
:background :blur
|
||||||
|
:on-press navigate-back}]
|
||||||
|
[rn/view {:style style/page-container}
|
||||||
|
[rn/view {:style style/title-container}
|
||||||
|
[quo/text
|
||||||
|
{:size :heading-1
|
||||||
|
:weight :semi-bold
|
||||||
|
:style {:color colors/white}}
|
||||||
|
(i18n/label :t/encrypted-key-pairs)]]
|
||||||
|
[rn/view {:style style/qr-container}
|
||||||
|
(if valid-connection-string?
|
||||||
|
[qr-codes/qr-code {:url code}]
|
||||||
|
[rn/view {:style {:flex-direction :row}}
|
||||||
|
[rn/image
|
||||||
|
{:source (resources/get-image :qr-code)
|
||||||
|
:style {:width "100%"
|
||||||
|
:background-color colors/white-opa-70
|
||||||
|
:border-radius 12
|
||||||
|
:aspect-ratio 1}}]])
|
||||||
|
(when valid-connection-string?
|
||||||
|
[rn/view {:style style/valid-cs-container}
|
||||||
|
[rn/view {:style style/sub-text-container}
|
||||||
|
[quo/text
|
||||||
|
{:size :paragraph-2
|
||||||
|
:style {:color colors/white-opa-40}}
|
||||||
|
(i18n/label :t/encrypted-key-pairs-code)]
|
||||||
|
[countdown/view cleanup-clock]]
|
||||||
|
[quo/input
|
||||||
|
{:default-value code
|
||||||
|
:type :password
|
||||||
|
:default-shown? true
|
||||||
|
:editable false}]
|
||||||
|
[quo/button
|
||||||
|
{:on-press (fn []
|
||||||
|
(clipboard/set-string code)
|
||||||
|
(rf/dispatch [:toasts/upsert
|
||||||
|
{:type :positive
|
||||||
|
:text (i18n/label
|
||||||
|
:t/sharing-copied-to-clipboard)}]))
|
||||||
|
:type :grey
|
||||||
|
:container-style {:margin-top 12}
|
||||||
|
:icon-left :i/copy}
|
||||||
|
(i18n/label :t/copy-qr)]])
|
||||||
|
(when-not valid-connection-string?
|
||||||
|
[rn/view {:style style/standard-auth}
|
||||||
|
[standard-auth/slide-button
|
||||||
|
{:blur? true
|
||||||
|
:size :size-40
|
||||||
|
:track-text (i18n/label :t/slide-to-reveal-qr-code)
|
||||||
|
:customization-color customization-color
|
||||||
|
:on-auth-success on-auth-success
|
||||||
|
:auth-button-label (i18n/label :t/reveal-qr-code)
|
||||||
|
:auth-button-icon-left :i/reveal}]])]]
|
||||||
|
(when-not valid-connection-string?
|
||||||
|
[quo/text
|
||||||
|
{:size :paragraph-2
|
||||||
|
:style style/warning-text}
|
||||||
|
(i18n/label :t/make-sure-no-camera-warning)])]]))
|
|
@ -57,6 +57,8 @@
|
||||||
[status-im.contexts.profile.settings.screens.password.change-password.view :as change-password]
|
[status-im.contexts.profile.settings.screens.password.change-password.view :as change-password]
|
||||||
[status-im.contexts.profile.settings.screens.password.view :as settings-password]
|
[status-im.contexts.profile.settings.screens.password.view :as settings-password]
|
||||||
[status-im.contexts.profile.settings.view :as settings]
|
[status-im.contexts.profile.settings.view :as settings]
|
||||||
|
[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.rename.view :as keypair-rename]
|
||||||
[status-im.contexts.settings.wallet.keypairs-and-accounts.view :as keypairs-and-accounts]
|
[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.network-settings.view :as network-settings]
|
||||||
|
@ -509,6 +511,10 @@
|
||||||
:options (assoc options/dark-screen :sheet? true)
|
:options (assoc options/dark-screen :sheet? true)
|
||||||
:component keypair-rename/view}
|
:component keypair-rename/view}
|
||||||
|
|
||||||
|
{:name :screen/settings.encrypted-key-pair-qr
|
||||||
|
:options options/transparent-screen-options
|
||||||
|
:component encrypted-key-pair-qr/view}
|
||||||
|
|
||||||
{:name :screen/settings.saved-addresses
|
{:name :screen/settings.saved-addresses
|
||||||
:options options/transparent-modal-screen-options
|
:options options/transparent-modal-screen-options
|
||||||
:component saved-addresses-settings/view}
|
:component saved-addresses-settings/view}
|
||||||
|
|
|
@ -28,3 +28,9 @@
|
||||||
:<- [:syncing]
|
:<- [:syncing]
|
||||||
(fn [syncing]
|
(fn [syncing]
|
||||||
(:pairing-status syncing)))
|
(:pairing-status syncing)))
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
:pairing/has-paired-devices
|
||||||
|
:<- [:pairing/enabled-installations]
|
||||||
|
(fn [installations]
|
||||||
|
(> (count installations) 1)))
|
||||||
|
|
|
@ -524,6 +524,8 @@
|
||||||
"enable": "Enable",
|
"enable": "Enable",
|
||||||
"enable-notifications-sub-title": "Receive notifications about your new messages or wallet transactions",
|
"enable-notifications-sub-title": "Receive notifications about your new messages or wallet transactions",
|
||||||
"encrypt-with-password": "Encrypt with password",
|
"encrypt-with-password": "Encrypt with password",
|
||||||
|
"encrypted-key-pairs": "Encrypted key pairs",
|
||||||
|
"encrypted-key-pairs-code": "Encrypted key pairs code",
|
||||||
"ending-not-allowed": "{{ending}} ending is not allowed",
|
"ending-not-allowed": "{{ending}} ending is not allowed",
|
||||||
"ends-with-space": "Cannot end with space",
|
"ends-with-space": "Cannot end with space",
|
||||||
"ens-10-SNT": "10 SNT",
|
"ens-10-SNT": "10 SNT",
|
||||||
|
@ -939,6 +941,7 @@
|
||||||
"main-wallet": "Main Wallet",
|
"main-wallet": "Main Wallet",
|
||||||
"make-admin": "Make admin",
|
"make-admin": "Make admin",
|
||||||
"make-moderator": "Make moderator",
|
"make-moderator": "Make moderator",
|
||||||
|
"make-sure-no-camera-warning": "Make sure no camera or person can see this screen before revealing",
|
||||||
"manage-keys-and-storage": "Manage keys and storage",
|
"manage-keys-and-storage": "Manage keys and storage",
|
||||||
"mark-as-read": "Mark as read",
|
"mark-as-read": "Mark as read",
|
||||||
"mark-all-read": "Mark all read",
|
"mark-all-read": "Mark all read",
|
||||||
|
@ -1272,6 +1275,7 @@
|
||||||
"reset-card-description": "This operation will reset card to initial state. It will erase all card data including private keys. Operation is not reversible.",
|
"reset-card-description": "This operation will reset card to initial state. It will erase all card data including private keys. Operation is not reversible.",
|
||||||
"retry": "Retry",
|
"retry": "Retry",
|
||||||
"reveal-sync-code": "Reveal sync code",
|
"reveal-sync-code": "Reveal sync code",
|
||||||
|
"reveal-qr-code": "Reveal QR code",
|
||||||
"revoke-access": "Revoke access",
|
"revoke-access": "Revoke access",
|
||||||
"save": "Save",
|
"save": "Save",
|
||||||
"save-address": "Save address",
|
"save-address": "Save address",
|
||||||
|
@ -1337,6 +1341,7 @@
|
||||||
"show-more": "Show more",
|
"show-more": "Show more",
|
||||||
"show-qr": "Show QR code",
|
"show-qr": "Show QR code",
|
||||||
"show-transaction-data": "Show transaction data",
|
"show-transaction-data": "Show transaction data",
|
||||||
|
"show-encrypted-qr-of-key-pairs": "Show encrypted QR of key pairs on device",
|
||||||
"sign-and-send": "Sign and send",
|
"sign-and-send": "Sign and send",
|
||||||
"sign-in": "Sign in",
|
"sign-in": "Sign in",
|
||||||
"sign-message": "Sign Message",
|
"sign-message": "Sign Message",
|
||||||
|
@ -1970,6 +1975,7 @@
|
||||||
"slide-to-request-to-join": "Slide to request to join",
|
"slide-to-request-to-join": "Slide to request to join",
|
||||||
"slide-to-reveal-code": "Slide to reveal code",
|
"slide-to-reveal-code": "Slide to reveal code",
|
||||||
"slide-to-create-account": "Slide to create account",
|
"slide-to-create-account": "Slide to create account",
|
||||||
|
"slide-to-reveal-qr-code": "Slide to reveal QR code",
|
||||||
"minimum-received": "Minimum received",
|
"minimum-received": "Minimum received",
|
||||||
"powered-by-paraswap": "Powered by Paraswap",
|
"powered-by-paraswap": "Powered by Paraswap",
|
||||||
"priority": "Priority",
|
"priority": "Priority",
|
||||||
|
|
Loading…
Reference in New Issue