forked from EvergreenCrypto/docker-finance
php: fetch: prices: add Mobula support
This commit is contained in:
@@ -214,6 +214,145 @@ namespace docker_finance\prices\internal\prices\crypto
|
||||
return 'max';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Mobula price aggregator API
|
||||
* @since docker-finance 1.0.0
|
||||
*/
|
||||
final class Mobula extends internal\Impl
|
||||
{
|
||||
public function __construct(utils\Env $env)
|
||||
{
|
||||
parent::__construct($env);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief REST API request generator
|
||||
* @param string $id Symbol's ID to request
|
||||
* @param string $timestamp Timestamp to request
|
||||
* @return mixed REST API response data
|
||||
*/
|
||||
protected function request(string $id, string $timestamp): mixed
|
||||
{
|
||||
// If `key` exists, append to header (used in all plans)
|
||||
$key = $this->get_env()->get_env('API_PRICES_KEY');
|
||||
$domain = 'api.mobula.io';
|
||||
$header = [];
|
||||
if ($key != 'None') {
|
||||
$header = ["Authorization: $key"];
|
||||
}
|
||||
$url = "https://{$domain}/api/1/market/history?asset={$id}&from={$timestamp}";
|
||||
|
||||
$response = $this->request_impl($url, $header);
|
||||
if (array_key_exists('error', $response)) {
|
||||
throw new \Exception($response['error']);
|
||||
}
|
||||
|
||||
$prices = $response['data']['price_history'];
|
||||
utils\CLI::print_debug($prices);
|
||||
|
||||
return $prices;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Parse given prices for given symbol
|
||||
* @param string $symbol Given symbol associated with Mobula's ID
|
||||
* @param array<mixed> $prices Array of [N]([timestamp][price])for given year(s)
|
||||
* @return array<string> Prices for all given symbols
|
||||
*/
|
||||
protected function parse_prices(string $symbol, array $prices): array
|
||||
{
|
||||
$total = 0;
|
||||
$prev_date = "";
|
||||
$date_counter = 0;
|
||||
|
||||
$stack = []; // date => daily average price
|
||||
|
||||
for($i = 0; $i < count($prices); $i++) {
|
||||
/**
|
||||
* Expectation:
|
||||
*
|
||||
* array[0] = oldest entry
|
||||
* array[0][0] = timestamp
|
||||
* array[0][1] = price
|
||||
*
|
||||
* array[1] = next entry
|
||||
* array[1][0] = timestamp
|
||||
* array[1][1] = price
|
||||
*
|
||||
* ...etc.
|
||||
*/
|
||||
|
||||
$timestamp = $prices[$i][0] / 1000;
|
||||
$date = date('Y/m/d', $timestamp);
|
||||
$price = $prices[$i][1];
|
||||
|
||||
utils\CLI::print_debug("$date = $price");
|
||||
|
||||
//
|
||||
// Get daily average
|
||||
//
|
||||
|
||||
// Either a kick-off date or a single daily average (per their API)
|
||||
// NOTE: this *MUST* be overwritten below if computing non-daily
|
||||
if ($prev_date == "") {
|
||||
$stack[$date] = $price;
|
||||
}
|
||||
|
||||
// Average will be based on given dates (currently every 6 hours or 5 minutes)
|
||||
if ($prev_date == $date) {
|
||||
$total += $price;
|
||||
$date_counter++;
|
||||
} else {
|
||||
// They provided a single date, and *that* is the daily average
|
||||
if (!$total) {
|
||||
$total = $price;
|
||||
}
|
||||
|
||||
// Avoid divide by zero (if only a single date was provided)
|
||||
if (!$date_counter) {
|
||||
$date_counter = 1;
|
||||
}
|
||||
|
||||
// Finished previous date, calculate and push to stack
|
||||
$average = $total / $date_counter;
|
||||
|
||||
// Always overwrite with most recent daily average
|
||||
if ($date_counter > 1) {
|
||||
$stack[$prev_date] = $average;
|
||||
} else {
|
||||
$stack[$date] = $average;
|
||||
}
|
||||
|
||||
$total = 0;
|
||||
$date_counter = 0;
|
||||
}
|
||||
|
||||
$prev_date = $date;
|
||||
}
|
||||
|
||||
return $stack;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Make Mobula timestamp used in request
|
||||
* @param string $year Given year
|
||||
* @return mixed Unix timestamp in milliseconds
|
||||
*/
|
||||
protected function make_timestamp(string $year): mixed
|
||||
{
|
||||
// Number of days back to beginning of given year
|
||||
if ($year != 'all') {
|
||||
$timestamp = strtotime($this->get_env()->get_env('API_FETCH_YEAR') . '-01-01') * 1000;
|
||||
utils\CLI::print_debug($timestamp);
|
||||
return $timestamp;
|
||||
}
|
||||
|
||||
// From genesis to present
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace docker_finance\prices\internal\prices\crypto
|
||||
|
||||
//! @since docker-finance 1.0.0
|
||||
@@ -244,6 +383,26 @@ namespace docker_finance\prices\internal\prices
|
||||
$this->api->fetcher();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Facade for Mobula implementation
|
||||
* @ingroup php_prices
|
||||
* @since docker-finance 1.0.0
|
||||
*/
|
||||
final class Mobula extends \docker_finance\prices\API
|
||||
{
|
||||
private crypto\Mobula $api; //!< Internal API
|
||||
|
||||
public function __construct(utils\Env $env)
|
||||
{
|
||||
$this->api = new crypto\Mobula($env);
|
||||
}
|
||||
|
||||
public function fetch(): void
|
||||
{
|
||||
$this->api->fetcher();
|
||||
}
|
||||
}
|
||||
} // namespace docker_finance\prices\internal\prices
|
||||
|
||||
# vim: sw=4 sts=4 si ai et
|
||||
|
||||
Reference in New Issue
Block a user