mod canonicalize;
mod client;
mod create;
mod did;
mod eip712;
mod jws;
mod server;
pub use canonicalize::{canonicalize, canonicalize_to_bytes};
pub use client::{
DecodedOffer, decode_signed_offers, extract_offers_from_payment_required,
extract_receipt_from_settle_response, find_accepts_object_from_signed_offer,
verify_receipt_matches_offer,
};
pub use create::{
DEFAULT_OFFER_VALIDITY_SECONDS, EXTENSION_VERSION, create_offer_eip712, create_offer_jws,
create_receipt_eip712, create_receipt_jws, extract_offer_payload, extract_receipt_payload,
};
pub use did::public_key_from_kid;
pub use eip712::{
Eip712DigestSigner, Eip712Verification, hash_offer_typed_data, hash_receipt_typed_data,
verify_offer_signature_eip712, verify_receipt_signature_eip712,
};
pub use jws::{
EddsaJwsSigner, Es256JwsSigner, Es256kJwsSigner, JwsHeader, JwsPublicKey, JwsSigner,
create_jws, extract_jws_header, extract_jws_payload, verify_jws, verify_offer_signature_jws,
verify_receipt_signature_jws,
};
use serde::{Deserialize, Serialize};
pub use server::{
DynOfferReceiptIssuer, Eip712OfferReceiptIssuer, JwsOfferReceiptIssuer, OfferReceiptExtension,
OfferReceiptIssuer, create_eip712_offer_receipt_issuer, create_jws_offer_receipt_issuer,
declare_offer_receipt_extension,
};
pub const OFFER_RECEIPT: &str = "offer-receipt";
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum SignatureFormat {
Jws,
Eip712,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct OfferPayload {
pub version: u64,
pub resource_url: String,
pub scheme: String,
pub network: String,
pub asset: String,
pub pay_to: String,
pub amount: String,
pub valid_until: u64,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct ReceiptPayload {
pub version: u64,
pub network: String,
pub resource_url: String,
pub payer: String,
pub issued_at: u64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub transaction: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "format")]
pub enum SignedOffer {
#[serde(rename = "jws")]
Jws {
#[serde(
default,
skip_serializing_if = "Option::is_none",
rename = "acceptIndex"
)]
accept_index: Option<u32>,
signature: String,
},
#[serde(rename = "eip712")]
Eip712 {
#[serde(
default,
skip_serializing_if = "Option::is_none",
rename = "acceptIndex"
)]
accept_index: Option<u32>,
payload: OfferPayload,
signature: String,
},
}
impl SignedOffer {
#[must_use]
pub const fn accept_index(&self) -> Option<u32> {
match self {
Self::Jws { accept_index, .. } | Self::Eip712 { accept_index, .. } => *accept_index,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "format")]
pub enum SignedReceipt {
#[serde(rename = "jws")]
Jws {
signature: String,
},
#[serde(rename = "eip712")]
Eip712 {
payload: ReceiptPayload,
signature: String,
},
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OfferInput {
pub accept_index: u32,
pub scheme: String,
pub network: String,
pub asset: String,
pub pay_to: String,
pub amount: String,
pub offer_validity_seconds: Option<u64>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ReceiptInput {
pub resource_url: String,
pub payer: String,
pub network: String,
pub transaction: Option<String>,
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum OfferReceiptError {
#[error("invalid JWS format")]
InvalidJws,
#[error("cannot canonicalize: {0}")]
Canonicalize(String),
#[error("sign failed: {0}")]
Sign(String),
#[error("verify failed: {0}")]
Verify(String),
#[error("unknown format: {0}")]
UnknownFormat(String),
#[error("clock error")]
Clock,
#[error("missing resource URL")]
MissingResourceUrl,
#[error("unsupported DID method: {0}")]
UnsupportedDid(String),
#[error("invalid DID: {0}")]
InvalidDid(String),
#[error("{0}")]
Serde(String),
}
impl From<serde_json::Error> for OfferReceiptError {
fn from(err: serde_json::Error) -> Self {
Self::Serde(err.to_string())
}
}