feat: crypto.c
This commit is contained in:
parent
aed80a7e9b
commit
981b512c6e
60
.gitignore
vendored
Normal file
60
.gitignore
vendored
Normal file
@ -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
|
27
Makefile
Normal file
27
Makefile
Normal file
@ -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
|
23
README.md
23
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
|
||||
```
|
||||
|
10
config.def.h
Normal file
10
config.def.h
Normal file
@ -0,0 +1,10 @@
|
||||
#define CUR "$"
|
||||
|
||||
struct wallet_s {
|
||||
char *from;
|
||||
char *to;
|
||||
float value;
|
||||
} WALLET[] = {
|
||||
{"BTC", "USDT", 1.00000000},
|
||||
{0},
|
||||
};
|
103
crypto.c
Normal file
103
crypto.c
Normal file
@ -0,0 +1,103 @@
|
||||
#include <curl/curl.h>
|
||||
#include <errno.h>
|
||||
#include <error.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user