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
125
126
127
128
129
130
131
132
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,
        validate_pdf,
    },
};

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,
        value_parser = validate_pdf,
        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
        )
    }
}