Vanilla
The vanilla template uses plain HTML and JavaScript for the web client.
You can start a new project using this template with:
pnpm create mud@latest tutorial --template vanilla
For more information, see the quickstart guide.
Onchain code
This template uses the standard Counter
onchain code.
Offchain code
The files you are likely to need to change in the offchain code are:
packages/client/index.html
(opens in a new tab), which controls the information displayed to the user.packages/client/src/index.ts
(opens in a new tab), which contains the setup code. It is the place where you register handlers that are called when the value in a component (basically, a table) changes.packages/client/src/mud/createSystemCalls.ts
(opens in a new tab), which is where you write code that performs calls to an onchain system.
index.html
This is the HTML displayed to the user. The lines that are relevant to MUD are:
<script type="module" src="/src/index.ts"></script>
Import the script that runs most of the application.
<div>Counter: <span id="counter">0</span></div>
Create an HTML span (opens in a new tab) that JavaScript code can update. This span will be updated every time the value of the counter changes.
<button id="incrementButton">Increment</button>
A button that is set to call window.increment()
, which calls the onchain system to increment the counter.
index.ts
This is the main TypeScript file.
import { setup } from "./mud/setup";
import mudConfig from "contracts/mud.config";
const {
components,
systemCalls: { increment },
network,
} = await setup();
The general setup code (opens in a new tab) for MUD.
// Components expose a stream that triggers when the component is updated.
components.Counter.update$.subscribe((update) => {
const [nextValue, prevValue] = update.value;
console.log("Counter updated", update, { nextValue, prevValue });
document.getElementById("counter")!.innerHTML = String(nextValue?.value ?? "unset");
});
Specify a function to be called when the value of Counter
changes.
This function emits a log message (opens in a new tab) and then updates the counter
span.
// Attach the increment function to the html element with ID `incrementButton` (if it exists)
document.querySelector("#incrementButton")?.addEventListener("click", increment);
Here we attach the increment
function from createSystemCalls.ts
to incrementButton
.
createSystemCalls.ts
This file is where you place the calls that go to the onchain system.
In this case there is only one, increment
.
const increment = async () => {
/*
* Because IncrementSystem
* (https://mud.dev/tutorials/walkthrough/minimal-onchain#incrementsystemsol)
* is in the root namespace, `.increment` can be called directly
* on the World contract.
*/
const tx = await worldContract.write.increment();
await waitForTransaction(tx);
return getComponentValue(Counter, singletonEntity);
};
You create a transaction, wait for it to be included, and return the value. If there is any need for translation between the parameters provided by the user interface and those that are expected by the onchain code, this is where you would add it.