diff --git a/config.def.h b/config.def.h index d9a00b0..167165b 100644 --- a/config.def.h +++ b/config.def.h @@ -1,10 +1,12 @@ -#define CUR "$" +#define FMT "%s=$%f" -struct wallet_s { - char *from; - char *to; - float value; +// curl https://api.coingecko.com/api/v3/simple/supported_vs_currencies +#define VS "usd" + +// curl https://api.coingecko.com/api/v3/coins/list +static const struct wallet_s { + char *id; char *fmt; float value; } WALLET[] = { - {"BTC", "USDT", 1.00000000}, + {"bitcoin", "BTC", 1.00000000}, {0}, }; diff --git a/crypto.c b/crypto.c index fa54955..44e957b 100644 --- a/crypto.c +++ b/crypto.c @@ -7,18 +7,15 @@ #include #include "config.h" -#define BUF_SIZE 1024 +#define ARRLEN(a) (sizeof (a) / sizeof *(a)) +#define BUF_SIZE 256 * ARRLEN(WALLET) -// [{"symbol":"BTCUSDT","price":"69420.69420"}] -static int get_next_symbol(char* buf, float* price) +// {"bitcoin":{"usd":69420.69}} +static int get_next_symbol(char *buf, float *price) { - static const char output[] = "\"symbol\":\"%*[^\"]\",\"price\":\"%f\""; - char* tmp = strtok(buf, "{"); + static const char output[] = "\"%*[a-z]\":{\"" VS "\":%f}"; + char *tmp = strtok(buf, ","); - if (!tmp) { - return 1; - } - tmp = strtok(0, "}"); if (!tmp) { return 1; } @@ -27,73 +24,65 @@ static int get_next_symbol(char* buf, float* price) static size_t write_callback(char *response, size_t s, size_t n, void *buf) { - size_t size = s * n; - - return snprintf(buf, MIN(size, BUF_SIZE), response); + return snprintf(buf, MIN(s * n, BUF_SIZE), response); } -static char* build_url(void) +static char *build_url(void) { - const char base[] = - "https://api.binance.com/api/v3/ticker/price?symbols=["; - size_t s = sizeof base; - char* url; - char* tmp = (char*)s - 1; + const char base[] = "https://api.coingecko.com/api/v3/simple/price?ids=%s&vs_currencies=" VS; + size_t ids_size = 0; + char *url; + char ids[BUF_SIZE] = {0}; - for (size_t i = 0; WALLET[i].to; i++) { - s += strlen(WALLET[i].from) + strlen(WALLET[i].to) + 3; // ["SYMBOL",] + for (size_t i = 0; WALLET[i].id; i++) { + strcpy(ids + ids_size, WALLET[i].id); + ids_size += strlen(WALLET[i].id); + ids[ids_size++] = ','; } - url = malloc(s); + ids[ids_size - 1] = '\0'; + url = malloc(sizeof base + ids_size * (sizeof *url)); if (!url) { - return 0; + return NULL; } - strcpy(url, base); - tmp += (size_t)url; - for (size_t i = 0; WALLET[i].to; i++) { - tmp += sprintf(tmp, "\"%s%s\",", WALLET[i].from, WALLET[i].to); - } - url[strlen(url) - 1] = ']'; + sprintf(url, base, ids); return url; } -static CURL* init_curl(char* response) +static int perform_request(char *response) { - char* url = build_url(); - CURL* curl = curl_easy_init(); - + char *url = build_url(); + CURL *curl = curl_easy_init(); if (!url || !curl) { free(url); curl_easy_cleanup(curl); - return 0; + return 1; } curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, response); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_perform(curl); + curl_easy_cleanup(curl); free(url); - return curl; + return 0; } int main(void) { char response[BUF_SIZE]; - CURL* curl = init_curl(response); - int err; - float price, current; - float sum = 0; + int err = perform_request(response); + float price, current, sum = 0; - if (!curl) { + if (err) { error(1, errno, "cannot init curl"); } - err = get_next_symbol(response, &price); - for (size_t i = 0; !err && WALLET[i].to; i++) { + err = get_next_symbol(response + 1, &price); + for (size_t i = 0; !err && WALLET[i].id; i++) { current = price * WALLET[i].value; - printf("%s=%.2f" CUR " ", WALLET[i].from, current); + printf(FMT " ", WALLET[i].fmt, current); sum += current; - err = get_next_symbol(0, &price); + err = get_next_symbol(NULL, &price); } - printf("TOT=%.2f" CUR "\n", sum); - curl_easy_cleanup(curl); + printf(FMT, "TOT", sum); return 0; }