-
Notifications
You must be signed in to change notification settings - Fork 46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add use two otp options on create wallet #65
Changes from 2 commits
658f052
0d7ce6b
0f497a4
bef6494
7a845ae
a9adb9d
e1bff30
f606270
73deab0
a5b9f93
41c3f4a
266c747
57ef96b
f4346b8
ace8dd7
ca1f770
dc64057
b6ebe9b
26a0b54
e213814
ec5ab14
36a3594
8c3478e
4d658c5
344f9bd
5970e3e
7c13508
45af94f
08834d7
e11ec8d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,7 +6,7 @@ import api from '../api' | |
import ONEUtil from '../../../lib/util' | ||
import ONENames from '../../../lib/names' | ||
// import { uniqueNamesGenerator, colors, animals } from 'unique-names-generator' | ||
import { Button, Row, Space, Typography, Slider, Image, message, Progress, Timeline, Select } from 'antd' | ||
import { Button, Row, Space, Typography, Slider, Image, message, Progress, Timeline, Select, Checkbox } from 'antd' | ||
import { RedoOutlined, LoadingOutlined, SearchOutlined } from '@ant-design/icons' | ||
import humanizeDuration from 'humanize-duration' | ||
import AnimatedSection from '../components/AnimatedSection' | ||
|
@@ -37,16 +37,32 @@ const genName = (existingNames) => { | |
return name | ||
} | ||
|
||
const generateOtpSeed = () => { | ||
const otpSeedBuffer = new Uint8Array(20) | ||
return window.crypto.getRandomValues(otpSeedBuffer) | ||
} | ||
|
||
const sectionViews = { | ||
setupWalletDetails: 1, | ||
setupOtp: 2, | ||
setupSecondOtp: 3, | ||
prepareWallet: 4, | ||
walletSetupDone: 5 | ||
} | ||
|
||
const Create = () => { | ||
const generateNewOtpName = () => genName(Object.keys(wallets).map(k => wallets[k].name)) | ||
|
||
const { isMobile } = useWindowDimensions() | ||
const dispatch = useDispatch() | ||
const history = useHistory() | ||
const network = useSelector(state => state.wallet.network) | ||
const wallets = useSelector(state => state.wallet.wallets) | ||
const [name, setName] = useState(genName(Object.keys(wallets).map(k => wallets[k].name))) | ||
const otpSeedBuffer = new Uint8Array(20) | ||
const [name, setName] = useState(generateNewOtpName()) | ||
// eslint-disable-next-line no-unused-vars | ||
const [seed, setSeed] = useState(generateOtpSeed()) | ||
// eslint-disable-next-line no-unused-vars | ||
const [seed, setSeed] = useState(window.crypto.getRandomValues(otpSeedBuffer)) | ||
const [seed2, setSeed2] = useState(generateOtpSeed()) | ||
const [duration, setDuration] = useState(WalletConstants.defaultDuration) | ||
const [lastResortAddress, setLastResortAddress] = useState() | ||
const [dailyLimit] = useState(WalletConstants.defaultDailyLimit) | ||
|
@@ -60,52 +76,72 @@ const Create = () => { | |
const [progressStage, setProgressStage] = useState(0) | ||
const [address, setAddress] = useState() // '0x12345678901234567890' | ||
const [effectiveTime, setEffectiveTime] = useState() | ||
const [doubleOtp, setDoubleOtp] = useState(false) | ||
|
||
const [durationVisible, setDurationVisible] = useState(false) | ||
const [section, setSection] = useState(2) | ||
const [section, setSection] = useState(sectionViews.setupOtp) | ||
const [qrCodeData, setQRCodeData] = useState() | ||
const [otp, setOtp] = useState('') | ||
|
||
const [deploying, setDeploying] = useState() | ||
|
||
const otpRef = useRef() | ||
|
||
const getQRCodeUri = () => { | ||
const getQRCodeUri = (otpSeed) => { | ||
// otpauth://TYPE/LABEL?PARAMETERS | ||
return `otpauth://totp/${name}?secret=${b32.encode(seed)}&issuer=Harmony` | ||
return `otpauth://totp/${name}?secret=${b32.encode(otpSeed)}&issuer=Harmony` | ||
} | ||
|
||
useEffect(() => { | ||
(async function () { | ||
const uri = getQRCodeUri() | ||
const otpSeed = section === sectionViews.setupSecondOtp ? seed2 : seed | ||
|
||
const uri = getQRCodeUri(otpSeed) | ||
|
||
const data = await qrcode.toDataURL(uri, { errorCorrectionLevel: 'low', width: isMobile ? 192 : 256 }) | ||
|
||
setQRCodeData(data) | ||
})() | ||
}, [name]) | ||
|
||
useEffect(() => { | ||
if (section === 2 && worker) { | ||
if (section === sectionViews.setupOtp && worker) { | ||
console.log('posting to worker') | ||
const t = Math.floor(Date.now() / WalletConstants.interval) * WalletConstants.interval | ||
setEffectiveTime(t) | ||
worker && worker.postMessage({ | ||
seed, effectiveTime: t, duration, slotSize, interval: WalletConstants.interval | ||
seed, seed2, effectiveTime: t, duration, slotSize, interval: WalletConstants.interval | ||
}) | ||
} | ||
}, [section, worker]) | ||
|
||
useEffect(() => { | ||
const settingUpSecondOtp = section === sectionViews.setupSecondOtp | ||
|
||
if (otp.length !== 6) { | ||
return | ||
} | ||
const expected = ONEUtil.genOTP({ seed }) | ||
|
||
const currentSeed = settingUpSecondOtp ? seed2 : seed | ||
|
||
const expected = ONEUtil.genOTP({ seed: currentSeed }) | ||
|
||
const code = new DataView(expected.buffer).getUint32(0, false).toString() | ||
|
||
setOtp('') | ||
|
||
if (code.padStart(6, '0') !== otp.padStart(6, '0')) { | ||
console.log(`Expected: ${code}. Got: ${otp}`) | ||
message.error('Code is incorrect. Please try again.') | ||
setOtp('') | ||
|
||
otpRef?.current?.focusInput(0) | ||
} else if (doubleOtp && !settingUpSecondOtp) { | ||
setSection(sectionViews.setupSecondOtp) | ||
|
||
setName(`${name} (2nd)`) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be incorrect to change the name state variable because the wallet would be saved as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point. So we still want to save the name as original |
||
|
||
otpRef?.current?.focusInput(0) | ||
} else { | ||
setSection(3) | ||
setSection(sectionViews.prepareWallet) | ||
} | ||
}, [otp]) | ||
|
||
|
@@ -124,14 +160,17 @@ const Create = () => { | |
} | ||
|
||
let normalizedAddress = '' | ||
|
||
if (lastResortAddress !== '') { | ||
// Ensure valid address for both 0x and one1 formats | ||
normalizedAddress = util.safeExec(util.normalizedAddress, [lastResortAddress], handleAddressError) | ||
if (!normalizedAddress) { | ||
return | ||
} | ||
} | ||
|
||
setDeploying(true) | ||
|
||
try { | ||
const { address } = await api.relayer.create({ | ||
root: ONEUtil.hexString(root), | ||
|
@@ -155,6 +194,7 @@ const Create = () => { | |
dailyLimit: ONEUtil.toFraction(dailyLimit).toString(), | ||
hseed: ONEUtil.hexView(hseed), | ||
network, | ||
doubleOtp, | ||
} | ||
await storeLayers() | ||
dispatch(walletActions.updateWallet(wallet)) | ||
|
@@ -193,7 +233,7 @@ const Create = () => { | |
|
||
return ( | ||
<> | ||
<AnimatedSection show={section === 1} style={{ maxWidth: 640 }}> | ||
<AnimatedSection show={section === sectionViews.setupWalletDetails} style={{ maxWidth: 640 }}> | ||
<Heading>What do you want to call your wallet?</Heading> | ||
<Hint>This is only stored on your computer to distinguish your wallets.</Hint> | ||
<Row align='middle' style={{ marginBottom: 32, marginTop: 16 }}> | ||
|
@@ -203,7 +243,7 @@ const Create = () => { | |
value={name} onChange={({ target: { value } }) => setName(value)} | ||
style={{ padding: 0 }} | ||
/> | ||
<Button type='primary' shape='round' size='large' onClick={() => setSection(2)}>Next</Button> | ||
<Button type='primary' shape='round' size='large' onClick={() => setSection(sectionViews.setupOtp)}>Next</Button> | ||
</Space> | ||
</Row> | ||
|
||
|
@@ -221,7 +261,7 @@ const Create = () => { | |
</Space>} | ||
</Space> | ||
</AnimatedSection> | ||
<AnimatedSection show={section === 2} style={{ maxWidth: 640 }}> | ||
<AnimatedSection show={section === sectionViews.setupOtp} style={{ maxWidth: 640 }}> | ||
<Row> | ||
<Space direction='vertical'> | ||
{/* <Heading>Now, scan the QR code with your Google Authenticator</Heading> */} | ||
|
@@ -243,8 +283,38 @@ const Create = () => { | |
/> | ||
</Space> | ||
</Row> | ||
<Row justify='center'> | ||
<Checkbox onChange={() => setDoubleOtp(!doubleOtp)}> | ||
<Hint>Setup second One Time Password for enhanced security</Hint> | ||
<br /> | ||
<Hint>You will need to scan the QR code again in next step</Hint> | ||
</Checkbox> | ||
</Row> | ||
</AnimatedSection> | ||
<AnimatedSection show={section === sectionViews.setupSecondOtp} style={{ maxWidth: 640 }}> | ||
<Row> | ||
<Space direction='vertical'> | ||
{/* <Heading>Now, scan the QR code with your Google Authenticator</Heading> */} | ||
<Heading>Setup Second One Time Password</Heading> | ||
<Hint align='center'>Use two One Time Password for enhanced security</Hint> | ||
<Row justify='center'> | ||
{qrCodeData && <Image src={qrCodeData} preview={false} width={isMobile ? 192 : 256} />} | ||
</Row> | ||
</Space> | ||
</Row> | ||
<Row> | ||
<Space direction='vertical' size='large' align='center'> | ||
<Hint>After you are done, type in the 6-digit code from Google authenticator.</Hint> | ||
<OtpBox | ||
shouldAutoFocus | ||
ref={otpRef} | ||
value={otp} | ||
onChange={setOtp} | ||
/> | ||
</Space> | ||
</Row> | ||
</AnimatedSection> | ||
<AnimatedSection show={section === 3} style={{ maxWidth: 640 }}> | ||
<AnimatedSection show={section === sectionViews.prepareWallet} style={{ maxWidth: 640 }}> | ||
<Row> | ||
<Space direction='vertical'> | ||
<Heading>Prepare Your ONE Wallet</Heading> | ||
|
@@ -317,7 +387,7 @@ const Create = () => { | |
</Space> | ||
</Row> | ||
</AnimatedSection> | ||
<AnimatedSection show={section === 4}> | ||
<AnimatedSection show={section === sectionViews.walletSetupDone}> | ||
<Space direction='vertical'> | ||
<Heading>You are all set!</Heading> | ||
<Space direction='vertical' size='small'> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to use a slightly different name here. e.g. instead of
${name}
, use${name} (2nd)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the
name
is the same, but append(2nd)
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes