Skip to content

Commit 518574d

Browse files
committed
rewrite state model of webwallet
1 parent f406298 commit 518574d

File tree

13 files changed

+147
-102
lines changed

13 files changed

+147
-102
lines changed

.cargo/config.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@ rustflags = ["-C", "target-feature=+atomics,+bulk-memory,+mutable-globals"]
77
# [unstable]
88
# build-std = ["panic_abort", "std"]
99

10-
# [build]
11-
# target = "wasm32-unknown-unknown"
10+
[build]
11+
target = "wasm32-unknown-unknown"

.vscode/settings.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"rust-analyzer.workspace.discoverConfig": null,
3+
"rust-analyzer.cargo.features": "all"
4+
}

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
9595
tracing = "0.1.40"
9696
rayon = { version = "1.8", features = ["web_spin_lock"] }
9797
subtle = "2.6.1"
98-
wasm_thread = { git = "https://github.com/WilsonGramer/wasm_thread.git", rev = "eb41bcc0d98ce0620a313687c0344341391b9d78", features = ["keep_worker_alive"] }
98+
wasm_thread = { git = "https://github.com/WilsonGramer/wasm_thread.git", rev = "eb41bcc0d98ce0620a313687c0344341391b9d78", default-features = false, features = ["keep_worker_alive"] }
9999

100100
wasm_sync = "0.1.2"
101101
http = { version = "1.1.0", default-features = false }

justfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ default:
22
just --list
33

44
build:
5-
wasm-pack build --no-opt --target web --scope webzjs --release --out-dir ./packages/webz-core --no-default-features --features="wasm,sync2" -Z build-std="panic_abort,std"
5+
wasm-pack build --target web --scope webzjs --release --out-dir ./packages/webz-core --no-default-features --features="wasm-parallel,sync2" -Z build-std="panic_abort,std"
66

77
# All Wasm Tests
88
test-web *features:

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
{
22
"scripts": {
33
"preinstall": "npx only-allow pnpm",
4-
"start:dev": "parcel --no-autoinstall packages/demo-wallet"
4+
"start:dev": "parcel --no-autoinstall packages/demo-wallet",
5+
"build": "parcel build --no-cache --no-autoinstall packages/demo-wallet"
56
},
67
"dependencies": {
78
"@webzjs/webz-core": "workspace:^",
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import initWasm, { initThreadPool, WebWallet } from "@webzjs/webz-core";
2+
3+
import { Action } from "./App";
4+
import { MAINNET_LIGHTWALLETD_PROXY } from "./constants";
5+
6+
export async function init(dispatch: React.Dispatch<Action>) {
7+
await initWasm();
8+
await initThreadPool(10);
9+
dispatch({
10+
type: "set-web-wallet",
11+
payload: new WebWallet("main", MAINNET_LIGHTWALLETD_PROXY, 1),
12+
});
13+
}
14+
15+
export async function syncStateWithWallet(
16+
webWallet: WebWallet | undefined,
17+
dispatch: React.Dispatch<Action>
18+
) {
19+
if (!webWallet) {
20+
return;
21+
}
22+
let summary = await webWallet?.get_wallet_summary();
23+
if (summary) {
24+
dispatch({ type: "set-summary", payload: summary });
25+
}
26+
let chainHeight = await webWallet?.get_latest_block();
27+
if (chainHeight) {
28+
dispatch({ type: "set-chain-height", payload: chainHeight });
29+
}
30+
}
31+
32+
export async function triggerRescan(
33+
webWallet: WebWallet | undefined,
34+
dispatch: React.Dispatch<Action>
35+
) {
36+
if (!webWallet) {
37+
return;
38+
}
39+
await webWallet?.sync2();
40+
await syncStateWithWallet(webWallet, dispatch);
41+
}

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

Lines changed: 52 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,99 @@
11
import "./App.css";
22

3-
import React, { useState, useEffect, createContext } from "react";
3+
import React, { useState, useEffect, createContext, useReducer } from "react";
44

55
import Tab from "react-bootstrap/Tab";
66
import Tabs from "react-bootstrap/Tabs";
77
import Stack from "react-bootstrap/Stack";
88

9-
import initWasm, {
10-
initThreadPool,
11-
start,
9+
import {
1210
WebWallet,
1311
WalletSummary,
1412
} from "@webzjs/webz-core";
1513

14+
import { init } from "./Actions";
1615
import { Header } from "./components/Header";
1716
import { ImportAccount } from "./components/ImportAccount";
1817
import { SendFunds } from "./components/SendFunds";
1918
import { ReceiveFunds } from "./components/ReceiveFunds";
2019
import { Summary } from "./components/Summary";
2120

22-
const MAINNET_LIGHTWALLETD_PROXY = "https://zcash-mainnet.chainsafe.dev";
21+
type State = {
22+
webWallet?: WebWallet;
23+
activeAccount?: number;
24+
summary?: WalletSummary;
25+
chainHeight?: bigint;
26+
};
2327

24-
export const WalletContext = createContext<WebWallet | null>(null);
28+
const initialState: State = {
29+
activeAccount: undefined,
30+
summary: undefined,
31+
chainHeight: undefined,
32+
};
2533

26-
export function App() {
27-
useEffect(() => {
28-
async function init() {
29-
await initWasm();
30-
await initThreadPool(10);
31-
setWebWallet(new WebWallet("main", MAINNET_LIGHTWALLETD_PROXY, 1));
32-
}
33-
init();
34-
}, []);
34+
export type Action =
35+
| { type: "set-active-account"; payload: number }
36+
| { type: "set-web-wallet"; payload: WebWallet }
37+
| { type: "set-summary"; payload: WalletSummary }
38+
| { type: "set-chain-height"; payload: bigint };
3539

36-
let [webWallet, setWebWallet] = useState<WebWallet | null>(null);
37-
let [summary, setSummary] = useState<WalletSummary | null>(null);
38-
let [chainHeight, setChainHeight] = useState<bigint | null>(null);
39-
let [activeAccoumt, setActiveAccount] = useState<number>(0);
40-
41-
const refreshSummary = async () => {
42-
if (!webWallet) {
43-
return;
40+
const reducer = (state: State, action: Action): State => {
41+
switch (action.type) {
42+
case "set-active-account": {
43+
return { ...state, activeAccount: action.payload };
4444
}
45-
let summary = await webWallet?.get_wallet_summary();
46-
if (summary) {
47-
setSummary(summary);
45+
case "set-web-wallet": {
46+
return { ...state, webWallet: action.payload };
4847
}
49-
let chainHeight = await webWallet?.get_latest_block();
50-
if (chainHeight) {
51-
setChainHeight(chainHeight);
48+
case "set-summary": {
49+
return { ...state, summary: action.payload };
5250
}
53-
};
51+
case "set-chain-height": {
52+
return { ...state, chainHeight: action.payload };
53+
}
54+
default:
55+
return state;
56+
}
57+
};
58+
59+
export const WalletContext = createContext<{
60+
state: State;
61+
dispatch: React.Dispatch<Action>;
62+
}>({ state: initialState, dispatch: () => {} });
63+
64+
export function App() {
65+
const [state, dispatch] = useReducer(reducer, initialState);
66+
67+
useEffect(() => {
68+
init(dispatch);
69+
}, [dispatch]);
5470

5571
const triggerRescan = () => {
56-
if (!webWallet) {
72+
if (!state.webWallet) {
5773
return;
5874
}
5975
console.log("rescanning");
60-
webWallet.sync2().then(() => {
76+
state.webWallet.sync2().then(() => {
6177
console.log("rescan complete");
6278
});
6379
};
6480

6581
return (
6682
<div>
67-
<WalletContext.Provider value={webWallet}>
83+
<WalletContext.Provider value={{ state, dispatch }}>
6884
<Stack>
6985
<h1>WebZjs Wallet Demo</h1>
70-
<Header
71-
walletSummary={summary}
72-
refreshSummary={refreshSummary}
73-
activeAccount={activeAccoumt}
74-
setActiveAccount={setActiveAccount}
75-
triggerRescan={triggerRescan}
76-
chainHeight={chainHeight}
77-
/>
86+
<Header />
7887
<Tabs
7988
defaultActiveKey="import"
8089
id="base-wallet-tabs"
8190
className="mb-3"
8291
>
8392
<Tab eventKey="import" title="Import Account">
84-
<ImportAccount refreshSummary={refreshSummary} />
93+
<ImportAccount />
8594
</Tab>
8695
<Tab eventKey="summary" title="Summary">
87-
<Summary walletSummary={summary} />
96+
<Summary summary={state.summary}/>
8897
</Tab>
8998
<Tab eventKey="send" title="Send">
9099
<SendFunds />
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const MAINNET_LIGHTWALLETD_PROXY = "https://zcash-mainnet.chainsafe.dev";

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

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,24 @@
1-
import React, { useContext, useEffect, useState } from "react";
1+
import React, { useContext } from "react";
22

33
import Form from "react-bootstrap/Form";
44
import Card from "react-bootstrap/Card";
55
import Stack from "react-bootstrap/Stack";
66

77
import { WalletContext } from "../App";
8-
import { WalletSummary } from "@webzjs/webz-core";
8+
import { syncStateWithWallet, triggerRescan } from "../Actions";
99
import { Button } from "react-bootstrap";
1010

11-
export function Header({
12-
walletSummary,
13-
refreshSummary,
14-
activeAccount,
15-
setActiveAccount,
16-
triggerRescan,
17-
chainHeight,
18-
}: {
19-
walletSummary: WalletSummary | null;
20-
refreshSummary: () => Promise<void>;
21-
activeAccount: number;
22-
setActiveAccount: (account: number) => void;
23-
triggerRescan: () => void;
24-
chainHeight: bigint | null;
25-
}) {
11+
export function Header() {
12+
13+
const { state, dispatch } = useContext(WalletContext);
14+
2615
return (
2716
<Stack direction="horizontal" gap={3}>
2817
<Form.Select
29-
value={activeAccount}
30-
onChange={(e) => setActiveAccount(parseInt(e.target.value))}
18+
value={state.activeAccount}
19+
onChange={(e) => dispatch({ type: "set-active-account", payload: parseInt(e.target.value)})}
3120
>
32-
{walletSummary?.account_balances.map(([id]) => (
21+
{state.summary?.account_balances.map(([id]) => (
3322
<option key={id} value={id}>
3423
Account {id}
3524
</option>
@@ -40,12 +29,12 @@ export function Header({
4029
<Card.Text>Available Balance: {0} ZEC</Card.Text>
4130
</Card>
4231
<Card style={{ width: "30rem" }}>
43-
<Card.Text>Chain Height: {chainHeight ? ""+chainHeight : '?'}</Card.Text>
44-
<Card.Text>Synced Height: {walletSummary?.fully_scanned_height ? walletSummary?.fully_scanned_height : '?'}</Card.Text>
32+
<Card.Text>Chain Height: {state.chainHeight ? ""+state.chainHeight : '?'}</Card.Text>
33+
<Card.Text>Synced Height: {state.summary?.fully_scanned_height ? state.summary?.fully_scanned_height : '?'}</Card.Text>
4534
</Card>
4635
<Stack>
47-
<Button onClick={async () => await refreshSummary()}>Refresh</Button>
48-
<Button onClick={() => triggerRescan()}>Sync</Button>
36+
<Button onClick={async () => await syncStateWithWallet(state.webWallet, dispatch)}>Refresh</Button>
37+
<Button onClick={() => triggerRescan(state.webWallet, dispatch)}>Sync</Button>
4938
</Stack>
5039
</Stack>
5140
);

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,21 @@ import Form from "react-bootstrap/Form";
55
import { ToastContainer, toast } from "react-toastify";
66

77
import { WalletContext } from "../App";
8+
import { syncStateWithWallet } from "../Actions";
89

9-
export function ImportAccount({refreshSummary}: {refreshSummary: () => Promise<void>}) {
10-
let webWallet = useContext(WalletContext);
10+
export function ImportAccount() {
11+
let {state, dispatch} = useContext(WalletContext);
1112

1213
let [birthdayHeight, setBirthdayHeight] = useState(2657762);
1314
let [seedPhrase, setSeedPhrase] = useState("mix sample clay sweet planet lava giraffe hand fashion switch away pool rookie earth purity truly square trumpet goose move actor save jaguar volume");
1415

1516
const handleSubmit = async (event: FormEvent) => {
1617
event.preventDefault();
17-
await webWallet?.create_account(seedPhrase, 0, birthdayHeight);
18+
await state.webWallet?.create_account(seedPhrase, 0, birthdayHeight);
1819
toast.success("Account imported successfully", {
1920
position: "top-center",
2021
});
21-
await refreshSummary();
22+
await syncStateWithWallet(state.webWallet, dispatch);
2223
setBirthdayHeight(0);
2324
setSeedPhrase("");
2425
};

0 commit comments

Comments
 (0)