recovery flow v1
Signed-off-by: Dmitry Novotochinov <dmitry.novot@gmail.com>
This commit is contained in:
parent
ba112a765b
commit
b635691c25
2
.env
2
.env
|
@ -7,7 +7,7 @@ ETHEREUM_DEV_CLUSTER=1
|
|||
EXTENSIONS=0
|
||||
FLEET=eth.beta
|
||||
GROUP_CHATS_ENABLED=1
|
||||
HARDWALLET_ENABLED=0
|
||||
HARDWALLET_ENABLED=1
|
||||
LOG_LEVEL_STATUS_GO=info
|
||||
LOG_LEVEL=debug
|
||||
MAILSERVER_CONFIRMATIONS_ENABLED=1
|
||||
|
|
|
@ -6,7 +6,7 @@ ETHEREUM_DEV_CLUSTER=1
|
|||
EXTENSIONS=0
|
||||
FLEET=eth.beta
|
||||
GROUP_CHATS_ENABLED=1
|
||||
HARDWALLET_ENABLED=0
|
||||
HARDWALLET_ENABLED=1
|
||||
LOG_LEVEL_STATUS_GO=info
|
||||
LOG_LEVEL=debug
|
||||
MAILSERVER_CONFIRMATIONS_ENABLED=1
|
||||
|
|
|
@ -568,5 +568,6 @@ var TopLevel = {
|
|||
"multiAccountDeriveAddresses" : function () {},
|
||||
"multiAccountReset" : function () {},
|
||||
"multiAccountLoadAccount" : function () {},
|
||||
"multiAccountStoreAccount" : function () {}
|
||||
"multiAccountStoreAccount" : function () {},
|
||||
"multiAccountImportMnemonic" : function () {},
|
||||
}
|
||||
|
|
|
@ -774,6 +774,25 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
|||
StatusThreadPoolExecutor.getInstance().execute(r);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void multiAccountImportMnemonic(final String json, final Callback callback) {
|
||||
Log.d(TAG, "multiAccountImportMnemonic");
|
||||
if (!checkAvailability()) {
|
||||
callback.invoke(false);
|
||||
return;
|
||||
}
|
||||
Runnable r = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String res = Statusgo.multiAccountImportMnemonic(json);
|
||||
|
||||
callback.invoke(res);
|
||||
}
|
||||
};
|
||||
|
||||
StatusThreadPoolExecutor.getInstance().execute(r);
|
||||
}
|
||||
|
||||
private String createIdentifier() {
|
||||
return UUID.randomUUID().toString();
|
||||
}
|
||||
|
|
|
@ -384,7 +384,17 @@ RCT_EXPORT_METHOD(multiAccountStoreDerived:(NSString *)json
|
|||
callback(@[result]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// MultiAccountDeriveAddresses
|
||||
//////////////////////////////////////////////////////////////////// multiAccountImportMnemonic
|
||||
RCT_EXPORT_METHOD(multiAccountImportMnemonic:(NSString *)json
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
NSLog(@"MultiAccountImportMnemonic() method called");
|
||||
#endif
|
||||
NSString *result = StatusgoMultiAccountImportMnemonic(json);
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// multiAccountDeriveAddresses
|
||||
RCT_EXPORT_METHOD(multiAccountDeriveAddresses:(NSString *)json
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
|
@ -21,17 +21,25 @@
|
|||
(defn valid-word-counts? [v]
|
||||
(boolean (valid-word-counts (count v))))
|
||||
|
||||
(defn words-count [s]
|
||||
(if (empty? s)
|
||||
nil
|
||||
(-> s
|
||||
passphrase->words
|
||||
count)))
|
||||
|
||||
(defn- valid-word? [s]
|
||||
(re-matches #"^[A-z]+$" s))
|
||||
|
||||
(defn valid-words? [v]
|
||||
(and (valid-word-counts? v)
|
||||
(every? valid-word? v)))
|
||||
|
||||
(defn valid-phrase? [s]
|
||||
(defn valid-length? [s]
|
||||
(-> s
|
||||
passphrase->words
|
||||
valid-words?))
|
||||
valid-word-counts?))
|
||||
|
||||
(defn valid-words? [s]
|
||||
(->> s
|
||||
passphrase->words
|
||||
(every? valid-word?)))
|
||||
|
||||
(defn status-generated-phrase? [s]
|
||||
(every? dictionary (passphrase->words s)))
|
||||
|
|
|
@ -307,13 +307,6 @@
|
|||
(fn [cofx _]
|
||||
(multiaccounts.recover/recover-multiaccount cofx)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:multiaccounts.recover.callback/recover-multiaccount-success
|
||||
[(re-frame/inject-cofx :random-guid-generator)
|
||||
(re-frame/inject-cofx :multiaccounts.create/get-signing-phrase)]
|
||||
(fn [cofx [_ result password]]
|
||||
(multiaccounts.recover/on-multiaccount-recovered cofx result password)))
|
||||
|
||||
;; multiaccounts login module
|
||||
|
||||
(handlers/register-handler-fx
|
||||
|
|
|
@ -404,18 +404,19 @@
|
|||
(navigation/navigate-to-cofx :keycard-recovery-enter-mnemonic nil)))
|
||||
|
||||
(fx/defn start-import-flow
|
||||
{:events [:recovery.ui/recover-with-keycard-pressed
|
||||
{:events [:recover.ui/recover-with-keycard-pressed
|
||||
:keycard.login.ui/recover-key-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:hardwallet :flow] :import)
|
||||
:dispatch [:bottom-sheet/hide-sheet]
|
||||
:hardwallet/check-nfc-enabled nil}
|
||||
(navigation/navigate-to-cofx :keycard-recovery-intro nil)))
|
||||
|
||||
(fx/defn access-key-pressed
|
||||
{:events [:multiaccounts.recover.ui/recover-multiaccount-button-pressed]}
|
||||
[cofx]
|
||||
(multiaccounts.recover/navigate-to-recover-multiaccount-screen cofx))
|
||||
{:dispatch [:bottom-sheet/show-sheet :recover-sheet]})
|
||||
|
||||
(fx/defn recovery-keycard-selected
|
||||
{:events [:recovery.ui/keycard-option-pressed]}
|
||||
|
@ -425,19 +426,6 @@
|
|||
:hardwallet/check-nfc-enabled nil}
|
||||
(navigation/navigate-to-cofx :keycard-onboarding-intro nil)))
|
||||
|
||||
;NOTE to be removed when Recovery flow will be implemented
|
||||
(fx/defn enter-mnemonic-next-button-pressed
|
||||
{:events [:keycard.recovery.enter-mnemonic.ui/input-submitted
|
||||
:keycard.recovery.enter-mnemonic.ui/next-pressed]}
|
||||
[cofx]
|
||||
(recovery-keycard-selected cofx))
|
||||
|
||||
;NOTE to be removed when Recovery flow will be implemented
|
||||
(fx/defn enter-mnemonic-input-changed
|
||||
{:events [:keycard.recovery.enter-mnemonic.ui/input-changed]}
|
||||
[{:keys [db]} input]
|
||||
{:db (assoc-in db [:hardwallet :secrets :mnemonic] input)})
|
||||
|
||||
(fx/defn password-option-pressed
|
||||
[{:keys [db] :as cofx}]
|
||||
(if (= (get-in db [:hardwallet :flow]) :create)
|
||||
|
|
|
@ -228,6 +228,9 @@
|
|||
(= (get-in cofx [:db :view-id])
|
||||
:create-multiaccount))
|
||||
|
||||
(defn recovering-multiaccount? [cofx]
|
||||
(boolean (get-in cofx [:db :multiaccounts/recover])))
|
||||
|
||||
(defn- keycard-setup? [cofx]
|
||||
(boolean (get-in cofx [:db :hardwallet :flow])))
|
||||
|
||||
|
@ -242,6 +245,7 @@
|
|||
(stickers/init-stickers-packs)
|
||||
(multiaccounts.update/update-sign-in-time)
|
||||
#(when-not (or (creating-multiaccount? %)
|
||||
(recovering-multiaccount? %)
|
||||
(keycard-setup? %))
|
||||
(login-only-events % address stored-pns)))))
|
||||
|
||||
|
|
|
@ -283,11 +283,23 @@
|
|||
|
||||
(fx/defn verify-multiaccount
|
||||
[{:keys [db] :as cofx} {:keys [realm-error]}]
|
||||
(fx/merge cofx
|
||||
{:db (-> db
|
||||
(assoc :node/on-ready :verify-multiaccount)
|
||||
(assoc :realm-error realm-error))}
|
||||
(node/initialize nil)))
|
||||
(if (get-in db [:multiaccounts/recover])
|
||||
(fx/merge cofx
|
||||
{:db (-> db
|
||||
(update :multiaccounts/recover assoc
|
||||
:processing? false
|
||||
:password ""
|
||||
:password-confirmation ""
|
||||
:password-error :recover-password-invalid)
|
||||
(update :multiaccounts/recover dissoc
|
||||
:password-valid?))
|
||||
:node/stop nil}
|
||||
(navigation/navigate-to-cofx :recover-multiaccount-enter-password nil))
|
||||
(fx/merge cofx
|
||||
{:db (-> db
|
||||
(assoc :node/on-ready :verify-multiaccount)
|
||||
(assoc :realm-error realm-error))}
|
||||
(node/initialize nil))))
|
||||
|
||||
(fx/defn unknown-realm-error
|
||||
[cofx {:keys [realm-error erase-button]}]
|
||||
|
|
|
@ -20,11 +20,14 @@
|
|||
|
||||
(defn check-phrase-errors [recovery-phrase]
|
||||
(cond (string/blank? recovery-phrase) :required-field
|
||||
(not (mnemonic/valid-phrase? recovery-phrase)) :recovery-phrase-invalid))
|
||||
(not (mnemonic/valid-words? recovery-phrase)) :recovery-phrase-invalid
|
||||
(not (mnemonic/valid-length? recovery-phrase)) :recovery-phrase-wrong-length
|
||||
(not (mnemonic/status-generated-phrase? recovery-phrase)) :recovery-phrase-unknown-words))
|
||||
|
||||
(defn check-phrase-warnings [recovery-phrase]
|
||||
(when (not (mnemonic/status-generated-phrase? recovery-phrase))
|
||||
:recovery-phrase-unknown-words))
|
||||
(cond (string/blank? recovery-phrase) :required-field
|
||||
(not (mnemonic/valid-words? recovery-phrase)) :recovery-phrase-invalid
|
||||
(not (mnemonic/status-generated-phrase? recovery-phrase)) :recovery-phrase-unknown-words))
|
||||
|
||||
(defn recover-multiaccount! [masked-passphrase password]
|
||||
(status/recover-multiaccount
|
||||
|
@ -42,22 +45,31 @@
|
|||
(fx/defn set-phrase
|
||||
[{:keys [db]} masked-recovery-phrase]
|
||||
(let [recovery-phrase (security/safe-unmask-data masked-recovery-phrase)]
|
||||
{:db (update db :multiaccounts/recover assoc
|
||||
:passphrase (string/lower-case recovery-phrase)
|
||||
:passphrase-valid? (not (check-phrase-errors recovery-phrase)))}))
|
||||
(fx/merge
|
||||
{:db (update db :multiaccounts/recover assoc
|
||||
:passphrase (string/lower-case recovery-phrase)
|
||||
:passphrase-error nil
|
||||
:next-button-disabled? (or (empty? recovery-phrase)
|
||||
(not (mnemonic/valid-length? recovery-phrase))))})))
|
||||
|
||||
(fx/defn validate-phrase
|
||||
[{:keys [db]}]
|
||||
(let [recovery-phrase (get-in db [:multiaccounts/recover :passphrase])]
|
||||
{:db (update db :multiaccounts/recover assoc
|
||||
:passphrase-error (check-phrase-errors recovery-phrase)
|
||||
:passphrase-warning (check-phrase-warnings recovery-phrase))}))
|
||||
:passphrase-error (check-phrase-errors recovery-phrase))}))
|
||||
|
||||
(fx/defn validate-phrase-for-warnings
|
||||
[{:keys [db]}]
|
||||
(let [recovery-phrase (get-in db [:multiaccounts/recover :passphrase])]
|
||||
{:db (update db :multiaccounts/recover assoc
|
||||
:passphrase-error (check-phrase-warnings recovery-phrase))}))
|
||||
|
||||
(fx/defn set-password
|
||||
[{:keys [db]} masked-password]
|
||||
(let [password (security/safe-unmask-data masked-password)]
|
||||
{:db (update db :multiaccounts/recover assoc
|
||||
:password password
|
||||
:password-error nil
|
||||
:password-valid? (not (check-password-errors password)))}))
|
||||
|
||||
(fx/defn validate-password
|
||||
|
@ -66,52 +78,51 @@
|
|||
{:db (assoc-in db [:multiaccounts/recover :password-error] (check-password-errors password))}))
|
||||
|
||||
(fx/defn validate-recover-result
|
||||
[{:keys [db] :as cofx} {:keys [error pubkey address walletAddress walletPubKey chatAddress chatPubKey]} password]
|
||||
(if (empty? error)
|
||||
(let [multiaccount-address (-> address
|
||||
(string/lower-case)
|
||||
(string/replace-first "0x" ""))
|
||||
keycard-multiaccount? (boolean (get-in db [:multiaccounts/multiaccounts multiaccount-address :keycard-instance-uid]))]
|
||||
(if keycard-multiaccount?
|
||||
;; trying to recover multiaccount created with keycard
|
||||
{:db (-> db
|
||||
(update :multiaccounts/recover assoc
|
||||
:processing? false
|
||||
:passphrase-error :recover-keycard-multiaccount-not-supported)
|
||||
(update :multiaccounts/recover dissoc
|
||||
:passphrase-valid?))
|
||||
:node/stop nil}
|
||||
(let [multiaccount {:derived {constants/path-whisper-keyword {:publicKey chatPubKey
|
||||
:address chatAddress}
|
||||
constants/path-default-wallet-keyword {:publicKey walletPubKey
|
||||
:address walletAddress}}
|
||||
:address address
|
||||
:mnemonic ""}]
|
||||
(multiaccounts.create/on-multiaccount-created
|
||||
cofx multiaccount password {:seed-backed-up? true}))))
|
||||
{:db (-> db
|
||||
(update :multiaccounts/recover assoc
|
||||
:processing? false
|
||||
:password ""
|
||||
:password-error :recover-password-invalid)
|
||||
(update :multiaccounts/recover dissoc
|
||||
:password-valid?))
|
||||
:node/stop nil}))
|
||||
[{:keys [db] :as cofx} password]
|
||||
(let [multiaccount (get-in db [:multiaccounts/recover :root-key])
|
||||
multiaccount-address (-> (:address multiaccount)
|
||||
(string/lower-case)
|
||||
(string/replace-first "0x" ""))
|
||||
keycard-multiaccount? (boolean (get-in db [:multiaccounts/multiaccounts multiaccount-address :keycard-instance-uid]))]
|
||||
(if keycard-multiaccount?
|
||||
;; trying to recover multiaccount created with keycard
|
||||
{:db (-> db
|
||||
(update :multiaccounts/recover assoc
|
||||
:processing? false
|
||||
:passphrase-error :recover-keycard-multiaccount-not-supported)
|
||||
(update :multiaccounts/recover dissoc
|
||||
:passphrase-valid?))
|
||||
:node/stop nil}
|
||||
(let [multiaccount' (assoc multiaccount :derived (get-in db [:multiaccounts/recover :derived]))]
|
||||
(multiaccounts.create/on-multiaccount-created
|
||||
cofx multiaccount' password {:seed-backed-up? true})))))
|
||||
|
||||
(fx/defn on-multiaccount-recovered
|
||||
[cofx result password]
|
||||
(let [data (types/json->clj result)]
|
||||
(validate-recover-result cofx data password)))
|
||||
{:events [:multiaccounts.recover.callback/recover-multiaccount-success]
|
||||
:interceptors [(re-frame/inject-cofx :random-guid-generator)
|
||||
(re-frame/inject-cofx :multiaccounts.create/get-signing-phrase)]}
|
||||
[cofx password]
|
||||
(validate-recover-result cofx password))
|
||||
|
||||
(fx/defn multiaccount-store-derived
|
||||
[{:keys [db]}]
|
||||
(let [id (get-in db [:multiaccounts/recover :root-key :id])
|
||||
password (get-in db [:multiaccounts/recover :password])]
|
||||
(status/multiaccount-store-derived
|
||||
id
|
||||
[constants/path-whisper constants/path-default-wallet]
|
||||
password
|
||||
#(re-frame/dispatch [:multiaccounts.recover.callback/recover-multiaccount-success password]))))
|
||||
|
||||
(fx/defn recover-multiaccount
|
||||
[{:keys [db random-guid-generator] :as cofx}]
|
||||
(fx/merge
|
||||
cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:multiaccounts/recover :processing?] true)
|
||||
(assoc :node/on-ready :recover-multiaccount)
|
||||
(assoc :multiaccounts/new-installation-id (random-guid-generator)))}
|
||||
(node/initialize nil)))
|
||||
(let [{:keys [password passphrase]} (:multiaccounts/recover db)]
|
||||
(fx/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:multiaccounts/recover :processing?] true)
|
||||
(assoc :multiaccounts/new-installation-id (random-guid-generator)))
|
||||
:multiaccounts.recover/recover-multiaccount
|
||||
[(security/mask-data passphrase) password]})))
|
||||
|
||||
(fx/defn recover-multiaccount-with-checks [{:keys [db] :as cofx}]
|
||||
(let [{:keys [passphrase processing?]} (:multiaccounts/recover db)]
|
||||
|
@ -127,9 +138,164 @@
|
|||
(fx/defn navigate-to-recover-multiaccount-screen [{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
{:db (dissoc db :multiaccounts/recover)}
|
||||
(navigation/navigate-to-cofx :recover nil)))
|
||||
(navigation/navigate-to-cofx :recover-multiaccount nil)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:multiaccounts.recover/recover-multiaccount
|
||||
(fn [[masked-passphrase password]]
|
||||
(recover-multiaccount! masked-passphrase password)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:multiaccounts.recover/import-mnemonic
|
||||
(fn [{:keys [passphrase password]}]
|
||||
(status-im.native-module.core/multiaccount-import-mnemonic
|
||||
passphrase
|
||||
password
|
||||
(fn [result]
|
||||
(re-frame/dispatch [:multiaccounts.recover/import-mnemonic-success result])))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:multiaccounts.recover/derive-addresses
|
||||
(fn [{:keys [account-id paths]}]
|
||||
(status-im.native-module.core/multiaccount-derive-addresses
|
||||
account-id
|
||||
paths
|
||||
(fn [result]
|
||||
(re-frame/dispatch [:multiaccounts.recover/derive-addresses-success result])))))
|
||||
|
||||
(fx/defn on-import-mnemonic-success
|
||||
{:events [:multiaccounts.recover/import-mnemonic-success]}
|
||||
[{:keys [db] :as cofx} result]
|
||||
(let [{:keys [id] :as data} (types/json->clj result)]
|
||||
{:db (assoc-in db [:multiaccounts/recover :root-key] data)
|
||||
:multiaccounts.recover/derive-addresses {:account-id id
|
||||
:paths [constants/path-default-wallet
|
||||
constants/path-whisper]}}))
|
||||
|
||||
(fx/defn on-derive-addresses-success
|
||||
{:events [:multiaccounts.recover/derive-addresses-success]}
|
||||
[{:keys [db] :as cofx} result]
|
||||
(let [data (types/json->clj result)]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:multiaccounts/recover :derived] data)}
|
||||
(navigation/navigate-to-cofx :recover-multiaccount-success nil))))
|
||||
|
||||
(fx/defn re-encrypt-pressed
|
||||
{:events [:recover.success.ui/re-encrypt-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:intro-wizard :selected-storage-type] :default)}
|
||||
(navigation/navigate-to-cofx :recover-multiaccount-select-storage nil)))
|
||||
|
||||
(fx/defn enter-phrase-pressed
|
||||
{:events [:recover.ui/enter-phrase-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
{:db (assoc db :multiaccounts/recover {:next-button-disabled? true})
|
||||
:dispatch [:bottom-sheet/hide-sheet]}
|
||||
(navigation/navigate-to-cofx :recover-multiaccount-enter-phrase nil)))
|
||||
|
||||
(fx/defn prepare-to-recover
|
||||
[{:keys [db random-guid-generator] :as cofx}]
|
||||
(fx/merge cofx
|
||||
{:db (-> db
|
||||
(assoc :node/on-ready :import-mnemonic)
|
||||
(assoc :multiaccounts/new-installation-id (random-guid-generator)))}
|
||||
(node/initialize nil)))
|
||||
|
||||
(fx/defn import-mnemonic
|
||||
[{:keys [db]}]
|
||||
(let [{:keys [password passphrase]} (:multiaccounts/recover db)]
|
||||
{:multiaccounts.recover/import-mnemonic
|
||||
{:passphrase passphrase
|
||||
:password password}}))
|
||||
|
||||
(fx/defn proceed-to-import-mnemonic
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [{:keys [passphrase]} (:multiaccounts/recover db)
|
||||
node-started? (= :started (:node/status db))]
|
||||
(when (mnemonic/valid-length? passphrase)
|
||||
(if node-started?
|
||||
(import-mnemonic cofx)
|
||||
(prepare-to-recover cofx)))))
|
||||
|
||||
(fx/defn enter-phrase-next-button-pressed
|
||||
{:events [:recover.enter-passphrase.ui/input-submitted
|
||||
:recover.enter-passphrase.ui/next-pressed]
|
||||
:interceptors [(re-frame/inject-cofx :random-guid-generator)]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
(proceed-to-import-mnemonic)))
|
||||
|
||||
(fx/defn cancel-pressed
|
||||
{:events [:recover.ui/cancel-pressed]}
|
||||
[cofx]
|
||||
(navigation/navigate-back cofx))
|
||||
|
||||
(fx/defn select-storage-next-pressed
|
||||
{:events [:recover.select-storage.ui/next-pressed]
|
||||
:interceptors [(re-frame/inject-cofx :random-guid-generator)]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [storage-type (get-in db [:intro-wizard :selected-storage-type])]
|
||||
(if (= storage-type :advanced)
|
||||
{:dispatch [:recovery.ui/keycard-option-pressed]})
|
||||
(navigation/navigate-to-cofx cofx :recover-multiaccount-enter-password nil)))
|
||||
|
||||
(fx/defn proceed-to-password-confirm
|
||||
[{:keys [db] :as cofx}]
|
||||
(when (nil? (get-in db [:multiaccounts/recover :password-error]))
|
||||
(navigation/navigate-to-cofx cofx :recover-multiaccount-confirm-password nil)))
|
||||
|
||||
(fx/defn enter-password-next-button-pressed
|
||||
{:events [:recover.enter-password.ui/input-submitted
|
||||
:recover.enter-password.ui/next-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
(validate-password)
|
||||
(proceed-to-password-confirm)))
|
||||
|
||||
(fx/defn confirm-password-next-button-pressed
|
||||
{:events [:recover.confirm-password.ui/input-submitted
|
||||
:recover.confirm-password.ui/next-pressed]
|
||||
:interceptors [(re-frame/inject-cofx :random-guid-generator)]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [{:keys [password password-confirmation]} (:multiaccounts/recover db)]
|
||||
(if (= password password-confirmation)
|
||||
(fx/merge cofx
|
||||
{:db (assoc db :intro-wizard nil)}
|
||||
(multiaccount-store-derived)
|
||||
(navigation/navigate-to-cofx :keycard-welcome nil))
|
||||
{:db (assoc-in db [:multiaccounts/recover :password-error] :password_error1)})))
|
||||
|
||||
(fx/defn count-words
|
||||
[{:keys [db]}]
|
||||
(let [passphrase (get-in db [:multiaccounts/recover :passphrase])]
|
||||
{:db (assoc-in db [:multiaccounts/recover :words-count]
|
||||
(mnemonic/words-count passphrase))}))
|
||||
|
||||
(fx/defn run-validation
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [passphrase (get-in db [:multiaccounts/recover :passphrase])]
|
||||
(when (= (last passphrase) " ")
|
||||
(fx/merge cofx
|
||||
(validate-phrase-for-warnings)))))
|
||||
|
||||
(fx/defn enter-phrase-input-changed
|
||||
{:events [:recover.enter-passphrase.ui/input-changed]}
|
||||
[cofx input]
|
||||
(fx/merge cofx
|
||||
(set-phrase input)
|
||||
(count-words)
|
||||
(run-validation)))
|
||||
|
||||
(fx/defn enter-password-input-changed
|
||||
{:events [:recover.enter-password.ui/input-changed]}
|
||||
[cofx input]
|
||||
(set-password cofx input))
|
||||
|
||||
(fx/defn confirm-password-input-changed
|
||||
{:events [:recover.confirm-password.ui/input-changed]}
|
||||
[{:keys [db]} input]
|
||||
{:db (-> db
|
||||
(assoc-in [:multiaccounts/recover :password-confirmation] input)
|
||||
(assoc-in [:multiaccounts/recover :password-error] nil))})
|
||||
|
|
|
@ -40,6 +40,9 @@
|
|||
(defn multiaccount-generate-and-derive-addresses [n mnemonic-length paths callback]
|
||||
(native-module/multiaccount-generate-and-derive-addresses n mnemonic-length paths callback))
|
||||
|
||||
(defn multiaccount-import-mnemonic [mnemonic password callback]
|
||||
(native-module/multiaccount-import-mnemonic mnemonic password callback))
|
||||
|
||||
(defn login [address password main-account watch-addresses callback]
|
||||
(native-module/login address password main-account watch-addresses callback))
|
||||
|
||||
|
|
|
@ -106,6 +106,14 @@
|
|||
|
||||
on-result)))
|
||||
|
||||
(defn multiaccount-import-mnemonic [mnemonic password on-result]
|
||||
(when (and @node-started (status))
|
||||
(.multiAccountImportMnemonic (status)
|
||||
(types/clj->json {:mnemonicPhrase mnemonic
|
||||
:Bip39Passphrase password})
|
||||
|
||||
on-result)))
|
||||
|
||||
(defn login [address password main-account watch-addresses on-result]
|
||||
(when (and @node-started (status))
|
||||
(.login (status)
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
:keycard-lock (js-require/js-require "./resources/images/ui/keycard-lock.png")
|
||||
:keycard (js-require/js-require "./resources/images/ui/keycard.png")
|
||||
:keycard-logo (js-require/js-require "./resources/images/ui/keycard-logo.png")
|
||||
:keycard-logo-blue (js-require/js-require "./resources/images/ui/keycard-logo-blue.png")
|
||||
:keycard-logo-gray (js-require/js-require "./resources/images/ui/keycard-logo-gray.png")
|
||||
:keycard-key (js-require/js-require "./resources/images/ui/keycard-key.png")
|
||||
:keycard-empty (js-require/js-require "./resources/images/ui/keycard-empty.png")
|
||||
:keycard-phone (js-require/js-require "./resources/images/ui/keycard-phone.png")
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.security :as security]
|
||||
[status-im.utils.types :as types]
|
||||
[taoensso.timbre :as log]))
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.multiaccounts.recover.core :as multiaccounts.recover]))
|
||||
|
||||
(fx/defn status-node-started
|
||||
[{db :db :as cofx}]
|
||||
|
@ -38,11 +39,8 @@
|
|||
:create-multiaccount
|
||||
(fn [_]
|
||||
{:multiaccounts.create/create-multiaccount (select-keys create [:id :password])})
|
||||
:recover-multiaccount
|
||||
(fn [{:keys [db]}]
|
||||
(let [{:keys [password passphrase]} (:multiaccounts/recover db)]
|
||||
{:multiaccounts.recover/recover-multiaccount
|
||||
[(security/mask-data passphrase) password]}))
|
||||
:import-mnemonic
|
||||
(multiaccounts.recover/import-mnemonic)
|
||||
:create-keycard-multiaccount
|
||||
(hardwallet/create-keycard-multiaccount)
|
||||
:start-onboarding
|
||||
|
|
|
@ -3,16 +3,20 @@
|
|||
[status-im.ui.components.common.common :refer [list-separator]]
|
||||
[status-im.ui.components.icons.vector-icons :as vi]
|
||||
[status-im.ui.components.react :as rn]
|
||||
[status-im.ui.components.colors :as colors]))
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.react-native.resources :as resources]))
|
||||
|
||||
(defn action-button [{:keys [label accessibility-label icon icon-opts on-press label-style cyrcle-color]}]
|
||||
(defn action-button [{:keys [label accessibility-label icon icon-opts image image-opts on-press label-style cyrcle-color]}]
|
||||
[rn/touchable-highlight (merge {:on-press on-press
|
||||
:underlay-color (colors/alpha colors/gray 0.15)}
|
||||
(when accessibility-label
|
||||
{:accessibility-label accessibility-label}))
|
||||
[rn/view {:style st/action-button}
|
||||
[rn/view {:style (st/action-button-icon-container cyrcle-color)}
|
||||
[vi/icon icon icon-opts]]
|
||||
(if image
|
||||
[react/image (assoc image-opts :source (resources/get-image image))]
|
||||
[vi/icon icon icon-opts])]
|
||||
[rn/view st/action-button-label-container
|
||||
[rn/text {:style (merge st/action-button-label label-style)}
|
||||
label]]]])
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
{:padding-horizontal 16
|
||||
:padding-vertical 9
|
||||
:background-color color
|
||||
:elevation 2
|
||||
:border-radius 8})
|
||||
|
||||
(def bottom-tooltip-text-container
|
||||
|
|
|
@ -19,7 +19,8 @@
|
|||
[status-im.ui.components.toolbar.view :as toolbar]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.ui.components.status-bar.view :as status-bar]
|
||||
[status-im.constants :as constants]))
|
||||
[status-im.constants :as constants]
|
||||
[status-im.utils.config :as config]))
|
||||
|
||||
(defn dots-selector [{:keys [on-press n selected color]}]
|
||||
[react/view {:style (styles/dot-selector n)}
|
||||
|
@ -128,20 +129,26 @@
|
|||
(utils/get-shortened-address public-key)]]
|
||||
[radio/radio selected?]]]))])
|
||||
|
||||
(defn storage-entry [{:keys [type icon icon-width icon-height title desc]} selected-storage-type]
|
||||
(defn storage-entry [{:keys [type icon icon-width icon-height
|
||||
image image-selected image-width image-height
|
||||
title desc]} selected-storage-type]
|
||||
(let [selected? (= type selected-storage-type)]
|
||||
[react/view
|
||||
[react/view {:style {:padding-top 14 :padding-bottom 4}}
|
||||
[react/text {:style (assoc styles/wizard-text :text-align :left :margin-left 16)}
|
||||
(i18n/label type)]]
|
||||
[react/touchable-highlight
|
||||
{:on-press #(re-frame/dispatch [:intro-wizard/on-key-storage-selected type])}
|
||||
{:on-press #(re-frame/dispatch [:intro-wizard/on-key-storage-selected (if config/hardwallet-enabled? type :default)])}
|
||||
[react/view (assoc (styles/list-item selected?)
|
||||
:align-items :flex-start
|
||||
:padding-top 20
|
||||
:padding-bottom 12)
|
||||
[vector-icons/icon icon {:color (if selected? colors/blue colors/gray)
|
||||
:width icon-width :height icon-height}]
|
||||
(if image
|
||||
[react/image
|
||||
{:source (resources/get-image (if selected? image-selected image))
|
||||
:style {:width image-width :height image-height}}]
|
||||
[vector-icons/icon icon {:color (if selected? colors/blue colors/gray)
|
||||
:width icon-width :height icon-height}])
|
||||
[react/view {:style {:margin-horizontal 16 :flex 1}}
|
||||
[react/text {:style (assoc styles/wizard-text :font-weight "500" :color colors/black :text-align :left)}
|
||||
(i18n/label title)]
|
||||
|
@ -157,12 +164,13 @@
|
|||
:icon-height 24
|
||||
:title :this-device
|
||||
:desc :this-device-desc}
|
||||
{:type :advanced
|
||||
:icon :main-icons/keycard-logo
|
||||
:icon-width 13
|
||||
:icon-height 22
|
||||
:title :keycard
|
||||
:desc :keycard-desc}]]
|
||||
{:type :advanced
|
||||
:image :keycard-logo-gray
|
||||
:image-selected :keycard-logo-blue
|
||||
:image-width 24
|
||||
:image-height 24
|
||||
:title :keycard
|
||||
:desc :keycard-desc}]]
|
||||
[react/view {:style {:flex 1
|
||||
:justify-content :flex-end
|
||||
;; We have to align top storage entry
|
||||
|
|
|
@ -397,58 +397,3 @@
|
|||
:label (i18n/label :t/next)
|
||||
:disabled? (empty? input-word)
|
||||
:forward? true}]]]]])))
|
||||
|
||||
;NOTE temporary screen, to be removed after Recovery will be implemented
|
||||
(defview enter-mnemonic []
|
||||
(letsubs [mnemonic [:hardwallet-mnemonic]]
|
||||
[react/view styles/container
|
||||
[toolbar/toolbar
|
||||
{:transparent? true
|
||||
:style {:margin-top 32}}
|
||||
[toolbar/nav-text
|
||||
{:handler #(re-frame/dispatch [:keycard.onboarding.ui/cancel-pressed])
|
||||
:style {:padding-left 21}}
|
||||
(i18n/label :t/cancel)]
|
||||
[react/text {:style {:color colors/gray}}
|
||||
(i18n/label :t/step-i-of-n {:step "1"
|
||||
:number "2"})]]
|
||||
[react/view {:flex 1
|
||||
:flex-direction :column
|
||||
:justify-content :space-between
|
||||
:align-items :center}
|
||||
[react/view {:flex-direction :column
|
||||
:align-items :center}
|
||||
[react/view {:margin-top 16}
|
||||
[react/text {:style {:typography :header
|
||||
:text-align :center}}
|
||||
"Enter your recovery phrase"]]
|
||||
[react/view {:margin-top 16
|
||||
:width "85%"
|
||||
:align-items :center}
|
||||
[react/text {:style {:color colors/gray
|
||||
:text-align :center}}
|
||||
"Enter your recovery phrase, separate the words by single spaces"]]]
|
||||
[react/view
|
||||
[text-input/text-input-with-label
|
||||
{:on-change-text #(re-frame/dispatch [:keycard.recovery.enter-mnemonic.ui/input-changed %])
|
||||
:auto-focus true
|
||||
:on-submit-editing #(re-frame/dispatch [:keycard.recovery.enter-mnemonic.ui/input-submitted])
|
||||
:placeholder nil
|
||||
:height 125
|
||||
:multiline true
|
||||
:auto-correct false
|
||||
:container {:background-color :white}
|
||||
:style {:background-color :white
|
||||
:typography :header}}]]
|
||||
[react/view {:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:align-items :center
|
||||
:width "100%"
|
||||
:height 86}
|
||||
[react/view]
|
||||
[react/view {:margin-right 20}
|
||||
[components.common/bottom-button
|
||||
{:on-press #(re-frame/dispatch [:keycard.recovery.enter-mnemonic.ui/next-pressed])
|
||||
:label (i18n/label :t/next)
|
||||
:disabled? (empty? mnemonic)
|
||||
:forward? true}]]]]]))
|
||||
|
|
|
@ -105,10 +105,12 @@
|
|||
[react/i18n-text {:style styles/processing :key :processing}]])
|
||||
[react/view {:style styles/bottom-button-container}
|
||||
[components.common/button
|
||||
{:label (i18n/label :t/access-key)
|
||||
{:label (i18n/label :t/access-key)
|
||||
:button-style styles/bottom-button
|
||||
:background? false
|
||||
:on-press #(re-frame/dispatch [:multiaccounts.recover.ui/recover-multiaccount-button-pressed])}]
|
||||
:background? false
|
||||
:on-press #(do
|
||||
(react/dismiss-keyboard!)
|
||||
(re-frame/dispatch [:multiaccounts.recover.ui/recover-multiaccount-button-pressed]))}]
|
||||
[components.common/button
|
||||
{:label (i18n/label :t/submit)
|
||||
:button-style styles/bottom-button
|
||||
|
|
|
@ -16,7 +16,17 @@
|
|||
[status-im.ui.components.common.common :as components.common]
|
||||
[status-im.utils.security :as security]
|
||||
[status-im.utils.platform :as platform]
|
||||
[clojure.string :as string]))
|
||||
[clojure.string :as string]
|
||||
[status-im.ui.components.action-button.styles :as action-button.styles]
|
||||
[status-im.ui.components.action-button.action-button :as action-button]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.utils.gfycat.core :as gfy]
|
||||
[status-im.utils.identicon :as identicon]
|
||||
[status-im.ui.components.radio :as radio]
|
||||
[status-im.ui.components.icons.vector-icons :as vector-icons]
|
||||
[status-im.ui.screens.intro.views :as intro.views]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.constants :as constants]))
|
||||
|
||||
(defview passphrase-input [passphrase error warning]
|
||||
(letsubs [input-ref (reagent/atom nil)]
|
||||
|
@ -94,3 +104,343 @@
|
|||
:label (i18n/label :t/sign-in)
|
||||
:disabled? disabled?
|
||||
:on-press sign-in}]])])))
|
||||
|
||||
(defn bottom-sheet-view []
|
||||
[react/view {:flex 1 :flex-direction :row}
|
||||
[react/view action-button.styles/actions-list
|
||||
[action-button/action-button
|
||||
{:label (i18n/label :t/enter-seed-phrase)
|
||||
:accessibility-label :enter-seed-phrase-button
|
||||
:icon :main-icons/text
|
||||
:icon-opts {:color colors/blue}
|
||||
:on-press #(re-frame/dispatch [:recover.ui/enter-phrase-pressed])}]
|
||||
[action-button/action-button
|
||||
{:label (i18n/label :t/recover-with-keycard)
|
||||
:label-style (if config/hardwallet-enabled? {} {:color colors/gray})
|
||||
:accessibility-label :recover-with-keycard-button
|
||||
:image :keycard-logo-blue
|
||||
:image-opts {:style {:width 24 :height 24}}
|
||||
:on-press #(when config/hardwallet-enabled?
|
||||
(re-frame/dispatch [:recover.ui/recover-with-keycard-pressed]))}]]])
|
||||
|
||||
(def bottom-sheet
|
||||
{:content bottom-sheet-view
|
||||
:content-height 130})
|
||||
|
||||
(defview enter-phrase []
|
||||
(letsubs [{:keys [passphrase
|
||||
processing?
|
||||
passphrase-error
|
||||
words-count
|
||||
next-button-disabled?]} [:get-recover-multiaccount]]
|
||||
[react/keyboard-avoiding-view {:flex 1
|
||||
:justify-content :space-between
|
||||
:background-color colors/white}
|
||||
[toolbar/toolbar
|
||||
{:transparent? true
|
||||
:style {:margin-top 32}}
|
||||
[toolbar/nav-text
|
||||
{:handler #(re-frame/dispatch [:recover.ui/cancel-pressed])
|
||||
:style {:padding-left 21}}
|
||||
(i18n/label :t/cancel)]
|
||||
[react/text {:style {:color colors/gray}}
|
||||
(i18n/label :t/step-i-of-n {:step "1"
|
||||
:number "2"})]]
|
||||
[react/view {:flex 1
|
||||
:flex-direction :column
|
||||
:justify-content :space-between
|
||||
:align-items :center}
|
||||
[react/view {:flex-direction :column
|
||||
:align-items :center}
|
||||
[react/view {:margin-top 16}
|
||||
[react/text {:style {:typography :header
|
||||
:text-align :center}}
|
||||
(i18n/label :t/multiaccounts-recover-enter-phrase-title)]]
|
||||
[react/view {:margin-top 16}
|
||||
[text-input/text-input-with-label
|
||||
{:on-change-text #(re-frame/dispatch [:recover.enter-passphrase.ui/input-changed (security/mask-data %)])
|
||||
:auto-focus true
|
||||
:on-submit-editing #(re-frame/dispatch [:recover.enter-passphrase.ui/input-submitted])
|
||||
:error (when passphrase-error (i18n/label passphrase-error))
|
||||
:placeholder nil
|
||||
:height 120
|
||||
:multiline true
|
||||
:auto-correct false
|
||||
:container {:background-color :white
|
||||
:min-width "50%"}
|
||||
:style {:background-color :white
|
||||
:text-align :center
|
||||
:font-size 16
|
||||
:font-weight "700"}}]]
|
||||
[react/view {:align-items :center}
|
||||
(when words-count
|
||||
[react/view {:flex-direction :row
|
||||
:height 11
|
||||
:align-items :center}
|
||||
(when-not next-button-disabled?
|
||||
[vector-icons/tiny-icon :tiny-icons/tiny-check])
|
||||
[react/text {:style {:font-size 14
|
||||
:padding-left 4
|
||||
:text-align :center
|
||||
:color colors/black}}
|
||||
(i18n/label-pluralize words-count :t/words-n)]])]
|
||||
(when next-button-disabled?
|
||||
[react/view {:margin-top 17
|
||||
:align-items :center}
|
||||
[react/text {:style {:color colors/black
|
||||
:font-size 14
|
||||
:text-align :center}}
|
||||
(i18n/label :t/multiaccounts-recover-enter-phrase-text)]])]
|
||||
(when processing?
|
||||
[react/view
|
||||
[react/activity-indicator {:size :large
|
||||
:animating true}]
|
||||
[react/text {:style {:color colors/gray
|
||||
:margin-top 8}}
|
||||
(i18n/label :t/processing)]])
|
||||
[react/view {:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:align-items :center
|
||||
:width "100%"
|
||||
:height 86}
|
||||
(when-not processing?
|
||||
[react/view])
|
||||
(when-not processing?
|
||||
[react/view {:margin-right 20}
|
||||
[components.common/bottom-button
|
||||
{:on-press #(re-frame/dispatch [:recover.enter-passphrase.ui/next-pressed])
|
||||
:label (i18n/label :t/next)
|
||||
:disabled? next-button-disabled?
|
||||
:forward? true}]])]]]))
|
||||
|
||||
(defview success []
|
||||
(letsubs [multiaccount [:get-recover-multiaccount]]
|
||||
(let [pubkey (get-in multiaccount [:derived constants/path-whisper-keyword :publicKey])]
|
||||
[react/view {:flex 1
|
||||
:justify-content :space-between
|
||||
:background-color colors/white}
|
||||
[toolbar/toolbar
|
||||
{:transparent? true
|
||||
:style {:margin-top 32}}
|
||||
nil
|
||||
nil]
|
||||
[react/view {:flex 1
|
||||
:flex-direction :column
|
||||
:justify-content :space-between
|
||||
:align-items :center}
|
||||
[react/view {:flex-direction :column
|
||||
:align-items :center}
|
||||
[react/view {:margin-top 16}
|
||||
[react/text {:style {:typography :header
|
||||
:text-align :center}}
|
||||
(i18n/label :t/keycard-recovery-success-header)]]
|
||||
[react/view {:margin-top 16
|
||||
:width "85%"
|
||||
:align-items :center}
|
||||
[react/text {:style {:color colors/gray
|
||||
:text-align :center}}
|
||||
(i18n/label :t/recovery-success-text)]]]
|
||||
[react/view {:flex-direction :column
|
||||
:flex 1
|
||||
:justify-content :center
|
||||
:align-items :center}
|
||||
[react/view {:margin-horizontal 16
|
||||
:flex-direction :column}
|
||||
[react/view {:justify-content :center
|
||||
:align-items :center
|
||||
:margin-bottom 11}
|
||||
[react/image {:source {:uri (identicon/identicon pubkey)}
|
||||
:style {:width 61
|
||||
:height 61
|
||||
:border-radius 30
|
||||
:border-width 1
|
||||
:border-color (colors/alpha colors/black 0.1)}}]]
|
||||
[react/text {:style {:text-align :center
|
||||
:color colors/black
|
||||
:font-weight "500"}
|
||||
:number-of-lines 1
|
||||
:ellipsize-mode :middle}
|
||||
(gfy/generate-gfy pubkey)]
|
||||
[react/text {:style {:text-align :center
|
||||
:margin-top 4
|
||||
:color colors/gray
|
||||
:font-family "monospace"}
|
||||
:number-of-lines 1
|
||||
:ellipsize-mode :middle}
|
||||
(utils/get-shortened-address pubkey)]]]
|
||||
[react/view {:margin-bottom 50}
|
||||
[react/touchable-highlight
|
||||
{:on-press #(re-frame/dispatch [:recover.success.ui/re-encrypt-pressed])}
|
||||
[react/view {:background-color colors/gray-background
|
||||
:align-items :center
|
||||
:justify-content :center
|
||||
:flex-direction :row
|
||||
:width 193
|
||||
:height 44
|
||||
:border-radius 10}
|
||||
[react/text {:style {:color colors/blue}}
|
||||
(i18n/label :t/re-encrypt-key)]]]]]])))
|
||||
|
||||
(defview select-storage []
|
||||
(letsubs [{:keys [selected-storage-type]} [:intro-wizard]
|
||||
{view-height :height} [:dimensions/window]]
|
||||
[react/view {:flex 1
|
||||
:justify-content :space-between
|
||||
:background-color colors/white}
|
||||
[toolbar/toolbar
|
||||
{:transparent? true
|
||||
:style {:margin-top 32}}
|
||||
[toolbar/nav-text
|
||||
{:handler #(re-frame/dispatch [:recover.ui/cancel-pressed])
|
||||
:style {:padding-left 21}}
|
||||
(i18n/label :t/cancel)]
|
||||
nil]
|
||||
[react/view {:flex 1
|
||||
:justify-content :space-between}
|
||||
[react/view {:flex-direction :column
|
||||
:align-items :center}
|
||||
[react/view {:margin-top 16}
|
||||
[react/text {:style {:typography :header
|
||||
:text-align :center}}
|
||||
(i18n/label :t/intro-wizard-title3)]]
|
||||
[react/view {:margin-top 16
|
||||
:width "85%"
|
||||
:align-items :center}
|
||||
[react/text {:style {:color colors/gray
|
||||
:text-align :center}}
|
||||
(i18n/label :t/intro-wizard-text3)]]]
|
||||
[intro.views/select-key-storage {:selected-storage-type (if config/hardwallet-enabled? selected-storage-type :default)} view-height]
|
||||
[react/view {:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:align-items :center
|
||||
:width "100%"
|
||||
:height 86}
|
||||
[react/view components.styles/flex]
|
||||
[react/view {:margin-right 20}
|
||||
[components.common/bottom-button
|
||||
{:on-press #(re-frame/dispatch [:recover.select-storage.ui/next-pressed])
|
||||
:forward? true}]]]]]))
|
||||
|
||||
(defview enter-password []
|
||||
(letsubs [{:keys [password password-error]} [:get-recover-multiaccount]]
|
||||
[react/keyboard-avoiding-view {:flex 1
|
||||
:justify-content :space-between
|
||||
:background-color colors/white}
|
||||
[toolbar/toolbar
|
||||
{:transparent? true
|
||||
:style {:margin-top 32}}
|
||||
[toolbar/nav-text
|
||||
{:handler #(re-frame/dispatch [:recover.ui/cancel-pressed])
|
||||
:style {:padding-left 21}}
|
||||
(i18n/label :t/cancel)]
|
||||
[react/text {:style {:color colors/gray}}
|
||||
(i18n/label :t/step-i-of-n {:step "1"
|
||||
:number "2"})]]
|
||||
[react/view {:flex 1
|
||||
:flex-direction :column
|
||||
:justify-content :space-between
|
||||
:align-items :center}
|
||||
[react/view {:flex-direction :column
|
||||
:align-items :center}
|
||||
[react/view {:margin-top 16}
|
||||
[react/text {:style {:typography :header
|
||||
:text-align :center}}
|
||||
(i18n/label :t/intro-wizard-title-alt4)]]
|
||||
[react/view {:margin-top 16
|
||||
:width "85%"
|
||||
:align-items :center}
|
||||
[react/text {:style {:color colors/gray
|
||||
:text-align :center}}
|
||||
(i18n/label :t/password-description)]]
|
||||
[react/view {:margin-top 16}
|
||||
[text-input/text-input-with-label
|
||||
{:on-change-text #(re-frame/dispatch [:recover.enter-password.ui/input-changed (security/mask-data %)])
|
||||
:auto-focus true
|
||||
:on-submit-editing #(re-frame/dispatch [:recover.enter-password.ui/input-submitted])
|
||||
:secure-text-entry true
|
||||
:error (when password-error (i18n/label password-error))
|
||||
:placeholder nil
|
||||
:height 125
|
||||
:multiline false
|
||||
:auto-correct false
|
||||
:container {:background-color :white
|
||||
:min-width "50%"}
|
||||
:style {:background-color :white
|
||||
:width 200
|
||||
:text-align :center
|
||||
:font-size 20
|
||||
:font-weight "700"}}]]]
|
||||
[react/view {:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:align-items :center
|
||||
:width "100%"
|
||||
:height 86}
|
||||
[react/view]
|
||||
[react/view {:margin-right 20}
|
||||
[components.common/bottom-button
|
||||
{:on-press #(re-frame/dispatch [:recover.enter-password.ui/next-pressed])
|
||||
:label (i18n/label :t/next)
|
||||
:disabled? (empty? password)
|
||||
:forward? true}]]]]]))
|
||||
|
||||
(defview confirm-password []
|
||||
(letsubs [{:keys [password-confirmation password-error]} [:get-recover-multiaccount]]
|
||||
[react/keyboard-avoiding-view {:flex 1
|
||||
:justify-content :space-between
|
||||
:background-color colors/white}
|
||||
[toolbar/toolbar
|
||||
{:transparent? true
|
||||
:style {:margin-top 32}}
|
||||
[toolbar/nav-text
|
||||
{:handler #(re-frame/dispatch [:recover.ui/cancel-pressed])
|
||||
:style {:padding-left 21}}
|
||||
(i18n/label :t/cancel)]
|
||||
[react/text {:style {:color colors/gray}}
|
||||
(i18n/label :t/step-i-of-n {:step "1"
|
||||
:number "2"})]]
|
||||
[react/view {:flex 1
|
||||
:flex-direction :column
|
||||
:justify-content :space-between
|
||||
:align-items :center}
|
||||
[react/view {:flex-direction :column
|
||||
:align-items :center}
|
||||
[react/view {:margin-top 16}
|
||||
[react/text {:style {:typography :header
|
||||
:text-align :center}}
|
||||
(i18n/label :t/intro-wizard-title-alt5)]]
|
||||
[react/view {:margin-top 16
|
||||
:width "85%"
|
||||
:align-items :center}
|
||||
[react/text {:style {:color colors/gray
|
||||
:text-align :center}}
|
||||
(i18n/label :t/password-description)]]
|
||||
[react/view {:margin-top 16}
|
||||
[text-input/text-input-with-label
|
||||
{:on-change-text #(re-frame/dispatch [:recover.confirm-password.ui/input-changed %])
|
||||
:auto-focus true
|
||||
:on-submit-editing #(re-frame/dispatch [:recover.confirm-password.ui/input-submitted])
|
||||
:error (when password-error (i18n/label password-error))
|
||||
:secure-text-entry true
|
||||
:placeholder nil
|
||||
:height 125
|
||||
:multiline false
|
||||
:auto-correct false
|
||||
:container {:background-color :white
|
||||
:min-width "50%"}
|
||||
:style {:background-color :white
|
||||
:width 200
|
||||
:text-align :center
|
||||
:font-size 20
|
||||
:font-weight "700"}}]]]
|
||||
[react/view {:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:align-items :center
|
||||
:width "100%"
|
||||
:height 86}
|
||||
[react/view]
|
||||
[react/view {:margin-right 20}
|
||||
[components.common/bottom-button
|
||||
{:on-press #(re-frame/dispatch [:recover.confirm-password.ui/next-pressed])
|
||||
:label (i18n/label :t/next)
|
||||
:disabled? (empty? password-confirmation)
|
||||
:forward? true}]]]]]))
|
||||
|
|
|
@ -5,7 +5,12 @@
|
|||
#{:login
|
||||
:progress
|
||||
:create-multiaccount
|
||||
:recover
|
||||
:recover-multiaccount
|
||||
:recover-multiaccount-enter-phrase
|
||||
:recover-multiaccount-select-storage
|
||||
:recover-multiaccount-enter-password
|
||||
:recover-multiaccount-confirm-password
|
||||
:recover-multiaccount-success
|
||||
:multiaccounts
|
||||
:intro
|
||||
:intro-wizard
|
||||
|
@ -32,7 +37,6 @@
|
|||
:keycard-onboarding-recovery-phrase
|
||||
:keycard-onboarding-recovery-phrase-confirm-word1
|
||||
:keycard-onboarding-recovery-phrase-confirm-word2
|
||||
:keycard-recovery-enter-mnemonic
|
||||
:keycard-recovery-intro
|
||||
:keycard-recovery-start
|
||||
:keycard-recovery-pair
|
||||
|
@ -46,7 +50,12 @@
|
|||
:screens (cond-> [:login
|
||||
:progress
|
||||
:create-multiaccount
|
||||
:recover
|
||||
:recover-multiaccount
|
||||
:recover-multiaccount-enter-phrase
|
||||
:recover-multiaccount-select-storage
|
||||
:recover-multiaccount-enter-password
|
||||
:recover-multiaccount-confirm-password
|
||||
:recover-multiaccount-success
|
||||
:multiaccounts]
|
||||
|
||||
config/hardwallet-enabled?
|
||||
|
@ -85,7 +94,6 @@
|
|||
:keycard-onboarding-recovery-phrase
|
||||
:keycard-onboarding-recovery-phrase-confirm-word1
|
||||
:keycard-onboarding-recovery-phrase-confirm-word2
|
||||
:keycard-recovery-enter-mnemonic
|
||||
:keycard-recovery-intro
|
||||
:keycard-recovery-start
|
||||
:keycard-recovery-pair
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
[status-im.ui.screens.about-app.views :as about-app]
|
||||
[status-im.ui.screens.multiaccounts.create.views :as multiaccounts.create]
|
||||
[status-im.ui.screens.multiaccounts.login.views :as login]
|
||||
[status-im.ui.screens.multiaccounts.recover.views :as recover]
|
||||
[status-im.ui.screens.multiaccounts.recover.views :as multiaccounts.recover]
|
||||
[status-im.ui.screens.multiaccounts.views :as multiaccounts]
|
||||
[status-im.ui.screens.add-new.new-chat.views :as new-chat]
|
||||
[status-im.ui.screens.add-new.new-public-chat.view :as new-public-chat]
|
||||
|
@ -71,7 +71,12 @@
|
|||
{:login login/login
|
||||
:progress progress/progress
|
||||
:create-multiaccount multiaccounts.create/create-multiaccount
|
||||
:recover recover/recover
|
||||
:recover-multiaccount multiaccounts.recover/recover
|
||||
:recover-multiaccount-enter-phrase multiaccounts.recover/enter-phrase
|
||||
:recover-multiaccount-select-storage multiaccounts.recover/select-storage
|
||||
:recover-multiaccount-enter-password multiaccounts.recover/enter-password
|
||||
:recover-multiaccount-confirm-password multiaccounts.recover/confirm-password
|
||||
:recover-multiaccount-success multiaccounts.recover/success
|
||||
:multiaccounts multiaccounts/multiaccounts
|
||||
:intro intro/intro
|
||||
:intro-wizard intro/wizard
|
||||
|
@ -94,7 +99,6 @@
|
|||
:keycard-onboarding-recovery-phrase keycard.onboarding/recovery-phrase
|
||||
:keycard-onboarding-recovery-phrase-confirm-word1 keycard.onboarding/recovery-phrase-confirm-word
|
||||
:keycard-onboarding-recovery-phrase-confirm-word2 keycard.onboarding/recovery-phrase-confirm-word
|
||||
:keycard-recovery-enter-mnemonic keycard.onboarding/enter-mnemonic
|
||||
:keycard-pairing keycard/pairing
|
||||
:keycard-nfc-on keycard/nfc-on
|
||||
:keycard-connection-lost keycard/connection-lost
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
[status-im.ui.screens.routing.core :as routing]
|
||||
[status-im.ui.screens.signing.views :as signing]
|
||||
[status-im.ui.screens.popover.views :as popover]
|
||||
[status-im.ui.screens.multiaccounts.recover.views :as recover.views]
|
||||
[status-im.utils.dimensions :as dimensions]
|
||||
status-im.ui.screens.wallet.collectibles.etheremon.views
|
||||
status-im.ui.screens.wallet.collectibles.cryptostrikers.views
|
||||
|
@ -59,7 +60,10 @@
|
|||
(merge home.sheet/private-chat-actions)
|
||||
|
||||
(= view :group-chat-actions)
|
||||
(merge home.sheet/group-chat-actions))]
|
||||
(merge home.sheet/group-chat-actions)
|
||||
|
||||
(= view :recover-sheet)
|
||||
(merge recover.views/bottom-sheet))]
|
||||
|
||||
[bottom-sheet/bottom-sheet opts])))
|
||||
|
||||
|
|
|
@ -6,7 +6,21 @@ class PassphraseInput(BaseEditBox):
|
|||
|
||||
def __init__(self, driver):
|
||||
super(PassphraseInput, self).__init__(driver)
|
||||
self.locator = self.Locator.accessibility_id("enter-12-words")
|
||||
self.locator = self.Locator.xpath_selector("//android.widget.EditText")
|
||||
|
||||
|
||||
class EnterSeedPhraseButton(BaseButton):
|
||||
|
||||
def __init__(self, driver):
|
||||
super(EnterSeedPhraseButton, self).__init__(driver)
|
||||
self.locator = self.Locator.accessibility_id("enter-seed-phrase-button")
|
||||
|
||||
|
||||
class ReencryptYourKeyButton(BaseButton):
|
||||
|
||||
def __init__(self, driver):
|
||||
super(ReencryptYourKeyButton, self).__init__(driver)
|
||||
self.locator = self.Locator.xpath_selector("//android.widget.TextView[@text='Re-encrypt your key']")
|
||||
|
||||
|
||||
class ConfirmRecoverAccess(BaseButton):
|
||||
|
@ -72,7 +86,9 @@ class RecoverAccessView(SignInView):
|
|||
self.driver = driver
|
||||
|
||||
self.passphrase_input = PassphraseInput(self.driver)
|
||||
self.enter_seed_phrase_button = EnterSeedPhraseButton(self.driver)
|
||||
self.confirm_recover_access = ConfirmRecoverAccess(self.driver)
|
||||
self.reencrypt_your_key_button = ReencryptYourKeyButton(self.driver)
|
||||
self.warnings = Warnings(self.driver)
|
||||
self.confirm_phrase_button = ConfirmPhraseButton(self.driver)
|
||||
self.cancel_button = CancelPhraseButton(self.driver)
|
||||
|
|
|
@ -34,15 +34,15 @@ class RecoverAccountPasswordInput(BaseEditBox):
|
|||
class CreatePasswordInput(BaseEditBox):
|
||||
def __init__(self, driver):
|
||||
super(CreatePasswordInput, self).__init__(driver)
|
||||
self.locator = self.Locator.xpath_selector("//android.widget.TextView[@text='Create a password']"
|
||||
"/following-sibling::android.widget.EditText")
|
||||
self.locator = self.Locator.xpath_selector("//android.widget.TextView[@text='Create a password']/.."
|
||||
"//android.widget.EditText")
|
||||
|
||||
|
||||
class ConfirmYourPasswordInput(BaseEditBox):
|
||||
def __init__(self, driver):
|
||||
super(ConfirmYourPasswordInput, self).__init__(driver)
|
||||
self.locator = self.Locator.xpath_selector("//android.widget.TextView[@text='Confirm your password']"
|
||||
"/following-sibling::android.widget.EditText")
|
||||
self.locator = self.Locator.xpath_selector("//android.widget.TextView[@text='Confirm your password']/.."
|
||||
"//android.widget.EditText")
|
||||
|
||||
|
||||
class SignInButton(BaseButton):
|
||||
|
@ -198,11 +198,16 @@ class SignInView(BaseView):
|
|||
recover_access_view = self.add_existing_multiaccount_button.click()
|
||||
else:
|
||||
recover_access_view = self.access_key_button.click()
|
||||
recover_access_view.enter_seed_phrase_button.click()
|
||||
recover_access_view.passphrase_input.click()
|
||||
recover_access_view.passphrase_input.set_value(passphrase)
|
||||
recover_access_view.recover_account_password_input.click()
|
||||
recover_access_view.recover_account_password_input.set_value(password)
|
||||
recover_access_view.sign_in_button.click_until_presence_of_element(recover_access_view.home_button)
|
||||
recover_access_view.next_button.click()
|
||||
recover_access_view.reencrypt_your_key_button.click()
|
||||
recover_access_view.next_button.click()
|
||||
recover_access_view.create_password_input.set_value(password)
|
||||
recover_access_view.next_button.click()
|
||||
recover_access_view.confirm_your_password_input.set_value(password)
|
||||
recover_access_view.next_button.click_until_presence_of_element(recover_access_view.home_button)
|
||||
return self.get_home_view()
|
||||
|
||||
def sign_in(self, password=common_password):
|
||||
|
|
|
@ -1,16 +1,22 @@
|
|||
(ns status-im.test.ethereum.mnemonic
|
||||
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||
[status-im.ethereum.mnemonic :as mnemonic]))
|
||||
[status-im.ethereum.mnemonic :as mnemonic]
|
||||
[clojure.string :as string]))
|
||||
|
||||
(deftest valid-length?
|
||||
(is (not (mnemonic/valid-length? "rate rate")))
|
||||
(is (not (mnemonic/valid-length? (string/join " " (repeat 13 "rate")))))
|
||||
(is (not (mnemonic/valid-length? (string/join " " (repeat 16 "rate")))))
|
||||
(is (mnemonic/valid-length? (string/join " " (repeat 12 "rate"))))
|
||||
(is (mnemonic/valid-length? (string/join " " (repeat 15 "rate"))))
|
||||
(is (mnemonic/valid-length? (string/join " " (repeat 18 "rate"))))
|
||||
(is (mnemonic/valid-length? (string/join " " (repeat 21 "rate"))))
|
||||
(is (mnemonic/valid-length? (string/join " " (repeat 24 "rate")))))
|
||||
|
||||
(deftest valid-words?
|
||||
(is (not (mnemonic/valid-words? ["rate" "rate"])))
|
||||
(is (not (mnemonic/valid-words? ["rate" "rate" "rate" "rate" "rate" "rate" "rate" "rate" "rate" "rate" "rate" "rate?"])))
|
||||
(is (mnemonic/valid-words? ["rate" "rate" "rate" "rate" "rate" "rate" "rate" "rate" "rate" "rate" "rate" "rate"])))
|
||||
|
||||
(deftest valid-phrase
|
||||
(is (not (mnemonic/valid-phrase? "rate rate")))
|
||||
(is (not (mnemonic/valid-phrase? "rate rate rate rate rate rate rate rate rate rate rate rate?")))
|
||||
(is (mnemonic/valid-phrase? "rate rate rate rate rate rate rate rate rate rate rate rate")))
|
||||
(is (not (mnemonic/valid-words? "rate! rate")))
|
||||
(is (not (mnemonic/valid-words? "rate rate rate rate rate rate rate rate rate rate rate rate?")))
|
||||
(is (mnemonic/valid-words? "rate rate rate rate rate rate rate rate rate rate rate rate")))
|
||||
|
||||
(deftest passphrase->words?
|
||||
(is (= ["one" "two" "three" "for" "five" "six" "seven" "height" "nine" "ten" "eleven" "twelve"]
|
||||
|
|
|
@ -21,15 +21,15 @@
|
|||
(is (= :required-field (models/check-phrase-errors nil)))
|
||||
(is (= :required-field (models/check-phrase-errors " ")))
|
||||
(is (= :required-field (models/check-phrase-errors " \t\n ")))
|
||||
(is (= :recovery-phrase-invalid (models/check-phrase-errors "phrase with four words")))
|
||||
(is (= :recovery-phrase-invalid (models/check-phrase-errors "phrase with five cool words")))
|
||||
(is (= :recovery-phrase-wrong-length (models/check-phrase-errors "phrase with four words")))
|
||||
(is (= :recovery-phrase-wrong-length (models/check-phrase-errors "phrase with five cool words")))
|
||||
(is (nil? (models/check-phrase-errors "monkey monkey monkey monkey monkey monkey monkey monkey monkey monkey monkey monkey")))
|
||||
(is (nil? (models/check-phrase-errors (string/join " " (repeat 15 "monkey")))))
|
||||
(is (nil? (models/check-phrase-errors (string/join " " (repeat 18 "monkey")))))
|
||||
(is (nil? (models/check-phrase-errors (string/join " " (repeat 24 "monkey")))))
|
||||
(is (= :recovery-phrase-invalid (models/check-phrase-errors (string/join " " (repeat 14 "monkey")))))
|
||||
(is (= :recovery-phrase-invalid (models/check-phrase-errors (string/join " " (repeat 11 "monkey")))))
|
||||
(is (= :recovery-phrase-invalid (models/check-phrase-errors (string/join " " (repeat 19 "monkey")))))
|
||||
(is (= :recovery-phrase-wrong-length (models/check-phrase-errors (string/join " " (repeat 14 "monkey")))))
|
||||
(is (= :recovery-phrase-wrong-length (models/check-phrase-errors (string/join " " (repeat 11 "monkey")))))
|
||||
(is (= :recovery-phrase-wrong-length (models/check-phrase-errors (string/join " " (repeat 19 "monkey")))))
|
||||
(is (= :recovery-phrase-invalid (models/check-phrase-errors "monkey monkey monkey 12345 monkey adf+123 monkey monkey monkey monkey monkey monkey")))
|
||||
;;NOTE(goranjovic): the following check should be ok because we sanitize extra whitespace
|
||||
(is (nil? (models/check-phrase-errors " monkey monkey monkey\t monkey monkey monkey monkey monkey monkey monkey monkey monkey \t "))))
|
||||
|
@ -42,44 +42,49 @@
|
|||
;;;; handlers
|
||||
|
||||
(deftest set-phrase
|
||||
(is (= {:db {:multiaccounts/recover {:passphrase "game buzz method pretty olympic fat quit display velvet unveil marine crater"
|
||||
:passphrase-valid? true}}}
|
||||
(is (= {:db {:multiaccounts/recover {:passphrase "game buzz method pretty olympic fat quit display velvet unveil marine crater"
|
||||
:passphrase-error nil
|
||||
:next-button-disabled? false}}}
|
||||
(models/set-phrase {:db {}} (security/mask-data "game buzz method pretty olympic fat quit display velvet unveil marine crater"))))
|
||||
(is (= {:db {:multiaccounts/recover {:passphrase "game buzz method pretty olympic fat quit display velvet unveil marine crater"
|
||||
:passphrase-valid? true}}}
|
||||
(is (= {:db {:multiaccounts/recover {:passphrase "game buzz method pretty olympic fat quit display velvet unveil marine crater"
|
||||
:passphrase-error nil
|
||||
:next-button-disabled? false}}}
|
||||
(models/set-phrase {:db {}} (security/mask-data "Game buzz method pretty Olympic fat quit DISPLAY velvet unveil marine crater"))))
|
||||
(is (= {:db {:multiaccounts/recover {:passphrase "game buzz method pretty zeus fat quit display velvet unveil marine crater"
|
||||
:passphrase-valid? true}}}
|
||||
(is (= {:db {:multiaccounts/recover {:passphrase "game buzz method pretty zeus fat quit display velvet unveil marine crater"
|
||||
:passphrase-error nil
|
||||
:next-button-disabled? false}}}
|
||||
(models/set-phrase {:db {}} (security/mask-data "game buzz method pretty zeus fat quit display velvet unveil marine crater"))))
|
||||
(is (= {:db {:multiaccounts/recover {:passphrase " game\t buzz method pretty olympic fat quit\t display velvet unveil marine crater "
|
||||
:passphrase-valid? true}}}
|
||||
(is (= {:db {:multiaccounts/recover {:passphrase " game\t buzz method pretty olympic fat quit\t display velvet unveil marine crater "
|
||||
:passphrase-error nil
|
||||
:next-button-disabled? false}}}
|
||||
(models/set-phrase {:db {}} (security/mask-data " game\t buzz method pretty olympic fat quit\t display velvet unveil marine crater "))))
|
||||
(is (= {:db {:multiaccounts/recover {:passphrase "game buzz method pretty 1234 fat quit display velvet unveil marine crater"
|
||||
:passphrase-valid? false}}}
|
||||
(is (= {:db {:multiaccounts/recover {:passphrase "game buzz method pretty 1234 fat quit display velvet unveil marine crater"
|
||||
:passphrase-error nil
|
||||
:next-button-disabled? false}}}
|
||||
(models/set-phrase {:db {}} (security/mask-data "game buzz method pretty 1234 fat quit display velvet unveil marine crater")))))
|
||||
|
||||
(deftest validate-phrase
|
||||
(is (= {:db {:multiaccounts/recover {:passphrase-error nil
|
||||
:passphrase-warning nil
|
||||
:passphrase "game buzz method pretty olympic fat quit display velvet unveil marine crater"}}}
|
||||
(models/validate-phrase {:db {:multiaccounts/recover {:passphrase "game buzz method pretty olympic fat quit display velvet unveil marine crater"}}})))
|
||||
(is (= {:db {:multiaccounts/recover {:passphrase-error nil
|
||||
:passphrase-warning :recovery-phrase-unknown-words
|
||||
:passphrase "game buzz method pretty zeus fat quit display velvet unveil marine crater"}}}
|
||||
(is (= {:db {:multiaccounts/recover {:passphrase-error :recovery-phrase-unknown-words
|
||||
:passphrase "game buzz method pretty zeus fat quit display velvet unveil marine crater"}}}
|
||||
(models/validate-phrase {:db {:multiaccounts/recover {:passphrase "game buzz method pretty zeus fat quit display velvet unveil marine crater"}}})))
|
||||
(is (= {:db {:multiaccounts/recover {:passphrase-error :recovery-phrase-invalid
|
||||
:passphrase-warning :recovery-phrase-unknown-words
|
||||
:passphrase "game buzz method pretty 1234 fat quit display velvet unveil marine crater"}}}
|
||||
(models/validate-phrase {:db {:multiaccounts/recover {:passphrase "game buzz method pretty 1234 fat quit display velvet unveil marine crater"}}}))))
|
||||
|
||||
(deftest set-password
|
||||
(is (= {:db {:multiaccounts/recover {:password " "
|
||||
:password-error nil
|
||||
:password-valid? false}}}
|
||||
(models/set-password {:db {}} (security/mask-data " "))))
|
||||
(is (= {:db {:multiaccounts/recover {:password "abc"
|
||||
:password-error nil
|
||||
:password-valid? false}}}
|
||||
(models/set-password {:db {}} (security/mask-data "abc"))))
|
||||
(is (= {:db {:multiaccounts/recover {:password "thisisapaswoord"
|
||||
:password-error nil
|
||||
:password-valid? true}}}
|
||||
(models/set-password {:db {}} (security/mask-data "thisisapaswoord")))))
|
||||
|
||||
|
@ -99,18 +104,15 @@
|
|||
:db {:multiaccounts/recover
|
||||
{:passphrase "game buzz method pretty zeus fat quit display velvet unveil marine crater"
|
||||
:password "thisisapaswoord"}}})]
|
||||
(is (contains? new-cofx :node/start))
|
||||
(is (= "random" (get-in new-cofx [:db :multiaccounts/new-installation-id])))
|
||||
(is (= :recover-multiaccount (get-in new-cofx [:db :node/on-ready])))))
|
||||
(is (not (nil? (get new-cofx :multiaccounts.recover/recover-multiaccount))))))
|
||||
|
||||
(deftest recover-multiaccount-with-checks
|
||||
(let [new-cofx (models/recover-multiaccount-with-checks {:random-guid-generator (constantly "random")
|
||||
:db {:multiaccounts/recover
|
||||
{:passphrase "game buzz method pretty olympic fat quit display velvet unveil marine crater"
|
||||
:password "thisisapaswoord"}}})]
|
||||
(is (contains? new-cofx :node/start))
|
||||
(is (= "random" (get-in new-cofx [:db :multiaccounts/new-installation-id])))
|
||||
(is (= :recover-multiaccount (get-in new-cofx [:db :node/on-ready]))))
|
||||
(is (= "random" (get-in new-cofx [:db :multiaccounts/new-installation-id]))))
|
||||
(let [new-cofx (models/recover-multiaccount-with-checks {:random-guid-generator (constantly "random")
|
||||
:db {:multiaccounts/recover
|
||||
{:passphrase "game buzz method pretty zeus fat quit display velvet unveil marine crater"
|
||||
|
|
|
@ -302,7 +302,6 @@
|
|||
"save-password": "Save password",
|
||||
"submit": "Submit",
|
||||
"recover-key": "Recover key",
|
||||
"processing": "Processing...",
|
||||
"currency-display-name-kes": "Kenyan Shilling",
|
||||
"view-etheremon": "View in Etheremon",
|
||||
"wallet-transaction-fee-details": "Gas limit caps the units of gas spent on the transaction. Gas price sets the price per unit of gas. Increasing gas price can make your transaction faster.",
|
||||
|
@ -736,6 +735,7 @@
|
|||
"browser-not-secure": "Connection is not secure! Do not sign transactions or send personal data on this site.",
|
||||
"welcome-to-status-description": "Here you can chat with people in a secure private chat, browse and interact with DApps.",
|
||||
"recovery-phrase-invalid": "Recovery phrase is invalid",
|
||||
"recovery-phrase-wrong-length": "Please make sure the phrase you enter has 12, 15, 18, 21, or 24 words.",
|
||||
"currency-display-name-cny": "China Yuan Renminbi",
|
||||
"clear-history-confirmation-content": "Are you sure you want to clear this chat history?",
|
||||
"mailserver-reconnect": "Could not connect to mailserver. Tap to reconnect",
|
||||
|
@ -1269,5 +1269,16 @@
|
|||
"account-color": "Account color",
|
||||
"to-encrypt-enter-password": "To encrypt the account please enter your password",
|
||||
"accounts": "Accounts",
|
||||
"add-account-incorrect-password": "Password seems to be incorrect. Enter the password you use to unlock the app."
|
||||
"add-account-incorrect-password": "Password seems to be incorrect. Enter the password you use to unlock the app.",
|
||||
"remember-me": "Remember me",
|
||||
"enter-seed-phrase": "Enter Seed phrase",
|
||||
"recover-with-keycard": "Recover with Keycard",
|
||||
"multiaccounts-recover-enter-phrase-title": "Enter your seed phrase",
|
||||
"multiaccounts-recover-enter-phrase-text": "Enter 12, 15, 18, 21 or 24 words.\nSeperate words by a single space.",
|
||||
"words-n": {
|
||||
"one": "1 word",
|
||||
"other": "{{count}} words"
|
||||
},
|
||||
"re-encrypt-key": "Re-encrypt your key",
|
||||
"recovery-success-text": "You will have to create a new code or password to re-encrypt your key"
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue