function getJSON($arguments) { $result = array(); foreach (get_all_currencies() as $cur) { $instance = \DiscoveredComponents\Currencies::getInstance($cur); $result[] = array("code" => $instance->getCode(), "abbr" => $instance->getAbbr(), "name" => $instance->getName(), "cryptocurrency" => $instance->isCryptocurrency(), "fiat" => $instance->isFiat(), "commodity" => $instance->isCommodity()); } return $result; }
/** * Return a HTML link for inspecting a given cryptocurrency address. */ function crypto_address($currency, $address) { foreach (\DiscoveredComponents\Currencies::getAddressCurrencies() as $cur) { if ($cur === $currency) { $instance = \DiscoveredComponents\Currencies::getInstance($cur); return "<span class=\"address " . $currency . "_address\"><code>" . htmlspecialchars($address) . "</code>\n <a class=\"inspect\" href=\"" . htmlspecialchars($instance->getBalanceURL($address)) . "\" title=\"Inspect with " . htmlspecialchars($instance->getExplorerName()) . "\">?</a>\n </span>"; } } foreach (get_blockchain_currencies() as $explorer => $currencies) { foreach ($currencies as $cur) { if ($cur == $currency) { return "<span class=\"address " . $currency . "_address\"><code>" . htmlspecialchars($address) . "</code>\n <a class=\"inspect\" href=\"" . htmlspecialchars(sprintf(get_site_config($currency . "_address_url"), $address)) . "\" title=\"Inspect with " . htmlspecialchars($explorer) . "\">?</a>\n </span>"; } } } return htmlspecialchars($address); }
function run(Connection $db, Logger $logger) { $job = $this->job; switch ($job['job_type']) { // average jobs case "average": require __DIR__ . "/../jobs/average.php"; break; // account jobs // account jobs case "generic": require __DIR__ . "/../jobs/generic.php"; break; case "cryptostocks": require __DIR__ . "/../jobs/cryptostocks.php"; break; case "securities_cryptostocks": require __DIR__ . "/../jobs/securities_cryptostocks.php"; break; case "havelock": require __DIR__ . "/../jobs/havelock.php"; break; case "securities_havelock": require __DIR__ . "/../jobs/securities_havelock.php"; break; case "securities_crypto-trade": require __DIR__ . "/../jobs/securities_cryptotrade.php"; break; case "796": require __DIR__ . "/../jobs/796.php"; break; case "securities_796": require __DIR__ . "/../jobs/securities_796.php"; break; case "litecoininvest": require __DIR__ . "/../jobs/litecoininvest.php"; break; // individual securities jobs // individual securities jobs case "individual_cryptostocks": require __DIR__ . "/../jobs/individual_cryptostocks.php"; break; case "individual_havelock": require __DIR__ . "/../jobs/individual_havelock.php"; break; case "individual_crypto-trade": require __DIR__ . "/../jobs/individual_crypto-trade.php"; break; case "individual_796": require __DIR__ . "/../jobs/individual_796.php"; break; case "individual_litecoininvest": require __DIR__ . "/../jobs/individual_litecoininvest.php"; break; // summary jobs // summary jobs case "sum": require __DIR__ . "/../jobs/sum.php"; break; case "securities_count": require __DIR__ . "/../jobs/securities_count.php"; break; // notification jobs // notification jobs case "notification": require __DIR__ . "/../jobs/notification.php"; break; // system jobs // system jobs case "securities_update": require __DIR__ . "/../jobs/securities_update.php"; break; case "version_check": require __DIR__ . "/../jobs/version_check.php"; break; case "vote_coins": require __DIR__ . "/../jobs/vote_coins.php"; break; case "missing_average_find": require __DIR__ . "/../jobs/missing_average_find.php"; break; case "missing_average": require __DIR__ . "/../jobs/missing_average.php"; break; // transaction jobs // transaction jobs case "transaction_creator": require __DIR__ . "/../jobs/transaction_creator.php"; break; case "transactions": require __DIR__ . "/../jobs/transactions.php"; break; // cleanup jobs, admin jobs etc // cleanup jobs, admin jobs etc case "outstanding": require __DIR__ . "/../jobs/outstanding.php"; break; case "expiring": require __DIR__ . "/../jobs/expiring.php"; break; case "expire": require __DIR__ . "/../jobs/expire.php"; break; case "cleanup": require __DIR__ . "/../jobs/cleanup.php"; break; case "disable_warning": require __DIR__ . "/../jobs/disable_warning.php"; break; case "disable": require __DIR__ . "/../jobs/disable.php"; break; case "delete_user": require __DIR__ . "/../jobs/delete_user.php"; break; default: if (substr($job['job_type'], 0, strlen("address_")) === "address_") { // address job $currency = substr($job['job_type'], strlen("address_")); if (!in_array($currency, get_address_currencies())) { throw new JobException("Currency {$currency} is not a valid address currency"); } if (in_array($currency, \DiscoveredComponents\Currencies::getBalanceCurrencies())) { require __DIR__ . "/../jobs/addresses/discovered.php"; } else { // TODO eventually remove this block once we have no currencies that are also in getBalanceCurrencies() if (!file_exists(__DIR__ . "/../jobs/addresses/" . safe_include_arg($currency) . ".php")) { throw new JobException("Could not find any addresses/{$currency}.php include"); } require __DIR__ . "/../jobs/addresses/" . safe_include_arg($currency) . ".php"; } break; } if (substr($job['job_type'], 0, strlen("blockcount_")) === "blockcount_") { // address job $currency = substr($job['job_type'], strlen("blockcount_")); if (!in_array($currency, \DiscoveredComponents\Currencies::getBlockCurrencies())) { throw new JobException("Currency {$currency} is not a valid block currency"); } require __DIR__ . "/../jobs/blockcount/discovered.php"; break; } if (substr($job['job_type'], 0, strlen("difficulty_")) === "difficulty_") { // address job $currency = substr($job['job_type'], strlen("difficulty_")); if (!in_array($currency, \DiscoveredComponents\Currencies::getDifficultyCurrencies())) { throw new JobException("Currency {$currency} is not a valid difficulty currency"); } require __DIR__ . "/../jobs/difficulty/discovered.php"; break; } if (substr($job['job_type'], 0, strlen("markets_")) === "markets_") { // address job $exchange = substr($job['job_type'], strlen("markets_")); if (!in_array($exchange, \DiscoveredComponents\Exchanges::getKeys())) { throw new JobException("Exchange {$exchange} is not a valid exchange"); } require __DIR__ . "/../jobs/markets/discovered.php"; break; } if (substr($job['job_type'], 0, strlen("ticker_")) === "ticker_") { // address job $exchange = substr($job['job_type'], strlen("ticker_")); if (!in_array($exchange, \DiscoveredComponents\Exchanges::getKeys())) { throw new JobException("Exchange {$exchange} is not a valid exchange"); } require __DIR__ . "/../jobs/ticker/discovered.php"; break; } if (substr($job['job_type'], 0, strlen("currencies_")) === "currencies_") { // address job $exchange = substr($job['job_type'], strlen("currencies_")); if (!in_array($exchange, \DiscoveredComponents\Accounts::getKeys())) { throw new JobException("Account {$exchange} is not a valid account"); } require __DIR__ . "/../jobs/currencies/discovered.php"; break; } if (substr($job['job_type'], 0, strlen("hashrates_")) === "hashrates_") { // address job $exchange = substr($job['job_type'], strlen("hashrates_")); if (!in_array($exchange, \DiscoveredComponents\Accounts::getMiners())) { throw new JobException("Account {$exchange} is not a valid miner"); } require __DIR__ . "/../jobs/hashrates/discovered.php"; break; } if (substr($job['job_type'], 0, strlen("account_")) === "account_") { // address job $exchange = substr($job['job_type'], strlen("account_")); if (!in_array($exchange, \DiscoveredComponents\Accounts::getKeys())) { throw new JobException("Account {$exchange} is not a valid account"); } require __DIR__ . "/../jobs/account/discovered.php"; break; } throw new JobException("Unknown job type '" . htmlspecialchars($job['job_type']) . "'"); } }
function getJSON($arguments) { $instance = \DiscoveredComponents\Currencies::getInstance($arguments['currency']); return array("code" => $instance->getCode(), "abbr" => $instance->getAbbr(), "name" => $instance->getName(), "cryptocurrency" => $instance->isCryptocurrency(), "fiat" => $instance->isFiat(), "commodity" => $instance->isCommodity()); }
/** * Get all the currencies we want to create block counts for. */ function getCurrencies() { return \DiscoveredComponents\Currencies::getBlockCurrencies(); }
<th>Name</th> <th>Class</th> <th>Abbr</th> <th>Type</th> <th>Explorer</th> <th>Block</th> <th>Difficulty</th> <th>Confirmable</th> <th>BlockBalance</th> <th>Receivable</th> <th>Hashable</th> </tr> </thead> <tbody> <?php foreach (\DiscoveredComponents\Currencies::getAllInstances() as $code => $currency) { echo "<tr>"; echo "<th>" . htmlspecialchars($code) . "</th>"; echo "<td><span class=\"currency_name currency_" . $code . "\">" . htmlspecialchars($currency->getName()) . "</span></td>"; echo "<td><i>" . get_class($currency) . "</i></td>"; echo "<td>" . htmlspecialchars($currency->getAbbr()) . "</td>"; echo "<td>"; if ($currency->isCryptocurrency()) { echo "Cryptocurrency"; } if ($currency->isFiat()) { echo "Fiat"; } if ($currency->isCommodity()) { echo "Commodity"; }
/** * Get all the currencies we want to create block counts for. */ function getCurrencies() { return \DiscoveredComponents\Currencies::getDifficultyCurrencies(); }
/** * Address job for a currency that has been discovered through * DiscoveredComponents\Currencies. */ if (!$currency) { throw new JobException("No currency defined"); } // get the relevant address $q = db()->prepare("SELECT * FROM addresses WHERE user_id=? AND id=?"); $q->execute(array($job['user_id'], $job['arg_id'])); $address = $q->fetch(); if (!$address) { throw new JobException("Cannot find an address " . $job['arg_id'] . " for user " . $job['user_id']); } $instance = \DiscoveredComponents\Currencies::getInstance($currency); if ($instance instanceof \Openclerk\Currencies\ConfirmableCurrency) { // directly request confirmations $balance = $instance->getBalanceWithConfirmations($address['address'], \Openclerk\Config::get($currency . "_confirmations", 6), $logger); insert_new_address_balance($job, $address, $balance); } else { if ($instance instanceof \Openclerk\Currencies\BlockBalanceableCurrency) { // get the most recent block count, to calculate confirmations $block = null; $q = db()->prepare("SELECT * FROM blockcount_" . $currency . " WHERE is_recent=1"); $q->execute(); if ($result = $q->fetch()) { $block = $result['blockcount'] - \Openclerk\Config::get($currency . "_confirmations", 6); } $balance = $instance->getBalanceAtBlock($address['address'], $block, $logger); insert_new_address_balance($job, $address, $balance);
$query = array(); $args = array(); foreach ($data as $key => $value) { $query[] = $key . " = :" . $key; $args[$key] = $value; } $args["id"] = $this->account['id']; crypto_log("Self-updating table '{$table}'"); $q = db()->prepare("UPDATE {$table} SET " . implode(", ", $query) . " WHERE id=:id"); $q->execute($args); } } if ($instance instanceof \Account\SelfUpdatingAccount) { $callback = new SelfUpdatingAccountCallback($account, $table); $instance->registerAccountUpdateCallback(array($callback, 'callback')); } // normal balances $balances = $instance->fetchBalances($account, $factory, $logger); foreach ($balances as $currency => $balance) { // only store currencies we are actually interested in if (in_array($currency, \DiscoveredComponents\Currencies::getKeys())) { // some accounts, e.g. ghash, don't return a balance if (isset($balance['confirmed'])) { insert_new_balance($job, $account, $exchange, $currency, $balance['confirmed']); } // hashrate balances if (isset($balance['hashrate'])) { insert_new_hashrate($job, $account, $exchange, $currency, $balance['hashrate'] / 1000000.0); } } }
/** * All currencies defined in {@link get_address_currencies()} should have * an equivalent PHP script in {@code jobs/addresses/CUR.php}. */ function testAllAddressCurrenciesHaveAddressIncludes() { foreach (get_address_currencies() as $cur) { // skip ones that are discovered if (\DiscoveredComponents\Currencies::hasKey($cur)) { continue; } $file = __DIR__ . "/../jobs/addresses/{$cur}.php"; $this->assertTrue(file_exists($file), "File '{$file}' did not exist for address currency '{$cur}'"); } }
function get_explorer_address($currency, $address) { foreach (\DiscoveredComponents\Currencies::getAddressCurrencies() as $cur) { if ($cur === $currency) { $instance = \DiscoveredComponents\Currencies::getInstance($cur); return $instance->getBalanceURL($address); } } foreach (get_blockchain_currencies() as $explorer => $currencies) { foreach ($currencies as $cur) { if ($cur == $currency) { return sprintf(get_site_config($currency . "_address_url"), $address); } } } }
/** * Get a list of all jobs that need to be queued, as an array of associative * arrays with (job_type, arg_id, [user_id]). * * This could use e.g. {@link JobTypeFinder} */ function findJobs(Connection $db, Logger $logger) { $standard_jobs = self::getStandardJobs(); $logger->info("Current time: " . date('r')); // get all disabled users $disabled = array(); $q = $db->prepare("SELECT * FROM user_properties WHERE is_disabled=1"); $q->execute(); while ($d = $q->fetch()) { $disabled[$d['id']] = $d; } foreach (array(true, false) as $is_premium_only) { $job_count = 0; foreach ($standard_jobs as $standard) { $always = isset($standard['always']) && $standard['always']; $field = isset($standard['user_id_field']) ? $standard['user_id_field'] : 'user_id'; $query_extra = isset($standard['query']) ? $standard['query'] : ""; $args_extra = isset($standard['args']) ? $standard['args'] : array(); if (isset($standard['failure']) && $standard['failure']) { $query_extra .= " AND is_disabled=0"; } $args = array(); if (!$always) { // we want to run system jobs at least every 0.1 hours = 6 minutes $args[] = isset($standard['hours']) ? $standard['hours'] : (isset($standard['user_id']) && $standard['user_id'] == get_site_config('system_user_id') ? get_site_config('refresh_queue_hours_system') : ($is_premium_only ? get_site_config('refresh_queue_hours_premium') : get_site_config('refresh_queue_hours'))); } $queue_field = isset($standard['queue_field']) ? $standard['queue_field'] : 'last_queue'; if ($is_premium_only && (!isset($standard['user_id']) || $standard['user_id'] != get_site_config('system_user_id'))) { $query_extra .= " AND {$field} IN (SELECT id FROM user_properties WHERE is_premium=1)"; } // multiply queue_hours by 0.8 to ensure that user jobs are always executed within the specified timeframe try { $q = $db->prepare("SELECT * FROM " . $standard['table'] . " WHERE " . ($always ? "1" : "({$queue_field} <= DATE_SUB(NOW(), INTERVAL (? * 0.8) HOUR) OR ISNULL({$queue_field}))") . " {$query_extra}"); $q->execute(array_join($args, $args_extra)); } catch (\PdoException $e) { throw new \Exception("Could not find jobs for table '" . $standard['table'] . "': " . $e->getMessage(), $e->getCode(), $e); } $disabled_count = 0; while ($address = $q->fetch()) { $job = array("job_type" => $standard['type'], "user_id" => isset($standard['user_id']) ? $standard['user_id'] : $address[$field], "arg_id" => $address['id'], "queue_field" => $queue_field, "object" => $address, "table" => $standard['table']); // check that this user is not disabled if (isset($disabled[$job['user_id']])) { if ($disabled_count == 0) { $logger->info("Skipping job '" . $standard['type'] . "' for user " . $job['user_id'] . ": user is disabled"); } $disabled_count++; continue; } $result[] = $job; $job_count++; } if ($disabled_count > 1) { $logger->info("Also skipped another " . number_format($disabled_count) . " " . $standard['type'] . " jobs due to disabled users"); } } $logger->info($is_premium_only ? "Found {$job_count} premium jobs" : "Found {$job_count} general user jobs"); } $block_jobs = array('version_check', 'vote_coins', 'average', 'missing_average_find'); foreach ($block_jobs as $name) { // as often as we can (or on request), run litecoin_block jobs $result[] = array('job_type' => $name, 'user_id' => get_site_config('system_user_id'), 'arg_id' => -1); } // block count jobs (using the new Currencies framework) foreach (\DiscoveredComponents\Currencies::getBlockCurrencies() as $cur) { $name = "blockcount_" . $cur; $result[] = array('job_type' => $name, 'user_id' => get_site_config('system_user_id'), 'arg_id' => -1); } // difficulty jobs (using the new Currencies framework) foreach (\DiscoveredComponents\Currencies::getDifficultyCurrencies() as $cur) { $name = "difficulty_" . $cur; $result[] = array('job_type' => $name, 'user_id' => get_site_config('system_user_id'), 'arg_id' => -1); } // markets jobs (using the new Exchanges framework: #400) foreach (\DiscoveredComponents\Exchanges::getKeys() as $exchange) { if (!in_array($exchange, \DiscoveredComponents\Exchanges::getDisabled())) { $name = "markets_" . $exchange; $result[] = array('job_type' => $name, 'user_id' => get_site_config('system_user_id'), 'arg_id' => -1); $name = "ticker_" . $exchange; $result[] = array('job_type' => $name, 'user_id' => get_site_config('system_user_id'), 'arg_id' => -1); } } // supported currencies jobs (using the new Accounts framework) foreach (\DiscoveredComponents\Accounts::getKeys() as $key) { if (!in_array($key, \DiscoveredComponents\Accounts::getDisabled())) { $name = "currencies_" . $key; $result[] = array('job_type' => $name, 'user_id' => get_site_config('system_user_id'), 'arg_id' => -1); } } // supported hashrates jobs (using the new Accounts framework) foreach (\DiscoveredComponents\Accounts::getMiners() as $key) { if (!in_array($key, \DiscoveredComponents\Accounts::getDisabled())) { $name = "hashrates_" . $key; $result[] = array('job_type' => $name, 'user_id' => get_site_config('system_user_id'), 'arg_id' => -1); } } return $result; }
<p> <?php echo htmlspecialchars(get_site_config('site_name')); ?> currently supports the following cryptocurrencies: </p> <p> <ul class="currency_list"> <?php // get_all_cryptocurrencies() so that it's sorted foreach (get_all_cryptocurrencies() as $code) { if (!\DiscoveredComponents\Currencies::hasKey($code)) { continue; } $currency = \DiscoveredComponents\Currencies::getInstance($code); echo "<li>"; echo "<span class=\"currency_name_" . $currency->getCode() . "\">" . link_to($currency->getURL(), $currency->getName(), array("target" => "_blank")) . "</span>"; foreach ($currency->getCommunityLinks() as $url => $title) { echo " - " . link_to($url, $title, array("target" => "_blank")); } echo "</li>"; } ?> </ul> </p> <p> Support for additional cryptocurrencies will be <a href="<?php echo htmlspecialchars(url_for('help/add_currency')); ?>