Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
lightning-bits
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
bitsoko services
lightning-bits
Commits
89b74488
Unverified
Commit
89b74488
authored
May 16, 2019
by
valentinewallace
Committed by
GitHub
May 16, 2019
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1106 from lightninglabs/dev/seed-recovery-mobile
Dev/seed recovery mobile
parents
e110f571
87d1b607
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
154 additions
and
118 deletions
+154
-118
nav-mobile.js
src/action/nav-mobile.js
+0
-4
nav.js
src/action/nav.js
+0
-4
wallet.js
src/action/wallet.js
+14
-16
store.js
src/store.js
+1
-1
main-mobile.js
src/view/main-mobile.js
+4
-0
main.js
src/view/main.js
+0
-4
restore-password.js
src/view/restore-password.js
+0
-53
restore-seed-mobile.js
src/view/restore-seed-mobile.js
+89
-0
restore-seed.js
src/view/restore-seed.js
+10
-3
screen-story.js
stories/screen-story.js
+4
-4
nav.spec.js
test/unit/action/nav.spec.js
+0
-7
wallet.spec.js
test/unit/action/wallet.spec.js
+32
-22
No files found.
src/action/nav-mobile.js
View file @
89b74488
...
...
@@ -55,10 +55,6 @@ class NavAction {
this
.
_navigate
(
'RestoreSeed'
);
}
goRestorePin
()
{
this
.
_navigate
(
'RestorePin'
);
}
goSeedSuccess
()
{
this
.
_navigate
(
'SeedSuccess'
);
}
...
...
src/action/nav.js
View file @
89b74488
...
...
@@ -29,10 +29,6 @@ class NavAction {
this
.
_store
.
route
=
'RestoreSeed'
;
}
goRestorePassword
()
{
this
.
_store
.
route
=
'RestorePassword'
;
}
goSeedSuccess
()
{
this
.
_store
.
route
=
'SeedSuccess'
;
}
...
...
src/action/wallet.js
View file @
89b74488
...
...
@@ -53,7 +53,15 @@ class WalletAction {
* @param {number} options.index The seed index
*/
setRestoreSeed
({
word
,
index
})
{
this
.
_store
.
wallet
.
restoreSeed
[
index
]
=
word
;
this
.
_store
.
seedMnemonic
[
index
]
=
word
;
}
/**
* Set which seed restore input is in focus.
* @param {number} options.index The index of the input.
*/
setFocusedRestoreInd
({
index
})
{
this
.
_store
.
wallet
.
focusedRestoreInd
=
index
;
}
//
...
...
@@ -212,6 +220,7 @@ class WalletAction {
}
await
this
.
initWallet
({
walletPassword
:
newPassword
,
recoveryWindow
:
this
.
_store
.
settings
.
restoring
?
RECOVERY_WINDOW
:
0
,
seedMnemonic
:
this
.
_store
.
seedMnemonic
.
toJSON
(),
});
}
...
...
@@ -311,6 +320,7 @@ class WalletAction {
* @return {undefined}
*/
initRestoreWallet
()
{
this
.
_store
.
seedMnemonic
=
Array
(
24
).
fill
(
''
);
this
.
_store
.
wallet
.
restoreIndex
=
0
;
this
.
_nav
.
goRestoreSeed
();
}
...
...
@@ -324,8 +334,9 @@ class WalletAction {
initNextRestorePage
()
{
if
(
this
.
_store
.
wallet
.
restoreIndex
<
21
)
{
this
.
_store
.
wallet
.
restoreIndex
+=
3
;
this
.
_store
.
wallet
.
focusedRestoreInd
=
this
.
_store
.
wallet
.
restoreIndex
;
}
else
{
this
.
_nav
.
goRestore
Password
();
this
.
initSet
Password
();
}
}
...
...
@@ -337,6 +348,7 @@ class WalletAction {
initPrevRestorePage
()
{
if
(
this
.
_store
.
wallet
.
restoreIndex
>=
3
)
{
this
.
_store
.
wallet
.
restoreIndex
-=
3
;
this
.
_store
.
wallet
.
focusedRestoreInd
=
this
.
_store
.
wallet
.
restoreIndex
;
}
else
{
this
.
_nav
.
goSelectSeed
();
}
...
...
@@ -375,20 +387,6 @@ class WalletAction {
await
this
.
unlockWallet
({
walletPassword
:
password
});
}
/**
* Initialize the wallet with the password input the seed that was already
* inputted, and the default recovery window.
* @return {Promise<undefined>}
*/
async
restoreWallet
()
{
const
{
password
,
restoreSeed
}
=
this
.
_store
.
wallet
;
await
this
.
initWallet
({
walletPassword
:
password
,
seedMnemonic
:
restoreSeed
.
toJSON
(),
recoveryWindow
:
RECOVERY_WINDOW
,
});
}
/**
* Unlock the wallet by calling the grpc api with the user chosen password.
* @param {string} options.walletPassword The password used to encrypt the wallet
...
...
src/store.js
View file @
89b74488
...
...
@@ -51,7 +51,7 @@ export class Store {
seedVerify
:
[
''
,
''
,
''
],
seedIndex
:
0
,
restoreIndex
:
0
,
restoreSeed
:
Array
(
24
).
fill
(
''
)
,
focusedRestoreInd
:
0
,
},
transactions
:
[],
selectedTransaction
:
null
,
...
...
src/view/main-mobile.js
View file @
89b74488
...
...
@@ -16,6 +16,7 @@ import SeedVerifyView from './seed-verify-mobile';
import
SetPinView
from
'./set-pin-mobile'
;
import
SetPinConfirmView
from
'./set-pin-confirm-mobile'
;
import
SeedSuccessView
from
'./seed-success-mobile'
;
import
RestoreSeedView
from
'./restore-seed-mobile'
;
import
NewAddressView
from
'./new-address-mobile'
;
import
PinView
from
'./pin-mobile'
;
...
...
@@ -84,6 +85,8 @@ const SetPasswordConfirm = () => (
const
SeedSuccess
=
()
=>
<
SeedSuccessView
wallet
=
{
wallet
}
/>
;
const
RestoreSeed
=
()
=>
<
RestoreSeedView
store
=
{
store
}
wallet
=
{
wallet
}
/>
;
const
NewAddress
=
()
=>
(
<
NewAddressView
store
=
{
store
}
invoice
=
{
invoice
}
info
=
{
info
}
/
>
);
...
...
@@ -190,6 +193,7 @@ const MainStack = createStackNavigator(
SetPassword
,
SetPasswordConfirm
,
SeedSuccess
,
RestoreSeed
,
NewAddress
,
Password
,
LoaderSyncing
,
...
...
src/view/main.js
View file @
89b74488
...
...
@@ -11,7 +11,6 @@ import SeedSuccess from './seed-success';
import
SetPassword
from
'./set-password'
;
import
SetPasswordConfirm
from
'./set-password-confirm'
;
import
RestoreSeed
from
'./restore-seed'
;
import
RestorePassword
from
'./restore-password'
;
import
Password
from
'./password'
;
import
ResetPasswordCurrent
from
'./reset-password-current'
;
import
ResetPasswordNew
from
'./reset-password-new'
;
...
...
@@ -83,9 +82,6 @@ class MainView extends Component {
{
route
===
'RestoreSeed'
&&
(
<
RestoreSeed
store
=
{
store
}
wallet
=
{
wallet
}
/
>
)}
{
route
===
'RestorePassword'
&&
(
<
RestorePassword
store
=
{
store
}
wallet
=
{
wallet
}
nav
=
{
nav
}
/
>
)}
{
route
===
'Password'
&&
<
Password
store
=
{
store
}
wallet
=
{
wallet
}
/>
}
{
route
===
'ResetPasswordCurrent'
&&
(
<
ResetPasswordCurrent
store
=
{
store
}
nav
=
{
nav
}
wallet
=
{
wallet
}
/
>
...
...
src/view/restore-password.js
deleted
100644 → 0
View file @
e110f571
import
React
from
'react'
;
import
{
StyleSheet
}
from
'react-native'
;
import
{
observer
}
from
'mobx-react'
;
import
PropTypes
from
'prop-types'
;
import
{
SplitBackground
}
from
'../component/background'
;
import
MainContent
from
'../component/main-content'
;
import
{
H1Text
}
from
'../component/text'
;
import
{
Header
}
from
'../component/header'
;
import
{
Button
,
BackButton
,
GlasButton
}
from
'../component/button'
;
import
{
PasswordCard
}
from
'../component/password-entry'
;
import
{
color
}
from
'../component/style'
;
//
// Restore Wallet Password View
//
const
styles
=
StyleSheet
.
create
({
content
:
{
justifyContent
:
'flex-end'
,
},
title
:
{
textAlign
:
'center'
,
marginBottom
:
20
,
},
});
const
RestorePasswordView
=
({
store
,
wallet
,
nav
})
=>
(
<
SplitBackground
image
=
"purple-gradient-bg"
bottom
=
{
color
.
blackDark
}
>
<
Header
>
<
BackButton
onPress
=
{()
=>
nav
.
goSelectSeed
()}
/
>
<
Button
disabled
onPress
=
{()
=>
{}}
/
>
<
/Header
>
<
MainContent
style
=
{
styles
.
content
}
>
<
H1Text
style
=
{
styles
.
title
}
>
Restore
wallet
<
/H1Text
>
<
PasswordCard
copy
=
"Please enter your password."
placeholder
=
"Password"
password
=
{
store
.
wallet
.
password
}
onChangeText
=
{
password
=>
wallet
.
setPassword
({
password
})}
onSubmitEditing
=
{()
=>
wallet
.
restoreWallet
()}
/
>
<
GlasButton
onPress
=
{()
=>
wallet
.
restoreWallet
()}
>
Restore
<
/GlasButton
>
<
/MainContent
>
<
/SplitBackground
>
);
RestorePasswordView
.
propTypes
=
{
store
:
PropTypes
.
object
.
isRequired
,
wallet
:
PropTypes
.
object
.
isRequired
,
nav
:
PropTypes
.
object
.
isRequired
,
};
export
default
observer
(
RestorePasswordView
);
src/view/restore-seed-mobile.js
0 → 100644
View file @
89b74488
import
React
from
'react'
;
import
{
observer
}
from
'mobx-react'
;
import
PropTypes
from
'prop-types'
;
import
SeedEntry
from
'../component/seed-entry'
;
import
{
Button
,
BackButton
,
SmallGlasButton
}
from
'../component/button'
;
import
{
FormSubText
}
from
'../component/form'
;
import
Background
from
'../component/background'
;
import
MainContent
from
'../component/main-content'
;
import
{
CopyOnboardText
}
from
'../component/text'
;
import
{
Header
}
from
'../component/header'
;
import
Card
from
'../component/card'
;
import
{
createStyles
,
maxWidth
}
from
'../component/media-query'
;
import
{
smallBreakWidth
}
from
'../component/style'
;
//
// Restore Seed View (Mobile)
//
const
baseStyles
=
{
content
:
{
justifyContent
:
'flex-end'
,
},
title
:
{
textAlign
:
'center'
,
marginBottom
:
20
,
},
subText
:
{
maxWidth
:
235
,
},
};
const
styles
=
createStyles
(
baseStyles
,
maxWidth
(
smallBreakWidth
,
{
title
:
{
fontSize
:
30
,
lineHeight
:
40
,
},
})
);
const
RestoreSeedView
=
({
store
,
wallet
})
=>
(
<
Background
image
=
"purple-gradient-bg"
>
<
Header
>
<
BackButton
onPress
=
{()
=>
wallet
.
initPrevRestorePage
()}
/
>
<
Button
disabled
onPress
=
{()
=>
{}}
/
>
<
/Header
>
<
MainContent
style
=
{
styles
.
content
}
>
<
CopyOnboardText
style
=
{
styles
.
title
}
>
Restore
your
wallet
<
/CopyOnboardText
>
<
Card
>
<
FormSubText
style
=
{
styles
.
subText
}
>
{
store
.
restoreVerifyCopy
}
<
/FormSubText
>
{
store
.
restoreVerifyIndexes
.
map
((
seedIndex
,
i
)
=>
(
<
SeedEntry
seedIndex
=
{
seedIndex
}
value
=
{
store
.
seedMnemonic
[
seedIndex
-
1
]}
onChangeText
=
{
word
=>
wallet
.
setRestoreSeed
({
word
,
index
:
seedIndex
-
1
})
}
key
=
{
i
}
autoFocus
=
{
seedIndex
-
1
===
store
.
wallet
.
focusedRestoreInd
}
onSubmitEditing
=
{()
=>
i
===
2
?
wallet
.
initNextRestorePage
()
:
wallet
.
setFocusedRestoreInd
({
index
:
seedIndex
})
}
onClick
=
{()
=>
wallet
.
setFocusedRestoreInd
({
index
:
seedIndex
-
1
})
}
/
>
))}
<
/Card
>
<
SmallGlasButton
onPress
=
{()
=>
wallet
.
initNextRestorePage
()}
>
Next
<
/SmallGlasButton
>
<
/MainContent
>
<
/Background
>
);
RestoreSeedView
.
propTypes
=
{
store
:
PropTypes
.
object
.
isRequired
,
wallet
:
PropTypes
.
object
.
isRequired
,
};
export
default
observer
(
RestoreSeedView
);
src/view/restore-seed.js
View file @
89b74488
...
...
@@ -47,13 +47,20 @@ const RestoreSeedView = ({ store, wallet }) => (
{
store
.
restoreVerifyIndexes
.
map
((
seedIndex
,
i
)
=>
(
<
SeedEntry
seedIndex
=
{
seedIndex
}
value
=
{
store
.
wallet
.
restoreSeed
[
seedIndex
-
1
]}
value
=
{
store
.
seedMnemonic
[
seedIndex
-
1
]}
onChangeText
=
{
word
=>
wallet
.
setRestoreSeed
({
word
,
index
:
seedIndex
-
1
})
}
key
=
{
i
}
autoFocus
=
{
i
===
0
}
onSubmitEditing
=
{()
=>
wallet
.
initNextRestorePage
()}
autoFocus
=
{
seedIndex
-
1
===
store
.
wallet
.
focusedRestoreInd
}
onSubmitEditing
=
{()
=>
i
===
2
?
wallet
.
initNextRestorePage
()
:
wallet
.
setFocusedRestoreInd
({
index
:
seedIndex
})
}
onClick
=
{()
=>
wallet
.
setFocusedRestoreInd
({
index
:
seedIndex
-
1
})
}
/
>
))}
<
/Card
>
...
...
stories/screen-story.js
View file @
89b74488
...
...
@@ -73,7 +73,6 @@ import SetPasswordConfirm from '../src/view/set-password-confirm';
import
SetPinConfirmMobile
from
'../src/view/set-pin-confirm-mobile'
;
import
Password
from
'../src/view/password'
;
import
PinMobile
from
'../src/view/pin-mobile'
;
import
RestorePassword
from
'../src/view/restore-password'
;
import
ResetPasswordCurrent
from
'../src/view/reset-password-current'
;
import
ResetPasswordNew
from
'../src/view/reset-password-new'
;
import
ResetPasswordConfirm
from
'../src/view/reset-password-confirm'
;
...
...
@@ -83,6 +82,7 @@ import NewAddressMobile from '../src/view/new-address-mobile';
import
Wait
from
'../src/view/wait'
;
import
WaitMobile
from
'../src/view/wait-mobile'
;
import
RestoreSeed
from
'../src/view/restore-seed'
;
import
RestoreSeedMobile
from
'../src/view/restore-seed-mobile'
;
const
store
=
new
Store
();
store
.
init
();
...
...
@@ -139,6 +139,9 @@ storiesOf('Screens', module)
.
add
(
'Restore Wallet: Seed'
,
()
=>
(
<
RestoreSeed
store
=
{
store
}
wallet
=
{
wallet
}
/
>
))
.
add
(
'Restore Wallet: Seed (Mobile)'
,
()
=>
(
<
RestoreSeedMobile
store
=
{
store
}
wallet
=
{
wallet
}
/
>
))
.
add
(
'Seed Success'
,
()
=>
<
SeedSuccess
wallet
=
{
wallet
}
/>
)
.
add
(
'Seed Success (Mobile)'
,
()
=>
<
SeedSuccessMobile
wallet
=
{
wallet
}
/>
)
.
add
(
'Set Password'
,
()
=>
(
...
...
@@ -155,9 +158,6 @@ storiesOf('Screens', module)
))
.
add
(
'Password'
,
()
=>
<
Password
store
=
{
store
}
wallet
=
{
wallet
}
/>
)
.
add
(
'PIN (Mobile)'
,
()
=>
<
PinMobile
store
=
{
store
}
auth
=
{
auth
}
/>
)
.
add
(
'Restore Wallet: Password'
,
()
=>
(
<
RestorePassword
store
=
{
store
}
wallet
=
{
wallet
}
nav
=
{
nav
}
/
>
))
.
add
(
'Reset Password - Current'
,
()
=>
(
<
ResetPasswordCurrent
store
=
{
store
}
wallet
=
{
wallet
}
nav
=
{
nav
}
/
>
))
...
...
test/unit/action/nav.spec.js
View file @
89b74488
...
...
@@ -81,13 +81,6 @@ describe('Action Nav Unit Tests', () => {
});
});
describe
(
'goRestorePassword()'
,
()
=>
{
it
(
'should set correct route'
,
()
=>
{
nav
.
goRestorePassword
();
expect
(
store
.
route
,
'to equal'
,
'RestorePassword'
);
});
});
describe
(
'goNewAddress()'
,
()
=>
{
it
(
'should set correct route'
,
()
=>
{
nav
.
goNewAddress
();
...
...
test/unit/action/wallet.spec.js
View file @
89b74488
...
...
@@ -214,6 +214,7 @@ describe('Action Wallet Unit Tests', () => {
expect
(
wallet
.
initWallet
,
'was called with'
,
{
walletPassword
:
'secret123'
,
seedMnemonic
:
[
'foo'
,
'bar'
,
'baz'
],
recoveryWindow
:
0
,
});
});
...
...
@@ -234,6 +235,18 @@ describe('Action Wallet Unit Tests', () => {
expect
(
wallet
.
initSetPassword
,
'was called once'
);
expect
(
notification
.
display
,
'was called once'
);
});
it
(
'init wallet correctly during restore'
,
async
()
=>
{
store
.
settings
.
restoring
=
true
;
wallet
.
setNewPassword
({
password
:
'secret123'
});
wallet
.
setPasswordVerify
({
password
:
'secret123'
});
await
wallet
.
checkNewPassword
();
expect
(
wallet
.
initWallet
,
'was called with'
,
{
walletPassword
:
'secret123'
,
seedMnemonic
:
[
'foo'
,
'bar'
,
'baz'
],
recoveryWindow
:
RECOVERY_WINDOW
,
});
});
});
describe
(
'checkResetPassword()'
,
()
=>
{
...
...
@@ -354,16 +367,27 @@ describe('Action Wallet Unit Tests', () => {
it
(
'should clear attributes and navigate to view'
,
()
=>
{
store
.
wallet
.
restoreIndex
=
42
;
wallet
.
initRestoreWallet
();
expect
(
store
.
wallet
.
restoreSeed
.
length
,
'to equal'
,
24
);
expect
(
store
.
seedMnemonic
.
length
,
'to equal'
,
24
);
expect
(
store
.
wallet
.
restoreIndex
,
'to equal'
,
0
);
expect
(
nav
.
goRestoreSeed
,
'was called once'
);
});
});
describe
(
'setRestoreSeed()'
,
()
=>
{
beforeEach
(()
=>
{
store
.
seedMnemonic
=
Array
(
24
).
fill
(
''
);
});
it
(
'should clear attributes'
,
()
=>
{
wallet
.
setRestoreSeed
({
word
:
'foo'
,
index
:
1
});
expect
(
store
.
wallet
.
restoreSeed
[
1
],
'to equal'
,
'foo'
);
expect
(
store
.
seedMnemonic
[
1
],
'to equal'
,
'foo'
);
});
});
describe
(
'setFocusedRestoreInd()'
,
()
=>
{
it
(
'should set the currently focused restore seed index'
,
()
=>
{
wallet
.
setFocusedRestoreInd
({
index
:
5
});
expect
(
store
.
wallet
.
focusedRestoreInd
,
'to equal'
,
5
);
});
});
...
...
@@ -377,9 +401,11 @@ describe('Action Wallet Unit Tests', () => {
it
(
'should decrement restoreIndex if greater than 2'
,
async
()
=>
{
store
.
wallet
.
restoreIndex
=
3
;
store
.
wallet
.
focusedRestoreInd
=
5
;
wallet
.
initPrevRestorePage
();
expect
(
nav
.
goSelectSeed
,
'was not called'
);
expect
(
store
.
wallet
.
restoreIndex
,
'to equal'
,
0
);
expect
(
store
.
wallet
.
focusedRestoreInd
,
'to equal'
,
0
);
});
});
...
...
@@ -387,15 +413,17 @@ describe('Action Wallet Unit Tests', () => {
it
(
'should navigate to password screen if restoreIndex > 20'
,
()
=>
{
store
.
wallet
.
restoreIndex
=
21
;
wallet
.
initNextRestorePage
();
expect
(
nav
.
go
Restore
Password
,
'was called once'
);
expect
(
nav
.
go
Set
Password
,
'was called once'
);
expect
(
store
.
wallet
.
restoreIndex
,
'to equal'
,
21
);
});
it
(
'should increment restoreIndex if less than 21'
,
async
()
=>
{
store
.
wallet
.
restoreIndex
=
18
;
store
.
wallet
.
focusedRestoreInd
=
19
;
wallet
.
initNextRestorePage
();
expect
(
nav
.
go
Restore
Password
,
'was not called'
);
expect
(
nav
.
go
Set
Password
,
'was not called'
);
expect
(
store
.
wallet
.
restoreIndex
,
'to equal'
,
21
);
expect
(
store
.
wallet
.
focusedRestoreInd
,
'to equal'
,
21
);
});
});
...
...
@@ -469,24 +497,6 @@ describe('Action Wallet Unit Tests', () => {
});
});
describe
(
'restoreWallet()'
,
()
=>
{
beforeEach
(()
=>
{
sandbox
.
stub
(
wallet
,
'initWallet'
);
});
it
(
'calls initWallet with password and restoreSeed'
,
async
()
=>
{
wallet
.
setPassword
({
password
:
'secret123'
});
const
seed
=
Array
(
24
).
fill
(
'foo'
);
store
.
wallet
.
restoreSeed
=
seed
;
await
wallet
.
restoreWallet
();
expect
(
wallet
.
initWallet
,
'was called with'
,
{
walletPassword
:
'secret123'
,
seedMnemonic
:
seed
,
recoveryWindow
:
RECOVERY_WINDOW
,
});
});
});
describe
(
'unlockWallet()'
,
()
=>
{
it
(
'should unlock wallet'
,
async
()
=>
{
grpc
.
sendUnlockerCommand
.
withArgs
(
'UnlockWallet'
).
resolves
();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment