~gruberb/onetutorial

Introduction tutorial to the Rust programming language
Add solution for step 13
Update header for step 7
Update solution for step 12

refs

main
browse  log 

clone

read-only
https://git.sr.ht/~gruberb/onetutorial
read/write
git@git.sr.ht:~gruberb/onetutorial

You can also use your local clone with git send-email.

#OneTutorial - A practical journey into the Rust Programming Language

This little project will help you touch many topics around Rust, in a small and contained way. It will touch

#What you will build

You can adjust the tutorial to your needs, but I find it more usefull to create something you will actually use. Therefore:

Update and read from a Google Sheet where you store your latest financial information and send out an E-Mail with a summary.

This can be adjuste to:

Update and read from a CSV file where you store your latest financial information and send out an E-Mail with a summary.

If you are not interested in the topic (finance), feel free to adjust it to whatever data inputs you consume a lot and want to automise.

#Before you begin

If you want to go down the Google Sheets route, you need to:

  1. Create a "Service Account" via the Google Console.
  2. Create a key which downloads a JSON file you need for the library we are going to use.
  3. Create a new Google Sheet and share it with the Service Account E-Mail so the secret you just downloaded can read and modify the Google Sheet.

Depending on which external APIs you are going to use, you need to create API keys for them as well. For this tutorial, I am using:

  1. The coinmarketcap.com API to fetch the latest Crypto prices
  2. The eodhistoricaldata.com API to fetch ETF prices

#The Tutorial

  1. Send a GET request to https://httpbin.org/ip and print the result to the console.
  2. Send out a request to CMC and fetch the price of BTC.
  3. Read the API key from an .env file.
  4. Get the name, symbol, price and 7day of the BTC and store it in a struct.
  5. Pass the list of currencies to fetch via the CLI.
  6. Save the result in a CSV file.
  7. In case the API returns an error, write it out to a log file and abort the application.
  8. In addition to the coin prices, fetch the price of a random ETF and store it also in a struct.
  9. Add a rows in your Google Sheet with ISN, amount of coins, price, total and a row with the total value of your portfolio.
  10. Instead of saving the result to a CSV, update your Google sheet.
  11. Move out your business logic in different modules.
  12. Build your Rust code and move the binary to a server and run it from there.
  13. Send out an E-Mail with the coin and ETF overview and redeploy your application/binary.

#Solutions

#Step 1 - Send HTTP request

Solution in branch step_1

#Step 2 - Send paramterised HTTP GET to CMC

Solution in branch step_2

#Step 3 - Read API key from .env instead of hardcoded

Solution in branch step_3

#Step 4 - Store result in custom struct

Solution in branch step_4

#Step 5 - Pass list of currencies via CLI

Solution in branch step_5

#Step 6 - Save results in CSV file

Solution in branch step_6

#Step 7 - Logging and Error handling

Solution in branch step_7

#Step 8 - Fetch ETF from different API

Solution in branch step_8

#Step 9 - Prepare Google Sheets

This step is done in the browser.

#Step 10 - Adding GoogleSheets library

Solution in branch step_10

#Step 11 - Move logic in modules

Solution in branch step_11

#Step 12 - Cross-compile your code via musl

This is done mostly locally.

> rustup target add x86_64-unknown-linux-musl
> cargo build --release --target=x86_64-unknown-linux-musl

You need to add a ssl dependency to Cargo.toml, and depending on your OS, install other third party packages. The error message is quite helpful.

Solution in branch step_12

#Step 13 - Send out E-Mail

For this, I overcomplicated things a bit to show some nice features of Rust. We can have different types in Rust. And instead of the "EMail-Type" knowing too much how to display information, we let the types themselves decide how to "display" their information in a HTML way. For this, we require types passed down to an E-Mail implement the HTML trait. Later on, we can have a Vec of Generics, and the "send_email" function has the trait bound to require the types to implement this trait.

Solution in branch step_13