Exemplo n.º 1
0
 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);
 }
Exemplo n.º 2
0
 function testAllExchangeCurrencies()
 {
     foreach (get_exchange_pairs() as $exchange => $pairs) {
         foreach ($pairs as $p) {
             $this->assertTrue(in_array($p[0], get_all_currencies()), "Exchange {$exchange} had invalid currency {$p['0']} in pair {$p['0']}/{$p['1']}");
             $this->assertTrue(in_array($p[1], get_all_currencies()), "Exchange {$exchange} had invalid currency {$p['1']} in pair {$p['0']}/{$p['1']}");
         }
     }
 }
Exemplo n.º 3
0
/**
 * Get all of the defined public graph types. These are then included into graph_types()
 * as necessary.
 */
function graph_types_public($summaries = array())
{
    $data = array();
    $data['category_exchanges'] = array('title' => t('Exchanges'), 'category' => true);
    // we can generate a list of daily graphs from all of the exchanges that we support
    // but we'll only want to display currency pairs that we're interested in
    $all_pairs = get_exchange_pairs() + get_disabled_exchange_pairs();
    foreach ($all_pairs as $key => $pairs) {
        $data['subcategory_exchanges_' . $key] = array('title' => get_exchange_name($key), 'subcategory' => true);
        foreach ($pairs as $pair) {
            $pp = get_currency_abbr($pair[0]) . "/" . get_currency_abbr($pair[1]);
            $data[$key . "_" . $pair[0] . $pair[1] . "_daily"] = array('title' => t(":exchange historical :pair (graph)", array(':exchange' => get_exchange_name($key), ':pair' => $pp)), 'heading' => get_exchange_name($key) . " {$pp}", 'description' => t("A line graph displaying the historical bid/ask values for :pair on :exchange.", array(':exchange' => get_exchange_name($key), ':pair' => $pp)), 'pairs' => $pair, 'hide' => !(isset($summaries[$pair[0]]) && isset($summaries[$pair[1]])), 'public' => true, 'days' => true, 'technical' => true, 'delta' => true, 'historical' => 'get_exchange_historical', 'historical_arg0' => array('key' => $key, 'pair' => $pair), 'exchange' => $key);
        }
        foreach ($pairs as $pair) {
            $pp = get_currency_abbr($pair[0]) . "/" . get_currency_abbr($pair[1]);
            $data["pair_" . $key . "_" . $pair[0] . $pair[1]] = array('title' => t(":exchange :pair (table)", array(':exchange' => get_exchange_name($key), ':pair' => $pp)), 'heading' => get_exchange_name($key) . " {$pp}", 'description' => t("A simple table displaying the current bid/ask :pair price on :exchange.", array(':exchange' => get_exchange_name($key), ':pair' => $pp)), 'pairs' => $pair, 'hide' => !(isset($summaries[$pair[0]]) && isset($summaries[$pair[1]])), 'public' => true, 'days' => false, 'technical' => false, 'delta' => false, 'historical' => 'get_exchange_historical', 'historical_arg0' => array('key' => $key, 'pair' => $pair), 'exchange' => $key);
        }
    }
    // generate the possible average graphs independently, using ticker_recent
    $key = 'average';
    // get the averages pairs once
    $q = db()->prepare("SELECT * FROM ticker_recent WHERE exchange=? ORDER BY currency1 ASC, currency2 ASC");
    $q->execute(array($key));
    $averages = $q->fetchAll();
    $data['subcategory_exchanges_' . $key] = array('title' => get_exchange_name($key), 'subcategory' => true);
    foreach ($averages as $ticker) {
        if (!in_array($ticker['currency1'], get_all_currencies())) {
            continue;
        }
        if (!in_array($ticker['currency2'], get_all_currencies())) {
            continue;
        }
        $pp = get_currency_abbr($ticker['currency1']) . "/" . get_currency_abbr($ticker['currency2']);
        $data[$key . "_" . $ticker['currency1'] . $ticker['currency2'] . "_daily"] = array('title' => t(":exchange historical :pair (graph)", array(':exchange' => get_exchange_name($key), ':pair' => $pp)), 'heading' => get_exchange_name($key) . " {$pp}", 'description' => t("A line graph displaying the historical average market bid/ask values for :pair.", array(':pair' => $pp)), 'pairs' => $pair, 'hide' => !(isset($summaries[$ticker['currency1']]) && isset($summaries[$ticker['currency2']])), 'public' => true, 'days' => true, 'technical' => true, 'delta' => true, 'historical' => 'get_average_exchange_historical', 'historical_arg0' => array('key' => $key, 'currency1' => $ticker['currency1'], 'currency2' => $ticker['currency2']), 'exchange' => $key);
    }
    foreach ($averages as $ticker) {
        if (!in_array($ticker['currency1'], get_all_currencies())) {
            continue;
        }
        if (!in_array($ticker['currency2'], get_all_currencies())) {
            continue;
        }
        $pp = get_currency_abbr($ticker['currency1']) . "/" . get_currency_abbr($ticker['currency2']);
        $data[$key . "_" . $ticker['currency1'] . $ticker['currency2'] . "_markets"] = array('title' => t(":exchange historical :pair (market data)", array(':exchange' => get_exchange_name($key), ':pair' => $pp)), 'heading' => t(":exchange :pair exchange data", array(':exchange' => get_exchange_name($key), ':pair' => $pp)), 'description' => t("A table displaying the market data used to generate the average market price for :pair.", array(':pair' => $pp)), 'pairs' => $pair, 'hide' => !(isset($summaries[$ticker['currency1']]) && isset($summaries[$ticker['currency2']])), 'public' => true, 'days' => true, 'technical' => true, 'delta' => true, 'historical' => 'get_average_exchange_markets', 'historical_arg0' => array('key' => $key, 'currency1' => $ticker['currency1'], 'currency2' => $ticker['currency2']), 'exchange' => $key);
    }
    $data['category_securities'] = array('title' => t('Securities'), 'category' => true);
    $data['subcategory_securities'] = array('title' => t('Security values'), 'subcategory' => true);
    // get all securities
    foreach (get_security_exchange_pairs() as $key => $currencies) {
        foreach ($currencies as $c) {
            $data['securities_' . $key . '_' . $c] = array('title' => t(':exchange :currency security value (graph)', array(':exchange' => get_exchange_name($key), ':currency' => get_currency_abbr($c))), 'heading' => t(":exchange security", array(':exchange' => get_exchange_name($key))), 'description' => t('A line graph displaying the historical value of a particular :exchange security.', array(':exchange' => get_exchange_name($key))), 'hide' => !isset($summaries[$c]), 'days' => true, 'delta' => true, 'arg0' => 'get_security_instances_keys', 'arg0_title' => t('Security:'), 'param0' => $key, 'param1' => $c, 'technical' => true, 'historical' => 'get_security_instances_historical', 'historical_param0' => $key, 'historical_param1' => $c, 'title_callback' => 'get_security_instance_title');
        }
    }
    $data['category_tools'] = array('title' => t('Tools'), 'category' => true);
    $data['subcategory_tools'] = array('title' => t('Tools'), 'subcategory' => true);
    $data['calculator'] = array('title' => t('Currency converter (calculator)'), 'heading' => t('Currency converter'), 'description' => t('A :calculator to convert any currency into any other currency, using the most recent exchange rates.', array(':calculator' => link_to(url_for('calculator'), t("simple calculator")))), 'technical' => false, 'no_refresh' => true);
    $data['external_historical'] = array('title' => t('External API status (graph)'), 'heading' => t('External API status'), 'description' => t('A line graph displaying the historical status of an external API, by displaying the percentage of failing samples.'), 'days' => true, 'arg0' => 'get_external_status_titles', 'arg0_title' => t('External API:'), 'technical' => false, 'historical' => 'get_external_status_historical');
    $data['statistics_queue'] = array('title' => "Job queue delay (graph)", 'heading' => "Job queue delay (hours)", 'description' => 'The job queue delay for free and premium users, represented as a graph over time.', 'hide' => true, 'admin' => true);
    $data['admin_statistics'] = array('title' => "Site status (table)", 'heading' => "Site status", 'description' => 'Key performance metics of the site.', 'hide' => true, 'admin' => true);
    $data['statistics_system_load'] = array('title' => "System load (graph)", 'heading' => "System load (hours)", 'description' => 'The system load, represented as a graph over time.', 'hide' => true, 'admin' => true);
    $data['statistics_db_system_load'] = array('title' => "Database system load (graph)", 'heading' => "Database system load (hours)", 'description' => 'The database system load, represented as a graph over time.', 'hide' => true, 'admin' => true);
    $data['metrics_db_slow_queries_graph'] = array('title' => "Slowest DB queries (graph)", 'heading' => "Slowest DB queries (ms)", 'description' => 'The slowest database queries represented as a graph over time.', 'hide' => true, 'admin' => true);
    $data['metrics_curl_slow_urls_graph'] = array('title' => "Slowest CURL URLs (graph)", 'heading' => "Slowest CURL URLs (ms)", 'description' => 'The slowest CURL requests represented as a graph over time.', 'hide' => true, 'admin' => true);
    $data['metrics_slow_jobs_graph'] = array('title' => "Slowest jobs (graph)", 'heading' => "Slowest jobs (ms)", 'description' => 'The slowest jobs represented as a graph over time.', 'hide' => true, 'admin' => true);
    $data['metrics_slow_jobs_db_graph'] = array('title' => "Slowest jobs database time (graph)", 'heading' => "Slowest jobs database time (ms)", 'description' => 'The time spent in the database on the slowest jobs represented as a graph over time.', 'hide' => true, 'admin' => true);
    $data['metrics_slow_pages_graph'] = array('title' => "Slowest pages (graph)", 'heading' => "Slowest pages (ms)", 'description' => 'The slowest pages represented as a graph over time.', 'hide' => true, 'admin' => true);
    $data['metrics_slow_pages_db_graph'] = array('title' => "Slowest pages database time (graph)", 'heading' => "Slowest pages database time (ms)", 'description' => 'The time spent in the database on the slowest pages represented as a graph over time.', 'hide' => true, 'admin' => true);
    $data['metrics_slow_graphs_graph'] = array('title' => "Slowest graphs (graph)", 'heading' => "Slowest graphs (ms)", 'description' => 'The slowest graphs represented as a graph over time.', 'hide' => true, 'admin' => true);
    $data['metrics_slow_graphs_db_graph'] = array('title' => "Slowest graphs database time (graph)", 'heading' => "Slowest graphs database time (ms)", 'description' => 'The time spent in the database on the slowest graphs represented as a graph over time.', 'hide' => true, 'admin' => true);
    $data['metrics_slow_graphs_count_graph'] = array('title' => "Slowest graphs frequency (graph)", 'heading' => "Slowest graphs frequency", 'description' => 'The frequency that the slowest graphs are requested, represented as a graph over time.', 'hide' => true, 'admin' => true);
    $data['metrics_jobs_frequency_graph'] = array('title' => "Job frequency (graph)", 'heading' => "Job frequency (jobs/hour)", 'description' => 'The frequency of particular jobs per hour, represented as a graph over time.', 'hide' => true, 'admin' => true);
    return $data;
}
Exemplo n.º 4
0
/**
 * Calculate all of the different types of managed graphs that
 * may be provided to a given user, in each category of managed
 * graphs (see get_managed_graph_categories()).
 */
function calculate_all_managed_graphs($user)
{
    $result = array();
    $summaries = get_all_summary_currencies();
    $all_summaries = get_all_summaries();
    $currencies = get_all_currencies();
    $accounts = account_data_grouped();
    $wallets = get_supported_wallets();
    $order_currency = array();
    foreach (get_all_currencies() as $c) {
        $order_currency[$c] = count($order_currency);
    }
    $order_exchange = array();
    foreach (get_all_exchanges() as $key => $label) {
        $order_exchange[$key] = count($order_exchange) * 10;
    }
    $default_order = array('btc_equivalent' => -1000, 'composition_pie' => 0, 'balances_table' => 1000, 'exchange_daily' => 2000, 'total_daily' => 3000, 'all_daily' => 4000, 'composition_daily' => 5000, 'hashrate_daily' => 6000);
    $result['summary'] = array();
    $result['all_summary'] = array();
    $result['summary']['balances_table'] = array('order' => $default_order['balances_table'], 'width' => get_site_config('default_user_graph_height'), 'free' => true, 'priority' => 1);
    if (count($summaries) >= 2 && isset($summaries['btc'])) {
        $result['summary']['btc_equivalent'] = array('order' => $default_order['btc_equivalent'], 'width' => get_site_config('default_user_graph_height'), 'free' => true, 'priority' => 2);
    }
    foreach (get_all_cryptocurrencies() as $cur) {
        if (isset($summaries[$cur])) {
            $result['summary']["composition_" . $cur . "_pie"] = array('order' => $default_order['composition_pie'] + $order_currency[$cur], 'width' => get_site_config('default_user_graph_height'), 'free' => $cur == $user['preferred_crypto'], 'priority' => $cur == $user['preferred_crypto'] ? 100 : 300 + $order_currency[$cur]);
            $result['summary']["composition_" . $cur . "_daily"] = array('order' => $default_order['composition_daily'] + $order_currency[$cur], 'free' => $cur == $user['preferred_crypto'], 'priority' => $cur == $user['preferred_crypto'] ? 105 : 200 + $order_currency[$cur]);
            $result['summary']['total_' . $cur . '_daily'] = array('order' => $default_order['total_daily'] + $order_currency[$cur], 'source' => $cur, 'free' => $cur == $user['preferred_crypto'], 'priority' => 100 + $order_currency[$cur]);
        }
    }
    foreach (get_all_commodity_currencies() as $cur) {
        if (isset($summaries[$cur])) {
            $result['summary']['total_' . $cur . '_daily'] = array('order' => $default_order['total_daily'] + $order_currency[$cur], 'source' => $cur, 'free' => $cur == $user['preferred_crypto'], 'priority' => 100 + $order_currency[$cur]);
        }
    }
    $result['currency'] = array();
    $result['all_currency'] = array();
    foreach (get_exchange_pairs() as $exchange => $pairs) {
        foreach ($pairs as $pair) {
            // we are interested in both of these currencies
            if (isset($summaries[$pair[0]]) && isset($summaries[$pair[1]])) {
                // and one of these currencies are a preferred currency
                if ($pair[0] == $user['preferred_crypto'] || $pair[0] == $user['preferred_fiat'] || $pair[1] == $user['preferred_crypto'] || $pair[1] == $user['preferred_fiat']) {
                    // and we have a summary instance for this pair somewhere
                    $possible_summaries = array('summary_' . $pair[0] . '_' . $exchange, 'summary_' . $pair[1] . '_' . $exchange);
                    if (in_array($pair[0], get_all_cryptocurrencies())) {
                        $possible_summaries[] = "summary_" . $pair[0];
                    }
                    if (in_array($pair[1], get_all_cryptocurrencies())) {
                        $possible_summaries[] = "summary_" . $pair[1];
                    }
                    foreach ($possible_summaries as $p) {
                        if (isset($all_summaries[$p])) {
                            $is_default = is_fiat_currency($pair[0]) && get_default_currency_exchange($pair[0]) == $exchange || is_fiat_currency($pair[1]) && get_default_currency_exchange($pair[1]) == $exchange;
                            $result['all_currency'][$exchange . "_" . $pair[0] . $pair[1] . "_daily"] = array('order' => $default_order['exchange_daily'] + $order_exchange[$exchange] + $order_currency[$pair[0]], 'source' => $p, 'priority' => 150 + $order_currency[$pair[0]]);
                            if ($is_default) {
                                $result['currency'][$exchange . "_" . $pair[0] . $pair[1] . "_daily"] = array('order' => $default_order['exchange_daily'] + $order_exchange[$exchange] + $order_currency[$pair[0]], 'source' => $p, 'free' => true, 'priority' => 150 + $order_currency[$pair[0]]);
                            }
                            // don't display all2btc etc
                            if (!in_array(substr($p, strlen("summary_")), get_all_cryptocurrencies())) {
                                $result['all_summary']['all2' . substr($p, strlen("summary_")) . '_daily'] = array('order' => $default_order['all_daily'] + $order_exchange[$exchange] + $order_currency[$pair[0]], 'source' => $p, 'priority' => 50 + $order_currency[$pair[0]]);
                                if ($is_default) {
                                    $result['summary']['all2' . substr($p, strlen("summary_")) . '_daily'] = array('order' => $default_order['all_daily'] + $order_exchange[$exchange] + $order_currency[$pair[0]], 'source' => $p, 'free' => $pair[0] == $user['preferred_crypto'] || $pair[0] == $user['preferred_fiat'], 'priority' => 5 + $order_currency[$pair[0]]);
                                }
                            }
                            break;
                        }
                    }
                }
            }
        }
    }
    $result['securities'] = array();
    // no graphs to put in here yet...
    // TODO in the future: securities composition graphs? e.g. composition_litecoinglobal_daily
    $result['mining'] = array();
    foreach (get_all_hashrate_currencies() as $cur) {
        if (isset($summaries[$cur])) {
            // we need to have at least one pool that supports reporting hashrate
            $has_hashing_account = false;
            foreach ($accounts['Mining pools'] as $key => $account) {
                if (!isset($wallets[$key])) {
                    continue;
                }
                $instances = get_all_user_account_instances($key);
                if ($instances) {
                    if (in_array('hash', $wallets[$key])) {
                        $has_hashing_account = $key;
                    }
                }
            }
            if (!$has_hashing_account) {
                continue;
            }
            $result['mining']["hashrate_" . $cur . "_daily"] = array('order' => $default_order['hashrate_daily'] + $order_currency[$cur], 'source' => $has_hashing_account, 'free' => $cur == $user['preferred_crypto'], 'priority' => 150 + $order_currency[$cur]);
        }
    }
    // all 'summary' are also 'all_summary' etc
    foreach ($result['summary'] as $key => $value) {
        $result['all_summary'][$key] = $value;
    }
    foreach ($result['currency'] as $key => $value) {
        $result['all_currency'][$key] = $value;
    }
    // go through each category and sort by order
    foreach ($result as $key => $value) {
        uasort($result[$key], '_sort_by_order_key');
    }
    return $result;
}
Exemplo n.º 5
0
/**
 * We use Javascript to update the list of notifications, so that it is easy to edit them and we don't
 * have to write the same interface twice.
 */
?>
<script type="text/javascript">
function get_supported_notifications() {
  return <?php 
// get a list of all possible notifications
$supported_notifications = array('exchanges' => array(), 'total_currencies' => array(), 'total_hashrate_currencies' => array(), 'all2_summaries' => array());
$supported_exchange_currencies = array();
// all the exchanges we may be interested in
require __DIR__ . "/../graphs/util.php";
$summaries = get_all_summary_currencies();
$conversions = get_all_conversion_currencies();
foreach (get_exchange_pairs() as $exchange => $pairs) {
    foreach ($pairs as $pair) {
        if (isset($summaries[$pair[0]]) && isset($summaries[$pair[1]])) {
            if (!isset($supported_notifications['exchanges'][$exchange])) {
                $supported_notifications['exchanges'][$exchange] = array();
            }
            $supported_notifications['exchanges'][$exchange][] = $pair;
            $supported_exchange_currencies[$pair[0] . $pair[1]] = get_currency_abbr($pair[0]) . "/" . get_currency_abbr($pair[1]);
        }
    }
}
foreach (get_summary_types() as $key => $summary) {
    $cur = $summary['currency'];
    if (isset($summaries[$summary['currency']])) {
        $supported_notifications['total_currencies'][$cur] = get_currency_abbr($cur);
        if (in_array($summary['currency'], get_all_hashrate_currencies())) {
Exemplo n.º 6
0
function get_total_conversion_summary_types()
{
    global $global_get_total_conversion_summary_types;
    if ($global_get_total_conversion_summary_types == null) {
        $summary_types = array();
        // add fiat pairs automatically
        foreach (get_exchange_pairs() as $exchange => $pairs) {
            foreach ($pairs as $pair) {
                if ($pair[1] == 'btc') {
                    // fiat currency
                    $summary_types[$pair[0] . '_' . $exchange] = array('currency' => $pair[0], 'title' => get_currency_name($pair[0]) . ' (converted through ' . get_exchange_name($exchange) . ')', 'short_title' => get_currency_abbr($pair[0]) . ' (' . get_exchange_name($exchange) . ')', 'exchange' => $exchange);
                }
            }
        }
        // and also all average pairs for all fiats
        // (if there is a result in the ticker_recent)
        foreach (get_all_fiat_currencies() as $cur) {
            $exchange = "average";
            $q = db()->prepare("SELECT * FROM ticker_recent WHERE currency1=? AND currency2=? AND exchange=? LIMIT 1");
            $q->execute(array($cur, 'btc', 'average'));
            if ($q->fetch()) {
                $summary_types[$cur . '_' . $exchange] = array('currency' => $cur, 'title' => get_currency_name($cur) . ' (converted using market average)', 'short_title' => get_currency_abbr($cur) . ' (market average)', 'exchange' => $exchange);
            }
        }
        // sort by currency order, then title
        uasort($summary_types, 'sort_get_total_conversion_summary_types');
        $global_get_total_conversion_summary_types = $summary_types;
    }
    return $global_get_total_conversion_summary_types;
}
Exemplo n.º 7
0
 public function getData($days)
 {
     $key_column = array('type' => 'string', 'title' => ct("Currency"));
     $columns = array();
     $last_updated = false;
     $columns[] = array('type' => 'string', 'title' => "", 'heading' => true);
     // a matrix table of each currency vs. each currency, and their current
     // last_trade and volume on each exchange the user is interested in
     $currencies = get_all_currencies();
     $summaries = get_all_summary_currencies($this->getUser());
     $conversion = get_all_conversion_currencies($this->getUser());
     $graph["last_updated"] = 0;
     $interested = array();
     foreach ($currencies as $c) {
         if (isset($summaries[$c])) {
             $interested[] = $c;
             $columns[] = array('type' => 'string', 'title' => get_currency_abbr($c));
         }
     }
     foreach ($interested as $c1) {
         $row = array(get_currency_abbr($c1));
         foreach ($interested as $c2) {
             // go through each exchange pair
             $cell = "";
             foreach (get_exchange_pairs() as $exchange => $pairs) {
                 foreach ($pairs as $pair) {
                     if ($c1 == $pair[0] && $c2 == $pair[1]) {
                         $q = db()->prepare("SELECT * FROM ticker_recent WHERE exchange=? AND currency1=? AND currency2=? LIMIT 1");
                         $q->execute(array($exchange, $c1, $c2));
                         if ($ticker = $q->fetch()) {
                             // TODO currency_format should be a graph option
                             $exchange_short = strlen($exchange) > 8 ? substr($exchange, 0, 7) . "..." : $exchange;
                             $cell .= "<li><span class=\"rate\">" . number_format_html($ticker['last_trade'], 4) . "</span> " . ($ticker['volume'] == 0 ? "" : "<span class=\"volume\">(" . number_format_html($ticker['volume'], 4) . ")</span>");
                             $cell .= " <span class=\"exchange\" title=\"" . htmlspecialchars(get_exchange_name($exchange)) . "\">[" . htmlspecialchars($exchange_short) . "]</span>";
                             $cell .= "</li>\n";
                             $last_updated = max($last_updated, strtotime($ticker['created_at']));
                         } else {
                             $cell .= "<li class=\"warning\">" . t("Could not find rate for :exchange: :pair", array(':exchange' => $exchange, ':pair' => $c1 . "/" . $c2)) . "</li>\n";
                         }
                     }
                 }
             }
             if ($cell) {
                 $cell = "<ul class=\"rate_matrix\">" . $cell . "</ul>";
             }
             $row[] = $cell;
         }
         $data[] = $row;
     }
     // now delete any empty rows or columns
     // columns
     $deleteRows = array();
     $deleteColumns = array();
     for ($i = 0; $i < count($data) - 1; $i++) {
         $empty = true;
         for ($j = 1; $j < count($data[$i]); $j++) {
             if ($data[$i][$j]) {
                 $empty = false;
                 break;
             }
         }
         if ($empty) {
             $deleteRows[] = $i;
         }
     }
     for ($i = 1; $i < count($data); $i++) {
         $empty = true;
         for ($j = 0; $j < count($data[$i]) - 1; $j++) {
             if ($data[$j][$i]) {
                 $empty = false;
                 break;
             }
         }
         if ($empty) {
             $deleteColumns[] = $i;
         }
     }
     $new_data = array();
     foreach ($data as $i => $row) {
         if (in_array($i, $deleteRows)) {
             continue;
         }
         $x = array();
         foreach ($data[$i] as $j => $cell) {
             if (in_array($j, $deleteColumns)) {
                 continue;
             }
             $x[] = $cell;
         }
         $new_data[] = $x;
     }
     foreach ($deleteColumns as $i) {
         unset($columns[$i]);
     }
     $columns = array_values($columns);
     return array('key' => $key_column, 'columns' => $columns, 'data' => $new_data, 'last_updated' => $last_updated, 'add_more_currencies' => true);
 }
    $all_currencies[$cur] = $cur;
}
ksort($all_currencies);
// now render it
echo "<table class=\"fancy reported-currencies\">";
echo "<tr>";
echo "<th>Exchange</th>";
foreach ($all_currencies as $cur => $ignored) {
    $class = in_array($cur, get_all_currencies()) ? "supported" : "";
    if (require_get("only_supported", false) && !in_array($cur, get_all_currencies())) {
        continue;
    }
    echo "<th class=\"{$class}\">" . htmlspecialchars($cur) . "</th>";
}
echo "</tr>\n";
$exchange_pairs = get_exchange_pairs();
$get_supported_wallets = get_supported_wallets();
foreach ($exchanges as $exchange) {
    echo "<tr>";
    echo "<th>" . htmlspecialchars($exchange->getName()) . "</th>";
    foreach ($all_currencies as $cur => $ignored) {
        if (require_get("only_supported", false) && !in_array($cur, get_all_currencies())) {
            continue;
        }
        $class = isset($matrix[$exchange->getCode()][$cur]) ? "reported" : "";
        // do we have at least one exchange pair for this defined?
        $pair_supported = false;
        foreach ($exchange_pairs[$exchange->getCode()] as $pair) {
            if ($pair[0] == $cur || $pair[1] == $cur) {
                $pair_supported = true;
            }