-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
sync: fresh and existing wallets skip trial decryption (#164)
* onboarding metadata for quick sync * wallet birthday * linting * refactor to use zustand store for in-memory state management * proper error propogation to caller in order to display in ui * address more gabe's comments * change type to support undefined * ui formatting for wallet birthday * add changeset * [pairing] draft updates * combine zustand slices * [pairing] use react-query * controlled form * ui styling --------- Co-authored-by: Gabe Rodriguez <grod220@gmail.com>
- Loading branch information
Showing
23 changed files
with
631 additions
and
447 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
'@repo/context': major | ||
'chrome-extension': major | ||
--- | ||
|
||
fresh and existing wallets skip trial decryption |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import { useQuery } from '@tanstack/react-query'; | ||
import { sample } from 'lodash'; | ||
import { createPromiseClient } from '@connectrpc/connect'; | ||
import { createGrpcWebTransport } from '@connectrpc/connect-web'; | ||
import { TendermintProxyService } from '@penumbra-zone/protobuf'; | ||
import { ChainRegistryClient } from '@penumbra-labs/registry'; | ||
import { useStore } from '../state'; | ||
import { networkSelector } from '../state/network'; | ||
|
||
// Utility function to fetch the block height by randomly querying one of the RPC endpoints | ||
// from the chain registry, using a recursive callback to try another endpoint if the current | ||
// one fails. Additionally, this implements a timeout mechanism at the request level to avoid | ||
// hanging from stalled requests. | ||
const fetchBlockHeightWithFallback = async (endpoints: string[]): Promise<number> => { | ||
if (endpoints.length === 0) { | ||
throw new Error('All RPC endpoints failed to fetch the block height.'); | ||
} | ||
|
||
// Randomly select an RPC endpoint from the chain registry | ||
const randomGrpcEndpoint = sample(endpoints); | ||
if (!randomGrpcEndpoint) { | ||
throw new Error('No RPC endpoints found.'); | ||
} | ||
|
||
try { | ||
return await fetchBlockHeight(randomGrpcEndpoint); | ||
} catch (e) { | ||
// Remove the current endpoint from the list and retry with remaining endpoints | ||
const remainingEndpoints = endpoints.filter(endpoint => endpoint !== randomGrpcEndpoint); | ||
return fetchBlockHeightWithFallback(remainingEndpoints); | ||
} | ||
}; | ||
|
||
// Fetch the block height from a specific RPC endpoint with a timeout to prevent hanging requests. | ||
export const fetchBlockHeight = async (grpcEndpoint: string): Promise<number> => { | ||
const tendermintClient = createPromiseClient( | ||
TendermintProxyService, | ||
createGrpcWebTransport({ baseUrl: grpcEndpoint, defaultTimeoutMs: 2000 }), | ||
); | ||
|
||
const result = await tendermintClient.getStatus({}); | ||
if (!result.syncInfo) { | ||
throw new Error('No syncInfo in getStatus result'); | ||
} | ||
return Number(result.syncInfo.latestBlockHeight); | ||
}; | ||
|
||
export const useLatestBlockHeightWithFallback = () => { | ||
return useQuery({ | ||
queryKey: ['latestBlockHeightWithFallback'], | ||
queryFn: async () => { | ||
const chainRegistryClient = new ChainRegistryClient(); | ||
const { rpcs } = chainRegistryClient.bundled.globals(); | ||
const suggestedEndpoints = rpcs.map(i => i.url); | ||
return await fetchBlockHeightWithFallback(suggestedEndpoints); | ||
}, | ||
retry: false, | ||
}); | ||
}; | ||
|
||
export const useLatestBlockHeight = () => { | ||
const { grpcEndpoint } = useStore(networkSelector); | ||
|
||
return useQuery({ | ||
queryKey: ['latestBlockHeight'], | ||
queryFn: async () => { | ||
if (!grpcEndpoint) { | ||
return; | ||
} | ||
return await fetchBlockHeight(grpcEndpoint); | ||
}, | ||
enabled: Boolean(grpcEndpoint), | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import { BackIcon } from '@repo/ui/components/ui/icons/back-icon'; | ||
import { Button } from '@repo/ui/components/ui/button'; | ||
import { | ||
Card, | ||
CardContent, | ||
CardDescription, | ||
CardHeader, | ||
CardTitle, | ||
} from '@repo/ui/components/ui/card'; | ||
import { FadeTransition } from '@repo/ui/components/ui/fade-transition'; | ||
import { usePageNav } from '../../../utils/navigate'; | ||
import { PagePath } from '../paths'; | ||
import { FormEvent, useState } from 'react'; | ||
import { Input } from '@repo/ui/components/ui/input'; | ||
import { localExtStorage } from '../../../storage/local'; | ||
|
||
export const ImportWalletCreationHeight = () => { | ||
const navigate = usePageNav(); | ||
const [blockHeight, setBlockHeight] = useState<number>(); | ||
|
||
const handleSubmit = (event: FormEvent) => { | ||
event.preventDefault(); | ||
|
||
void (async () => { | ||
await localExtStorage.set('walletCreationBlockHeight', blockHeight ? blockHeight : 0); | ||
navigate(PagePath.SET_PASSWORD); | ||
})(); | ||
}; | ||
|
||
return ( | ||
<FadeTransition> | ||
<BackIcon className='float-left mb-4' onClick={() => navigate(-1)} /> | ||
<Card className='w-[600px] p-8' gradient> | ||
<CardHeader className='items-center text-center'> | ||
<CardTitle className='text-xl font-semibold'> | ||
Enter your wallet's birthday (Optional) | ||
</CardTitle> | ||
<CardDescription className='mt-2 text-sm'> | ||
This is the block height at the time your wallet was created. Providing your | ||
wallet's block creation height can help speed up the synchronization process, but | ||
it's not required. If you don't have this information, you can safely skip | ||
this step. | ||
</CardDescription> | ||
</CardHeader> | ||
<CardContent className='mt-8'> | ||
<form className='grid gap-6' onSubmit={handleSubmit}> | ||
<Input | ||
type='number' | ||
placeholder='Enter block height' | ||
value={blockHeight ? blockHeight : ''} // prevents uncontrolled form react err | ||
onChange={e => setBlockHeight(Number(e.target.value))} | ||
className='rounded-md border border-gray-700 p-3 text-[16px] font-normal leading-[24px]' | ||
/> | ||
<Button className='mt-6 w-full' variant='gradient' onClick={handleSubmit}> | ||
Continue | ||
</Button> | ||
</form> | ||
</CardContent> | ||
</Card> | ||
</FadeTransition> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.