打赏

[易学易懂系列|rustlang语言|零基础|快速入门|(28)|实战5:实现BTC价格转换工具]

[易学易懂系列|rustlang语言|零基础|快速入门|(28)|实战5:实现BTC价格转换工具]

项目实战

实战5:实现BTC价格转换工具

今天我们来开发一个简单的BTC实时价格转换工具。

我们首先创建一个目录:

cargo new btc_converter

我们用TDD方式来开发。

然后 我们先写一些测试代码。

在src/main.rs下面,增加代码如下:

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_convert_success() {
        match convert_btc(1.2, "BTC", "USD") {
            Ok(_) => assert!(true),
            Err(_) => assert!(false),
        }
    }
    #[test]
    fn test_convert_success2() {
        match convert_btc(2.1, "BTC", "MKD") {
            Ok(_) => assert!(true),
            Err(_) => assert!(false),
        }
    }

    #[test]
    fn test_convert_error_wrong_from() {
        match convert_btc(1.2, "wrongvalue", "USD") {
            Ok(_) => assert!(false),
            Err(_) => assert!(true),
        }
    }

    #[test]
    fn test_convert_error_wrong_to() {
        match convert_btc(1.2, "USD", "wrongvalue") {
            Ok(_) => assert!(false),
            Err(_) => assert!(true),
        }
    }
}

我们运行命令:

cargo test

结果肯定是不通过。

我现在我们来增加核心业务代码 :

const API_URL: &str = "https://apiv2.bitcoinaverage.com/convert/global";

//错误信息
#[derive(From, Display, Debug)]
enum BtcError {
    ApiError,
    Reqwest(reqwest::Error),
}
//响应信息结构体
#[derive(Deserialize, Debug)]
struct BtcResponse {
    time: String,
    success: bool,
    price: f64,
}


//价格转换,直接调用相关API
fn convert_btc(amount: f64, from: &str, to: &str) -> Result<BtcResponse, BtcError> {
    use BtcError::*;
    println!("---convert_btc-----{:?},{:?}", from, to);
    let client = reqwest::Client::new();
    let request =
        client
            .get(API_URL)
            .query(&[("from", from), ("to", to), ("amount", &amount.to_string())]);
    let response_result: BtcResponse = request.send()?.json()?;

    if !response_result.success {
        return Err(ApiError);
    }

    return Ok(response_result);
}

然后,我们再跑一下测试用例。

现在应该都通过 了。

当然我们要引用相关包:

[dependencies]
reqwest = "0.9.12"
serde_derive = "1.0.89"
serde = "1.0.89"
serde_json = "1.0.39"
structopt = "0.2.15"
derive_more = "0.14.0"

src/main.rs完整代码如下:

#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate derive_more;
use reqwest;
use std::process::exit;
use structopt::StructOpt;

fn main() {
    let opt = Opt::from_args();

    let response = match convert_btc(opt.amount, &opt.from, &opt.to) {
        Ok(value) => value,
        Err(e) => {
            println!("A error occurred when try to get value from api");
            if opt.verbose {
                println!("Message: {} - Details: {:?}", e, e);
            }
            exit(1);
        }
    };

    if opt.silent {
        println!("{}", response.price);
    } else {
        println!("{} {}", response.price, &opt.to);
    }
}
const API_URL: &str = "https://apiv2.bitcoinaverage.com/convert/global";
//错误信息
#[derive(From, Display, Debug)]
enum BtcError {
    ApiError,
    Reqwest(reqwest::Error),
}
//响应信息结构体
#[derive(Deserialize, Debug)]
struct BtcResponse {
    time: String,
    success: bool,
    price: f64,
}

#[derive(Debug, StructOpt)]
#[structopt(
    name = "btc_converter",
    about = "Get value of a btc value to a currency"
)]
struct Opt {
    /// Set amount to convert to a currency or from a currency
    #[structopt(default_value = "1")]
    amount: f64,
    /// Set the initial currency of
    #[structopt(short = "f", long = "from", default_value = "BTC")]
    from: String,
    /// Set the final currency to convert
    #[structopt(short = "t", long = "to", default_value = "USD")]
    to: String,
    /// Silent information about currency result
    #[structopt(short = "s", long = "silent")]
    silent: bool,
    /// Verbose errors
    #[structopt(short = "v", long = "verbose")]
    verbose: bool,
}
fn convert_btc(amount: f64, from: &str, to: &str) -> Result<BtcResponse, BtcError> {
    use BtcError::*;
    println!("---convert_btc-----{:?},{:?}", from, to);
    let client = reqwest::Client::new();
    let request =
        client
            .get(API_URL)
            .query(&[("from", from), ("to", to), ("amount", &amount.to_string())]);
    let response_result: BtcResponse = request.send()?.json()?;

    if !response_result.success {
        return Err(ApiError);
    }

    return Ok(response_result);
}
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_convert_success() {
        match convert_btc(1.2, "BTC", "USD") {
            Ok(_) => assert!(true),
            Err(_) => assert!(false),
        }
    }
    #[test]
    fn test_convert_success2() {
        match convert_btc(2.1, "BTC", "MKD") {
            Ok(_) => assert!(true),
            Err(_) => assert!(false),
        }
    }

    #[test]
    fn test_convert_error_wrong_from() {
        match convert_btc(1.2, "wrongvalue", "USD") {
            Ok(_) => assert!(false),
            Err(_) => assert!(true),
        }
    }

    #[test]
    fn test_convert_error_wrong_to() {
        match convert_btc(1.2, "USD", "wrongvalue") {
            Ok(_) => assert!(false),
            Err(_) => assert!(true),
        }
    }
}

API地址:

https://apiv2.bitcoinaverage.com

以上,希望对你有用。

如果遇到什么问题,欢迎加入:rust新手群,在这里我可以提供一些简单的帮助,加微信:360369487,注明:博客园+rust
posted @ 2019-12-23 18:35  gyc567  阅读(275)  评论(0编辑  收藏  举报