Skip to content

Commit

Permalink
feature: add /market command to show market chart (#7)
Browse files Browse the repository at this point in the history
* feat: add coins command (not tested yet)

* fix: make returned tokens/coins as list from bot

* chore: fix failing build by updating the index

* chore: fix missing sudo

* feat: add /market to fetch market chart for spesific token id by currency and days
  • Loading branch information
igprad authored Oct 17, 2023
1 parent f6b85c9 commit 8dd5c6a
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 1 deletion.
2 changes: 2 additions & 0 deletions include/coingecko.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,7 @@ namespace gecko {

void fetch_tokens(dpp::slashcommand_t event);
void fetch_price(dpp::slashcommand_t event);
void fetch_market_chart(dpp::slashcommand_t event);
size_t write_callback(char* ptr, size_t size, size_t nmemb, std::string* data);

} // namespace gecko
14 changes: 14 additions & 0 deletions include/quickchart.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include <curl/curl.h>

#include <cstdlib>
#include <iostream>
#include <vector>

#include "nlohmann/json.hpp"

namespace qchart {

std::string generate_chart(std::string label1, std::vector<long> data1,
std::string label2, std::vector<long> data2);
size_t write_callback(char* ptr, size_t size, size_t nmemb, std::string* data);
} // namespace qchart
56 changes: 55 additions & 1 deletion src/coingecko.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
#include <coingecko.h>
#include <quickchart.h>

using json = nlohmann::json;

// This callback function is called by curl_easy_perform() to write the response
// data into a string
size_t write_callback(char* ptr, size_t size, size_t nmemb, std::string* data) {
size_t gecko::write_callback(char* ptr, size_t size, size_t nmemb,
std::string* data) {
data->append(ptr, size * nmemb);
return size * nmemb;
}
Expand Down Expand Up @@ -109,3 +111,55 @@ void gecko::fetch_tokens(dpp::slashcommand_t event) {

curl_easy_cleanup(curl);
}

void gecko::fetch_market_chart(dpp::slashcommand_t event) {
std::string token_id = std::get<std::string>(event.get_parameter("token_id"));
std::string currency = std::get<std::string>(event.get_parameter("currency"));
std::string days = std::get<std::string>(event.get_parameter("days"));

CURL* curl = curl_easy_init();
if (!curl) {
std::cerr << "Error: could not initialize libcurl" << std::endl;
return;
}

std::string url = "https://api.coingecko.com/api/v3/coins/" + token_id +
"/market_chart?vs_currency=" + currency + "&days=" + days;
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());

std::string response_data;
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_data);

CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK) {
std::cerr << "Error: curl_easy_perform() failed: "
<< curl_easy_strerror(res) << std::endl;
curl_easy_cleanup(curl);
return;
}

try {
json response_json = json::parse(response_data);
// std::cout << "=============================" << std::endl;
// std::cout << ">> coingecko response: " << response_json << std::endl;
std::vector<long> timestamps;
std::vector<long> prices;
for (auto& chart : response_json["market_caps"]) {
timestamps.push_back(chart.at(0));
prices.push_back(chart.at(1));
}
auto chart = qchart::generate_chart("test", timestamps, "test", prices);
event.reply(chart);
std::cout << chart << std::endl;

} catch (const std::exception& e) {
std::cerr << "Error: failed to parse JSON response: " << e.what()
<< std::endl;
curl_easy_cleanup(curl);

event.reply(":exclamation: coins: error failed to call API data.");
}

curl_easy_cleanup(curl);
}
18 changes: 18 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ int main() {
if (input == "coins") {
gecko::fetch_tokens(event);
}
if (input == "market") {
gecko::fetch_market_chart(event);
}
return 0;
});

Expand All @@ -36,6 +39,21 @@ int main() {
dpp::command_option(dpp::co_string, "coingecko_id",
"(Coingecko) ID of the token: ", true));
bot.global_command_create(command_price);

dpp::slashcommand command_market;
command_market.set_name("market")
.set_description("Get market chart of a crypto token.")
.set_application_id(bot.me.id)
.add_option(
dpp::command_option(dpp::co_string, "token_id",
"(Coingecko) Id of the token: ", true))
.add_option(
dpp::command_option(dpp::co_string, "currency",
"(Coingecko) Currency for the price: ", true))
.add_option(dpp::command_option(
dpp::co_string, "days",
"(Coingecko) Duration market in days: ", true));
bot.global_command_create(command_market);
}
});

Expand Down
64 changes: 64 additions & 0 deletions src/quickchart.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include <quickchart.h>

using json = nlohmann::json;

// This callback function is called by curl_easy_perform() to write the response
// data into a string
size_t qchart::write_callback(char* ptr, size_t size, size_t nmemb,
std::string* data) {
data->append(ptr, size * nmemb);
return size * nmemb;
}

std::string qchart::generate_chart(std::string label1, std::vector<long> data1,
std::string label2,
std::vector<long> data2) {
CURL* curl = curl_easy_init();
if (!curl) {
std::cerr << "Error: could not initialize libcurl" << std::endl;
return "";
}
json datasets = json::array();
datasets.push_back({{"label", label2}, {"data", data2}});
json req_body = {{"backgroundColor", "#fff"},
{"width", 500},
{"height", 300},
{"devicePixelRatio", 1.0},
{"chart",
{{"type", "bar"},
{"data", {{"labels", data1}, {"datasets", datasets}}}}}};
std::cout << to_string(req_body).c_str() << std::endl;
std::string url = "https://quickchart.io/chart/create";
struct curl_slist* slist1 = NULL;
slist1 = curl_slist_append(slist1, "Content-Type: application/json");
slist1 = curl_slist_append(slist1, "Accept: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist1);
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, to_string(req_body).c_str());
std::string response_data;
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_data);

CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK) {
std::cerr << "Error: curl_easy_perform() failed: "
<< curl_easy_strerror(res) << std::endl;
curl_easy_cleanup(curl);
return "";
}

try {
json response_json = json::parse(response_data);
std::cout << "=============================" << std::endl;
std::cout << ">> quickchart response: " << response_json << std::endl;
return response_json["url"];
} catch (const std::exception& e) {
std::cerr << "Error: failed to parse JSON response: " << e.what()
<< std::endl;
curl_easy_cleanup(curl);
return "";
}

curl_easy_cleanup(curl);
return "";
}

0 comments on commit 8dd5c6a

Please sign in to comment.