Skip to main content

Host APIs

Lyquid guest code reaches the node through the lyquor_api host bridge. Every host function returns LyquidResult<T>, so call them with ?. Most are wrapped by higher-level macros — call!, upc!, trigger!, submit_certified_call!, log!, println! — and you should prefer the macro. A handful are called directly: signing, randomness, time, HTTP, identity lookups, and oracle/sequencer metadata.

Context Restrictions

Many host APIs are restricted to one method category, and the restriction is enforced at runtime: calling a restricted API from the wrong context returns LyquidError::LyquorRuntime(...) instead of executing. This is how determinism is protected — a network method physically cannot read the clock, draw randomness, sign with the node key, or make an HTTP request.

In the tables below, the Context column is one of:

  • instance — instance methods only (errors from a network context)
  • network — network methods only (errors from an instance context)
  • any — allowed in both, deterministic

Directly Called APIs

APISignatureContextPurpose
signsign(msg: Bytes, cipher: Cipher) -> BytesinstanceSign a message with the node's key for the given Cipher
verifyverify(msg: Bytes, cipher: Cipher, sig: Bytes, pubkey: Bytes) -> boolanyVerify a signature (deterministic)
random_bytesrandom_bytes(length: usize) -> Vec<u8>instanceNode-local randomness
systimesystime() -> u64instanceCurrent node time as Unix milliseconds
http_requesthttp_request(request: http::Request, options: Option<http::RequestOptions>) -> http::ResponseinstancePerform an outbound HTTP(S) request
eth_contracteth_contract() -> Option<Address>anyThe EVM contract address bound to this Lyquid, if any
sequence_backend_idsequence_backend_id() -> SequenceBackendIDanyIdentifier of the active sequencing backend
fetch_oracle_infofetch_oracle_info(topic: String, target: OracleTarget, full_config: bool) -> Option<OracleEpochInfo>instanceRead oracle epoch/committee metadata for a topic and target
versionversion() -> LyquidNumberanyCurrent network state version
chain_poschain_pos() -> ChainPosanyCurrent chain position
get_ed25519_qxyget_ed25519_qxy(pubkey: [u8; 32]) -> (U256, U256)anyDecompress an ed25519 public key to curve coordinates
get_address_by_ed25519get_address_by_ed25519(pubkey: [u8; 32]) -> Option<Address>anyMap an ed25519 public key to its address
get_ed25519_by_addressget_ed25519_by_address(address: Address) -> Option<NodeID>anyMap an address to its node ID

Cipher is Ed25519 or Secp256k1. Note the asymmetry between sign (instance only, uses the node key) and verify (deterministic, allowed in network methods).

Macro-Wrapped APIs

Prefer the macro; it encodes/decodes named fields and applies the correct semantics. The underlying host function is listed for reference.

MacroHost functionContextNotes
call!inter_lyquid_callnetworkAtomic inter-Lyquid network call; aborts the slot on failure
upc!universal_procedural_callinstanceOff-chain inter-Lyquid call across hosting nodes
submit_certified_call!submit_callinstanceSubmit a certified call to the sequencing backend
trigger!triggeranySchedule a function; TriggerMode::Commit is network only
log!lognetworkEmit a Lyte log (EVM-event-like)
print! / println! / eprint! / eprintln!console_outputanyLyquid console output

state_set and state_get also exist on the bridge but are emitted by the generated state! code. Do not call them directly; use declared state variables instead.

HTTP Request Example

An instance method can fetch external data over HTTP. Decode the response body with serde_json or any other parser.

use lyquid::http::{Method, Request, RequestOptions};

#[method::instance]
fn fetch_price(ctx: &mut _, symbol: String) -> LyquidResult<U256> {
let req = Request {
method: Method::Get,
url: format!("https://api.example.com/ticker?symbol={symbol}"),
headers: vec![],
body: None,
};

let resp = lyquor_api::http_request(req, Some(RequestOptions { timeout_ms: Some(1000) }))?;
if resp.status != 200 {
return Err(LyquidError::LyquorRuntime(format!("HTTP {}", resp.status)));
}

// parse resp.body, store into instance state, or return a value
Ok(U256::ZERO)
}

http::Request carries method, url, headers: Vec<Header>, and body: Option<Vec<u8>>. http::Response carries status: u16, headers: Vec<Header>, and body: Vec<u8>. Because http_request is instance-only, results that must reach network state have to go through an oracle/certified-call flow — see Oracles and Certified Calls.