Skip to content

Commit

Permalink
get transaction sends working
Browse files Browse the repository at this point in the history
  • Loading branch information
willemolding committed Sep 26, 2024
1 parent 8ccc77c commit acf7bdc
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 42 deletions.
45 changes: 34 additions & 11 deletions packages/demo-wallet/src/App/Actions.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import initWasm, { initThreadPool, WebWallet } from "@webzjs/webz-core";

import { Action } from "./App";
import { State, Action } from "./App";
import { MAINNET_LIGHTWALLETD_PROXY } from "./constants";

export async function init(dispatch: React.Dispatch<Action>) {
Expand All @@ -12,31 +12,54 @@ export async function init(dispatch: React.Dispatch<Action>) {
});
}

export async function addNewAccount(state: State, dispatch: React.Dispatch<Action>, seedPhrase: string, birthdayHeight: number) {
await state.webWallet?.create_account(seedPhrase, 0, birthdayHeight);
dispatch({ type: "append-account-seed", payload: seedPhrase });
await syncStateWithWallet(state, dispatch);
}

export async function syncStateWithWallet(
webWallet: WebWallet | undefined,
state: State,
dispatch: React.Dispatch<Action>
) {
if (!webWallet) {
return;
if (!state.webWallet) {
throw new Error("Wallet not initialized");
}
let summary = await webWallet?.get_wallet_summary();
let summary = await state.webWallet?.get_wallet_summary();
if (summary) {
dispatch({ type: "set-summary", payload: summary });
}
let chainHeight = await webWallet?.get_latest_block();
let chainHeight = await state.webWallet?.get_latest_block();
if (chainHeight) {
dispatch({ type: "set-chain-height", payload: chainHeight });
}
dispatch({ type: "set-active-account", payload: summary?.account_balances[0][0] });
}

export async function triggerRescan(
webWallet: WebWallet | undefined,
state: State,
dispatch: React.Dispatch<Action>
) {
if (!webWallet) {
return;
if (!state.webWallet) {
throw new Error("Wallet not initialized");
}
await state.webWallet?.sync2();
await syncStateWithWallet(state, dispatch);
}

export async function triggerTransfer(
state: State,
dispatch: React.Dispatch<Action>,
toAddress: string,
amount: bigint
) {
if (!state.webWallet) {
throw new Error("Wallet not initialized");
}
await webWallet?.sync2();
await syncStateWithWallet(webWallet, dispatch);
if (state.activeAccount == null) {
throw new Error("No active account");
}

await state.webWallet?.transfer(state.accountSeeds[state.activeAccount], state.activeAccount, toAddress, amount);
await syncStateWithWallet(state, dispatch);
}
18 changes: 7 additions & 11 deletions packages/demo-wallet/src/App/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,24 @@ import { SendFunds } from "./components/SendFunds";
import { ReceiveFunds } from "./components/ReceiveFunds";
import { Summary } from "./components/Summary";

type State = {
export type State = {
webWallet?: WebWallet;
activeAccount?: number;
summary?: WalletSummary;
chainHeight?: bigint;
accountSeeds: string[];
};

const initialState: State = {
activeAccount: undefined,
summary: undefined,
chainHeight: undefined,
accountSeeds: [],
};

export type Action =
| { type: "set-active-account"; payload: number }
| { type: "append-account-seed"; payload: string }
| { type: "set-web-wallet"; payload: WebWallet }
| { type: "set-summary"; payload: WalletSummary }
| { type: "set-chain-height"; payload: bigint };
Expand All @@ -42,6 +45,9 @@ const reducer = (state: State, action: Action): State => {
case "set-active-account": {
return { ...state, activeAccount: action.payload };
}
case "append-account-seed": {
return { ...state, accountSeeds: [...state.accountSeeds, action.payload] };
}
case "set-web-wallet": {
return { ...state, webWallet: action.payload };
}
Expand All @@ -68,16 +74,6 @@ export function App() {
init(dispatch);
}, [dispatch]);

const triggerRescan = () => {
if (!state.webWallet) {
return;
}
console.log("rescanning");
state.webWallet.sync2().then(() => {
console.log("rescan complete");
});
};

return (
<div>
<WalletContext.Provider value={{ state, dispatch }}>
Expand Down
5 changes: 2 additions & 3 deletions packages/demo-wallet/src/App/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ export function Header() {
state.summary?.account_balances.find(
([id]) => id === state.activeAccount
);
console.log(activeBalanceReport);

let totalBalance = activeBalanceReport ? activeBalanceReport[1].sapling_balance + activeBalanceReport[1].orchard_balance : 0
return (
Expand Down Expand Up @@ -55,12 +54,12 @@ export function Header() {
<Stack>
<Button
onClick={async () =>
await syncStateWithWallet(state.webWallet, dispatch)
await syncStateWithWallet(state, dispatch)
}
>
Refresh
</Button>
<Button onClick={() => triggerRescan(state.webWallet, dispatch)}>
<Button onClick={() => triggerRescan(state, dispatch)}>
Sync
</Button>
</Stack>
Expand Down
9 changes: 4 additions & 5 deletions packages/demo-wallet/src/App/components/ImportAccount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,20 @@ import Form from "react-bootstrap/Form";
import { ToastContainer, toast } from "react-toastify";

import { WalletContext } from "../App";
import { syncStateWithWallet } from "../Actions";
import { addNewAccount } from "../Actions";

export function ImportAccount() {
let {state, dispatch} = useContext(WalletContext);

let [birthdayHeight, setBirthdayHeight] = useState(2657762);
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");

const handleSubmit = async (event: FormEvent) => {
event.preventDefault();
await state.webWallet?.create_account(seedPhrase, 0, birthdayHeight);
const handleSubmit = async (e: FormEvent) => {
e.preventDefault();
await addNewAccount(state, dispatch, seedPhrase, birthdayHeight);
toast.success("Account imported successfully", {
position: "top-center",
});
await syncStateWithWallet(state.webWallet, dispatch);
setBirthdayHeight(0);
setSeedPhrase("");
};
Expand Down
40 changes: 31 additions & 9 deletions packages/demo-wallet/src/App/components/SendFunds.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,44 @@
import React from "react";
import React, { FormEvent, useContext, useState } from "react";

import Button from "react-bootstrap/Button";
import Form from "react-bootstrap/Form";

import { WalletContext } from "../App";
import { triggerTransfer } from "../Actions";

export function SendFunds() {
let { state, dispatch } = useContext(WalletContext);

let [toAddress, setToAddress] = useState("");
let [amount, setAmount] = useState<bigint>(BigInt(0));

const handleSubmit = async (e: FormEvent) => {
e.preventDefault();
console.log("Sending", amount, "to", toAddress);
await triggerTransfer(state, dispatch, toAddress, amount);
console.log("Send complete");
};

return (
<Form>
<Form onSubmit={handleSubmit}>
<Form.Group className="mb-3" controlId="formSend">
<Form.Label>From Account:</Form.Label>
<Form.Select>
<option>Account 1</option>
</Form.Select>
<Form.Label>To:</Form.Label>
<Form.Control type="text" placeholder="Zcash z-address"/>
<Form.Control
type="text"
placeholder="Zcash z-address"
value={toAddress}
onChange={(e) => setToAddress(e.target.value)}
/>
<Form.Label>Amount:</Form.Label>
<Form.Control type="number" placeholder="0.0" size="lg"/>
<Form.Control
type="number"
placeholder="0.0"
size="lg"
value={"" + amount}
onChange={(e) => setAmount(BigInt(e.target.value))}
/>
<Form.Label>Memo (optional):</Form.Label>
<Form.Control type="text" placeholder="memo text (max 512 bytes)"/>
<Form.Control type="text" placeholder="memo text (max 512 bytes)" />
</Form.Group>
<Button variant="primary" type="submit">
Send
Expand Down
2 changes: 1 addition & 1 deletion packages/demo-wallet/src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<head>
<meta charset="utf-8" />
<title>WebZjs Wallet Demo</title>
<script src="enable-threads.js"></script>
<!-- <script src="enable-threads.js"></script> -->
</head>
<body>
<div id="app"></div>
Expand Down
2 changes: 1 addition & 1 deletion packages/demo-wallet/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */

/* Language and Environment */
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
"target": "es2020", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
"jsx": "react", /* Specify what JSX code is generated. */
// "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
Expand Down
2 changes: 2 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ pub enum Error {
#[cfg(feature = "sqlite-db")]
#[error("Sqlite error: {0}")]
SqliteError(#[from] zcash_client_sqlite::error::SqliteClientError),
#[error("Invalid seed phrase")]
InvalidSeedPhrase,
}

impl From<Error> for JsValue {
Expand Down
2 changes: 1 addition & 1 deletion src/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,7 @@ fn usk_from_seed_str(
account_index: u32,
network: &consensus::Network,
) -> Result<UnifiedSpendingKey, Error> {
let mnemonic = <Mnemonic<English>>::from_phrase(seed).unwrap();
let mnemonic = <Mnemonic<English>>::from_phrase(seed).map_err(|_| Error::InvalidSeedPhrase)?;
let seed = {
let mut seed = mnemonic.to_seed("");
let secret = seed.to_vec();
Expand Down

0 comments on commit acf7bdc

Please sign in to comment.