diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..528ba72 --- /dev/null +++ b/.gitignore @@ -0,0 +1,60 @@ +# Created by https://www.toptal.com/developers/gitignore/api/c +# Edit at https://www.toptal.com/developers/gitignore?templates=c + +### C ### +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# End of https://www.toptal.com/developers/gitignore/api/c +config.h +crypto diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0ada118 --- /dev/null +++ b/Makefile @@ -0,0 +1,27 @@ +CFLAGS = -Wall -Wpedantic -Wextra +LDFLAGS = -lcurl + +SRC = crypto.c + +OBJ = $(SRC:.c=.o) + +.PHONY: all clean re debug + +all: crypto + +$(OBJ): config.h + +config.h: + cp config.def.h $@ + +crypto: $(OBJ) + $(CC) -o $@ $(LDFLAGS) $(OBJ) + +clean: + $(RM) $(OBJ) + $(RM) crypto + +re: clean all + +debug: CFLAGS+=-g3 +debug: re diff --git a/README.md b/README.md index d4406d8..018ddc3 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,25 @@ # crypto +Get your current holding in crypto from Binance in your own currency. +Makefile inspired from suckless + +## Dependencies +### Arch +```console +# pacman -S curl +``` + +### Debian 11+ +```console +# apt-get install libcurl4-dev +``` + +## How-To +```console +$ make +``` +Set your settings in config.h +```console +$ make +$ ./crypto.sh +``` diff --git a/config.def.h b/config.def.h new file mode 100644 index 0000000..d9a00b0 --- /dev/null +++ b/config.def.h @@ -0,0 +1,10 @@ +#define CUR "$" + +struct wallet_s { + char *from; + char *to; + float value; +} WALLET[] = { + {"BTC", "USDT", 1.00000000}, + {0}, +}; diff --git a/crypto.c b/crypto.c new file mode 100644 index 0000000..38a9c0b --- /dev/null +++ b/crypto.c @@ -0,0 +1,103 @@ +#include +#include +#include +#include +#include +#include +#include +#include "config.h" + +#define BUF_SIZE 1024 + +// [{"symbol":"BTCUSDT","price":"69420.69420"}] +static int get_next_symbol(char* buf, float* price) +{ + static const char output[] = "\"symbol\":\"%*[^\"]\",\"price\":\"%f\""; + char* tmp = strtok(buf, "{"); + + if (!tmp) { + return 1; + } + tmp = strtok(0, "}"); + if (!tmp) { + return 1; + } + return !sscanf(tmp, output, 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); +} + +static char* build_url(void) +{ + static const char base[] = + "https://api.binance.com/api/v3/ticker/price?symbols=["; + size_t s = sizeof base; + char* url; + + for (size_t i = 0; WALLET[i].to; i++) { + s += strlen(WALLET[i].from) + strlen(WALLET[i].to) + 3; // ["SYMBOL",] + } + url = malloc(s); + if (!url) { + return 0; + } + strcpy(url, base); + for (size_t i = 0; WALLET[i].to; i++) { + strcat(strcat(strcat(strcat( + url, + "\""), + WALLET[i].from), + WALLET[i].to), + "\"," + ); + } + url[strlen(url) - 1] = ']'; + return url; +} + +static CURL* init_curl(char* response) +{ + char* url = build_url(); + CURL* curl = curl_easy_init(); + + + if (!url || !curl) { + free(url); + curl_easy_cleanup(curl); + return 0; + } + 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); + free(url); + return curl; +} + +int main(void) +{ + char response[BUF_SIZE]; + CURL* curl = init_curl(response); + int err; + float price, current; + float sum = 0; + + if (!curl) { + error(1, errno, "cannot init curl"); + } + err = get_next_symbol(response, &price); + for (size_t i = 0; !err && WALLET[i].to; i++) { + current = price * WALLET[i].value; + printf("%s=%.2f" CUR " ", WALLET[i].from, current); + sum += current; + err = get_next_symbol(0, &price); + } + printf("TOT=%.2f" CUR "\n", sum); + curl_easy_cleanup(curl); + return 0; +}