-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: introduce framework crate (#19)
- Loading branch information
Showing
4 changed files
with
243 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
[package] | ||
name = "balius" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
description = "SDK for building Headless dApps on UTxO-based blockchains" | ||
authors = ["TxPipe <[email protected]>"] | ||
license = "MIT OR Apache-2.0" | ||
repository = "https://github.com/txpipe/balius" | ||
documentation = "https://docs.rs/balius" | ||
readme = "README.md" | ||
keywords = ["blockchain", "dapp", "sdk", "utxo", "cardano"] | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
serde = "1.0.204" | ||
serde_json = "1.0.122" | ||
wit-bindgen = "0.29.0" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# Balius | ||
|
||
Balius is a framework for building Headless dApps on UTxO-based blockchains. | ||
|
||
## Usage | ||
|
||
Add this to your `Cargo.toml`: | ||
|
||
```toml | ||
[dependencies] | ||
balius = "0.1.0" | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
pub mod bindings { | ||
wit_bindgen::generate!({ | ||
pub_export_macro: true, | ||
default_bindings_module: "balius::bindings", | ||
}); | ||
} | ||
|
||
use bindings::{balius::odk, Response}; | ||
use serde::Serialize; | ||
use std::{ | ||
collections::HashMap, | ||
sync::{LazyLock, RwLock}, | ||
}; | ||
|
||
pub trait Handler: Send + Sync { | ||
fn handle( | ||
&self, | ||
evt: odk::driver::Event, | ||
) -> Result<odk::driver::Response, odk::driver::HandleError>; | ||
} | ||
|
||
impl<F, R> Handler for F | ||
where | ||
Response: From<R>, | ||
Self: Fn(odk::driver::Event) -> Result<R, odk::driver::HandleError> + Send + Sync, | ||
{ | ||
fn handle( | ||
&self, | ||
evt: odk::driver::Event, | ||
) -> Result<odk::driver::Response, odk::driver::HandleError> { | ||
let temp = self(evt)?; | ||
Ok(temp.into()) | ||
} | ||
} | ||
|
||
pub struct Json<T>(pub T); | ||
|
||
impl<T> From<Json<T>> for odk::driver::Response | ||
where | ||
T: Serialize, | ||
{ | ||
fn from(value: Json<T>) -> Self { | ||
Self::Json(serde_json::to_vec(&value.0).unwrap()) | ||
} | ||
} | ||
|
||
struct Channel { | ||
handler: Box<dyn Handler>, | ||
pattern: odk::driver::EventPattern, | ||
} | ||
|
||
type ChannelId = u32; | ||
type ChannelRegistry = HashMap<ChannelId, Channel>; | ||
|
||
static WORKER: LazyLock<RwLock<Worker>> = LazyLock::new(|| RwLock::new(Worker::new())); | ||
|
||
#[derive(Default)] | ||
pub struct Worker { | ||
channels: ChannelRegistry, | ||
} | ||
|
||
impl Worker { | ||
pub fn new() -> Self { | ||
Self::default() | ||
} | ||
|
||
pub fn handle_request<F>(mut self, method: &str, handler: F) -> Self | ||
where | ||
F: Handler + 'static, | ||
{ | ||
self.channels.insert( | ||
self.channels.len() as u32, | ||
Channel { | ||
handler: Box::new(handler), | ||
pattern: odk::driver::EventPattern::Request(method.to_owned()), | ||
}, | ||
); | ||
|
||
self | ||
} | ||
} | ||
|
||
pub trait Main { | ||
fn main() -> Worker; | ||
} | ||
|
||
impl<T: Main> self::bindings::Guest for T { | ||
fn handle( | ||
id: u32, | ||
evt: odk::driver::Event, | ||
) -> Result<odk::driver::Response, odk::driver::HandleError> { | ||
let worker = WORKER.read().unwrap(); | ||
let channel = worker.channels.get(&id).ok_or(1u32)?; | ||
|
||
channel.handler.handle(evt) | ||
} | ||
|
||
fn init(config: odk::driver::Cbor) { | ||
let worker = Self::main(); | ||
|
||
let mut singelton = WORKER.write().unwrap(); | ||
*singelton = worker; | ||
|
||
for (id, handler) in singelton.channels.iter() { | ||
odk::driver::register_channel(*id, &handler.pattern); | ||
} | ||
} | ||
} | ||
|
||
#[macro_export] | ||
macro_rules! entrypoint { | ||
($main:ident) => { | ||
struct _Main; | ||
|
||
impl balius::Main for _Main { | ||
fn main() -> balius::Worker { | ||
$main(Default::default()) | ||
} | ||
} | ||
|
||
balius::bindings::export!(_Main); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
package balius:odk; | ||
|
||
interface kv { | ||
type payload = list<u8>; | ||
type kv-error = u32; | ||
|
||
get-value: func(key: string) -> result<payload, kv-error>; | ||
set-value: func(key: string, value: payload) -> result<_, kv-error>; | ||
list-values: func(prefix: string) -> result<list<string>, kv-error>; | ||
} | ||
|
||
interface submit { | ||
type cbor = list<u8>; | ||
type submit-error = u32; | ||
|
||
submit-tx: func(tx: cbor) -> result<_, submit-error>; | ||
} | ||
|
||
interface broadcast { | ||
type msg = list<u8>; | ||
type broadcast-error = u32; | ||
|
||
publish-msg: func(topic: string, payload: msg) -> result<_, broadcast-error>; | ||
} | ||
|
||
interface driver { | ||
type handle-error = u32; | ||
type cbor = list<u8>; | ||
type json = list<u8>; | ||
type timestamp = u64; | ||
type params = json; | ||
|
||
variant event { | ||
utxo(cbor), | ||
utxo-undo(cbor), | ||
timer(timestamp), | ||
request(params), | ||
message(json), | ||
} | ||
|
||
type address = list<u8>; | ||
|
||
record token-pattern { | ||
policy: list<u8>, | ||
name: option<list<u8>>, | ||
} | ||
|
||
record utxo-pattern { | ||
address: option<address>, | ||
token: option<token-pattern>, | ||
} | ||
|
||
type timer-interval = string; | ||
|
||
type method = string; | ||
|
||
type topic = string; | ||
|
||
variant event-pattern { | ||
utxo(utxo-pattern), | ||
utxo-undo(utxo-pattern), | ||
timer(timer-interval), | ||
request(method), | ||
message(topic), | ||
} | ||
|
||
variant response { | ||
acknowledge, | ||
json(json), | ||
cbor(cbor), | ||
partial-tx(cbor) | ||
} | ||
|
||
register-channel: func(id: u32, pattern: event-pattern); | ||
} | ||
|
||
world worker { | ||
import kv; | ||
import broadcast; | ||
import submit; | ||
|
||
use driver.{event, handle-error, response}; | ||
|
||
type env = list<u8>; | ||
|
||
export init: func(env: env); | ||
|
||
export handle: func(channel: u32, evt: event) -> result<response, handle-error>; | ||
} |