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
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[workspace]
resolver = "2"
members = ["venus/compliant-stablecoin", "venus/event-example", "venus/event-example/observer", "venus/http-fetch", "venus/multi-http-get", "venus/multi-http-post", "venus/predict", "venus/price-alert", "venus/rex-wasm-crypto", "venus/rex-wasm-pipeline", "venus/rex-wasm-pipeline/artifact", "venus/swap-program", "venus/swap-program-v2", "venus/token-redemption", "venus/websocket-feed", "venus/wit-multi-param-test", "venus/wit-primitives-test", "venus/wit-strings-test"]
members = ["venus/compliant-stablecoin", "venus/event-example", "venus/event-example/observer", "venus/http-fetch", "venus/multi-http-get", "venus/multi-http-post", "venus/predict", "venus/price-alert", "venus/price-consensus", "venus/price-consensus/artifact", "venus/rex-wasm-crypto", "venus/rex-wasm-pipeline", "venus/rex-wasm-pipeline/artifact", "venus/swap-program", "venus/swap-program-v2", "venus/token-redemption", "venus/websocket-feed", "venus/wit-multi-param-test", "venus/wit-primitives-test", "venus/wit-strings-test"]

[workspace.package]
version = "0.4.0-alpha.0"
Expand Down
62 changes: 62 additions & 0 deletions venus/price-consensus/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
"""Build file for rialo-price-consensus."""

load("@crates//:defs.bzl", "aliases", "all_crate_deps")
load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test")
load("//rialo:defs.bzl", "rialo_program")

package(default_visibility = ["//visibility:public"])

# Export Cargo.toml for crate_universe
exports_files(["Cargo.toml"])

rust_library(
name = "rialo-price-consensus",
srcs = glob(["src/**/*.rs"]),
aliases = aliases(),
crate_name = "rialo_price_consensus",
edition = "2021",
proc_macro_deps = [
"//developer-frameworks/pdk/venus/rialo-venus-proc-macro:rialo-venus-proc-macro",
] + all_crate_deps(proc_macro = True),
deps = [
"//developer-frameworks/pdk/venus/rialo-venus:rialo-venus",
"//developer-frameworks/sdk/rialo-s-program-error:rialo-s-program-error",
"//developer-frameworks/sdk/rialo-s-program:rialo-s-program",
] + all_crate_deps(normal = True),
)

rust_test(
name = "rialo-price-consensus-test",
aliases = aliases(),
crate = ":rialo-price-consensus",
edition = "2021",
proc_macro_deps = [
"//developer-frameworks/pdk/venus/rialo-venus-proc-macro:rialo-venus-proc-macro",
] + all_crate_deps(
proc_macro = True,
proc_macro_dev = True,
),
deps = [
"//developer-frameworks/pdk/venus/rialo-venus:rialo-venus",
"//developer-frameworks/sdk/rialo-s-program-error:rialo-s-program-error",
"//developer-frameworks/sdk/rialo-s-program:rialo-s-program",
] + all_crate_deps(
normal = True,
normal_dev = True,
),
)

rialo_program(
name = "rialo-price-consensus-polkavm",
srcs = glob(["src/**/*.rs"]),
cargo_toml = "Cargo.toml",
)

# Whole-tree filegroup for runfiles consumers (e.g. rialo-examples-release
# integration tests, which WalkDir over developer-frameworks/examples/).
# Glob does not cross sub-package boundaries, so this only collects this
# package's own files; the parent BUILD aggregates per-subpackage filegroups.
filegroup(
name = "files",
srcs = glob(["**"], exclude = ["BUILD.bazel"]),
)
72 changes: 72 additions & 0 deletions venus/price-consensus/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
[package]
name = "rialo-price-consensus"
description = "Validator-response price consensus example for Rialo Venus"
authors = ["Subzero Labs"]
license = "Apache-2.0"
publish = false
edition = "2021"

# rialo-venus: used by rialo! proc macro expanded code
[package.metadata.cargo-machete]
ignored = ["rialo-venus"]

[lib]
crate-type = ["cdylib", "rlib"]

[lints.rust]
future_incompatible = "warn"
nonstandard_style = "warn"
rust_2018_idioms = "warn"
unsafe_code = "warn"

[features]
implementation = []

[lints.rust.unexpected_cfgs]
level = "warn"
check-cfg = [
'cfg(target_feature, values("static-syscalls"))',
'cfg(target_os, values("solana"))',
'cfg(feature, values("frozen-abi", "no-entrypoint", "custom-panic", "custom-heap"))',
'cfg(msim)',
'cfg(fail_points)',
'cfg(rialo_simtest_seed_sweep)',
'cfg(bazel)',
]

[dependencies]
rialo-s-program = { version = "0.18.1", default-features = false }
rialo-s-program-error = { version = "0.18.1", features = ["borsh"] }
rialo-venus = { version = "0.18.1" }
rialo-venus-proc-macro = { version = "0.18.1" }
serde = { version = "1.0.219", features = ["derive", "rc"] }
serde_json = { version = "1.0.143", features = ["alloc", "preserve_order", "raw_value"] }

[lints.clippy]
all = "warn"
debug_assert_with_mut_call = "warn"
empty_enums = "warn"
exit = "warn"
expl_impl_clone_on_copy = "warn"
fallible_impl_from = "warn"
filter_map_next = "warn"
float_cmp_const = "warn"
imprecise_flops = "warn"
invalid_upcast_comparisons = "warn"
large_digit_groups = "warn"
large_stack_arrays = "warn"
large_types_passed_by_value = "warn"
linkedlist = "warn"
lossy_float_literal = "warn"
macro_use_imports = "warn"
mutex_integer = "warn"
option_option = "warn"
path_buf_push_overwrite = "warn"
ptr_as_ptr = "warn"
rc_mutex = "warn"
ref_option_ref = "warn"
rest_pat_in_fully_bound_structs = "warn"
same_functions_in_if_condition = "warn"
string_add_assign = "warn"
trait_duplication_in_bounds = "warn"
zero_sized_map_values = "warn"
73 changes: 73 additions & 0 deletions venus/price-consensus/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Rialo Price Consensus

A Venus example that fetches a live asset price through Rialo REX validators
and derives a simple median consensus from the validator responses.

The workflow demonstrates how a Venus program can:

- issue an asynchronous HTTP request with `AFTER ... CALL ...`
- receive a `RexReport` containing multiple validator responses
- validate and reject malformed or failed responses
- normalize string-encoded prices into integer cents
- calculate min, max, and median prices
- store consensus statistics in persistent workflow state

## Workflow

1. `initialize` stores the price feed URL and symbol.
2. `check_price` creates an HTTP GET REX request.
3. Validators independently fetch the endpoint.
4. `handle_price_report` receives the aggregated `RexReport`.
5. Valid prices are converted to cents and sorted.
6. The median price is stored as `consensus_price`.

## Example endpoint

The example has been tested with the Binance US ticker endpoint:

```text
https://api.binance.us/api/v3/ticker/price?symbol=BTCUSDT
```

Initialize with:

```text
price_feed_url=https://api.binance.us/api/v3/ticker/price
symbol=BTCUSDT
```

## Consensus behavior

Each validator response is handled independently.

Successful JSON responses are parsed, while REX errors, malformed JSON,
unserializable responses, non-positive prices, and empty payloads are rejected.

For valid responses, the program records:

- `valid_responses`
- `rejected_responses`
- `min_price`
- `max_price`
- `consensus_price`
- `last_rex_round`
- `checks_completed`

`consensus_price` is the median of the accepted validator prices.

## Build

```bash
cargo check -p rialo-price-consensus
cargo build --manifest-path venus/price-consensus/artifact/Cargo.toml
```

The `artifact` crate builds the deployable PolkaVM program used by
`rialo client program deploy-venus`.

## Devnet verification

This workflow was verified on Rialo devnet with four validator responses.
All four responses were accepted and produced the same median price.

The exact returned market price naturally changes between executions.
11 changes: 11 additions & 0 deletions venus/price-consensus/artifact/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "rialo-price-consensus-artifact"
description = "Pre-compiled PolkaVM artifact for rialo-price-consensus"
authors = ["Subzero Labs"]
license = "Apache-2.0"
publish = false
edition = "2021"

[build-dependencies]
rialo-build-lib = { version = "0.18.1" }
rialo-venus-build-helper = { version = "0.18.1" }
12 changes: 12 additions & 0 deletions venus/price-consensus/artifact/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) Subzero Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

fn main() {
rialo_build_lib::build_script::setup_polkavm_artifact_build()
.program_path("..")
.run()
.unwrap();

rialo_venus_build_helper::compile_rex_components("..")
.expect("Failed to compile rex WASM components");
}
8 changes: 8 additions & 0 deletions venus/price-consensus/artifact/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Copyright (c) Subzero Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

pub const PROGRAM: &[u8] = include_bytes!(concat!(
env!("OUT_DIR"),
"/",
env!("RIALO_BUILD_ARTIFACT_FILE")
));
Loading