use std::convert::TryFrom; use affine_common::hashcash::Stamp; use napi::{Env, Result, Task, bindgen_prelude::AsyncTask}; use napi_derive::napi; pub struct AsyncVerifyChallengeResponse { response: String, bits: u32, resource: String, } #[napi] impl Task for AsyncVerifyChallengeResponse { type Output = bool; type JsValue = bool; fn compute(&mut self) -> Result { Ok(if let Ok(stamp) = Stamp::try_from(self.response.as_str()) { stamp.check(self.bits, &self.resource) } else { false }) } fn resolve(&mut self, _: Env, output: bool) -> Result { Ok(output) } } #[napi] pub fn verify_challenge_response( response: String, bits: u32, resource: String, ) -> AsyncTask { AsyncTask::new(AsyncVerifyChallengeResponse { response, bits, resource, }) } pub struct AsyncMintChallengeResponse { bits: Option, resource: String, } #[napi] impl Task for AsyncMintChallengeResponse { type Output = String; type JsValue = String; fn compute(&mut self) -> Result { Ok(Stamp::mint(self.resource.clone(), self.bits).format()) } fn resolve(&mut self, _: Env, output: String) -> Result { Ok(output) } } #[napi] pub fn mint_challenge_response(resource: String, bits: Option) -> AsyncTask { AsyncTask::new(AsyncMintChallengeResponse { bits, resource }) } #[cfg(test)] mod tests { use napi::Task; use super::*; #[test] fn hashcash_roundtrip() { let resource = "test-resource".to_string(); let mut mint = AsyncMintChallengeResponse { bits: Some(8), resource: resource.clone(), }; let stamp = mint.compute().unwrap(); let mut verify = AsyncVerifyChallengeResponse { response: stamp, bits: 8, resource, }; assert!(verify.compute().unwrap()); } }