Skip to content

Commit c253c8a

Browse files
authored
Merge pull request #69 from ChainSafe/irubido/displaySyncingData
feat: display syncing data with birthday block
2 parents 3b48af3 + 4c0ef2c commit c253c8a

19 files changed

+258
-76
lines changed

packages/demo-wallet/src/App/components/AddAccount.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export function AddAccount() {
4646
const handleMetamaskImport = async (e: FormEvent) => {
4747
e.preventDefault();
4848
const viewKey = (await invokeSnap({ method: 'getViewingKey' })) as string;
49-
console.log(viewKey);
49+
5050
await addNewAccountFromUfvk(state, dispatch, viewKey, birthdayHeight);
5151
toast.success('Account imported successfully', {
5252
position: 'top-center',

packages/snap/snap.manifest.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"url": "https://github.com/MetaMask/template-snap-monorepo.git"
88
},
99
"source": {
10-
"shasum": "5kk+7sR8jY1fw3MjTH9dRIPkwAHHo0pFgfCseq+3rko=",
10+
"shasum": "K0ntTcddlgOu8VTqTscszF/wJHveOkwBujyr7uvVf7g=",
1111
"location": {
1212
"npm": {
1313
"filePath": "dist/bundle.js",
@@ -27,7 +27,8 @@
2727
{
2828
"coinType": 133
2929
}
30-
]
30+
],
31+
"snap_manageState": {}
3132
},
3233
"platformVersion": "6.17.1",
3334
"manifestVersion": "0.1"

packages/snap/src/index.tsx

+22-10
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
import { getViewingKey } from './rpc/getViewingKey';
22
import { InitOutput } from '@webzjs/webz-keys';
33
import { initialiseWasm } from './utils/initialiseWasm';
4-
import { OnRpcRequestHandler, OnUserInputHandler, UserInputEventType } from '@metamask/snaps-sdk';
5-
import { setBirthdayBlock, SetBirthdayBlockParams } from './rpc/setBirthdayBlock';
4+
import {
5+
OnRpcRequestHandler,
6+
OnUserInputHandler,
7+
UserInputEventType,
8+
} from '@metamask/snaps-sdk';
9+
import { setBirthdayBlock } from './rpc/setBirthdayBlock';
10+
import { getSnapState } from './rpc/getSnapState';
11+
import { SetBirthdayBlockParams, SnapState } from './types';
12+
import { setSnapState } from './rpc/setSnapState';
613

714
let wasm: InitOutput;
815

@@ -24,24 +31,29 @@ export const onRpcRequest: OnRpcRequestHandler = async ({ request }) => {
2431
case 'getViewingKey':
2532
return await getViewingKey();
2633
case 'setBirthdayBlock':
27-
const params = request.params as SetBirthdayBlockParams;
28-
return await setBirthdayBlock(params);
34+
const setBirthdayBlockParams = request.params as SetBirthdayBlockParams;
35+
return await setBirthdayBlock(setBirthdayBlockParams);
36+
case 'getSnapStete':
37+
return await getSnapState();
38+
case 'setSnapStete':
39+
const setSnapStateParams = request.params as unknown as SnapState;
40+
return await setSnapState(setSnapStateParams);
2941
default:
3042
throw new Error('Method not found.');
3143
}
3244
};
3345

34-
export const onUserInput: OnUserInputHandler = async ({ id, event, context }) => {
46+
export const onUserInput: OnUserInputHandler = async ({ id, event }) => {
3547
if (event.type === UserInputEventType.FormSubmitEvent) {
3648
switch (event.name) {
37-
case "birthday-block-form":
49+
case 'birthday-block-form':
3850
await snap.request({
39-
method: "snap_resolveInterface",
51+
method: 'snap_resolveInterface',
4052
params: {
4153
id,
42-
value: event.value
43-
}
44-
})
54+
value: event.value,
55+
},
56+
});
4557

4658
default:
4759
break;
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { Json } from '@metamask/snaps-sdk';
2+
3+
export async function getSnapState(): Promise<Json> {
4+
const state = (await snap.request({
5+
method: 'snap_manageState',
6+
params: {
7+
operation: 'get',
8+
},
9+
})) as unknown as Json;
10+
11+
return state;
12+
}

packages/snap/src/rpc/setBirthdayBlock.tsx

+21-10
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/** @jsxImportSource @metamask/snaps-sdk */
12
import {
23
Form,
34
Box,
@@ -6,17 +7,17 @@ import {
67
Button,
78
Text,
89
Bold,
9-
Divider
10+
Divider,
1011
} from '@metamask/snaps-sdk/jsx';
12+
import { setSyncBlockHeight } from '../utils/setSyncBlockHeight';
1113

1214
type BirthdayBlockForm = { customBirthdayBlock: string | null };
1315

14-
export type SetBirthdayBlockParams = { latestBlock?: number };
16+
type SetBirthdayBlockParams = { latestBlock: number };
1517

1618
export async function setBirthdayBlock({
1719
latestBlock,
18-
}: SetBirthdayBlockParams): Promise<string | null> {
19-
20+
}: SetBirthdayBlockParams): Promise<number | null> {
2021
const interfaceId = await snap.request({
2122
method: 'snap_createInterface',
2223
params: {
@@ -29,12 +30,13 @@ export async function setBirthdayBlock({
2930
seed you can enter optional birthday block of that Wallet.
3031
</Text>
3132
<Divider />
32-
<Text>
33-
Syncing
34-
proccess will start from that block.
35-
</Text>
33+
<Text>Syncing proccess will start from that block.</Text>
3634
<Divider />
37-
{!!latestBlock && <Text>Latest block: <Bold>{latestBlock.toString()}</Bold></Text>}
35+
{!!latestBlock && (
36+
<Text>
37+
Latest block: <Bold>{latestBlock.toString()}</Bold>
38+
</Text>
39+
)}
3840
<Input
3941
min={0}
4042
step={1}
@@ -58,6 +60,15 @@ export async function setBirthdayBlock({
5860
},
5961
})) as BirthdayBlockForm;
6062

63+
const webWalletSyncStartBlock = setSyncBlockHeight(customBirthdayBlock, latestBlock);
64+
65+
await snap.request({
66+
method: 'snap_manageState',
67+
params: {
68+
operation: 'update',
69+
newState: { webWalletSyncStartBlock },
70+
},
71+
});
6172

62-
return customBirthdayBlock;
73+
return webWalletSyncStartBlock;
6374
}
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { Json } from '@metamask/snaps-sdk';
2+
import { SnapState } from 'src/types';
3+
4+
export async function setSnapState(newSnapState: SnapState): Promise<Json> {
5+
const state = (await snap.request({
6+
method: 'snap_manageState',
7+
params: {
8+
operation: 'update',
9+
newState: newSnapState,
10+
},
11+
})) as unknown as Json;
12+
13+
return state;
14+
}

packages/snap/src/types.ts

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { Json } from "@metamask/snaps-sdk";
2+
3+
export type SetBirthdayBlockParams = { latestBlock: number };
4+
5+
export interface SnapState extends Record<string, Json> {
6+
webWalletSyncStartBlock: string;
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//NU5 (Network Upgrade 5) (Block 1,687,104, May 31, 2022)
2+
const NU5_ACTIVATION = 1687104;
3+
4+
export function setSyncBlockHeight(
5+
userInputCreationBlock: string | null,
6+
latestBlock: number,
7+
) {
8+
if(userInputCreationBlock === null) return latestBlock;
9+
10+
const customBirthdayBlock = Number(userInputCreationBlock);
11+
12+
const latestAcceptableSyncBlock = NU5_ACTIVATION;
13+
14+
return customBirthdayBlock>latestAcceptableSyncBlock ? customBirthdayBlock : latestAcceptableSyncBlock
15+
}

packages/web-wallet/src/App.tsx

+1-12
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,11 @@
11
import { useInterval } from 'usehooks-ts';
2-
import { Outlet, useLocation } from 'react-router-dom';
2+
import { Outlet } from 'react-router-dom';
33
import { RESCAN_INTERVAL } from './config/constants';
4-
import { useEffect } from 'react';
54
import { useWebZjsActions } from './hooks';
65
import Layout from './components/Layout/Layout';
76

87
function App() {
98
const { triggerRescan } = useWebZjsActions();
10-
const location = useLocation();
11-
12-
useEffect(() => {
13-
// Add custom background to home page
14-
if (location.pathname === '/') {
15-
document.body.classList.add('home-page', 'home-page-bg');
16-
} else {
17-
document.body.classList.remove('home-page', 'home-page-bg');
18-
}
19-
}, [location.pathname]);
209

2110
useInterval(() => {
2211
triggerRescan();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { FC } from 'react';
2+
import { WebZjsState } from 'src/context/WebzjsContext';
3+
4+
export const BlockHeightCard: FC<{
5+
state: WebZjsState;
6+
syncedFrom?: string;
7+
}> = ({ state, syncedFrom }) => {
8+
return (
9+
<div className="grow shrink min-w-[317px] basis-0 p-6 bg-white rounded-xl border border-[#afafaf] flex-col justify-start items-start gap-2 inline-flex">
10+
{state.syncInProgress ? (
11+
<div className="self-stretch flex items-center gap-2">
12+
<svg
13+
className="animate-spin h-4 w-4 text-[#595959]"
14+
xmlns="http://www.w3.org/2000/svg"
15+
fill="none"
16+
viewBox="0 0 24 24"
17+
>
18+
<circle
19+
className="opacity-25"
20+
cx="12"
21+
cy="12"
22+
r="10"
23+
stroke="currentColor"
24+
strokeWidth="4"
25+
></circle>
26+
<path
27+
className="opacity-75"
28+
fill="currentColor"
29+
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
30+
></path>
31+
</svg>
32+
<span className="text-[#595959] text-sm font-semibold font-inter leading-[21px]">
33+
Sync in progress...
34+
</span>
35+
</div>
36+
) : null}
37+
<div className="self-stretch text-[#595959] text-sm font-semibold font-inter leading-[21px]">
38+
Chain Height
39+
</div>
40+
<div className="self-stretch justify-start items-center gap-2 inline-flex">
41+
<div className="text-black text-2xl font-medium font-['Inter'] leading-9">
42+
{state.chainHeight ? '' + state.chainHeight : '?'}
43+
</div>
44+
</div>
45+
<div className="self-stretch text-[#595959] text-sm font-semibold font-inter leading-[21px]">
46+
Synced Height
47+
</div>
48+
<div className="self-stretch justify-start items-center gap-2 inline-flex">
49+
<div className="text-black text-2xl font-medium font-['Inter'] leading-9">
50+
{state.summary?.fully_scanned_height
51+
? state.summary?.fully_scanned_height
52+
: '?'}
53+
</div>
54+
</div>
55+
{syncedFrom && (
56+
<>
57+
<div className="self-stretch text-[#595959] text-sm font-semibold font-inter leading-[21px]">
58+
Sync Start Block
59+
</div>
60+
<div className="self-stretch justify-start items-center gap-2 inline-flex">
61+
<div className="text-black text-2xl font-medium font-['Inter'] leading-9">
62+
{syncedFrom}
63+
</div>
64+
</div>
65+
</>
66+
)}
67+
</div>
68+
);
69+
};

packages/web-wallet/src/components/Header/Header.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const Header = (): React.JSX.Element => {
77
const isHomePage = location.pathname === '/';
88

99
return (
10-
<header className="font-inter h-[60px] fixed top-0 left-0 w-full px-16 flex grow items-center justify-between bg-transparent py-3 border-b border-neutral-200">
10+
<header className="font-inter h-[60px] w-full px-16 flex items-center justify-between bg-transparent py-3 border-b border-neutral-200">
1111
<Link to={'/'}>
1212
<div className="flex items-center">
1313
<img

packages/web-wallet/src/context/MetamaskContext.tsx

+10
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@ import { createContext, useContext, useEffect, useState } from 'react';
44

55
import type { Snap } from '../types';
66
import { getSnapsProvider } from '../utils';
7+
import { SnapState } from 'src/hooks/snaps/useGetSnapState';
78

89
type MetaMaskContextType = {
910
provider: MetaMaskInpageProvider | null;
1011
installedSnap: Snap | null;
1112
error: Error | null;
13+
snapState: SnapState | null;
14+
setSnapState: (SnapState: SnapState) => void;
1215
setInstalledSnap: (snap: Snap | null) => void;
1316
setError: (error: Error) => void;
1417
};
@@ -17,6 +20,8 @@ const MetaMaskContext = createContext<MetaMaskContextType>({
1720
provider: null,
1821
installedSnap: null,
1922
error: null,
23+
snapState: null,
24+
setSnapState: () => {},
2025
setInstalledSnap: () => {},
2126
setError: () => {},
2227
});
@@ -29,9 +34,12 @@ const MetaMaskContext = createContext<MetaMaskContextType>({
2934
* @returns JSX.
3035
*/
3136
export const MetaMaskProvider = ({ children }: { children: ReactNode }) => {
37+
// const { getSnapState } = useGetSnapState();
38+
3239
const [provider, setProvider] = useState<MetaMaskInpageProvider | null>(null);
3340
const [installedSnap, setInstalledSnap] = useState<Snap | null>(null);
3441
const [error, setError] = useState<Error | null>(null);
42+
const [snapState, setSnapState] = useState<SnapState | null>(null);
3543

3644
useEffect(() => {
3745
getSnapsProvider().then(setProvider).catch(console.error);
@@ -56,6 +64,8 @@ export const MetaMaskProvider = ({ children }: { children: ReactNode }) => {
5664
value={{
5765
provider,
5866
error,
67+
snapState,
68+
setSnapState,
5969
setError,
6070
installedSnap,
6171
setInstalledSnap,

packages/web-wallet/src/context/WebzjsContext.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { MAINNET_LIGHTWALLETD_PROXY } from '../config/constants';
1717
import { Snap } from '../types';
1818
import toast, { Toaster } from 'react-hot-toast';
1919

20-
interface State {
20+
export interface WebZjsState {
2121
webWallet: WebWallet | null;
2222
installedSnap: Snap | null;
2323
error: Error | null | string;
@@ -37,7 +37,7 @@ type Action =
3737
| { type: 'set-sync-in-progress'; payload: boolean }
3838
| { type: 'set-loading'; payload: boolean };
3939

40-
const initialState: State = {
40+
const initialState: WebZjsState = {
4141
webWallet: null,
4242
installedSnap: null,
4343
error: null,
@@ -48,7 +48,7 @@ const initialState: State = {
4848
loading: true,
4949
};
5050

51-
function reducer(state: State, action: Action): State {
51+
function reducer(state: WebZjsState, action: Action): WebZjsState {
5252
switch (action.type) {
5353
case 'set-web-wallet':
5454
return { ...state, webWallet: action.payload };
@@ -70,7 +70,7 @@ function reducer(state: State, action: Action): State {
7070
}
7171

7272
interface WebZjsContextType {
73-
state: State;
73+
state: WebZjsState;
7474
dispatch: React.Dispatch<Action>;
7575
}
7676

0 commit comments

Comments
 (0)