Skip to content
Draft
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
4 changes: 2 additions & 2 deletions Cargo-minimal.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4696,7 +4696,7 @@ dependencies = [
[[package]]
name = "uniffi-dart"
version = "0.1.0+v0.30.0"
source = "git+https://github.com/Uniffi-Dart/uniffi-dart.git?tag=v0.1.0%2Bv0.30.0#e3ed67f780257a5a7fae23231e13d84f931208e0"
source = "git+https://github.com/Uniffi-Dart/uniffi-dart.git?rev=26739b93ca0d3e95dee8c8362d5d971cc931c6f3#26739b93ca0d3e95dee8c8362d5d971cc931c6f3"
dependencies = [
"anyhow",
"camino",
Expand Down Expand Up @@ -4767,7 +4767,7 @@ dependencies = [
[[package]]
name = "uniffi_dart_macro"
version = "0.1.0+v0.30.0"
source = "git+https://github.com/Uniffi-Dart/uniffi-dart.git?tag=v0.1.0%2Bv0.30.0#e3ed67f780257a5a7fae23231e13d84f931208e0"
source = "git+https://github.com/Uniffi-Dart/uniffi-dart.git?rev=26739b93ca0d3e95dee8c8362d5d971cc931c6f3#26739b93ca0d3e95dee8c8362d5d971cc931c6f3"
dependencies = [
"futures",
"proc-macro2",
Expand Down
4 changes: 2 additions & 2 deletions Cargo-recent.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4696,7 +4696,7 @@ dependencies = [
[[package]]
name = "uniffi-dart"
version = "0.1.0+v0.30.0"
source = "git+https://github.com/Uniffi-Dart/uniffi-dart.git?tag=v0.1.0%2Bv0.30.0#e3ed67f780257a5a7fae23231e13d84f931208e0"
source = "git+https://github.com/Uniffi-Dart/uniffi-dart.git?rev=26739b93ca0d3e95dee8c8362d5d971cc931c6f3#26739b93ca0d3e95dee8c8362d5d971cc931c6f3"
dependencies = [
"anyhow",
"camino",
Expand Down Expand Up @@ -4767,7 +4767,7 @@ dependencies = [
[[package]]
name = "uniffi_dart_macro"
version = "0.1.0+v0.30.0"
source = "git+https://github.com/Uniffi-Dart/uniffi-dart.git?tag=v0.1.0%2Bv0.30.0#e3ed67f780257a5a7fae23231e13d84f931208e0"
source = "git+https://github.com/Uniffi-Dart/uniffi-dart.git?rev=26739b93ca0d3e95dee8c8362d5d971cc931c6f3#26739b93ca0d3e95dee8c8362d5d971cc931c6f3"
dependencies = [
"futures",
"proc-macro2",
Expand Down
2 changes: 1 addition & 1 deletion payjoin-ffi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ thiserror = "2.0.14"
tokio = { version = "1.47.1", features = ["full"], optional = true }
uniffi = { version = "0.30.0", features = ["cli"] }
uniffi-bindgen-cs = { git = "https://github.com/chavic/uniffi-bindgen-cs.git", rev = "878a3d269eacce64beadcd336ade0b7c8da09824", optional = true }
uniffi-dart = { git = "https://github.com/Uniffi-Dart/uniffi-dart.git", tag = "v0.1.0+v0.30.0", optional = true }
uniffi-dart = { git = "https://github.com/Uniffi-Dart/uniffi-dart.git", rev = "26739b93ca0d3e95dee8c8362d5d971cc931c6f3", optional = true }
url = "2.5.4"

# getrandom is ignored here because it's required by the wasm_js feature
Expand Down
152 changes: 152 additions & 0 deletions payjoin-ffi/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::error;
use std::sync::Arc;

/// Error arising due to the specific receiver implementation
///
Expand All @@ -17,6 +18,157 @@ impl From<ImplementationError> for payjoin::ImplementationError {
fn from(value: ImplementationError) -> Self { value.0 }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, uniffi::Enum)]
pub enum HpkeErrorKind {
InvalidPublicKey,
Hpke,
InvalidKeyLength,
PayloadTooLarge,
PayloadTooShort,
UnexpectedSecp256k1Error,
Other,
}

impl From<payjoin::HpkeErrorKind> for HpkeErrorKind {
fn from(value: payjoin::HpkeErrorKind) -> Self {
match value {
payjoin::HpkeErrorKind::InvalidPublicKey => Self::InvalidPublicKey,
payjoin::HpkeErrorKind::Hpke => Self::Hpke,
payjoin::HpkeErrorKind::InvalidKeyLength => Self::InvalidKeyLength,
payjoin::HpkeErrorKind::PayloadTooLarge => Self::PayloadTooLarge,
payjoin::HpkeErrorKind::PayloadTooShort => Self::PayloadTooShort,
payjoin::HpkeErrorKind::UnexpectedSecp256k1Error => Self::UnexpectedSecp256k1Error,
_ => Self::Other,
}
}
}

#[derive(Debug, thiserror::Error, uniffi::Object)]
#[error("{message}")]
pub struct HpkeError {
kind: HpkeErrorKind,
message: String,
payload_too_large_actual: Option<u64>,
payload_too_large_max: Option<u64>,
}

impl From<payjoin::HpkeErrorDetails> for HpkeError {
fn from(value: payjoin::HpkeErrorDetails) -> Self {
Self {
kind: value.kind().into(),
message: value.message().to_owned(),
payload_too_large_actual: value.payload_too_large_actual().map(|value| value as u64),
payload_too_large_max: value.payload_too_large_max().map(|value| value as u64),
}
}
}

#[uniffi::export]
impl HpkeError {
pub fn kind(&self) -> HpkeErrorKind { self.kind }

pub fn message(&self) -> String { self.message.clone() }

pub fn payload_too_large_actual(&self) -> Option<u64> { self.payload_too_large_actual }

pub fn payload_too_large_max(&self) -> Option<u64> { self.payload_too_large_max }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, uniffi::Enum)]
pub enum OhttpEncapsulationErrorKind {
Http,
Ohttp,
Bhttp,
ParseUrl,
Other,
}

impl From<payjoin::OhttpEncapsulationErrorKind> for OhttpEncapsulationErrorKind {
fn from(value: payjoin::OhttpEncapsulationErrorKind) -> Self {
match value {
payjoin::OhttpEncapsulationErrorKind::Http => Self::Http,
payjoin::OhttpEncapsulationErrorKind::Ohttp => Self::Ohttp,
payjoin::OhttpEncapsulationErrorKind::Bhttp => Self::Bhttp,
payjoin::OhttpEncapsulationErrorKind::ParseUrl => Self::ParseUrl,
_ => Self::Other,
}
}
}

#[derive(Debug, thiserror::Error, uniffi::Object)]
#[error("{message}")]
pub struct OhttpEncapsulationError {
kind: OhttpEncapsulationErrorKind,
message: String,
}

impl From<payjoin::OhttpEncapsulationErrorDetails> for OhttpEncapsulationError {
fn from(value: payjoin::OhttpEncapsulationErrorDetails) -> Self {
Self { kind: value.kind().into(), message: value.message().to_owned() }
}
}

#[uniffi::export]
impl OhttpEncapsulationError {
pub fn kind(&self) -> OhttpEncapsulationErrorKind { self.kind }

pub fn message(&self) -> String { self.message.clone() }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, uniffi::Enum)]
pub enum DirectoryResponseErrorKind {
InvalidSize,
OhttpDecapsulation,
UnexpectedStatusCode,
Other,
}

impl From<payjoin::DirectoryResponseErrorKind> for DirectoryResponseErrorKind {
fn from(value: payjoin::DirectoryResponseErrorKind) -> Self {
match value {
payjoin::DirectoryResponseErrorKind::InvalidSize => Self::InvalidSize,
payjoin::DirectoryResponseErrorKind::OhttpDecapsulation => Self::OhttpDecapsulation,
payjoin::DirectoryResponseErrorKind::UnexpectedStatusCode => Self::UnexpectedStatusCode,
_ => Self::Other,
}
}
}

#[derive(Debug, thiserror::Error, uniffi::Object)]
#[error("{message}")]
pub struct DirectoryResponseError {
kind: DirectoryResponseErrorKind,
message: String,
invalid_size: Option<u64>,
unexpected_status_code: Option<u16>,
ohttp_error: Option<Arc<OhttpEncapsulationError>>,
}

impl From<payjoin::DirectoryResponseErrorDetails> for DirectoryResponseError {
fn from(value: payjoin::DirectoryResponseErrorDetails) -> Self {
Self {
kind: value.kind().into(),
message: value.message().to_owned(),
invalid_size: value.invalid_size().map(|value| value as u64),
unexpected_status_code: value.unexpected_status_code(),
ohttp_error: value.ohttp_error().cloned().map(|details| Arc::new(details.into())),
}
}
}

#[uniffi::export]
impl DirectoryResponseError {
pub fn kind(&self) -> DirectoryResponseErrorKind { self.kind }

pub fn message(&self) -> String { self.message.clone() }

pub fn invalid_size(&self) -> Option<u64> { self.invalid_size }

pub fn unexpected_status_code(&self) -> Option<u16> { self.unexpected_status_code }

pub fn ohttp_error(&self) -> Option<Arc<OhttpEncapsulationError>> { self.ohttp_error.clone() }
}

#[derive(Debug, thiserror::Error, uniffi::Object)]
#[error("Error de/serializing JSON object: {0}")]
pub struct SerdeJsonError(#[from] serde_json::Error);
Expand Down
67 changes: 64 additions & 3 deletions payjoin-ffi/src/receive/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ use std::sync::Arc;

use payjoin::receive;

use crate::error::{FfiValidationError, ImplementationError};
use crate::error::{
DirectoryResponseError, FfiValidationError, HpkeError, ImplementationError,
OhttpEncapsulationError,
};
use crate::uri::error::IntoUrlError;

/// The top-level error type for the payjoin receiver
Expand Down Expand Up @@ -164,9 +167,67 @@ impl From<ProtocolError> for JsonReply {
}

/// Error that may occur during a v2 session typestate change
#[derive(Clone, Copy, Debug, PartialEq, Eq, uniffi::Enum)]
pub enum SessionErrorKind {
ParseUrl,
Expired,
OhttpEncapsulation,
Hpke,
DirectoryResponse,
Other,
}

impl From<receive::v2::SessionErrorKind> for SessionErrorKind {
fn from(value: receive::v2::SessionErrorKind) -> Self {
match value {
receive::v2::SessionErrorKind::ParseUrl => Self::ParseUrl,
receive::v2::SessionErrorKind::Expired => Self::Expired,
receive::v2::SessionErrorKind::OhttpEncapsulation => Self::OhttpEncapsulation,
receive::v2::SessionErrorKind::Hpke => Self::Hpke,
receive::v2::SessionErrorKind::DirectoryResponse => Self::DirectoryResponse,
_ => Self::Other,
}
}
}

#[derive(Debug, thiserror::Error, uniffi::Object)]
#[error(transparent)]
pub struct SessionError(#[from] receive::v2::SessionError);
#[error("{message}")]
pub struct SessionError {
kind: SessionErrorKind,
message: String,
hpke_error: Option<Arc<HpkeError>>,
ohttp_error: Option<Arc<OhttpEncapsulationError>>,
directory_response_error: Option<Arc<DirectoryResponseError>>,
}

impl From<receive::v2::SessionError> for SessionError {
fn from(value: receive::v2::SessionError) -> Self {
Self {
kind: value.kind().into(),
message: value.to_string(),
hpke_error: value.hpke_error().map(|error| Arc::new(error.into())),
ohttp_error: value.ohttp_error().map(|error| Arc::new(error.into())),
directory_response_error: value
.directory_response_error()
.map(|error| Arc::new(error.into())),
}
}
}

#[uniffi::export]
impl SessionError {
pub fn kind(&self) -> SessionErrorKind { self.kind }

pub fn message(&self) -> String { self.message.clone() }

pub fn hpke_error(&self) -> Option<Arc<HpkeError>> { self.hpke_error.clone() }

pub fn ohttp_error(&self) -> Option<Arc<OhttpEncapsulationError>> { self.ohttp_error.clone() }

pub fn directory_response_error(&self) -> Option<Arc<DirectoryResponseError>> {
self.directory_response_error.clone()
}
}

/// Protocol error raised during output substitution.
#[derive(Debug, thiserror::Error, uniffi::Object)]
Expand Down
Loading
Loading