Skip to content
This repository has been archived by the owner on Dec 12, 2024. It is now read-only.

Commit

Permalink
Implement RFC-0001 with empty functionality (#58)
Browse files Browse the repository at this point in the history
  • Loading branch information
KendallWeihe authored Jun 25, 2024
1 parent c5c234e commit 1ee3bb2
Show file tree
Hide file tree
Showing 77 changed files with 12,422 additions and 914 deletions.
13 changes: 10 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
[workspace]
members = [
"crates/*",
members = [
"bindings/tbdex_uniffi", "crates/pfi_exemplar_integration_test",
"crates/tbdex",
]
default-members = [
"crates/*",
"crates/tbdex",
]
resolver = "2"

[workspace.package]
homepage = "https://github.com/TBD54566975/tbdex-rs"
repository = "https://github.com/TBD54566975/tbdex-rs.git"
license-file = "LICENSE"

[workspace.dependencies]
serde = { version = "1.0.193", features = ["derive"] }
serde_json = "1.0.108"
thiserror = "1.0.50"
web5 = { git = "https://github.com/TBD54566975/web5-rs", rev = "f4de14fbada87543a335e1b8dd4442cd21c04db7" }
22 changes: 16 additions & 6 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ default: setup
setup:
#!/bin/bash
if [[ "$(cargo 2>&1)" == *"rustup could not choose a version of cargo to run"* ]]; then
rustup default stable
rustup default 1.78.0
fi

# Build a release variant
Expand All @@ -15,13 +15,23 @@ build: setup

# Run all tests
test: setup
cargo test
cargo test --workspace

# Run linting, look for warnings and/or diffs in the output to correct
lint: setup
cargo clippy --workspace
cargo fmt -- --check
cargo fmt

# Run formatting
fmt: setup
cargo fmt
bind: setup
just bind-kotlin

bind-kotlin: setup
cargo build --release --package tbdex_uniffi
cargo run --package tbdex_uniffi \
--bin uniffi-bindgen \
generate --library target/release/libtbdex_uniffi.dylib \
--language kotlin \
--out-dir target/bindgen-kotlin
cp target/release/libtbdex_uniffi.dylib bound/kt/src/main/resources/natives
cp target/bindgen-kotlin/tbdex/sdk/rust/tbdex.kt bound/kt/src/main/kotlin/tbdex/sdk/rust
cd bound/kt && ./fix-load.sh
25 changes: 25 additions & 0 deletions bindings/tbdex_uniffi/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
[package]
name = "tbdex_uniffi"
version = "0.1.0"
edition = "2021"
homepage.workspace = true
repository.workspace = true
license-file.workspace = true

[dependencies]
serde_json = { workspace = true }
tbdex = { path = "../../crates/tbdex" }
thiserror = { workspace = true }
uniffi = { version = "0.27.1", features = ["cli"] }
web5 = { workspace = true }
web5_uniffi_wrapper = { git = "https://github.com/TBD54566975/web5-rs", rev = "f4de14fbada87543a335e1b8dd4442cd21c04db7" }

[build-dependencies]
uniffi = { version = "0.27.1", features = ["build"] }

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

[[bin]]
name = "uniffi-bindgen"
path = "uniffi-bindgen.rs"
6 changes: 6 additions & 0 deletions bindings/tbdex_uniffi/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/// Cargo automatically picks up `build.rs` as a custom build script https://doc.rust-lang.org/cargo/reference/build-scripts.html
/// This build script generates the Rust scaffolded code for UniFFI bindings https://mozilla.github.io/uniffi-rs/tutorial/Rust_scaffolding.html#setup-for-crates-using-udl
/// ex. code like `#[no_mangle]` and `extern "C"` is necessary https://doc.rust-lang.org/nomicon/ffi.html#rust-side
fn main() {
uniffi::generate_scaffolding("src/tbdex.udl").unwrap();
}
99 changes: 99 additions & 0 deletions bindings/tbdex_uniffi/src/errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
use serde_json::Error as SerdeJsonError;
use std::sync::{Arc, PoisonError};
use std::{any::type_name, fmt::Debug};
use tbdex::http_client::HttpClientError;
use tbdex::messages::MessageError;
use tbdex::resources::ResourceError;
use thiserror::Error;

#[derive(Debug, Error)]
pub enum RustCoreError {
#[error("{message}")]
Error {
r#type: String,
variant: String,
message: String,
},
}

impl RustCoreError {
pub fn from_poison_error<T>(error: PoisonError<T>, error_type: &str) -> Arc<Self> {
Arc::new(RustCoreError::Error {
r#type: error_type.to_string(),
variant: "PoisonError".to_string(),
message: error.to_string(),
})
}
fn new<T>(error: T) -> Self
where
T: std::error::Error + 'static,
{
Self::Error {
r#type: type_of(&error).to_string(),
variant: variant_name(&error),
message: error.to_string(),
}
}

pub fn error_type(&self) -> String {
match self {
RustCoreError::Error {
r#type: error_type, ..
} => error_type.clone(),
}
}

pub fn variant(&self) -> String {
match self {
RustCoreError::Error {
variant: error_variant,
..
} => error_variant.clone(),
}
}

pub fn message(&self) -> String {
match self {
RustCoreError::Error { message, .. } => message.clone(),
}
}
}

fn type_of<T>(_: &T) -> &'static str {
type_name::<T>()
}

fn variant_name<T>(error: &T) -> String
where
T: Debug,
{
let message = format!("{:?}", error);
let variant_name = message.split('(').next().unwrap_or("UnknownVariant");
variant_name.to_string()
}

impl From<ResourceError> for RustCoreError {
fn from(error: ResourceError) -> Self {
RustCoreError::new(error)
}
}

impl From<MessageError> for RustCoreError {
fn from(error: MessageError) -> Self {
RustCoreError::new(error)
}
}

impl From<HttpClientError> for RustCoreError {
fn from(error: HttpClientError) -> Self {
RustCoreError::new(error)
}
}

impl From<SerdeJsonError> for RustCoreError {
fn from(error: SerdeJsonError) -> Self {
RustCoreError::new(error)
}
}

pub type Result<T> = std::result::Result<T, Arc<RustCoreError>>;
16 changes: 16 additions & 0 deletions bindings/tbdex_uniffi/src/http_client/balances.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use crate::{errors::Result, resources::balance::Balance};
use std::sync::{Arc, RwLock};
use web5_uniffi_wrapper::dids::bearer_did::BearerDid;

pub fn get_balances(pfi_did_uri: String, bearer_did: Arc<BearerDid>) -> Result<Vec<Arc<Balance>>> {
let inner_balances =
tbdex::http_client::balances::get_balances(&pfi_did_uri, &bearer_did.0.clone())
.map_err(|e| Arc::new(e.into()))?;

let balances = inner_balances
.into_iter()
.map(|b| Arc::new(Balance(Arc::new(RwLock::new(b)))))
.collect();

Ok(balances)
}
80 changes: 80 additions & 0 deletions bindings/tbdex_uniffi/src/http_client/exchanges.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use crate::{
errors::Result,
messages::{close::Close, order::Order, order_status::OrderStatus, quote::Quote, rfq::Rfq},
};
use std::sync::{Arc, RwLock};
use tbdex::http_client::exchanges::Exchange as InnerExchange;
use web5_uniffi_wrapper::dids::bearer_did::BearerDid;

pub struct Exchange {
pub rfq: Arc<Rfq>,
pub quote: Option<Arc<Quote>>,
pub order: Option<Arc<Order>>,
pub order_statuses: Option<Vec<Arc<OrderStatus>>>,
pub close: Option<Arc<Close>>,
}

impl Exchange {
pub fn from_inner(inner: InnerExchange) -> Self {
Self {
rfq: Arc::new(Rfq(Arc::new(RwLock::new(inner.rfq.clone())))),
quote: inner
.quote
.as_ref()
.map(|q| Arc::new(Quote(Arc::new(RwLock::new(q.clone()))))),
order: inner
.order
.as_ref()
.map(|o| Arc::new(Order(Arc::new(RwLock::new(o.clone()))))),
order_statuses: inner.order_statuses.as_ref().map(|os| {
os.iter()
.map(|o| Arc::new(OrderStatus(Arc::new(RwLock::new(o.clone())))))
.collect::<Vec<_>>()
}),
close: inner
.close
.as_ref()
.map(|c| Arc::new(Close(Arc::new(RwLock::new(c.clone()))))),
}
}
}

pub fn create_exchange(rfq: Arc<Rfq>, reply_to: Option<String>) -> Result<()> {
tbdex::http_client::exchanges::create_exchange(&rfq.to_inner()?, reply_to)
.map_err(|e| Arc::new(e.into()))?;
Ok(())
}

pub fn submit_order(order: Arc<Order>) -> Result<()> {
tbdex::http_client::exchanges::submit_order(&order.get_data()?)
.map_err(|e| Arc::new(e.into()))?;
Ok(())
}

pub fn submit_close(close: Arc<Close>) -> Result<()> {
tbdex::http_client::exchanges::submit_close(&close.get_data()?)
.map_err(|e| Arc::new(e.into()))?;
Ok(())
}

pub fn get_exchange(
pfi_did_uri: String,
bearer_did: Arc<BearerDid>,
exchange_id: String,
) -> Result<Exchange> {
let inner_exchange = tbdex::http_client::exchanges::get_exchange(
&pfi_did_uri,
&bearer_did.0.clone(),
&exchange_id,
)
.map_err(|e| Arc::new(e.into()))?;

Ok(Exchange::from_inner(inner_exchange))
}

pub fn get_exchanges(pfi_did_uri: String, bearer_did: Arc<BearerDid>) -> Result<Vec<String>> {
let exchange_ids =
tbdex::http_client::exchanges::get_exchanges(&pfi_did_uri, &bearer_did.0.clone())
.map_err(|e| Arc::new(e.into()))?;
Ok(exchange_ids)
}
3 changes: 3 additions & 0 deletions bindings/tbdex_uniffi/src/http_client/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod balances;
pub mod exchanges;
pub mod offerings;
14 changes: 14 additions & 0 deletions bindings/tbdex_uniffi/src/http_client/offerings.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use crate::{errors::Result, resources::offering::Offering};
use std::sync::{Arc, RwLock};

pub fn get_offerings(pfi_did_uri: String) -> Result<Vec<Arc<Offering>>> {
let inner_offerings = tbdex::http_client::offerings::get_offerings(&pfi_did_uri)
.map_err(|e| Arc::new(e.into()))?;

let offerings = inner_offerings
.into_iter()
.map(|o| Arc::new(Offering(Arc::new(RwLock::new(o)))))
.collect();

Ok(offerings)
}
Loading

0 comments on commit 1ee3bb2

Please sign in to comment.