#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "SCREAMING-KEBAB-CASE")]
pub enum Chain {
Eth,
#[serde(rename = "ETH-SEPOLIA")]
EthSepolia,
Avax,
#[serde(rename = "AVAX-FUJI")]
AvaxFuji,
Matic,
#[serde(rename = "MATIC-AMOY")]
MaticAmoy,
Algo,
Atom,
Arb,
#[serde(rename = "ARB-SEPOLIA")]
ArbSepolia,
Hbar,
Sol,
#[serde(rename = "SOL-DEVNET")]
SolDevnet,
Uni,
#[serde(rename = "UNI-SEPOLIA")]
UniSepolia,
Trx,
Xlm,
Bch,
Btc,
Bsv,
Etc,
Ltc,
Xmr,
Xrp,
Zrx,
Op,
Dot,
}
#[derive(Debug, Clone, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ScreenAddressRequest {
pub idempotency_key: String,
pub address: String,
pub chain: Chain,
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum RiskAction {
Approve,
Review,
FreezeWallet,
Deny,
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum RiskScore {
Unknown,
Low,
Medium,
High,
Severe,
Blocklist,
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum RiskCategory {
Sanctions,
Csam,
IllicitBehavior,
Gambling,
TerroristFinancing,
Unsupported,
Frozen,
Other,
HighRiskIndustry,
Pep,
Trusted,
Hacking,
HumanTrafficking,
SpecialMeasures,
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum RiskType {
Ownership,
Counterparty,
Indirect,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SignalSource {
pub row_id: String,
pub pointer: String,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RiskSignal {
pub source: String,
pub source_value: String,
pub risk_score: RiskScore,
pub risk_categories: Vec<RiskCategory>,
#[serde(rename = "type")]
pub risk_type: RiskType,
pub signal_source: Option<SignalSource>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AddressScreeningDecision {
pub screening_date: String,
pub rule_name: Option<String>,
pub actions: Option<Vec<RiskAction>>,
pub reasons: Option<Vec<RiskSignal>>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ScreeningVendorDetail {
pub id: String,
pub vendor: String,
pub response: serde_json::Value,
pub create_date: String,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct ScreenAddressEnvelope {
pub data: BlockchainAddressScreeningResponse,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BlockchainAddressScreeningResponse {
pub result: ScreeningResult,
pub decision: AddressScreeningDecision,
pub id: String,
pub address: String,
pub chain: Chain,
pub details: Vec<ScreeningVendorDetail>,
pub alert_id: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum ScreeningResult {
Approved,
Denied,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn chain_roundtrip() -> Result<(), Box<dyn std::error::Error>> {
let s = serde_json::to_string(&Chain::EthSepolia)?;
assert_eq!(s, "\"ETH-SEPOLIA\"");
let parsed: Chain = serde_json::from_str("\"MATIC\"")?;
assert_eq!(parsed, Chain::Matic);
Ok(())
}
#[test]
fn risk_action_deserializes() -> Result<(), Box<dyn std::error::Error>> {
let a: RiskAction = serde_json::from_str("\"APPROVE\"")?;
assert_eq!(a, RiskAction::Approve);
Ok(())
}
}