/*
* Copyright (c) 2021, evilny0
*
* This file is part of cpfm.
*
* cpfm is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* cpm is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with cpfm. If not, see .
*
*/
#include "datasources/blockchair.h"
Time BlockchainDataSourceTypeBTC_Blockchair::getTimeFromString(string s)
{
std::istringstream in{s};
date::sys_time tp;
in >> date::parse("%F %T", tp);
Time t;
t.setFromUnixTime(std::chrono::system_clock::to_time_t(tp));
return t;
}
list BlockchainDataSourceTypeBTC_Blockchair::getTxDetailsListForAddresses(list addresses)
{
linfo << "Blockchair : analyzing address list";
list l;
if (!bfs::exists(getCacheFilenameForAddresses(addresses)))
{
saveBlockchainAddressesDataToCacheFile(addresses);
}
if (!bfs::exists(getCacheFilenameForAddresses(addresses)))
{
lerr << "Blockchair : cache file could not be found. Addresses data was not retrieved.";
return l;
}
ifstream f;
f.open(getCacheFilenameForAddresses(addresses));
json::value jvalue = json::value::parse(f);
f.close();
for (int i=0;i addresses)
{
string s;
for (const auto a: addresses)
s = s+a;
string cacheFilename("data/cache/blockchair/"+m_blockchainName+"/addresses/" + s);
return cacheFilename;
}
string BlockchainDataSourceTypeBTC_Blockchair::getCacheFilenameForTx(string txHash)
{
string cacheFilename("data/cache/blockchair/"+m_blockchainName+"/tx/" + txHash);
return cacheFilename;
}
void BlockchainDataSourceTypeBTC_Blockchair::saveBlockchainAddressesDataToCacheFile(list addresses)
{
try
{
string s;
for (const auto a: addresses)
{
if (s.length())
s = s+","+a;
else
s = a;
}
linfo << "Blockchair : querying API about addresses : " << s;
string sRequestURL = "/"+m_blockchainName+"/dashboards/addresses/";
sRequestURL += s;
http_client apiclient("https://api.blockchair.com/");
m_currentRequestCacheFilename = getCacheFilenameForAddresses(addresses);
ltrace << "Blockchair : query : " << sRequestURL;
apiclient.request(methods::GET,sRequestURL).then([](http_response response)
{
if (response.status_code() == status_codes::OK)
{
ldebug << "Blockchair : response OK.";
return response.extract_json();
}
else if (response.status_code() == status_codes::TooManyRequests)
{
lwarn << "Blockchair : too many queries! We are being rate limited.";
pplx::task_from_result(json::value());
}
return pplx::task_from_result(json::value());
})
.then([this](pplx::task previousTask)
{
if (previousTask.get() != json::value::null())
{
linfo << "Blockchair : saving query result to " << m_currentRequestCacheFilename;
ofstream f;
f.open(m_currentRequestCacheFilename);
f << previousTask.get();
f.close();
}
else
{
lerr << "Blockchair : query result is empty. Nothing will be saved to the cache file.";
}
})
.wait();
}
catch(const http::http_exception& e)
{
lerr << "Blockchair : failed to query API";
}
}
void BlockchainDataSourceTypeBTC_Blockchair::saveBlockchainTxDataToCacheFile(string txHash)
{
try
{
linfo << "Blockchair : querying API about tx : " << txHash;
string sRequestURL = "/"+m_blockchainName+"/dashboards/transaction/";
sRequestURL += txHash;
http_client apiclient("https://api.blockchair.com/");
m_currentRequestCacheFilename = getCacheFilenameForTx(txHash);
ltrace << "Blockchair : query : " << sRequestURL;
apiclient.request(methods::GET,sRequestURL).then([](http_response response)
{
if (response.status_code() == status_codes::OK)
{
ldebug << "Blockchair : response OK.";
return response.extract_json();
}
else if (response.status_code() == status_codes::TooManyRequests)
{
lwarn << "Blockchair : too many queries! We are being rate limited.";
pplx::task_from_result(json::value());
}
return pplx::task_from_result(json::value());
})
.then([this](pplx::task previousTask)
{
if (previousTask.get() != json::value::null())
{
linfo << "Blockchair : saving query result to " << m_currentRequestCacheFilename;
ofstream f;
f.open(m_currentRequestCacheFilename);
f << previousTask.get();
f.close();
}
else
{
lerr << "Blockchair : query result is empty. Nothing will be saved to the cache file.";
}
})
.wait();
}
catch(const http::http_exception& e)
{
lerr << "Blockchair : failed to query API about " << txHash;
}
}