1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
mod publish_db;
mod publish_sc;

use crate::types::{ Audit, Project };

use publish_db::publish_audit_db;

use publish_sc::publish_audit_sc;

use crate::{
    cmd::utils::upload_ipfs,
    utils::{ apply_dotenv, max_length_string, parse_json, validate_emails, validate_links },
};

use std::path::PathBuf;

use clap::{ Parser, ValueHint };

#[derive(Debug, Clone, Parser)]
pub struct PublishAuditArgs {
    #[clap(
        short,
        long = "audit-data",
        help = "File path to JSON file with Audit data",
        value_name = "AUDIT_DATA_JSON_FILE",
        value_hint = ValueHint::FilePath,
        required(true)
    )]
    audit_file_path: PathBuf,

    #[clap(
        short,
        long = "report-pdf",
        help = "File path to audit report PDF file",
        value_name = "AUDIT_REPORT_PDF_FILE",
        value_hint = ValueHint::FilePath,
        required(true)
    )]
    report_pdf_file_path: PathBuf,

    #[clap(short = 'n', long, required(true), value_parser = max_length_string)]
    project_name: String,

    #[clap(short = 't', long, value_hint = ValueHint::Url, value_parser = validate_links)]
    project_twitter_link: Option<String>,

    #[clap(short = 'g', long, value_hint = ValueHint::Url, value_parser = validate_links)]
    project_github_link: Option<String>,

    #[clap(short = 'w', long, value_hint = ValueHint::Url, value_parser = validate_links)]
    project_website_link: Option<String>,

    #[clap(
        short = 'c',
        long,
        help = "Your point of contact in the project",
        value_hint = ValueHint::EmailAddress,
        value_parser = validate_emails
    )]
    project_contact_email: Option<String>,

    #[clap(short = 'k', long)]
    api_key: Option<String>,

    #[clap(short = 'p', long)]
    private_key: Option<String>,

    #[clap(short = 's', long, help = "Publish an audit to SC", default_value = "false")]
    publish_sc: bool,
}

impl PublishAuditArgs {
    pub async fn run(self) -> eyre::Result<()> {
        apply_dotenv()?;

        let project_data = self.clone().get_project_data();

        let audit_data = parse_json::<Audit>(&self.audit_file_path)?;

        let api_key = match self.api_key {
            Some(token) => token,
            None => std::env::var("API_KEY")?,
        };

        let project_id = project_data.fetch_project_id(&api_key).await?;

        let (report_hash, report_file_url) = upload_ipfs(
            self.report_pdf_file_path,
            &api_key
        ).await?;

        let audit_data = publish_audit_db(
            audit_data,
            project_id,
            report_hash.clone(),
            report_file_url,
            &api_key
        ).await?;

        if self.publish_sc {
            publish_audit_sc(
                audit_data,
                self.project_name,
                report_hash,
                self.private_key,
                &api_key
            ).await?;
        }

        println!("Audit published successfully");

        Ok(())
    }

    fn get_project_data(self) -> Project {
        Project::new(
            self.project_name,
            self.project_twitter_link,
            self.project_github_link,
            self.project_website_link,
            self.project_contact_email
        )
    }
}