Skip to content

Commit

Permalink
adds basic app and connected wasm package
Browse files Browse the repository at this point in the history
  • Loading branch information
willemolding committed Sep 24, 2024
1 parent 78abe06 commit bd2f660
Show file tree
Hide file tree
Showing 13 changed files with 308 additions and 0 deletions.
11 changes: 11 additions & 0 deletions packages/demo-wallet/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions

dist
.parcel-cache
wasm-pkg
7 changes: 7 additions & 0 deletions packages/demo-wallet/.proxyrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = function (app) {
app.use((req, res, next) => {
res.setHeader("Cross-Origin-Opener-Policy", "same-origin");
res.setHeader("Cross-Origin-Embedder-Policy", "require-corp");
next();
});
};
1 change: 1 addition & 0 deletions packages/demo-wallet/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# WebZjs Demo Web Wallet
14 changes: 14 additions & 0 deletions packages/demo-wallet/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "@webzjs/demo-wallet",
"source": "src/index.html",
"scripts": {
"start:dev": "parcel --no-autoinstall --no-cache src/index.html"
},
"dependencies": {
"@webzjs/webz-core": "workspace:^",
"bootstrap": "^5.3.3",
"react": "^18.2.0",
"react-bootstrap": "^2.10.4",
"react-dom": "^18.2.0"
}
}
10 changes: 10 additions & 0 deletions packages/demo-wallet/src/App/App.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/* Style inputs */
input, select, button {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
60 changes: 60 additions & 0 deletions packages/demo-wallet/src/App/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import "./App.css";
import "bootstrap/dist/css/bootstrap.min.css";

import { useState, useEffect, createContext } from "react";

import Tab from "react-bootstrap/Tab";
import Tabs from "react-bootstrap/Tabs";

import initWasm, { initThreadPool, start, WebWallet } from "@webzjs/webz-core";

import { ImportAccount } from "./components/ImportAccount";
import { SendFunds } from "./components/SendFunds";
import { ReceiveFunds } from "./components/ReceiveFunds";
import { Balance } from "./components/Balance";

const SAPLING_ACTIVATION = 419200;
const ORCHARD_ACTIVATION = 1687104;
const TIP = 2442739;

const MAINNET_LIGHTWALLETD_PROXY = "https://zcash-mainnet.chainsafe.dev";
const TESTNET_LIGHTWALLETD_PROXY = "https://zcash-testnet.chainsafe.dev";

export const WalletContext = createContext();

export function App() {

useEffect(() => {
async function init() {
await initWasm();
await initThreadPool(1);
setWebWallet(new WebWallet("main", MAINNET_LIGHTWALLETD_PROXY, 1));
}
init();
}, []);

let [webWallet, setWebWallet] = useState();

return (
<div>
<WalletContext.Provider value={webWallet}>
<h1>WebZjs Wallet Demo</h1>

<Tabs defaultActiveKey="import" id="base-wallet-tabs" className="mb-3">
<Tab eventKey="import" title="Import Account">
<ImportAccount />
</Tab>
<Tab eventKey="balance" title="Balance">
<Balance />
</Tab>
<Tab eventKey="send" title="Send">
<SendFunds />
</Tab>
<Tab eventKey="receive" title="Receive">
<ReceiveFunds />
</Tab>
</Tabs>
</WalletContext.Provider>
</div>
);
}
14 changes: 14 additions & 0 deletions packages/demo-wallet/src/App/components/Balance.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Form from "react-bootstrap/Form";

export function Balance() {
return (
<Form>
<Form.Group className="mb-3" controlId="formReceive">
<Form.Label>Shielded ZEC (spendable):</Form.Label>
<Form.Control type="text" disabled />
<Form.Label>Change Pending:</Form.Label>
<Form.Control type="text" disabled />
</Form.Group>
</Form>
);
}
52 changes: 52 additions & 0 deletions packages/demo-wallet/src/App/components/ImportAccount.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { useContext, useState } from "react";

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

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

export function ImportAccount() {
let webWallet = useContext(WalletContext);

let [birthdayHeight, setBirthdayHeight] = useState(0);
let [seedPhrase, setSeedPhrase] = useState("");

const handleSubmit = async (event) => {
event.preventDefault();
await webWallet.create_account(seedPhrase, 0, birthdayHeight);
};

return (
<Form onSubmit={handleSubmit}>
<Form.Group className="mb-3" controlId="seedPhrase">
<Form.Label>Seed Phrase</Form.Label>
<Form.Control
as="textarea"
placeholder="Enter 24 word seed phrase"
value={seedPhrase}
onChange={({ target: { value } }) => setSeedPhrase(value)}
rows={3}
/>
<Form.Text className="text-muted">
Do not import a seed phrase holding any significant funds into this
wallet demo
</Form.Text>
</Form.Group>

<Form.Group className="mb-3" controlId="birthdayHeight">
<Form.Label>Birthday Block Height</Form.Label>
<Form.Control
type="number"
placeholder="Birthday block height"
value={birthdayHeight}
onChange={({ target: { value } }) =>
setBirthdayHeight(parseInt(value))
}
/>
</Form.Group>
<Button variant="primary" type="submit">
Import
</Button>
</Form>
);
}
21 changes: 21 additions & 0 deletions packages/demo-wallet/src/App/components/ReceiveFunds.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import Form from "react-bootstrap/Form";

export function ReceiveFunds() {
return (
<Form>
<Form.Label>To Account:</Form.Label>
<Form.Select>
<option>Account 1</option>
</Form.Select>
<Form.Text className="text-muted">
Share one of these addresses to receive funds
</Form.Text>
<Form.Group className="mb-3" controlId="formReceive">
<Form.Label>Unified Address:</Form.Label>
<Form.Control type="text" disabled />
<Form.Label>Transparent Address:</Form.Label>
<Form.Control type="text" disabled />
</Form.Group>
</Form>
);
}
24 changes: 24 additions & 0 deletions packages/demo-wallet/src/App/components/SendFunds.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Button from "react-bootstrap/Button";
import Form from "react-bootstrap/Form";

export function SendFunds() {
return (
<Form>
<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.Label>Amount:</Form.Label>
<Form.Control type="number" placeholder="0.0" size="lg"/>
<Form.Label>Memo (optional):</Form.Label>
<Form.Control type="text" placeholder="memo text (max 512 bytes)"/>
</Form.Group>
<Button variant="primary" type="submit">
Send
</Button>
</Form>
);
}
76 changes: 76 additions & 0 deletions packages/demo-wallet/src/enable-threads.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// NOTE: This file creates a service worker that cross-origin-isolates the page (read more here: https://web.dev/coop-coep/) which allows us to use wasm threads.
// Normally you would set the COOP and COEP headers on the server to do this, but Github Pages doesn't allow this, so this is a hack to do that.

/* Edited version of: coi-serviceworker v0.1.6 - Guido Zuidhof, licensed under MIT */
// From here: https://github.com/gzuidhof/coi-serviceworker
if(typeof window === 'undefined') {
self.addEventListener("install", () => self.skipWaiting());
self.addEventListener("activate", e => e.waitUntil(self.clients.claim()));

async function handleFetch(request) {
if(request.cache === "only-if-cached" && request.mode !== "same-origin") {
return;
}

if(request.mode === "no-cors") { // We need to set `credentials` to "omit" for no-cors requests, per this comment: https://bugs.chromium.org/p/chromium/issues/detail?id=1309901#c7
request = new Request(request.url, {
cache: request.cache,
credentials: "omit",
headers: request.headers,
integrity: request.integrity,
destination: request.destination,
keepalive: request.keepalive,
method: request.method,
mode: request.mode,
redirect: request.redirect,
referrer: request.referrer,
referrerPolicy: request.referrerPolicy,
signal: request.signal,
});
}

let r = await fetch(request).catch(e => console.error(e));

if(r.status === 0) {
return r;
}

const headers = new Headers(r.headers);
headers.set("Cross-Origin-Embedder-Policy", "require-corp");
headers.set("Cross-Origin-Opener-Policy", "same-origin");

return new Response(r.body, { status: r.status, statusText: r.statusText, headers });
}

self.addEventListener("fetch", function(e) {
e.respondWith(handleFetch(e.request)); // respondWith must be executed synchonously (but can be passed a Promise)
});

} else {
(async function() {
if(window.crossOriginIsolated !== false) return;

let registration = await navigator.serviceWorker.register(window.document.currentScript.src).catch(e => console.error("COOP/COEP Service Worker failed to register:", e));
if(registration) {
console.log("COOP/COEP Service Worker registered", registration.scope);

registration.addEventListener("updatefound", () => {
console.log("Reloading page to make use of updated COOP/COEP Service Worker.");
window.location.reload();
});

// If the registration is active, but it's not controlling the page
if(registration.active && !navigator.serviceWorker.controller) {
console.log("Reloading page to make use of COOP/COEP Service Worker.");
window.location.reload();
}
}
})();
}

// Code to deregister:
// let registrations = await navigator.serviceWorker.getRegistrations();
// for(let registration of registrations) {
// await registration.unregister();
// }

12 changes: 12 additions & 0 deletions packages/demo-wallet/src/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>WebZjs Wallet Demo</title>
<script src="enable-threads.js"></script>
</head>
<body>
<div id="app"></div>
<script type="module" src="index.js"></script>
</body>
</html>
6 changes: 6 additions & 0 deletions packages/demo-wallet/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { createRoot } from "react-dom/client";
import { App } from "./app/App";

const container = document.getElementById("app");
const root = createRoot(container)
root.render(<App />);

0 comments on commit bd2f660

Please sign in to comment.