From 1a6836619fa107dc00649ba9d8f3b3ad21f6444e Mon Sep 17 00:00:00 2001 From: Joey Kraut Date: Fri, 28 Jun 2024 13:24:08 -0700 Subject: [PATCH] compliance: compliance-server: Define initial compliance api --- Cargo.toml | 15 +++++ compliance/compliance-api/Cargo.toml | 8 +++ compliance/compliance-api/src/lib.rs | 17 ++++++ compliance/compliance-server/Cargo.toml | 17 ++++++ compliance/compliance-server/src/error.rs | 17 ++++++ compliance/compliance-server/src/main.rs | 68 +++++++++++++++++++++++ fee-sweeper/Cargo.toml | 18 +++--- fee-sweeper/src/indexer/index_fees.rs | 3 +- fee-sweeper/src/indexer/queries.rs | 4 +- fee-sweeper/src/relayer_client.rs | 3 +- 10 files changed, 156 insertions(+), 14 deletions(-) create mode 100644 compliance/compliance-api/Cargo.toml create mode 100644 compliance/compliance-api/src/lib.rs create mode 100644 compliance/compliance-server/Cargo.toml create mode 100644 compliance/compliance-server/src/error.rs create mode 100644 compliance/compliance-server/src/main.rs diff --git a/Cargo.toml b/Cargo.toml index 379061a..ed5608a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,7 @@ [workspace] members = [ + "compliance/compliance-server", + "compliance/compliance-api", "dealer/renegade-dealer", "dealer/renegade-dealer-api", "fee-sweeper", @@ -14,3 +16,16 @@ debug = true [profile.release] opt-level = 3 # Full optimizations lto = true + +[workspace.dependencies] +# === Renegade Dependencies === # +arbitrum-client = { git = "https://github.com/renegade-fi/renegade.git", features = [ + "rand", +] } +renegade-api = { package = "external-api", git = "https://github.com/renegade-fi/renegade.git" } +renegade-common = { package = "common", git = "https://github.com/renegade-fi/renegade.git" } +renegade-constants = { package = "constants", git = "https://github.com/renegade-fi/renegade.git" } +renegade-circuits = { package = "circuits", git = "https://github.com/renegade-fi/renegade.git" } +renegade-circuit-types = { package = "circuit-types", git = "https://github.com/renegade-fi/renegade.git" } +renegade-crypto = { git = "https://github.com/renegade-fi/renegade.git" } +renegade-util = { package = "util", git = "https://github.com/renegade-fi/renegade.git" } diff --git a/compliance/compliance-api/Cargo.toml b/compliance/compliance-api/Cargo.toml new file mode 100644 index 0000000..45586f2 --- /dev/null +++ b/compliance/compliance-api/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "compliance-api" +version = "0.1.0" +edition = "2021" + +[dependencies] +serde = { version = "1", features = ["derive"] } +serde_json = { version = "1" } diff --git a/compliance/compliance-api/src/lib.rs b/compliance/compliance-api/src/lib.rs new file mode 100644 index 0000000..4e933d2 --- /dev/null +++ b/compliance/compliance-api/src/lib.rs @@ -0,0 +1,17 @@ +use serde::{Deserialize, Serialize}; + +/// The response type for a compliance check +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ComplianceCheckResponse { + /// The compliance status of the wallet + pub compliance_status: ComplianceStatus, +} + +/// The status on compliance for a wallet +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum ComplianceStatus { + /// The wallet is compliant + Compliant, + /// The wallet is not compliant + NotCompliant, +} diff --git a/compliance/compliance-server/Cargo.toml b/compliance/compliance-server/Cargo.toml new file mode 100644 index 0000000..83d55c9 --- /dev/null +++ b/compliance/compliance-server/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "compliance-server" +version = "0.1.0" +edition = "2021" + +[dependencies] +# === HTTP Server === # +http-body-util = "0.1.0" +warp = "0.3" +compliance-api = { path = "../compliance-api" } + +# === Renegade Dependencies === # +renegade-util = { workspace = true } + +# === Misc === # +clap = { version = "4.5", features = ["derive"] } +tokio = { version = "1.37", features = ["full"] } diff --git a/compliance/compliance-server/src/error.rs b/compliance/compliance-server/src/error.rs new file mode 100644 index 0000000..dd8daef --- /dev/null +++ b/compliance/compliance-server/src/error.rs @@ -0,0 +1,17 @@ +//! Error types for the compliance server + +use std::{error::Error, fmt::Display}; + +use warp::reject::Reject; + +/// The error type emitted by the compliance server +#[derive(Debug, Clone)] +pub enum ComplianceServerError {} + +impl Display for ComplianceServerError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "ComplianceServerError") + } +} +impl Error for ComplianceServerError {} +impl Reject for ComplianceServerError {} diff --git a/compliance/compliance-server/src/main.rs b/compliance/compliance-server/src/main.rs new file mode 100644 index 0000000..8841715 --- /dev/null +++ b/compliance/compliance-server/src/main.rs @@ -0,0 +1,68 @@ +use clap::Parser; +use compliance_api::{ComplianceCheckResponse, ComplianceStatus}; +use error::ComplianceServerError; +use renegade_util::telemetry::{setup_system_logger, LevelFilter}; +use warp::{reply::Json, Filter}; + +pub mod error; + +/// The CLI for the compliance server +#[derive(Debug, Clone, Parser)] +#[command(about = "The CLI for the compliance server")] +struct Cli { + /// The port to listen on + #[arg(short, long)] + port: u16, + /// The Chainalysis API key + #[arg(long)] + chainalysis_api_key: String, +} + +#[tokio::main] +async fn main() { + setup_system_logger(LevelFilter::INFO); + let cli = Cli::parse(); + + // Get compliance information for a wallet + let chainalysis_key = cli.chainalysis_api_key.clone(); + let compliance_check = warp::get() + .and(warp::path("v0")) + .and(warp::path("compliance-check")) + .and(warp::path::param::()) // wallet_address + .and_then(move |wallet_address| { + let key = chainalysis_key.clone(); + async move { + handle_req(wallet_address, &key).await + } + }); + + // GET /ping + let ping = warp::get() + .and(warp::path("ping")) + .map(|| warp::reply::with_status("PONG", warp::http::StatusCode::OK)); + + let routes = compliance_check.or(ping); + warp::serve(routes).run(([0, 0, 0, 0], cli.port)).await +} + +/// Handle a request for a compliance check +async fn handle_req( + wallet_address: String, + chainalysis_api_key: &str, +) -> Result { + let compliance_status = check_wallet_compliance(wallet_address, chainalysis_api_key).await?; + let resp = ComplianceCheckResponse { compliance_status }; + Ok(warp::reply::json(&resp)) +} + +/// Check the compliance of a wallet +async fn check_wallet_compliance( + wallet_address: String, + chainalysis_api_key: &str, +) -> Result { + // 1. Check the DB first + + // 2. If not present, check the chainalysis API + + todo!() +} diff --git a/fee-sweeper/Cargo.toml b/fee-sweeper/Cargo.toml index 43d7511..e7700f6 100644 --- a/fee-sweeper/Cargo.toml +++ b/fee-sweeper/Cargo.toml @@ -18,16 +18,14 @@ alloy-sol-types = "0.3.1" ethers = "2" # === Renegade Dependencies === # -arbitrum-client = { git = "https://github.com/renegade-fi/renegade.git", features = [ - "rand", -] } -renegade-api = { package = "external-api", git = "https://github.com/renegade-fi/renegade.git" } -renegade-common = { package = "common", git = "https://github.com/renegade-fi/renegade.git" } -renegade-constants = { package = "constants", git = "https://github.com/renegade-fi/renegade.git" } -renegade-circuits = { package = "circuits", git = "https://github.com/renegade-fi/renegade.git" } -renegade-circuit-types = { package = "circuit-types", git = "https://github.com/renegade-fi/renegade.git" } -renegade-crypto = { git = "https://github.com/renegade-fi/renegade.git" } -renegade-util = { package = "util", git = "https://github.com/renegade-fi/renegade.git" } +arbitrum-client = { workspace = true, features = ["rand"] } +renegade-api = { package = "external-api", workspace = true } +renegade-common = { package = "common", workspace = true } +renegade-constants = { package = "constants", workspace = true } +renegade-circuits = { package = "circuits", workspace = true } +renegade-circuit-types = { package = "circuit-types", workspace = true } +renegade-crypto = { workspace = true } +renegade-util = { package = "util", workspace = true } # === Misc Dependencies === # base64 = "0.22" diff --git a/fee-sweeper/src/indexer/index_fees.rs b/fee-sweeper/src/indexer/index_fees.rs index 29faa22..b0e4bb3 100644 --- a/fee-sweeper/src/indexer/index_fees.rs +++ b/fee-sweeper/src/indexer/index_fees.rs @@ -1,4 +1,5 @@ -//! Phase one of the sweeper's execution; index all fees since the last consistent block +//! Phase one of the sweeper's execution; index all fees since the last +//! consistent block use alloy_sol_types::SolCall; use arbitrum_client::abi::settleOfflineFeeCall; diff --git a/fee-sweeper/src/indexer/queries.rs b/fee-sweeper/src/indexer/queries.rs index 3de3c7d..87171f2 100644 --- a/fee-sweeper/src/indexer/queries.rs +++ b/fee-sweeper/src/indexer/queries.rs @@ -140,8 +140,8 @@ impl Indexer { return Ok(vec![]); } - // We query the fees table with a transformation that calculates the value of each fee using the prices passed in. - // This query looks something like: + // We query the fees table with a transformation that calculates the value of + // each fee using the prices passed in. This query looks something like: // SELECT tx_hash, mint, amount, // CASE // WHEN mint = '' then amount * diff --git a/fee-sweeper/src/relayer_client.rs b/fee-sweeper/src/relayer_client.rs index 2cd5027..1d7b12d 100644 --- a/fee-sweeper/src/relayer_client.rs +++ b/fee-sweeper/src/relayer_client.rs @@ -259,7 +259,8 @@ impl RelayerClient { // Enter a polling loop until the task finishes let poll_interval = Duration::from_millis(POLL_INTERVAL_MS); loop { - // For now, we assume that an error is a 404 in which case the task has completed + // For now, we assume that an error is a 404 in which case the task has + // completed // TODO: Improve this break condition if it proves problematic if self.get_relayer::(&path).await.is_err() { break;