Quickstart

Task Executor 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.

warning

In addition, follow the instructions to set up the app-key, but start the Yagna with a parameter that allows you to handle REST API requests with a CORS policy. You can do this by running the following command:

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.

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

Next, we'll create the main index.html file with the following content:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>WebRequestor QuickStart</title>
  </head>
  <body>
    <h1>WebRequestor - QuickStart</h1>
    <div class="container">
      <div class="col-6">
        <h3>Options</h3>
        <div class="column">
          <div>
            <label for="YAGNA_API_BASEPATH">Yagna Api BaseUrl: </label>
            <input id="YAGNA_API_BASEPATH" type="text" value="http://127.0.0.1:7465" />
          </div>
          <div>
            <label for="SUBNET_TAG">Subnet Tag: </label>
            <input id="SUBNET_TAG" type="text" value="public" />
          </div>
          <div>
            <label for="PAYMENT_NETWORK">Payment network: </label>
            <input id="PAYMENT_NETWORK" type="text" value="holesky" />
          </div>
        </div>
        <h3>Actions</h3>
        <div class="row vertical">
          <div>
            <button id="echo">Echo Hello World</button>
          </div>
        </div>
        <div class="results console">
          <h3>Results</h3>
          <ul id="results"></ul>
        </div>
      </div>
      <div class="col-6 border-left">
        <div class="logs console">
          <h3>Logs</h3>
          <ul id="logs"></ul>
        </div>
      </div>
    </div>
    <script type="module" src="requestor.mjs"></script>
  </body>
</html>

In this layout, there are three elements:

  • A "Echo Hello World" button, which executes the script on Golem
  • A "Results" container, which displays the results
  • A "Logs" container, which displays the API logs

Requestor script

Next, we'll create a requestor.mjs file with the following content:

import { TaskExecutor } from "https://unpkg.com/@golem-sdk/task-executor";

function appendResults(result) {
  const results = document.getElementById("results");
  const div = document.createElement("div");
  div.appendChild(document.createTextNode(result));
  results.appendChild(div);
}

function appendLog(msg, level = "info") {
  const logs = document.getElementById("logs");
  const div = document.createElement("div");
  div.appendChild(document.createTextNode(`[${new Date().toISOString()}] [${level}] ${msg}`));
  logs.appendChild(div);
}

const logger = {
  error: (msg) => appendLog(msg, "error"),
  info: (msg) => appendLog(msg, "info"),
  warn: (msg) => appendLog(msg, "warn"),
  debug: (msg) => appendLog(msg, "debug"),
  child: () => logger,
};

async function run() {
  const executor = await TaskExecutor.create({
    logger,
    api: { key: "try_golem", url: document.getElementById("YAGNA_API_BASEPATH").value },
    demand: {
      workload: {
        imageTag: "golem/node:20-alpine",
      },
      subnetTag: document.getElementById("SUBNET_TAG").value,
    },
    market: {
      rentHours: 0.5,
      pricing: {
        model: "linear",
        maxStartPrice: 0.5,
        maxCpuPerHourPrice: 1.0,
        maxEnvPerHourPrice: 0.5,
      },
    },
    payment: { network: document.getElementById("PAYMENT_NETWORK").value },
  });

  try {
    await executor.run(async (exe) => appendResults((await exe.run("echo 'Hello World'")).stdout));
  } catch (error) {
    logger.error("Computation failed:", error);
  } finally {
    await executor.shutdown();
  }
}

document.getElementById("echo").onclick = run;

Note the file contains the run() function that creates the body of the requestor script (similar to the one we use in Node.js) and a set of helper functions that will let us present the logs and 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 to http://localhost:8080

Launch http-server in the project folder.

http-server
warning

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 the requestor.mjs code and set the proper value there. See here for deails.

We should see our app available in the browser.

Open localhost

If you click the Echo Hello World button, after a while, in the result container, you should get the result of the script: Hello World and see the logs of executed commands in the log container.

Output logs