-
Notifications
You must be signed in to change notification settings - Fork 47
Wallet recovery #342
Wallet recovery #342
Changes from 9 commits
739a70f
ff39b25
e1ac6df
d1eca08
4b09caa
0b3eff0
20b84df
dfea315
2ff4efa
b4f60c9
20698d1
2284c26
fa2d29f
c179693
9fba928
1b0b469
85c8667
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 |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import { FunctionComponent, useState } from 'react'; | ||
import Modal from 'react-modal'; | ||
import Button from '../../../../components/Button'; | ||
import Range from '../../../../helpers/Range'; | ||
import StepOneInfo from './StepOneInfo'; | ||
import StepThreeRecover from './StepThreeRecover'; | ||
import StepTwoWalletCreation from './StepTwoWalletCreation'; | ||
|
||
const WorkflowNumbers: FunctionComponent<{ | ||
max: number; | ||
current: number; | ||
}> = ({ max, current }) => { | ||
return ( | ||
<div className="flex justify-center space-x-10"> | ||
{Range(max).map((i) => ( | ||
<div | ||
key={i} | ||
className={[ | ||
'icon-lg', | ||
'rounded-full', | ||
'text-center', | ||
'leading-8', | ||
'cursor-pointer', | ||
...(i <= current ? ['bg-blue-500', 'text-white'] : ['text-black']), | ||
].join(' ')} | ||
> | ||
{i + 1} | ||
</div> | ||
))} | ||
</div> | ||
); | ||
}; | ||
|
||
const RecoverWalletModal = () => { | ||
const [modalIsOpen, setIsOpen] = useState(false); | ||
const [pageIndex, setPageIndex] = useState(0); | ||
const [walletPrivateKey, setWalletPrivateKey] = useState<string>(''); | ||
|
||
return ( | ||
<div> | ||
<Button onPress={() => setIsOpen(true)} className="btn-secondary"> | ||
Import | ||
</Button> | ||
<Modal | ||
isOpen={modalIsOpen} | ||
onRequestClose={() => setIsOpen(false)} | ||
style={{ | ||
content: { | ||
width: '35rem', | ||
margin: 'auto', | ||
fontFamily: 'montserrat', | ||
padding: 0, | ||
border: 'none', | ||
height: '25rem', | ||
}, | ||
overlay: { | ||
backgroundColor: 'rgba(0, 0, 0, 0.5)', | ||
}, | ||
}} | ||
> | ||
<div className="p-8 h-full w-100 flex flex-col"> | ||
<WorkflowNumbers max={3} current={pageIndex} /> | ||
<div className="mt-8 h-100 flex-grow"> | ||
{ | ||
[ | ||
<StepOneInfo | ||
key={1} | ||
onComplete={() => { | ||
kautukkundan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
setPageIndex(1); | ||
}} | ||
/>, | ||
<StepTwoWalletCreation | ||
key={2} | ||
setWalletToParent={setWalletPrivateKey} | ||
onComplete={() => { | ||
setPageIndex(2); | ||
}} | ||
/>, | ||
<StepThreeRecover | ||
key={3} | ||
walletPrivateKey={walletPrivateKey} | ||
onComplete={() => setIsOpen(false)} | ||
/>, | ||
][pageIndex] | ||
} | ||
</div> | ||
</div> | ||
</Modal> | ||
</div> | ||
); | ||
}; | ||
|
||
export default RecoverWalletModal; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { CaretRight } from 'phosphor-react'; | ||
import { FunctionComponent } from 'react'; | ||
import Button from '../../../../components/Button'; | ||
|
||
const StepOneInfo: FunctionComponent<{ | ||
onComplete: () => void; | ||
}> = ({ onComplete }) => { | ||
return ( | ||
<div className="flex flex-col gap-4 h-full"> | ||
<div className="flex-grow"> | ||
<div className="text-[14pt]">Recover existing wallet in Quill</div> | ||
<div className="text-[10pt] text-grey-700 leading-loose"> | ||
You can recover existing instant BLS wallets into Quill. This is a | ||
simple 2 step process which requires you to copy-paste some stuff from | ||
kautukkundan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Quill to the instant wallet and then again from instant wallet to | ||
Quill | ||
</div> | ||
<br /> | ||
<div className="text-[10pt] text-grey-700 leading-loose font-bold mt-2"> | ||
Do not close this modal until you have completed all the steps that | ||
follows else you will lose access to your original keys! | ||
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. Thoughts on: "...steps that follow, else you..." |
||
</div> | ||
</div> | ||
|
||
<div className="flex justify-end"> | ||
<Button | ||
onPress={() => onComplete()} | ||
className="btn-primary h-10 text-[10pt] w-1/3" | ||
icon={<CaretRight size={15} />} | ||
> | ||
Continue | ||
</Button> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default StepOneInfo; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
import { ethers } from 'ethers'; | ||
import { Download } from 'phosphor-react'; | ||
import { FunctionComponent, useState } from 'react'; | ||
import Button from '../../../../components/Button'; | ||
import { useQuill } from '../../../../QuillContext'; | ||
|
||
const StepThreeRecover: FunctionComponent<{ | ||
onComplete: () => void; | ||
walletPrivateKey: string; | ||
}> = ({ onComplete, walletPrivateKey }) => { | ||
const { rpc } = useQuill(); | ||
|
||
const [salt, setSalt] = useState<string>(''); | ||
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. Similar point here and line below, do we want to explicitly state the type? |
||
const [instantWalletAddress, setInstantWalletAddress] = useState<string>(''); | ||
|
||
const handleRecover = async () => { | ||
await rpc.addRecoveryWallet( | ||
instantWalletAddress, | ||
ethers.utils.formatBytes32String(salt), | ||
walletPrivateKey, | ||
); | ||
jacque006 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
onComplete(); | ||
}; | ||
|
||
return ( | ||
<div className="flex flex-col gap-4 h-full"> | ||
<div className="flex-grow"> | ||
<div className="text-[14pt]">Almost There</div> | ||
<div className="text-[10pt] text-grey-700 leading-loose"> | ||
Your instant wallet recovery is in process. Once finished the same | ||
wallet will be visible inside Quill. | ||
<br /> | ||
<div | ||
className={[ | ||
'text-[10pt]', | ||
'text-grey-700', | ||
'leading-loose', | ||
'font-bold', | ||
'mt-2', | ||
].join(' ')} | ||
kautukkundan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
> | ||
Copy back the instant wallet address and salt entered | ||
</div> | ||
</div> | ||
|
||
<div className="mt-4 flex flex-col gap-2"> | ||
<input | ||
type="text" | ||
className={[ | ||
'bg-opacity-5', | ||
'border-opacity-45', | ||
'focus:border-opacity-85', | ||
'h-10', | ||
'text-[10pt]', | ||
].join(' ')} | ||
placeholder="Instant Wallet Address" | ||
onChange={(e) => { | ||
setInstantWalletAddress(e.target.value); | ||
}} | ||
/> | ||
|
||
<input | ||
type="text" | ||
className={[ | ||
'bg-opacity-5', | ||
'border-opacity-45', | ||
'focus:border-opacity-85', | ||
'h-10', | ||
'text-[10pt]', | ||
].join(' ')} | ||
placeholder="Recovery Salt" | ||
onChange={(e) => { | ||
setSalt(e.target.value); | ||
}} | ||
/> | ||
</div> | ||
</div> | ||
|
||
<div className="flex justify-end"> | ||
<Button | ||
onPress={() => handleRecover()} | ||
className="btn-primary h-10 text-[10pt] w-1/3" | ||
icon={<Download size={15} />} | ||
> | ||
Recover Wallet | ||
</Button> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default StepThreeRecover; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import { CaretRight, CircleNotch, CopySimple } from 'phosphor-react'; | ||
import { FunctionComponent, useEffect, useState } from 'react'; | ||
import Button from '../../../../components/Button'; | ||
import { useQuill } from '../../../../QuillContext'; | ||
|
||
const StepTwoWalletCreation: FunctionComponent<{ | ||
onComplete: () => void; | ||
setWalletToParent: (address: string) => void; | ||
}> = ({ onComplete, setWalletToParent }) => { | ||
const [walletAddress, setWalletAddress] = useState<string>(''); | ||
const [loading, setLoading] = useState<boolean>(true); | ||
|
||
const { rpc } = useQuill(); | ||
|
||
useEffect(() => { | ||
const createWallet = async () => { | ||
setLoading(true); | ||
const { address, privateKey } = await rpc.createTempAccount(); | ||
setWalletAddress(address); | ||
setWalletToParent(privateKey); | ||
setLoading(false); | ||
}; | ||
|
||
createWallet(); | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
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. Why are deps disabled here? Should just be 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. I sometimes don't understand these deps. Like it's not possible to change some deps without explicit reload which is gonna rerender anyway. But yeah, let's add rpc here. 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. Useful comment on this issue with links for further reading from Dan Abramov |
||
}, []); | ||
|
||
return ( | ||
<div className="flex flex-col gap-4 h-full"> | ||
<div className="flex-grow"> | ||
<div className="text-[14pt]">Recovery Wallet</div> | ||
<div className="text-[10pt] text-grey-700 leading-loose"> | ||
This is the wallet address which will be used to recover your instant | ||
wallet. | ||
</div> | ||
<br /> | ||
<div className="text-[10pt] text-grey-700 leading-loose font-bold mt-2"> | ||
Copy the address and paste it in the instant wallet. | ||
</div> | ||
<div className="mt-4 bg-grey-900 bg-opacity-25 rounded-md p-5"> | ||
{loading ? ( | ||
<div className="flex gap-4 text-[12pt] items-center "> | ||
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. Tiny bit of whitespace :) |
||
Generating wallet | ||
<div className="animate-spin relative"> | ||
<CircleNotch size={30} /> | ||
</div> | ||
</div> | ||
) : ( | ||
<div className="flex justify-between"> | ||
<div className="font-mono text-[11pt]">{walletAddress}</div> | ||
{/* eslint-disable-next-line */} | ||
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. What rule was disabled here? Better to disable a specific rule than all linting rules. 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 wanted to also have a "keyboard input" for the copy button which didn't make much sense to me. |
||
<div | ||
className="cursor-pointer" | ||
onClick={() => navigator.clipboard.writeText(walletAddress)} | ||
> | ||
<CopySimple size={20} /> | ||
</div> | ||
</div> | ||
)} | ||
</div> | ||
</div> | ||
|
||
<div className="flex justify-end"> | ||
<Button | ||
onPress={() => onComplete()} | ||
className="btn-primary h-10 text-[10pt] w-1/3" | ||
icon={<CaretRight size={15} />} | ||
> | ||
Continue | ||
</Button> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default StepTwoWalletCreation; |
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.
Do we need to explicitly add the type here? Can see that we're letting typescript infer the type for the above useState's
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.
My personal preference is to have explicit typing everywhere. Copied the above 2 lines from somewhere else in the codebase so missed adding type to it.
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.
I may lean towards letting typescript infer the type but don't have a strong opinion either way, so happy with either option as long as we're being consistent :)
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.
@kautukkundan Are you sure that's your preference in this case where TypeScript is correctly inferring the type? Would you also add
<boolean>
and<number>
to the previous lines?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.
@voltrevo Fine with me as is in this particular case.
The problem starts happening when using complex types. eg - let's say a new
Address
type is defined as a string that always starts with "0x". In this case initializing with default '' would also work as it'll infer type string, but may break code later when things get complex. This had been the case earlier when using sol.G1 and sol.G2 types in the HubbleBLS library.So looking at broader picture and anticipating future I prefer being explicit even with simpler types to maintain consistency, If that makes sense.