Requestor in browser Quickstart
Introduction
In most of our examples, we demonstrate how to run a requestor script in Node.js. However, you can also run your scripts in a browser context. This example will explain how to do it.
Before getting started, you need to install and launch the Yagna service in version 0.15.2 or later. It can be installed using instructions for manual Yagna installation available here.
Follow the Yagna installation instructions including the set up the app-key step.
Then, start the Yagna with a --api-allow-origin
that allows you to handle REST API requests with a CORS policy:
yagna service run --api-allow-origin='http://localhost:8080'
The --api-allow-origin
value should be set to the URL where your web application will be served.
In this example, we will use http-server
with a default port 8080.
Setting up the project
mkdir web_golem
cd web_golem
npm install --global http-server
This will install the http-server
utility to host our web page, where we will run our Golem app.
HTML page with embeded requestor script
Next, we'll create the main index.html
file with the following content:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Requestor in browser</title>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css"
integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN"
crossorigin="anonymous"
/>
</head>
<body>
<div class="container">
<h1 class="pb-4">Hello Golem</h1>
<div class="row pb-4">
<h3>Options</h3>
<div id="options" class="row">
<div class="col-4 form-group">
<label for="YAGNA_APPKEY">Yagna AppKey: </label>
<input id="YAGNA_APPKEY" class="form-control" type="text" value="" />
</div>
<div class="col-4 form-group">
<label for="YAGNA_API_BASEPATH">Yagna Api Url: </label>
<input id="YAGNA_API_BASEPATH" class="form-control" type="text" value="http://127.0.0.1:7465" />
</div>
</div>
<div class="row pb-4">
<div class="col-4 form-group">
<label for="IMAGE_TAG">Image Tag: </label>
<input id="IMAGE_TAG" type="text" class="form-control" value="golem/alpine:latest" />
</div>
<div class="col-4 form-group">
<label for="SUBNET_TAG">Subnet Tag: </label>
<input id="SUBNET_TAG" type="text" class="form-control" value="public" />
</div>
<div class="col-4 form-group">
<label for="PAYMENT_NETWORK">Payment Network: </label>
<input id="PAYMENT_NETWORK" type="text" class="form-control" value="holesky" />
</div>
</div>
</div>
<div class="row pb-4">
<h3>Actions</h3>
<div>
<button id="echo" class="btn btn-primary" onclick="run()">Echo Hello World</button>
</div>
</div>
<div class="row">
<div class="alert alert-info" role="alert">
<h4 class="alert-heading">Debugging</h4>
<p>You can see <code>@golem-sdk/golem-js</code> logs in your browser's <code>console</code> :)</p>
</div>
<h3>Results</h3>
<div class="col">
<ul id="results"></ul>
</div>
</div>
</div>
<script type="module">
import { GolemNetwork } from "https://unpkg.com/@golem-sdk/golem-js";
export function appendResults(result) {
const resultsEl = document.getElementById("results");
const li = document.createElement("li");
li.appendChild(document.createTextNode(result));
resultsEl.appendChild(li);
}
async function run() {
// This line allows you to watch golem-js internal logs in the browser console!
localStorage.debug = "golem-js:*";
const key = document.getElementById("YAGNA_APPKEY").value;
if (!key) {
alert("You didn't provide your Yagna AppKey");
return;
}
const url = document.getElementById("YAGNA_API_BASEPATH").value;
const subnetTag = document.getElementById("SUBNET_TAG").value;
const imageTag = document.getElementById("IMAGE_TAG").value;
const network = document.getElementById("PAYMENT_NETWORK").value;
// Define the order that we're going to place on the market
const order = {
demand: {
workload: {
imageTag,
},
subnetTag,
},
market: {
rentHours: 0.5,
pricing: {
model: "linear",
maxStartPrice: 0.5,
maxCpuPerHourPrice: 1.0,
maxEnvPerHourPrice: 0.5,
},
},
payment: { network },
};
const glm = new GolemNetwork({
api: { key, url },
});
glm.payment.events.on("invoiceAccepted", ({ invoice }) => appendResults(`Total cost: ${invoice.amount} GLM`));
try {
appendResults("Establishing a connection to the Golem Network");
await glm.connect();
appendResults("Request for renting a provider machine");
const rental = await glm.oneOf({ order });
appendResults("Rented resources from", rental.agreement.provider.name);
await rental
.getExeUnit()
.then(async (exe) =>
appendResults("Reply: " + (await exe.run(`echo 'Hello Golem! 👋 from ${exe.provider.name}!'`)).stdout),
);
appendResults("Finished all work with the resources");
await rental.stopAndFinalize();
appendResults("Finalized renting process");
} catch (err) {
console.error("Failed to run the example", err);
} finally {
await glm.disconnect();
}
}
window.run = run;
</script>
</body>
</html>
In this layout, there are three elements:
- An
Options
form, where you can define input params, - An
Actions
section with "Echo Hello World" button, which executes such a command on the remote Golem node, - A
Results
container, which displays the results
The js script defines:
- the
run()
function that creates the body of the requestor script - a helper functions that will let us present the results in the browser window.
Now, ensure you:
- have your Yagna APP key set to
try_golem
(as shown in the yagna installation instruction) and - have a running Yagna service started with the
--api-allow-origin
properly set tohttp://localhost:8080
Launch http-server
in the project folder.
http-server
If, instead of using the try_golem
app key defined by using the YAGNA_AUTOCONF_APPKEY
variable, you have created a unique app key, make sure you update appkey value in the respective Option field.
We should see our app available in the browser:
If you click the Echo Hello World button, after a while, in the result container, you should get the result of the script:
- the result of executing the script in the Results container
- debug logs in the console window