Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions videre/crates/videre-host/src/bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ mod venue_adapter {
path: [
"../../wit/videre-value-flow",
"../../wit/videre-types",
"../../wit/nexum-host",
"../../wit/deps/nexum-host",
"../../wit/videre-venue",
],
world: "videre:venue/venue-adapter",
Expand Down Expand Up @@ -54,7 +54,7 @@ mod client_host {
path: [
"../../wit/videre-value-flow",
"../../wit/videre-types",
"../../wit/nexum-host",
"../../wit/deps/nexum-host",
"../../wit/videre-venue",
],
imports: { default: async },
Expand Down Expand Up @@ -171,7 +171,7 @@ mod client_smoke {
path: [
"../../wit/videre-value-flow",
"../../wit/videre-types",
"../../wit/nexum-host",
"../../wit/deps/nexum-host",
"../../wit/videre-venue",
],
});
Expand Down
2 changes: 1 addition & 1 deletion videre/crates/videre-sdk/src/bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ world sdk-imports {
path: [
"../../wit/videre-value-flow",
"../../wit/videre-types",
"../../wit/nexum-host",
"../../wit/deps/nexum-host",
"../../wit/videre-venue",
],
world: "videre:sdk-shims/sdk-imports",
Expand Down
5 changes: 5 additions & 0 deletions videre/wit/deps.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[nexum-host]
url = "https://github.com/nullislabs/nexum-runtime/archive/refs/tags/nexum-host-v0.1.0.tar.gz"
prefix = "nexum-runtime-nexum-host-v0.1.0/wit/nexum-host"
sha256 = "c0a31ec3ff63a2b903daff7de9658d5caf9122737e388766fd6c380718e05587"
sha512 = "bcdba1c0e1c70c0eb42eb04591b0c45f923efb8de631d2acfbf2c9fecf455d5104af7a75513ac4cfa500a91700fbd8e82070d395939e5dfb50a190a6bb4a0413"
8 changes: 8 additions & 0 deletions videre/wit/deps.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Cross-repo WIT pins, vendored under wit/deps and verified against
# deps.lock by `wit-deps`. Pins are exact git tags of the owning repo;
# they converge to wkg/OCI (ghcr.io/nullislabs) with per-package semver
# once the packages are published.

[nexum-host]
url = "https://github.com/nullislabs/nexum-runtime/archive/refs/tags/nexum-host-v0.1.0.tar.gz"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pinned tag doesn't exist on the real nullislabs/nexum-runtime repo — verified two ways: gh api repos/nullislabs/nexum-runtime/tags returns an empty list, and fetching this exact archive URL resolves to a 404 after the redirect. Since nullislabs/nexum-runtime genuinely already exists as a separate repo (the carve has happened), wit-deps update/resolution against this pin will fail outright the moment anyone actually runs it — and scripts/check-dep-sync.sh only checks textual agreement across manifests, not live tag existence, so this placeholder currently sails through CI unnoticed. The sha256/sha512 digests in deps.lock can't be genuine either, since there's no real archive to have hashed. Fix: cut and push an actual nexum-host-v0.1.0 tag on nullislabs/nexum-runtime (or point at a real existing tag/commit), then regenerate deps.lock from that real source via the actual wit-deps tool rather than hand-written digests.

prefix = "nexum-runtime-nexum-host-v0.1.0/wit/nexum-host"
60 changes: 60 additions & 0 deletions videre/wit/deps/nexum-host/chain.wit
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package nexum:host@0.1.0;

interface chain {
use types.{chain-id, fault};

/// A JSON-RPC error response from the upstream node. `code` is the
/// node-reported numeric (typically `-32000` for an `eth_call`
/// revert). `data` is the decoded `error.data` payload: the host
/// hex-decodes the upstream JSON string once, so a guest receives
/// the raw abi-encoded revert bytes without any string handling.
record rpc-error {
code: s32,
message: string,
data: option<list<u8>>,
}

/// Failure of a chain call: either a shared host `fault` (transport
/// down, timed out, denied, ...) or a structured JSON-RPC error
/// carrying the node code and any decoded revert payload.
variant chain-error {
fault(fault),
rpc(rpc-error),
}

/// A single JSON-RPC request to be executed as part of a batch.
record rpc-request {
method: string,
params: string,
}

/// Result of a single request inside a batch. Each entry is independent;
/// one failing call does not abort the others.
variant rpc-result {
ok(string),
err(chain-error),
}

/// Execute a JSON-RPC request against the specified chain.
///
/// The host routes to its configured provider for the given chain,
/// applying whatever middleware is appropriate for the platform
/// (timeout, retry, rate-limit, fallback on server; simple HTTP
/// on mobile; window.ethereum or injected provider in WebView).
///
/// `method` includes the namespace prefix (e.g. "eth_call"). Each
/// host enforces its own permitted method surface; the reference
/// server host forwards only a read-only set and refuses signing
/// or mutating methods with a `denied` fault before they reach the
/// provider. `params` and the success value are JSON-encoded
/// strings.
request: func(chain-id: chain-id, method: string, params: string)
-> result<string, chain-error>;

/// Execute several JSON-RPC requests against the same chain in a single
/// round trip where the host transport supports it. Hosts that cannot
/// batch natively MUST fall back to sequential `request` calls. The
/// returned list is the same length as `requests` and in the same order.
request-batch: func(chain-id: chain-id, requests: list<rpc-request>)
-> result<list<rpc-result>, chain-error>;
}
24 changes: 24 additions & 0 deletions videre/wit/deps/nexum-host/event-module.wit
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package nexum:host@0.1.0;

/// Event-driven module — automation, background processing.
/// No UI capabilities. Runs on any conforming host.
world event-module {
use types.{config, event, fault};

// Six core primitives (always provided by a conforming host).
import chain;
import identity;
import local-store;
import remote-store;
import messaging;
import logging;

// Time, randomness, and outbound HTTP are WASI concerns, not
// nexum:host interfaces: wasi:clocks and wasi:random are linked
// into every module store, and hosts link
// wasi:http/outgoing-handler, gated per-module by the
// `[capabilities.http].allow` allowlist in module.toml.

export init: func(config: config) -> result<_, fault>;
export on-event: func(event: event) -> result<_, fault>;
}
24 changes: 24 additions & 0 deletions videre/wit/deps/nexum-host/identity.wit
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package nexum:host@0.1.0;

/// Identity / signing capability.
///
/// 0.2 ships a single, minimal interface. A future release (0.4+) is
/// expected to split this into `identity-read` and `identity-sign` and to
/// introduce a richer `signing-result` variant; for 0.2 the simple shape is
/// sufficient because user rejection can already be expressed via
/// `fault.denied`.
interface identity {
use types.{fault};

/// Return the list of account addresses (20-byte EVM addresses) the host
/// is willing to sign for. Empty list means no signing capability.
accounts: func() -> result<list<list<u8>>, fault>;

/// Sign an arbitrary message with personal_sign semantics (prepends the
/// "\x19Ethereum Signed Message:\n" prefix). Returns a 65-byte signature.
sign: func(account: list<u8>, message: list<u8>) -> result<list<u8>, fault>;

/// Sign EIP-712 typed data. `typed-data` is a JSON-encoded EIP-712 payload.
/// Returns a 65-byte signature.
sign-typed-data: func(account: list<u8>, typed-data: string) -> result<list<u8>, fault>;
}
29 changes: 29 additions & 0 deletions videre/wit/deps/nexum-host/local-store.wit
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package nexum:host@0.1.0;

interface local-store {
use types.{fault};

/// Get a value by key. Returns none if the key does not exist.
get: func(key: string) -> result<option<list<u8>>, fault>;

/// Set a key-value pair. Overwrites any existing value.
/// The host may enforce a size quota; if exceeded, returns err.
set: func(key: string, value: list<u8>) -> result<_, fault>;

/// Delete a key. No-op if the key does not exist.
delete: func(key: string) -> result<_, fault>;

/// List all keys matching a prefix. Empty prefix returns all keys.
list-keys: func(prefix: string) -> result<list<string>, fault>;

/// Whether the key exists, without transferring the value.
contains: func(key: string) -> result<bool, fault>;

/// Value byte length, none if the key is absent, without
/// transferring the value. On some backends this may be a scan.
len: func(key: string) -> result<option<u64>, fault>;

/// Number of keys matching a prefix, without materialising the key
/// list. On some backends this may be a scan.
count: func(prefix: string) -> result<u64, fault>;
}
15 changes: 15 additions & 0 deletions videre/wit/deps/nexum-host/logging.wit
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package nexum:host@0.1.0;

interface logging {
enum level {
trace,
debug,
info,
warn,
error,
}

/// Emit a structured log message.
/// The host decides how to handle it (stdout, file, discard).
log: func(level: level, message: string);
}
19 changes: 19 additions & 0 deletions videre/wit/deps/nexum-host/messaging.wit
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package nexum:host@0.1.0;

interface messaging {
use types.{fault, message};

/// Publish a message to a content topic.
///
/// Content topics follow the format: /<app>/<version>/<topic>/<encoding>
/// e.g. "/nexum/1/twap-updates/proto"
publish: func(content-topic: string, payload: list<u8>) -> result<_, fault>;

/// Query historical messages from the Waku store protocol.
query: func(
content-topic: string,
start-time: option<u64>,
end-time: option<u64>,
limit: option<u32>,
) -> result<list<message>, fault>;
}
25 changes: 25 additions & 0 deletions videre/wit/deps/nexum-host/query-module.wit
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package nexum:host@0.1.0;

/// Query module — synchronous, side-effect-free evaluation.
///
/// EXPERIMENTAL (0.2): the shape of this world is provisional and may
/// change in a future minor release without a major bump. Hosts and SDKs
/// should expect breakage here until the world is stabilised.
///
/// A query module exposes a single pure `evaluate` entry point. It is given
/// read-only access to the local store (for cached/derived state) and to
/// logging; everything else (chain access, network, messaging, signing) is
/// deliberately excluded so the host can run queries inside a tight
/// deterministic sandbox.
world query-module {
use types.{config, fault};

import local-store;
import logging;

export init: func(config: config) -> result<_, fault>;

/// Evaluate the query. `input` and the returned bytes are opaque to the
/// host; the module and its caller agree on the encoding.
export evaluate: func(input: list<u8>) -> result<list<u8>, fault>;
}
33 changes: 33 additions & 0 deletions videre/wit/deps/nexum-host/remote-store.wit
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package nexum:host@0.1.0;

interface remote-store {
use types.{fault};

/// Upload raw data to the decentralised store.
/// Returns the 32-byte content reference (Swarm address).
upload: func(data: list<u8>) -> result<list<u8>, fault>;

/// Download raw data by 32-byte content reference.
download: func(reference: list<u8>) -> result<list<u8>, fault>;

/// Read the latest value from a mutable feed.
///
/// Feeds are mutable pointers: (owner, topic) -> latest chunk.
/// `owner`: 20-byte Ethereum address of the feed owner.
/// `topic`: 32-byte topic hash.
read-feed: func(
owner: list<u8>,
topic: list<u8>,
) -> result<option<list<u8>>, fault>;

/// Update a mutable feed with new data.
///
/// The host signs the feed update with its configured identity.
/// `topic`: 32-byte topic hash.
/// `data`: the payload to publish.
/// Returns the 32-byte reference of the new chunk.
write-feed: func(
topic: list<u8>,
data: list<u8>,
) -> result<list<u8>, fault>;
}
106 changes: 106 additions & 0 deletions videre/wit/deps/nexum-host/types.wit
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package nexum:host@0.1.0;

/// Common types shared across all runtime interfaces.
///
/// All `u64` timestamps in this package are milliseconds since the Unix
/// epoch, UTC.
interface types {
type chain-id = u64;

record block {
chain-id: chain-id,
number: u64,
hash: list<u8>,
timestamp: u64,
}

/// One decoded log, mirroring the RPC `eth_getLogs` shape field for
/// field so the guest can rebuild the native alloy log losslessly.
/// Fixed-width byte fields are carried raw: `address` is 20 bytes,
/// each topic and hash is 32. The block-scoped fields are absent on a
/// pending log (mined logs carry them all).
record chain-log {
address: list<u8>,
topics: list<list<u8>>,
data: list<u8>,
block-hash: option<list<u8>>,
block-number: option<u64>,
block-timestamp: option<u64>,
transaction-hash: option<list<u8>>,
transaction-index: option<u64>,
log-index: option<u64>,
removed: bool,
}

/// A batch of logs delivered from one subscription. The alloy log type
/// carries no chain id, so it sits here once: every log in a delivery
/// shares the chain of the subscription that produced it.
record chain-logs {
chain-id: chain-id,
logs: list<chain-log>,
}

/// A message delivered over the messaging interface. Defined here (rather
/// than only in `messaging.wit`) so the `event` variant can reference it
/// without a cross-interface use clause.
record message {
content-topic: string,
payload: list<u8>,
timestamp: u64,
/// Optional sender identity (protocol-dependent).
sender: option<list<u8>>,
}

/// Fired by the host on a configured cadence. `fired-at` is the host's
/// wall-clock time (ms since Unix epoch, UTC) at which the tick was
/// generated.
record tick {
fired-at: u64,
}

/// A host-observed status transition for a previously submitted
/// intent. Transport-blind: the subscriber sees only where the
/// intent is in its life, never how the host learnt it.
record intent-status-update {
/// Venue id the receipt was issued by.
venue: string,
/// The venue-scoped intent identifier, opaque to the host.
receipt: list<u8>,
/// Opaque versioned status body: a leading u8 version tag,
/// then that version's borsh payload (v1: lifecycle status,
/// optional settlement proof, optional failure reason). An
/// unknown tag is a decode error and the body is never empty.
/// The host never inspects it.
status: list<u8>,
}

variant event {
block(block),
chain-logs(chain-logs),
tick(tick),
message(message),
intent-status(intent-status-update),
}

/// Opaque config from module.toml [config] section.
type config = list<tuple<string, string>>;

/// The cross-domain failure vocabulary richer interfaces embed as a
/// case. Each payload-bearing case carries a human-readable detail;
/// `rate-limited` carries structured backoff guidance instead.
variant fault {
unsupported(string),
unavailable(string),
denied(string),
rate-limited(rate-limit),
timeout,
invalid-input(string),
internal(string),
}

/// Backoff guidance for a `fault.rate-limited`. `retry-after-ms` is
/// the host's suggested wait before retrying, when known.
record rate-limit {
retry-after-ms: option<u64>,
}
}
1 change: 0 additions & 1 deletion videre/wit/nexum-host

This file was deleted.

Loading