web5-rust 1.1.9

A rust crate for interacting with Web5
Documentation
use super::Error;

use crate::ed25519::{SecretKey};

use std::time::{SystemTime, UNIX_EPOCH};
use std::collections::HashMap;

use serde::{Deserialize, Serialize};
use serde_bencode::value::Value;

use url::Url;

const PKARR_SIZE_LIMIT: usize = 1000;

#[derive(Deserialize, Serialize)]
struct Data {
    seq: u64,
    v: Value
}

pub struct PkarrRelay {}

impl PkarrRelay {
    pub async fn put(url: Url, dns_packet: Vec<u8>, secret_key: &SecretKey) -> Result<(), Error> {
        let seq = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs();
        let mut map: HashMap<Vec<u8>, Value> = HashMap::new();
        map.insert(b"seq".to_vec(), Value::Int(seq.try_into().unwrap()));
        map.insert(b"v".to_vec(), Value::Bytes(dns_packet.clone()));

        let v = serde_bencode::to_bytes(&Value::Dict(map))?;
        let v = v[1..v.len()-1].to_vec();
        if v.len() > PKARR_SIZE_LIMIT {return Err(Error::bad_request("PkarrRelay.put", "Document length exceeds limit"));}

        let sig = secret_key.sign(&v).to_vec();
        let body = [sig, seq.to_be_bytes().to_vec(), dns_packet].concat();

        let res = reqwest::Client::new().put(url)
            .header("Content-Type", "application/octet-stream")
            .body(body)
            .send().await?;

        if !res.status().is_success() {
            Err(Error::err("PkarrRelay.put", &res.text().await?))
        } else {
            Ok(())
        }
    }

    pub async fn get(url: Url) -> Result<Option<Vec<u8>>, Error> {
        let res = reqwest::get(url).await?;
        if !res.status().is_success() {
            if res.status() == reqwest::StatusCode::NOT_FOUND {return Ok(None);}
            Err(Error::err("PkarrRelay.get", &res.text().await?))
        } else {
            Ok(Some(res.bytes().await?.to_vec()))
        }
    }
}