#include #include #include #include static size_t WriteCallback(void *contents, size_t size, size_t nmemb, std::string *userp) { userp->append(static_cast(contents), size * nmemb); return size * nmemb; } double getConversionRate() { CURL *curl; CURLcode res; std::string readBuffer; double rate = 0.0; curl = curl_easy_init(); if(curl) { curl_easy_setopt(curl, CURLOPT_URL, "https://api.coingecko.com/api/v3/simple/price?ids=solana&vs_currencies=usd"); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer); res = curl_easy_perform(curl); curl_easy_cleanup(curl); if(res == CURLE_OK) { std::size_t usdPos = readBuffer.find("\"usd\":"); if (usdPos != std::string::npos) { std::size_t start = readBuffer.find(':', usdPos) + 1; std::size_t end = readBuffer.find_first_of("},", start); if(start < end) { std::string usdValue = readBuffer.substr(start, end - start); usdValue.erase(0, usdValue.find_first_not_of(" \n\r\t")); usdValue.erase(usdValue.find_last_not_of(" \n\r\t") + 1); try { rate = std::stod(usdValue); } catch (const std::invalid_argument& ia) { std::cerr << "Invalid argument: " << ia.what() << '\n'; } catch (const std::out_of_range& oor) { std::cerr << "Out of Range error: " << oor.what() << '\n'; } } } else { std::cerr << "USD rate not found in response." << std::endl; } } else { std::cerr << "CURL failed with error code: " << res << std::endl; } } return rate; } void displayMenu(WINDOW *menu_win, int highlight, const std::string choices[], int n_choices, double solRate) { int x = 2, y = 2; box(menu_win, 0, 0); if(solRate == 0.0) { mvwprintw(menu_win, 1, 1, "Fetching SOL price..."); } else { mvwprintw(menu_win, 1, 1, "1 SOL = $%.2f ", solRate); } for(int i = 0; i < n_choices; ++i) { if(highlight == i + 1) { wattron(menu_win, A_REVERSE); mvwprintw(menu_win, y + 1, x, "%s", choices[i].c_str()); wattroff(menu_win, A_REVERSE); } else mvwprintw(menu_win, y + 1, x, "%s", choices[i].c_str()); ++y; } wrefresh(menu_win); } void processChoice(int choice, double rate) { echo(); if (choice == 1) { printw("Enter amount in SOL: "); double sol; scanw("%lf", &sol); printw("%.2f SOL is approximately %.2f USD.\n", sol, sol * rate); } else if (choice == 2) { printw("Enter amount in USD: "); double usd; scanw("%lf", &usd); printw("%.2f USD is approximately %.2f SOL.\n", usd, usd / rate); } noecho(); } int main() { initscr(); clear(); noecho(); cbreak(); start_color(); init_pair(1, COLOR_CYAN, COLOR_BLACK); double rate = 0.0; WINDOW *menu_win = newwin(7, 60, 4, 4); keypad(menu_win, TRUE); refresh(); const std::string choices[] = {"Convert SOL to USD", "Convert USD to SOL", "Exit"}; int n_choices = sizeof(choices) / sizeof(std::string); int highlight = 1; bool needsFetch = true; displayMenu(menu_win, highlight, choices, n_choices, rate); int choice = 0; int c; while(1) { if (needsFetch) { refresh(); rate = getConversionRate(); needsFetch = false; clear(); displayMenu(menu_win, highlight, choices, n_choices, rate); } c = wgetch(menu_win); switch(c) { case KEY_UP: if(highlight == 1) highlight = n_choices; else --highlight; break; case KEY_DOWN: if(highlight == n_choices) highlight = 1; else ++highlight; break; case 10: { choice = highlight; clear(); refresh(); if (choice == 3) { endwin(); return 0; } rate = getConversionRate(); if (rate == 0.0) { printw("Failed to fetch conversion rate. Please try again later.\n"); } else { processChoice(choice, rate); } printw("Press any key to return to the menu."); getch(); clear(); displayMenu(menu_win, highlight, choices, n_choices, rate); break; } default: break; } displayMenu(menu_win, highlight, choices, n_choices, rate); } endwin(); return 0; }