auditfile 0.1.2

Bindings for the auditoor Auditfile
Documentation
use std::collections::HashMap;

use serde_derive::Deserialize;
use serde_derive::Serialize;

mod example;

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Audit {
    pub metadata: Metadata,
    pub revisions: Vec<Revision>,
    pub contracts: Vec<Contract>,
    pub audit: AuditDetails,
}

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Metadata {
    pub title: String,
    pub source: String,
    pub status: String,
    pub languages: Vec<String>,
    pub categories: Vec<String>,
    pub tags: Vec<String>,
    pub networks: Vec<String>,
    pub timestamps: AuditTimestamps,
    pub project: Project,
}

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AuditTimestamps {
    pub onboarded: i64,
    pub commencement: i64,
    pub completion: i64,
}

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Project {
    pub title: String,
    pub website: String,
    pub twitter: String,
    pub github: String,
}

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Revision {
    pub id: String,
    pub title: String,
    #[serde(rename = "source.commit")]
    pub source_commit: String,
    pub timestamps: Timestamps,
    pub status: String,
}

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Contract {
    pub id: String,
    pub revisions: HashMap<String, ContractRevisionDetails>,
    pub metadata: ContractMetadata,
}

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ContractRevisionDetails {
    pub file: String,
    pub name: String,
}

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ContractMetadata {
    pub livematch: Livematch,
    pub privileged: Vec<String>,
}

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Livematch {
    pub link: String,
    pub status: String,
    pub timestamps: Timestamps,
}

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Timestamps {
    pub commencement: i64,
    pub completion: i64,
}

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AuditDetails {
    pub contracts: HashMap<String, ContractAudit>,
}

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ContractAudit {
    pub description: String,
    pub issues: Issues,
}

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Issues {
    pub count: i64,
    pub severities: Severities,
}

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Severities {
    pub info: Info,
}

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Info {
    pub count: i64,
    pub issues: Vec<Issue>,
}

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Issue {
    pub id: String,
    pub title: String,
    pub description: String,
    pub recommendation: String,
    pub resolution: String,
    pub status: String,
    pub revisions: Revisions,
    pub timestamps: Timestamps,
}

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Revisions {
    pub raised: String,
    pub resolved: String,
}



#[cfg(test)]
mod tests {
    use serde_json;

    #[test]
    fn it_works() {
        let json_str = crate::example::tests::get_json();
        let audit: crate::Audit = serde_json::from_str(&json_str).unwrap();
        assert_eq!(audit.metadata.title, "XFarm Vaults");
        assert_eq!(audit.metadata.source, "https://github.com/xfarms/vaults");
        assert_eq!(audit.metadata.status, "auditing");
        assert_eq!(audit.metadata.languages, vec!["solidity"]);
        assert_eq!(audit.metadata.categories, vec!["vaults"]);
        assert_eq!(audit.metadata.tags, vec!["medium"]);
        assert_eq!(audit.metadata.networks, vec!["bsc"]);
        assert_eq!(audit.metadata.timestamps.onboarded, 12312312312);
        assert_eq!(audit.metadata.timestamps.commencement, 12313212312);
        assert_eq!(audit.metadata.timestamps.completion, 12312321312);
        assert_eq!(audit.metadata.project.title, "XFarm");
        assert_eq!(audit.metadata.project.website, "https://xfarms.io");
        assert_eq!(audit.metadata.project.twitter, "uno_farm");
        assert_eq!(audit.metadata.project.github, "https://github.com/xfarms");
        assert_eq!(audit.revisions.len(), 1);
        let revision = audit.revisions[0].clone();
        assert_eq!(revision.id, "preliminary");
        assert_eq!(revision.title, "Preliminary");
        assert_eq!(revision.source_commit, "https://github.com/xfarms/vaults/tree/4a6a247e017f96cb5f569331ca64c7f5fd41189d");
        assert_eq!(revision.status, "auditing");
        assert_eq!(revision.timestamps.commencement, 12312312312);
        assert_eq!(revision.timestamps.completion, 1231232131);

        assert_eq!(audit.contracts.len(), 1);
        let contract = audit.contracts[0].clone();
        assert_eq!(contract.id, "farm");
        assert_eq!(contract.revisions.len(), 1);
        let contract_revision = contract.revisions["preliminary"].clone();
        assert_eq!(contract_revision.file, "contracts/Farm.sol");
        assert_eq!(contract_revision.name, "Farm");
        assert_eq!(contract.metadata.livematch.link, "https://bscscan.com/address/0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000");
        assert_eq!(contract.metadata.livematch.status, "MATCHED");
        assert_eq!(contract.metadata.livematch.timestamps.commencement, 123123213);
        assert_eq!(contract.metadata.livematch.timestamps.completion, 12312312312);
        assert_eq!(contract.metadata.privileged.len(), 4);
        assert_eq!(contract.metadata.privileged[0], "transferOwnership");
        assert_eq!(contract.metadata.privileged[1], "renounceOwnership");
        assert_eq!(contract.metadata.privileged[2], "pause");
        assert_eq!(contract.metadata.privileged[3], "unpause");

        assert_eq!(audit.audit.contracts.len(), 1);
        let farm = audit.audit.contracts["farm"].clone();
        assert_eq!(farm.description, "The Farm contract is responsible for blabla");
        assert_eq!(farm.issues.count, 1);
        assert_eq!(farm.issues.severities.info.count, 1);
        assert_eq!(farm.issues.severities.info.issues.len(), 1);
        let issue = farm.issues.severities.info.issues[0].clone();
        assert_eq!(issue.id, "farm-typographicerrors");
        assert_eq!(issue.title, "Typographic Errors");
        assert_eq!(issue.description, "The contract contains the following typographic errors:\n\nLine 3\n ```uint256 precsicion```");
        assert_eq!(issue.recommendation, "Consider resolving the aforementioned errors.");
        assert_eq!(issue.resolution, "");
        assert_eq!(issue.status, "pending");
        assert_eq!(issue.revisions.raised, "preliminary");
        assert_eq!(issue.revisions.resolved, "resolutions1");
        assert_eq!(issue.timestamps.commencement, 12312321);
        assert_eq!(issue.timestamps.completion, 123123123);
    }
}