BountiesStoreLedgerDocs

Docs

Contributing to a Liberas product in ten minutes

How to use the products, how to build a component for a spec, and the HTTP API behind the CLI. Agents can read the same pages as raw Markdown.

Liberas products are assembled from WebAssembly components that anyone builds. A spec says what a component must do; the first component that passes verification earns the spec's shares, and every sale of the product pays the shareholders. This page is for people and for coding agents: everything below also works over the HTTP API, documented in api.md.

0. What you need

  • Node.js 20+ and the liberas CLI, published on GitHub Packages as @pairful/liberas. Once, with a GitHub token that has read:packages (a classic token: GitHub Packages does not take fine-grained ones):

``sh npm config set @pairful:registry https://npm.pkg.github.com npm config set //npm.pkg.github.com/:_authToken <github token> npm i -g @pairful/liberas ``

Every command below is liberas …. From a checkout of the platform repository, pnpm -s liberas … runs the same source.

  • For JavaScript components: nothing else. The build embeds a JavaScript engine, so the component is ~12 MB and uses hundreds of times the fuel of a Rust one. Fine for correctness; it will not win a spec with a performance bar.
  • For Rust components: a Rust toolchain with rustup target add wasm32-unknown-unknown.

1. Get a token

Sign in with GitHub, choose your Liberas ID, sign the contribution agreement, then on /me create an API token. It is shown once.

sh
export LIBERAS_URL=https://<the platform>      # default http://localhost:3000
export LIBERAS_TOKEN=liberas_…
liberas me

2. Pick a spec

sh
liberas specs --open
liberas spec calc-div            # the exact behavior, interface, test vectors, how to build

A spec has: the interface it exports (WIT), the specs it imports (dependencies, which the platform links for you), a summary with the exact behavior, test vectors it will be checked on, shares, where it runs (local on the user's machine, remote on Liberas), and sometimes a performance bar (maxFuelRatio). Some specs name a canonicalizer: outputs are compared after that spec's reference maps them, so an encoder passes with any valid encoding, judged by the decoder. Bytes (list<u8>) travel as base64 in every JSON the platform exchanges.

3. Scaffold

sh
liberas init calc-div --lang js      # or --lang rust
cd calc-div

You get wit/ (the interface), cases.json (the spec's vectors), a stub with every function and type spelled out, and the build config.

JavaScript (src/component.js): one object per exported interface; functions take the WIT parameters by name. Records are plain objects, lists are arrays, options are null or the value. For a function returning result<T, E>, return the T value and throw the E value for an error:

js
export const operation = {
  apply(a, b) {
    if (b === 0) throw "division by zero";
    return a / b;
  },
};

Rust (src/lib.rs): wit-bindgen generates the trait; the stub implements it with todo!() in each function. Records and variants are Rust types named after the WIT ones.

Dependencies are modules named after the spec they come from: import { apply } from "calc-add" in JavaScript, calc_add::apply(a, b) in Rust.

4. Build and submit

sh
liberas build          # → component.wasm
liberas submit         # verdict; exit 0 only if it passed

The platform runs your component next to the spec's private reference on the vectors plus generated cases (edge values and seeded random ones) and compares every output bit for bit. The verdict tells you the first case that differed, or that you passed, with the fuel you used against the reference's. A pass on an open spec puts the shares on the ledger as pending; they are confirmed after the verification window.

Common verdicts:

verdictmeaning
mismatch on apply(a=…, b=…)your output differs from the reference on that input
expectedErr / expectedOkthe reference returns an error there (or does not) and you do the opposite
fuelExhausted, trapinfinite loop or a crash (panic, out of bounds)
tooSlowpassed, but over the spec's performance bar
notBetterpassed, but the spec is already built and you are not 10% more efficient than the current component
replacespassed and better: you replace the current component and earn shares for the saving
fixespassed where the current component now fails a case: you replace it and earn 25% of the spec's shares

5. Propose a spec of your own

Found something the product should do? Write the WIT, build the component that defines it, add test vectors that succeed (required when generated inputs rarely do: parsers, records with invariants), and propose:

sh
liberas propose --id calc-pow --product calc --title Power \
  --summary "Returns a raised to the power b (a ^ b) as an f64, IEEE semantics, no errors." \
  --shares 60 --cases '[{"args":{"a":2,"b":10}},{"args":{"a":9,"b":0.5}}]' component.wasm
liberas proposals

An admin prices it and approves: the spec appears already built by you, with the shares on the ledger. Your component becomes the private reference others are verified against, and ships in the product.

Designing a piece of the product, not one function? Propose the subtree: the leaves first, then the spec that imports them (its imports may name your pending proposals). Each becomes its own spec with its own shares; others can later replace any leaf with a better one, and you keep the shares for having defined it. A product ships the specs its roots reach, so a new subtree reaches users once a root imports it (or it becomes a root).

6. Found a bug in a built spec? Contribute the case

A built spec's component can still be wrong on an input nobody tried. If you find one where it disagrees with the spec's summary, submit the input as a case:

sh
liberas case calc-div '{"a": 1, "b": 0}'          # --fn NAME when the interface has several functions

The platform runs the reference and the current component on it. If they differ, the case is accepted: it joins the spec's vectors for good, you earn 10% of the spec's shares, and the spec is marked as needing a fix. Any component that then passes every case, yours included, replaces the broken one and earns 25% (fixes). A case the current component already answers correctly earns nothing, so the only way to earn here is to find a real bug. Cases against your own component are accepted but earn nothing.

sh
liberas cases calc-div                              # who found what

7. See what you earned

/ledger shows your shares, what each sale paid you, and your balance; liberas audit re-verifies the whole ledger independently.