Skip to content

Creating Custom HyperBEAM Devices

You can create your own HyperBEAM devices with Erlang, Rust or C++, and test them using WAO JS SDK.

You should write unit tests in device's own language such as Erlang with eunit.

Minimum Viable Device

You can add an arbitrary device in the HyperBEAM/src directory.

-module(dev_foo).
-export([ info/3 ]).
-include_lib("eunit/include/eunit.hrl").
-include("include/hb.hrl").
 
info(Msg, _, Opts) ->
    {ok, hb_ao:set(Msg, #{ <<"version">> => <<"1.0">> }, Opts)}.

Then add your device to the preloaded_devices list in HyperBEAM/src/hb_ops.

preloaded_devices => [
  #{<<"name">> => <<"ans104@1.0">>, <<"module">> => dev_codec_ans104},
  #{<<"name">> => <<"compute@1.0">>, <<"module">> => dev_cu},
  ...
  #{<<"name">> => <<"foo@1.0">>, <<"module">> => dev_foo}
],

Now you can execute the functions using the WAO HB class.

import assert from "assert"
import { describe, it, before, after, beforeEach } from "node:test"
import { HyperBEAM } from "wao"
 
const cwd = "../HyperBEAM" // HyperBEAM directory
 
describe("Hyperbeam Legacynet", function () {
  let hbeam, hb
  before(async () => {
    hbeam = await new HyperBEAM({ cwd, reset: true }).ready()
  })
  beforeEach(async () => (hb = hbeam.hb))
  after(async () => hbeam.kill())
 
  it("should query a custome device", async () => {
    const { version } = await hb.g("/~foo@1.0/info")
	assert.equal("1.0", version)
  })
})

Execution Device for AO Process

To create an execution device for AO process, you need to implement at least init/3, normalize/3, compute/3 and snapshot/3.

-module(dev_foo).
-export([ compute/3, init/3, snapshot/3, normalize/3 ]).
-include_lib("eunit/include/eunit.hrl").
-include("include/hb.hrl").
 
compute(Msg1, Msg2, Opts) ->
    case hb_ao:get([<<"body">>,<<"Action">>], Msg2, Opts) of
	Other ->
	    {ok, hb_ao:set( Msg1, #{  }, Opts )}
    end.
 
init(Msg, Msg2, Opts) -> 
    {ok, hb_ao:set(Msg, #{ }, Opts)}.
 
snapshot(Msg, _Msg2, _Opts) -> {ok, Msg}.
 
normalize(Msg, _Msg2, _Opts) -> {ok, Msg}.

Now you can spawn a process by specifying execution-device.

import assert from "assert"
import { describe, it, before, after, beforeEach } from "node:test"
 
const cwd = "../HyperBEAM" // HyperBEAM directory
 
describe("Hyperbeam Legacynet", function () {
  let hbeam, hb
  before(async () => {
    hbeam = await new HyperBEAM({ cwd, reset: true }).ready()
  })
  beforeEach(async () => (hb = hbeam.hb))
  after(async () => hbeam.kill())
 
  it("should query a custom device", async () => {
    const { pid } = await hb.spawn({"excecution-device": "foo@1.0"})
    const { slot, res } = await hb.message({ pid })
  })
})