function get_knowledge_base() { $kb = array(t('Concepts') => array('cryptocurrencies' => array('title' => t("What are cryptocurrencies?"), 'inline' => 'inline_cryptocurrencies'), 'versions' => array('title' => t(":site_name Version History"), 'inline' => 'inline_versions', 'new' => true)), t('Interface') => array('bitcoin_csv' => t("How do I upload a Bitcoin-Qt CSV file?"), 'litecoin_csv' => t("How do I upload a Litecoin-Qt CSV file?"), 'notifications' => array('title' => t("How do automated notifications work?"), 'inline' => 'inline_notifications'), 'managed_graphs' => array('title' => t("How are graphs automatically managed?"), 'inline' => 'inline_managed_graphs'), 'graph_refresh' => array('title' => t("Do graphs live update?"), 'inline' => 'inline_graph_refresh'), 'finance' => array('title' => t("What is :site_name Finance?"), 'inline' => 'inline_finance', 'new' => true)), t('Accounts') => array('add_currency' => array('title' => t("Can you add support for another cryptocurrency?"), 'inline' => 'inline_add_currency'), 'add_fiat' => array('title' => t("Can you add support for another fiat currency?"), 'inline' => 'inline_add_fiat'), 'add_service' => array('title' => t("Can you add support for another exchange/mining pool?"), 'inline' => 'inline_add_service')), t('Notifications') => array('notifications_ticker' => array('title' => t("How do I get notified of exchange rate changes?"), 'inline' => 'inline_notifications_ticker'), 'notifications_reports' => array('title' => t("How do I get notified of changes in my reports?"), 'inline' => 'inline_notifications_reports'), 'notifications_hashrates' => array('title' => t("How do I get notified of changes in my hashrates?"), 'inline' => 'inline_notifications_hashrates')), t('Finance') => array('transaction_creation' => array('title' => t("How are transactions automatically created?"), 'inline' => 'inline_transaction_creation', 'new' => true))); // automatically construct KB for adding accounts through the wizards $wizards = array("Mining pools" => 'mining pool account', "Exchanges" => 'exchange account', "Securities" => 'securities exchange account', "Individual Securities" => 'securities', "Other" => ''); foreach (account_data_grouped() as $label => $group) { if (isset($wizards[$label])) { foreach ($group as $key => $data) { if ($data['disabled']) { continue; } if ($label == 'Individual Securities') { $title = 'How do I add individual ' . get_exchange_name($data['exchange']) . (isset($data['suffix']) ? $data['suffix'] : '') . ($wizards[$label] ? ' ' . $wizards[$label] : '') . '?'; } else { $title = 'How do I add a ' . get_exchange_name($key) . (isset($data['suffix']) ? $data['suffix'] : '') . ($wizards[$label] ? ' ' . $wizards[$label] : '') . '?'; } $kb[t('Accounts')][$key] = array('title' => $title, 'inline' => 'inline_accounts_' . $key, 'new' => in_array($key, get_new_supported_wallets()) || in_array($key, get_new_exchanges()) || in_array($key, get_new_security_exchanges()) || isset($data['exchange']) && in_array($data['exchange'], get_new_security_exchanges())); } } } // sort each section by title foreach ($kb as $label => $group) { uasort($kb[$label], '_sort_get_knowledge_base'); } return $kb; }
/** * Get a summary of how many accounts, graphs, pages etc the current user has. * Does not include disabled accounts towards the limit (#217). * May be cached per user. */ function user_limits_summary($user_id) { global $global_user_limits_summary; if (!isset($global_user_limits_summary[$user_id])) { $accounts = array(); foreach (account_data_grouped() as $group) { foreach ($group as $key => $data) { if (!isset($data['group'])) { continue; } $q = db()->prepare("SELECT COUNT(*) AS c FROM " . $data['table'] . " WHERE user_id=?" . ($data['failure'] ? " AND is_disabled=0" : "") . (isset($data['query']) ? $data['query'] : "")); $q->execute(array($user_id)); $accounts[$key] = $q->fetch(); $accounts[$key] = $accounts[$key]['c']; if (!isset($accounts['total_' . $data['group']])) { $accounts['total_' . $data['group']] = 0; } $accounts['total_' . $data['group']] += $accounts[$key]; if (!isset($data['wizard'])) { continue; } if (!isset($accounts['wizard_' . $data['wizard']])) { $accounts['wizard_' . $data['wizard']] = 0; } $accounts['wizard_' . $data['wizard']] += $accounts[$key]; } } $global_user_limits_summary[$user_id] = $accounts; } return $global_user_limits_summary[$user_id]; }
function testGenerate() { $templates = array('currencies_list' => array(), 'currencies_inline' => array(), 'fiat_currencies_list' => array(), 'fiat_currencies_inline' => array(), 'crypto_currencies_list' => array(), 'crypto_currencies_inline' => array(), 'commodity_currencies_list' => array(), 'commodity_currencies_inline' => array(), 'exchange_wallets_list' => array(), 'mining_pools_list' => array(), 'securities_list' => array(), 'exchange_list' => array()); foreach (get_all_currencies() as $cur) { $templates['currencies_list'][] = " * " . get_currency_name($cur); $templates['currencies_inline'][] = get_currency_abbr($cur); } foreach (get_all_fiat_currencies() as $cur) { $templates['fiat_currencies_list'][] = " * " . get_currency_name($cur); $templates['fiat_currencies_inline'][] = get_currency_abbr($cur); } foreach (get_all_cryptocurrencies() as $cur) { $templates['crypto_currencies_list'][] = " * " . get_currency_name($cur); $templates['crypto_currencies_inline'][] = get_currency_abbr($cur); } foreach (get_all_commodity_currencies() as $cur) { $templates['commodity_currencies_list'][] = " * " . get_currency_name($cur); $templates['commodity_currencies_inline'][] = get_currency_abbr($cur); } $grouped = account_data_grouped(); foreach ($grouped['Exchanges'] as $key => $data) { if (!$data['disabled']) { $templates['exchange_wallets_list'][] = " * " . get_exchange_name($key); } } foreach ($grouped['Mining pools'] as $key => $data) { if (!$data['disabled']) { $templates['mining_pools_list'][] = " * " . get_exchange_name($key); } } foreach ($grouped['Securities'] as $key => $data) { if (!$data['disabled']) { $templates['securities_list'][] = " * " . get_exchange_name($key); } } foreach (get_exchange_pairs() as $key => $pairs) { $templates['exchange_list'][] = " * " . get_exchange_name($key); } $templates['currencies_list'] = implode("\n", array_unique($templates['currencies_list'])); $templates['fiat_currencies_list'] = implode("\n", array_unique($templates['fiat_currencies_list'])); $templates['crypto_currencies_list'] = implode("\n", array_unique($templates['crypto_currencies_list'])); $templates['commodity_currencies_list'] = implode("\n", array_unique($templates['commodity_currencies_list'])); $templates['exchange_wallets_list'] = implode("\n", array_unique($templates['exchange_wallets_list'])); $templates['mining_pools_list'] = implode("\n", array_unique($templates['mining_pools_list'])); $templates['securities_list'] = implode("\n", array_unique($templates['securities_list'])); $templates['exchange_list'] = implode("\n", array_unique($templates['exchange_list'])); $templates['currencies_inline'] = implode(", ", array_unique($templates['currencies_inline'])); $templates['fiat_currencies_inline'] = implode(", ", array_unique($templates['fiat_currencies_inline'])); $templates['crypto_currencies_inline'] = implode(", ", array_unique($templates['crypto_currencies_inline'])); $templates['commodity_currencies_inline'] = implode(", ", array_unique($templates['commodity_currencies_inline'])); // load the template $input = file_get_contents(__DIR__ . "/../README.template.md"); foreach ($templates as $key => $value) { $input = str_replace('{$' . $key . '}', $value, $input); } // write it out file_put_contents(__DIR__ . "/../README.md", $input); }
function get_exchange_or_currency_name($exchange) { $account_data_grouped = account_data_grouped(); if (isset($account_data_grouped['Addresses'][$exchange])) { return $account_data_grouped['Addresses'][$exchange]['title']; } else { return get_exchange_name($exchange); } }
function delete_user($id) { $user = get_user($id); if (!$user) { throw new Exception("No such user {$id}"); } crypto_log("Deleting user " . ($user ? htmlspecialchars(print_r($user, true)) : "<i>(phantom)</i>")); // go through all accounts $already_done = array(); foreach (account_data_grouped() as $label => $accounts) { foreach ($accounts as $key => $account) { if ($account['table'] != 'graphs' && !isset($already_done[$account['table']])) { delete_from($account['table']); $already_done[$account['table']] = 1; } } } delete_from('balances'); delete_from('address_balances'); delete_from('hashrates'); delete_from('securities'); delete_from('offsets'); delete_from('summary_instances'); delete_from('summaries'); delete_from('graph_data_summary'); delete_from('graph_data_balances'); delete_from('pending_subscriptions'); // delete graphs crypto_log("Deleting graphs..."); $q = db()->prepare("SELECT * FROM graph_pages WHERE user_id=?"); $q->execute(array($user['id'])); $pages = $q->fetchAll(); foreach ($pages as $page) { $q = db()->prepare("DELETE FROM graphs WHERE page_id=?"); $q->execute(array($page['id'])); crypto_log("(" . number_format($q->rowCount()) . " rows deleted)"); } delete_from('graph_pages'); delete_from('managed_graphs'); crypto_log("Deleting user_properties..."); $q = db()->prepare("DELETE FROM user_properties WHERE id=?"); $q->execute(array($user['id'])); crypto_log("(" . number_format($q->rowCount()) . " rows deleted)"); // finally delete the user object crypto_log("Deleting user..."); $user = Users\User::findUser(db(), $user['id']); $user->delete(db()); }
/** * Implements failing tables; if an account type fails multiple times, * then send the user an email and disable the account. * @see OpenclerkJobQueuer#getStandardJobs() */ function failed(\Exception $runtime_exception, Connection $db, Logger $logger) { // is this a standard job? $standard = $this->findStandardJob(); if ($standard) { $logger->info("Using standard job " . print_r($standard, true)); if (!$standard['failure']) { $logger->info("Not a failure standard job"); return; } } else { return; } $failing_table = $standard['table']; $job = $this->job; // find the relevant account_data for this standard job $account_data = false; foreach (account_data_grouped() as $label => $group) { foreach ($group as $exchange => $data) { if (isset($data['job_type']) && $job['job_type'] == $data['job_type']) { $account_data = $data; $account_data['exchange'] = $exchange; break; } } } if (!$account_data) { $logger->warn("Could not find any account data for job type '" . $job['job_type'] . "'"); } $logger->info("Using account data " . print_r($account_data, true)); // don't count CloudFlare as a failure if ($runtime_exception instanceof CloudFlareException || $runtime_exception instanceof \Openclerk\Apis\CloudFlareException) { $logger->info("Not increasing failure count: was a CloudFlareException"); } else { if ($runtime_exception instanceof IncapsulaException || $runtime_exception instanceof \Openclerk\Apis\IncapsulaException) { $logger->info("Not increasing failure count: was a IncapsulaException"); } else { if ($runtime_exception instanceof BlockchainException || $runtime_exception instanceof \Core\BlockchainException) { $logger->info("Not increasing failure count: was a BlockchainException"); } else { $q = $db->prepare("UPDATE {$failing_table} SET failures=failures+1,first_failure=IF(ISNULL(first_failure), NOW(), first_failure) WHERE id=?"); $q->execute(array($job['arg_id'])); $logger->info("Increasing account failure count"); } } } $user = get_user($job['user_id']); if (!$user) { $logger->info("Warning: No user " . $job['user_id'] . " found"); } else { // failed too many times? $q = $db->prepare("SELECT * FROM {$failing_table} WHERE id=? LIMIT 1"); $q->execute(array($job['arg_id'])); $account = $q->fetch(); $logger->info("Current account failure count: " . number_format($account['failures'])); if ($account['failures'] >= get_premium_value($user, 'max_failures')) { // disable it and send an email $q = $db->prepare("UPDATE {$failing_table} SET is_disabled=1 WHERE id=?"); $q->execute(array($job['arg_id'])); crypto_log(print_r($account_data, true)); if ($user['email'] && !$account['is_disabled']) { $email_type = $job['job_type'] == "notification" ? "failure_notification" : "failure"; send_user_email($user, $email_type, array("name" => $user['name'] ? $user['name'] : $user['email'], "exchange" => get_exchange_name($account_data['exchange']), "label" => $account_data['label'], "labels" => $account_data['labels'], "failures" => number_format($account['failures']), "message" => $runtime_exception->getMessage(), "length" => recent_format(strtotime($account['first_failure']), "", ""), "title" => isset($account['title']) && $account['title'] ? "\"" . $account['title'] . "\"" : "untitled", "url" => absolute_url(url_for("wizard_accounts")))); $logger->info("Sent failure e-mail to " . htmlspecialchars($user['email']) . "."); } } } }
require __DIR__ . "/../layout/templates.php"; $messages = array(); $errors = array(); page_header("Admin: Show Explorers", "page_admin_show_explorers"); ?> <h1>Currency Explorers</h1> <p class="backlink"><a href="<?php echo htmlspecialchars(url_for('admin')); ?> ">< Back to Site Status</a></p> <ul> <?php $grouped = account_data_grouped(); $external = get_external_apis(); foreach ($grouped['Addresses'] as $key => $data) { echo "<li><span style=\"display: inline-block; min-width: 250px;\">"; echo get_currency_abbr($data['currency']); echo " using " . $external['Address balances'][$key]; echo " using " . $external['Address balances'][$key]['link']; echo ":</span> "; echo crypto_address($data['currency'], 'example'); echo "</li>"; } ?> </ul> <?php page_footer();
<?php /** * Goes through a users' accounts and identifies which accounts might need automatic transaction * generation deleted. */ // create a map of all the current user exchanges $accounts = account_data_grouped(); $current_accounts = array(); foreach ($accounts as $label => $accounts_data) { foreach ($accounts_data as $exchange => $account) { if (!isset($account['wizard'])) { continue; } $wizard = get_wizard_account_type($account['wizard']); if (!$wizard['transaction_creation']) { continue; } $q = db()->prepare("SELECT * FROM " . $account['table'] . " WHERE user_id=?" . (isset($account['query']) ? $account['query'] : false)); $q->execute(array($job['user_id'])); while ($a = $q->fetch()) { $a['exchange'] = $exchange; $current_accounts[$exchange . " " . $a['id']] = $a; } } } crypto_log("User " . $job['user_id'] . " has " . count($current_accounts) . " accounts to parse."); // are there any creators that need to be deleted for this user? $q = db()->prepare("SELECT * FROM transaction_creators WHERE user_id=?"); $q->execute(array($job['user_id'])); $to_delete = array();
<?php require_login(); $user = get_user(user_id()); require_user($user); $errors = array(); $messages = array(); // get all of our accounts $accounts = user_limits_summary(user_id()); // find the appropriate $account_data $account_data = false; foreach (account_data_grouped() as $label => $data) { foreach ($data as $key => $value) { if ($key == require_post("type")) { // we've found a valid account type $account_data = get_accounts_wizard_config($key); $account_data['disabled'] = $value['disabled']; $account_data['job_type'] = $value['job_type']; } } } if (!$account_data) { throw new Exception("Invalid account type '" . htmlspecialchars(require_post("type")) . "'"); } switch (require_post("callback")) { case "wizard_accounts_pools": case "wizard_accounts_exchanges": case "wizard_accounts_securities": case "wizard_accounts_individual_securities": case "wizard_accounts_offsets": case "wizard_accounts_other":
function get_all_user_account_instances($account_key) { global $get_all_user_account_instances; if (!isset($get_all_user_account_instances[$account_key])) { $accounts = account_data_grouped(); foreach ($accounts as $label => $group) { foreach ($group as $key => $value) { if ($key == $account_key) { $q = db()->prepare("SELECT * FROM " . $value['table'] . " WHERE user_id=?"); $q->execute(array(user_id())); $get_all_user_account_instances[$account_key] = $q->fetchAll(); } } } if (!isset($get_all_user_account_instances[$account_key])) { throw new Exception("No account type '{$account_key}' defined"); } } return $get_all_user_account_instances[$account_key]; }
/** * All exchanges, even those that are disabled, should have a definition through * {@link #get_accounts_wizard_config_basic()}. */ function testAllAccountsHaveWizardConfig() { $account_data_grouped = account_data_grouped(); foreach (array('Mining pools', 'Exchanges', 'Securities') as $group_key) { foreach ($account_data_grouped[$group_key] as $key => $data) { $this->assertNotNull(get_accounts_wizard_config_basic($key), "Expected a wizard config for exchange '{$key}'"); } } }
function get_accounts_wizard_config($exchange) { $result = get_accounts_wizard_config_basic($exchange); if (!isset($result['title'])) { $result['title'] = get_exchange_name($exchange) . " account"; } if (!isset($result['titles'])) { $result['titles'] = $result['title'] . "s"; } if (!isset($result['khash'])) { $result['khash'] = false; } if (!isset($result['interaction'])) { $result['interaction'] = false; } if (!isset($result['fixed_inputs'])) { $result['fixed_inputs'] = array(); } foreach ($result['inputs'] as $key => $data) { $result['inputs'][$key]['key'] = $key; if (!isset($result['inputs'][$key]['inline_title'])) { $result['inputs'][$key]['inline_title'] = $result['inputs'][$key]['title']; } } foreach (account_data_grouped() as $group => $data) { foreach ($data as $key => $values) { if ($key == $exchange && isset($values['wizard'])) { $result['wizard'] = $values['wizard']; } } } $result['exchange'] = $exchange; return $result; }
"><div class="splash"></div></a> <h3><?php echo ht("Track accounts & addresses"); ?> </h3> <p> <?php echo ht(":site_name supports a wide range of cryptocurrency applications\n and is regularly updated with new services. For example :site_name\n currently supports:"); ?> </p> <p> <dl> <?php foreach (account_data_grouped() as $category => $datas) { if ($category == 'Hidden' || $category == 'Individual Securities' || $category == 'Finance') { continue; } echo "<dt>" . ht($category) . "</dt>\n"; if ($category == "Offsets") { // Offsets have no subcategories; issue #344 continue; } $result = array(); foreach ($datas as $exchange => $data) { if (isset($data['disabled']) && $data['disabled']) { // don't display disabled accounts continue; } if ($category == 'Addresses') {