Compare commits

...

31 commits

Author SHA1 Message Date
Niko Storni
4065389798 retain the same resolution as the frontend 2022-06-21 18:21:12 +02:00
Niko Storni
a252dc05e6 fix typo 2022-06-17 20:00:48 +02:00
Niko Storni
e8c58e8c15 try 3 2022-06-17 18:59:32 +02:00
Niko Storni
e8e9346a70 tmp fix for stupid queries 2022-06-17 18:58:10 +02:00
Niko Storni
fdecf39f93 don't run stupid queries 2022-06-17 18:54:42 +02:00
Niko Storni
d3cd0e13f6 remove missing field 2022-06-17 18:32:31 +02:00
Niko Storni
f769cac5da fix thumbnails 2022-06-17 17:53:50 +02:00
Niko Storni
9b554eec1b fix issues with new chainquery schema
fix bittrex API
2022-06-17 17:15:19 +02:00
Niko Storni
07d9521cfe Merge remote-tracking branch 'origin/dependabot/composer/composer/composer-1.10.26' 2022-06-17 15:39:07 +02:00
dependabot[bot]
820f20a479
Bump composer/composer from 1.10.19 to 1.10.26
Bumps [composer/composer](https://github.com/composer/composer) from 1.10.19 to 1.10.26.
- [Release notes](https://github.com/composer/composer/releases)
- [Changelog](https://github.com/composer/composer/blob/1.10.26/CHANGELOG.md)
- [Commits](https://github.com/composer/composer/compare/1.10.19...1.10.26)

---
updated-dependencies:
- dependency-name: composer/composer
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-22 20:45:40 +00:00
Thomas Zarebczan
0c84ba3fae
Add new hot wallet 2021-02-03 11:20:40 -05:00
Niko Storni
e74d5b7b2d fix dependencies 2021-01-12 23:03:22 +01:00
Akinwale Ariwodola
fc0abe8d33
More claims fix (#91) 2020-10-28 15:57:26 +01:00
Jeremy Kauffman
7e9851ccfc
Merge pull request #80 from lbryio/dependabot/composer/cakephp/cakephp-3.7.7
Bump cakephp/cakephp from 3.7.1 to 3.7.7
2020-03-16 14:04:26 -04:00
Jeremy Kauffman
d7fb718dd0
Merge pull request #86 from kcseb/master
Change footer to .com
2020-03-16 14:03:03 -04:00
Kenneth C
6f4fa32078
Updated a missed .io 2020-03-09 20:33:19 -04:00
Kenneth C
8873373465
Update URL to .com 2020-03-09 20:32:16 -04:00
Akinwale Ariwodola
a73d65b1c2
Merge pull request #85 from lbryio/fix-utxosupply
fix custom configuration loading and gettxoutsetinfo request
2020-03-04 16:04:37 +01:00
Thomas Zarebczan
bb595d0027
update LBRY addresses 2020-02-27 18:22:34 -05:00
Akinwale Ariwodola
52d13987e5 fix custom configuration loading and gettxoutsetinfo request 2020-01-08 22:02:03 +01:00
Niko
57219734c3
Merge pull request #82 from lbryio/fix-utxosupply
Fix utxosupply
2020-01-08 14:06:36 +01:00
Akinwale Ariwodola
a7c1b9b346 update community, operational and institutional addresses 2020-01-08 08:04:00 +01:00
Akinwale Ariwodola
77ca91757b fix _gettxoutsetinfo return type 2020-01-07 23:37:50 +01:00
Akinwale Ariwodola
a147665e96 fix utxo supply 2020-01-07 23:34:50 +01:00
dependabot[bot]
0f197fc571
Bump cakephp/cakephp from 3.7.1 to 3.7.7
Bumps [cakephp/cakephp](https://github.com/cakephp/cakephp) from 3.7.1 to 3.7.7.
- [Release notes](https://github.com/cakephp/cakephp/releases)
- [Commits](https://github.com/cakephp/cakephp/compare/3.7.1...3.7.7)

Signed-off-by: dependabot[bot] <support@github.com>
2020-01-07 22:14:57 +00:00
Akinwale Ariwodola
31d515e992
Blocked claims (#81)
* handle blocked claims
* fix chainquery endpoint
* channel-level blocking
* don't show blocked claims in the result grid
* optimisation: break out of foreach loop if match found
* add caching for api request
* rename cache key
2020-01-07 23:13:38 +01:00
Niko
02551e98d7
Merge pull request #70 from lbryio/crash-fix
Crash fix
2019-10-21 11:41:58 -04:00
Akinwale Ariwodola
007cf0d34c add missing operator 2019-10-15 22:39:27 +01:00
Akinwale Ariwodola
c18431394c fix crash on large page numbers? 2019-10-15 22:28:45 +01:00
Niko
04cbdbcaee
Merge pull request #65 from lbryio/fix-dupes
fix dupes
2019-08-02 21:40:44 +02:00
Thomas Zarebczan
9b3a1f4097
remove decoder 2019-07-30 12:11:49 -04:00
18 changed files with 2173 additions and 887 deletions

View file

@ -2,19 +2,23 @@
A simple PHP block explorer for browsing transactions and claims on the [LBRY](https://lbry.com) blockchain. The explorer was developed using CakePHP which is a model-view-controller (MVC) PHP framework.
## Installation
## Requirements
There are some prerequisites that need to be installed before the explorer can be accessed.
* Web server - Apache, caddy or nginx
* [lbrycrd](https://github.com/lbryio/lbrycrd) with txindex turned on
* [Python claims decoder](https://github.com/cryptodevorg/lbry-decoder)
* MariaDB 10.2 or higher
* Redis Server (optional, only required for the CakePHP redis cache engine, or to run `forevermempool`)
* PHP 7.2 or higher
* PHP 7.4 or higher
* php-fpm
* [igbinary extension](https://github.com/igbinary/igbinary)
* [phpredis extension](https://github.com/phpredis/phpredis)
* composer (PHP package manager)
on ubuntu you may use this to install php requirements
```bash
sudo apt install php7.4-gmp php7.4-intl php7.4-mbstring php7.4-mysql php7.4-bcmath php7.4-gd
```
### Installation steps
* Clone the Github repository. `git clone https://github.com/lbryio/block-explorer`
* Create a MariaDB database using the DDL found in `block-explorer/sql/lbryexplorer.ddl.sql`

View file

@ -6,7 +6,7 @@
"license": "MIT",
"require": {
"php": ">=5.6",
"cakephp/cakephp": "3.7.1",
"cakephp/cakephp": "3.7.7",
"mobiledetect/mobiledetectlib": "2.*",
"cakephp/migrations": "~1.0",
"psr/simple-cache": "^1.0.0",
@ -41,7 +41,6 @@
"scripts": {
"post-install-cmd": "App\\Console\\Installer::postInstall",
"post-create-project-cmd": "App\\Console\\Installer::postInstall",
"post-autoload-dump": "Cake\\Composer\\Installer\\PluginInstaller::postAutoloadDump",
"check": [
"@test",
"@cs-check"
@ -50,5 +49,11 @@
"cs-fix": "phpcbf --colors --standard=vendor/cakephp/cakephp-codesniffer/CakePHP ./src ./tests",
"test": "phpunit --colors=always"
},
"prefer-stable": true
"prefer-stable": true,
"config": {
"allow-plugins": {
"cakephp/plugin-installer": true,
"kylekatarnls/update-helper": true
}
}
}

2704
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -222,7 +222,7 @@ return [
'className' => 'Cake\Database\Connection',
'driver' => 'Cake\Database\Driver\Mysql',
'persistent' => false,
'host' => 'chainquery.lbry.io',
'host' => 'chainquery.lbry.com',
/**
* CakePHP will use the default DB port based on the driver selected
* MySQL on MAMP uses port 8889, MAMP users will want to uncomment
@ -257,9 +257,9 @@ return [
*/
//'init' => ['SET GLOBAL innodb_stats_on_metadata = 0'],
'url' => env('DATABASE_URL', 'chainquery.lbry.io:3600'),
'url' => env('DATABASE_URL', 'chainquery.lbry.com:3600'),
],
'localdb' => [ // Local db for price history
'className' => 'Cake\Database\Connection',
'driver' => 'Cake\Database\Driver\Mysql',

View file

@ -226,5 +226,4 @@ if (Configure::read('debug')) {
Application::addPlugin('DebugKit', ['bootstrap' => true]);
}
Configure::load('lbry','lbry.default');
Configure::load('lbry', 'default');

4
dev.sh
View file

@ -2,7 +2,7 @@
set -e
PHPBIN=php7.2
PHPBIN=php7.4
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
@ -20,4 +20,4 @@ composer update
#$PHPBIN composer.phar install
$PHPBIN --server localhost:8000 --docroot "$DIR/webroot" "$DIR/webroot/index.php"
$PHPBIN --server localhost:8000 --docroot "$DIR/webroot" "$DIR/webroot/index.php"

View file

@ -32,9 +32,9 @@ class ClaimsController extends AppController {
}
$conn = ConnectionManager::get('default');
$stmt = $conn->execute('SELECT COUNT(Id) AS Total FROM Claims WHERE ThumbnailUrl IS NOT NULL AND LENGTH(TRIM(ThumbnailUrl)) > 0');
$count = $stmt->fetch(\PDO::FETCH_OBJ);
$numClaims = $count->Total;
// $stmt = $conn->execute('SELECT COUNT(Id) AS Total FROM Claims WHERE ThumbnailUrl IS NOT NULL AND LENGTH(TRIM(ThumbnailUrl)) > 0');
// $count = $stmt->fetch(\PDO::FETCH_OBJ);
$numClaims = 23000000;
if ($beforeId < 0) {
$beforeId = 0;
@ -58,4 +58,4 @@ class ClaimsController extends AppController {
}
}
?>
?>

View file

@ -7,6 +7,7 @@ use Mdanter\Ecc\Crypto\Signature\Signer;
use Mdanter\Ecc\Serializer\PublicKey\PemPublicKeySerializer;
use Mdanter\Ecc\Serializer\PublicKey\DerPublicKeySerializer;
use Mdanter\Ecc\Serializer\Signature\DerSignatureSerializer;
use Cake\Cache\Cache;
use Cake\Core\Configure;
use Cake\Datasource\ConnectionManager;
use Cake\Log\Log;
@ -18,23 +19,25 @@ use Endroid\QrCode\Response\QrCodeResponse;
class MainController extends AppController {
public static $rpcurl;
protected $rpcurl;
const lbcPriceKey = 'lbc.price';
const txOutSetInfo = 'lbrcrd.tosi';
const bittrexMarketUrl = 'https://bittrex.com/api/v1.1/public/getticker?market=BTC-LBC';
const bittrexMarketUrl = 'https://api.bittrex.com/v3/markets/LBC-BTC/ticker';
const blockchainTickerUrl = 'https://blockchain.info/ticker';
const tagReceiptAddress = 'bLockNgmfvnnnZw7bM6SPz6hk5BVzhevEp';
const blockedListUrl = 'https://api.odysee.com/file/list_blocked';
protected $redis;
public function initialize() {
parent::initialize();
self::$rpcurl = Configure::read('Lbry.RpcUrl');
$this->rpcurl = Configure::read('Lbry.RpcUrl');
$this->redis = new \Predis\Client(Configure::read('Redis.Url'));
try {
$this->redis->info('mem');
@ -69,13 +72,13 @@ class MainController extends AppController {
$btrxjson = json_decode(self::curl_get(self::bittrexMarketUrl));
$blckjson = json_decode(self::curl_get(self::blockchainTickerUrl));
if ($btrxjson->success) {
$onelbc = $btrxjson->result->Bid;
if ($btrxjson) {
$onelbc = $btrxjson->bidRate;
$lbcPrice = 0;
if (isset($blckjson->USD)) {
$lbcPrice = $onelbc * $blckjson->USD->buy;
if ($lbcPrice > 0) {
$priceInfo->price = number_format($lbcPrice, 2, '.', '');
$priceInfo->price = number_format($lbcPrice, 3, '.', '');
$priceInfo->time = $now->format('c');
if ($this->redis) {
$this->redis->set(self::lbcPriceKey, json_encode($priceInfo));
@ -96,11 +99,7 @@ class MainController extends AppController {
$lbcUsdPrice = $this->_getLatestPrice();
$this->set('lbcUsdPrice', $lbcUsdPrice);
$blocks = $this->Blocks->find()->select(['chainwork', 'confirmations', 'difficulty', 'hash', 'height', 'transaction_hashes', 'block_time', 'block_size'])->order(['height' => 'desc'])->limit(6)->toArray();
for ($i = 0; $i < count($blocks); $i++) {
$tx_hashes = preg_split('#,#', $blocks[$i]->transaction_hashes);
$blocks[$i]->transaction_count = count($tx_hashes);
}
$blocks = $this->Blocks->find()->select(['chainwork', 'confirmations', 'difficulty', 'hash', 'height', 'block_time', 'block_size','tx_count'])->order(['height' => 'desc'])->limit(6)->toArray();
// hash rate
$hashRate = $this->_formatHashRate($this->_gethashrate());
@ -132,9 +131,13 @@ class MainController extends AppController {
$page = intval($this->request->query('page'));
$conn = ConnectionManager::get('default');
$stmt = $conn->execute('SELECT COUNT(id) AS Total FROM claim');
$count = $stmt->fetch(\PDO::FETCH_OBJ);
$numClaims = $count->Total;
// $stmt = $conn->execute('SELECT COUNT(id) AS Total FROM claim');
// $count = $stmt->fetch(\PDO::FETCH_OBJ);
$numClaims = 20000000;
$stmt = $conn->execute('SELECT MAX(id) AS MaxId FROM claim');
$res = $stmt->fetch(\PDO::FETCH_OBJ);
$maxClaimId = $res->MaxId;
$numPages = ceil($numClaims / $pageLimit);
if ($page < 1) {
@ -144,14 +147,24 @@ class MainController extends AppController {
$page = $numPages;
}
$offset = ($page - 1) * $pageLimit;
$claims = $this->Claims->find()->select($this->Claims)->select(['publisher' => 'C.name'])->leftJoin(['C' => 'claim'], ['C.claim_id = Claims.publisher_id'])->order(['Claims.created_at' => 'DESC'])->offset($offset)->limit($pageLimit)->toArray();
$startLimitId = $maxClaimId - ($page * $pageLimit);
$endLimitId = $startLimitId + $pageLimit;
if ($endLimitId > $maxClaimId) {
$endLimitId = $maxClaimId;
}
$blockedList = json_decode($this->_getBlockedList());
$claims = $this->Claims->find()->select($this->Claims)->
select(['publisher' => 'C.name', 'publisher_transaction_hash_id' => 'C.transaction_hash_id', 'publisher_vout' => 'C.vout'])->
leftJoin(['C' => 'claim'], ['C.claim_id = Claims.publisher_id'])->
where(['Claims.id >' => $startLimitId, 'Claims.id <=' => $endLimitId])->
order(['Claims.id' => 'DESC'])->toArray();
for ($i = 0; $i < count($claims); $i++) {
if ($canConvert && $claims[$i]->fee > 0 && $claims[$i]->fee_currency == 'USD') {
$claims[$i]->price = $claims[$i]->fee / $priceInfo->price;
}
if (isset($claims[$i]->Stream)) {
$json = json_decode($claims[$i]->Stream->Stream);
if (isset($json->metadata->license)) {
@ -161,6 +174,17 @@ class MainController extends AppController {
$claims[$i]->LicenseUrl = $json->metadata->licenseUrl;
}
}
$claimChannel = null;
if ($claims[$i]->publisher_transaction_hash_id) {
$claimChannel = new \stdClass();
$claimChannel->transaction_hash_id = $claims[$i]->publisher_transaction_hash_id;
$claimChannel->vout = $claims[$i]->publisher_vout;
}
$blocked = $this->_isClaimBlocked($claims[$i], $claimChannel, $blockedList);
$claims[$i]->isBlocked = $blocked;
$claims[$i]->thumbnail_url = $blocked ? null : $claims[$i]->thumbnail_url; // don't show the thumbnails too
}
$this->set('pageLimit', $pageLimit);
@ -191,7 +215,15 @@ class MainController extends AppController {
$moreClaims = [];
if (isset($claim->publisher) || $claim->claim_type == 1) {
// find more claims for the publisher
$moreClaims = $this->Claims->find()->select($this->Claims)->select(['publisher' => 'C.name'])->leftJoin(['C' => 'claim'], ['C.claim_id = Claims.publisher_id'])->where(['Claims.claim_type' => 1, 'Claims.id <>' => $claim->id, 'Claims.publisher_id' => isset($claim->publisher) ? $claim->publisher_id : $claim->claim_id])->limit(9)->order(['Claims.fee' => 'DESC', 'RAND()' => 'DESC'])->toArray();
$moreClaimsQuery = $this->Claims->find()->select([
'claim_id', 'bid_state', 'fee', 'fee_currency', 'is_nsfw', 'claim_type', 'name',
'title', 'description', 'content_type', 'language', 'author', 'license', 'content_type',
'created_at'
])->select(['publisher' => 'C.name'])->leftJoin(['C' => 'claim'], ['C.claim_id = Claims.publisher_id'])->where(['Claims.claim_type' => 1, 'Claims.id <>' => $claim->id, 'Claims.publisher_id' => isset($claim->publisher) ? $claim->publisher_id : $claim->claim_id])->limit(9);
if (isset($claim->publisher) && $claim->publisher_id !== 'f2cf43b86b9d70175dc22dbb9ff7806241d90780') { // prevent ORDER BY for this particular claim
$moreClaimsQuery = $moreClaimsQuery->order(['Claims.fee' => 'DESC', 'RAND()' => 'DESC']);
$moreClaims = $moreClaimsQuery->toArray();
}
for ($i = 0; $i < count($moreClaims); $i++) {
if ($canConvert && $moreClaims[$i]->fee > 0 && $moreClaims[$i]->fee_currency == 'USD') {
$moreClaims[$i]->price = $moreClaims[$i]->fee / $priceInfo->price;
@ -208,8 +240,15 @@ class MainController extends AppController {
}
}
}
// fetch blocked list
$blockedList = json_decode($this->_getBlockedList());
$claimChannel = $this->Claims->find()->select(['transaction_hash_id', 'vout'])->where(['claim_id' => $claim->publisher_id])->first();
$claimIsBlocked = $this->_isClaimBlocked($claim, $claimChannel, $blockedList);
$this->set('claim', $claim);
$this->set('moreClaims', $moreClaims);
$this->set('claimIsBlocked', $claimIsBlocked);
$this->set('moreClaims', $claimIsBlocked ? [] : $moreClaims);
}
}
@ -219,14 +258,10 @@ class MainController extends AppController {
$this->loadModel('Outputs');
// load 10 blocks and transactions
$blocks = $this->Blocks->find()->select(['height', 'block_time', 'transaction_hashes'])->order(['height' => 'desc'])->limit(10)->toArray();
for ($i = 0; $i < count($blocks); $i++) {
$tx_hashes = preg_split('#,#', $blocks[$i]->transaction_hashes);
$blocks[$i]->transaction_count = count($tx_hashes);
}
$blocks = $this->Blocks->find()->select(['height', 'block_time', 'tx_count'])->order(['height' => 'desc'])->limit(10)->toArray();
$transactions = $this->Transactions->find()->select(['Transactions.id', 'Transactions.hash', 'Transactions.value', 'Transactions.input_count', 'Transactions.output_count', 'Transactions.transaction_time', 'Transactions.created_at'])->order(['Transactions.created_at' => 'desc'])->limit(10)->toArray();
$this->set('blocks', $blocks);
$this->set('txs', $transactions);
}
@ -292,7 +327,7 @@ class MainController extends AppController {
$page = intval($this->request->query('page'));
$conn = ConnectionManager::get('default');
$stmt = $conn->execute('SELECT COUNT(id) AS Total FROM block');
$stmt = $conn->execute('SELECT height AS Total FROM block order by id desc limit 1');
$count = $stmt->fetch(\PDO::FETCH_OBJ);
$numBlocks = $count->Total;
@ -307,7 +342,7 @@ class MainController extends AppController {
$offset = ($page - 1) * $pageLimit;
$currentBlock = $this->Blocks->find()->select(['height'])->order(['height' => 'DESC'])->first();
$blocks = $this->Blocks->find()->select(
['height', 'difficulty', 'transaction_hashes', 'block_size', 'nonce', 'block_time']
['height', 'difficulty', 'block_size', 'nonce', 'block_time','tx_count']
)->offset($offset)->limit($pageLimit)->order(['height' => 'DESC'])->toArray();
$this->set('currentBlock', $currentBlock);
$this->set('blocks', $blocks);
@ -359,21 +394,21 @@ class MainController extends AppController {
else {
$last_block = $this->Blocks->find()->select(['height'])->order(['height' => 'desc'])->first();
$confirmations = $last_block->height - $block->height + 1;
}
}
$inputs = $this->Inputs->find()->where(['transaction_id' => $tx->id])->order(['prevout_n' => 'asc'])->toArray();
foreach($inputs as $input) {
$inputAddresses = $this->Addresses->find()->select(['id', 'address'])->where(['id' => $input->input_address_id])->toArray();
$input->input_addresses = $inputAddresses;
}
$outputs = $this->Outputs->find()->select($this->Outputs)->select(['spend_input_hash' => 'I.transaction_hash', 'spend_input_id' => 'I.id'])->where(['Outputs.transaction_id' => $tx->id])->leftJoin(['I' => 'input'], ['I.id = Outputs.spent_by_input_id'])->order(['Outputs.vout' => 'asc'])->toArray();
for ($i = 0; $i < count($outputs); $i++) {
for ($i = 0; $i < count($outputs); $i++) {
$outputs[$i]->IsClaim = (strpos($outputs[$i]->script_pub_key_asm, 'CLAIM') > -1);
$outputs[$i]->IsSupportClaim = (strpos($outputs[$i]->script_pub_key_asm, 'SUPPORT_CLAIM') > -1);
$outputs[$i]->IsUpdateClaim = (strpos($outputs[$i]->script_pub_key_asm, 'UPDATE_CLAIM') > -1);
$claim = $this->Claims->find()->select(['id', 'claim_id', 'claim_address', 'vout', 'transaction_hash_id'])->where(['transaction_hash_id' => $tx->hash, 'vout' => $outputs[$i]->vout])->first();
$outputs[$i]->Claim = $claim;
$output_address = trim($outputs[$i]->address_list, '[""]');
if(!$output_address && $claim) {
$output_address = $claim->claim_address;
@ -416,7 +451,7 @@ class MainController extends AppController {
}
}
$lbryAddresses = ['rFLUohPG4tP3gZHYoyhvADCtrDMiaYb7Qd', 'r9PGXsejVJb9ZfMf3QVdDEJCzxkd9JLxzL', 'r9srwX7DEN7Mex3a8oR1mKSqQmLBizoJvi', 'bRo4FEeqqxY7nWFANsZsuKEWByEgkvz8Qt', 'bU2XUzckfpdEuQNemKvhPT1gexQ3GG3SC2', 'bay3VA6YTQBL4WLobbG7CthmoGeUKXuXkD', 'bLPbiXBp6Vr3NSnsHzDsLNzoy5o36re9Cz', 'bVUrbCK8hcZ5XWti7b9eNxKEBxzc1rr393', 'bZja2VyhAC84a9hMwT8dwTU6rDRXowrjxH', 'bMgqQqYfwzWWYBk5o5dBMXtCndVAoeqy6h', 'bMvUBo1h5WS46ThHtmfmXftz3z33VHL7wc'];
$lbryAddresses = ['rEqocTgdPdoD8NEbrECTUPfpquJ4zPVCJ8', 'rKaAUDxr24hHNNTQuNtRvNt8SGYJMdLXo3', 'r7hj61jdbGXcsccxw8UmEFCReZoCWLRr7t', 'bRo4FEeqqxY7nWFANsZsuKEWByEgkvz8Qt', 'bU2XUzckfpdEuQNemKvhPT1gexQ3GG3SC2', 'bay3VA6YTQBL4WLobbG7CthmoGeUKXuXkD', 'bLPbiXBp6Vr3NSnsHzDsLNzoy5o36re9Cz', 'bVUrbCK8hcZ5XWti7b9eNxKEBxzc1rr393', 'bZja2VyhAC84a9hMwT8dwTU6rDRXowrjxH', 'bMgqQqYfwzWWYBk5o5dBMXtCndVAoeqy6h', 'bMvUBo1h5WS46ThHtmfmXftz3z33VHL7wc', 'bX6napXtY2nVTBRc8PwULBuGWn2i3SCtrN', 'bG1fEEqDVepDy3AbvM8outQ3FQUu76aDot'];
$totalBalance = 0;
$maxBalance = 0;
$minBalance = 0;
@ -477,7 +512,7 @@ class MainController extends AppController {
$canTag = true;
$transactionAddresses = $this->TransactionAddresses->find()->where(['address_id' => $address->id])->toArray();
$numTransactions = count($transactionAddresses);
$all = $this->request->query('all');
if ($all === 'true') {
$offset = 0;
@ -495,7 +530,7 @@ class MainController extends AppController {
$offset = ($page - 1) * $pageLimit;
}
$stmt = $conn->execute(sprintf(
'SELECT T.id, T.hash, T.input_count, T.output_count, T.block_hash_id, ' .
' TA.debit_amount, TA.credit_amount, ' .
@ -552,7 +587,7 @@ class MainController extends AppController {
echo $qrCode->writeString();
exit(0);
}
public function apiblocksize($timePeriod = '24h') {
$this->autoRender = false;
@ -587,7 +622,7 @@ class MainController extends AppController {
$resultSet[$price->TimePeriod]['AvgUSD'] = (float) $price->AvgUSD;
}
*/
$conn = ConnectionManager::get('default');
// get avg block sizes for the time period
$stmt = $conn->execute("SELECT AVG(block_size) AS AvgBlockSize, DATE_FORMAT(FROM_UNIXTIME(block_time), '$sqlDateFormat') AS TimePeriod " .
@ -602,21 +637,16 @@ class MainController extends AppController {
return $this->_jsonResponse(['success' => true, 'data' => $resultSet]);
}
public function apirealtimeblocks() {
// Load 10 blocks
$this->autoRender = false;
$this->loadModel('Blocks');
$blocks = $this->Blocks->find()->select(['Height' => 'height', 'BlockTime' => 'block_time', 'transaction_hashes'])->order(['Height' => 'desc'])->limit(10)->toArray();
for ($i = 0; $i < count($blocks); $i++) {
$tx_hashes = preg_split('#,#', $blocks[$i]->transaction_hashes);
$blocks[$i]->TransactionCount = count($tx_hashes);
unset($blocks[$i]->transaction_hashes);
}
$blocks = $this->Blocks->find()->select(['Height' => 'height', 'BlockTime' => 'block_time', 'TransactionCount'=>'tx_count'])->order(['Height' => 'desc'])->limit(10)->toArray();
$this->_jsonResponse(['success' => true, 'blocks' => $blocks]);
}
public function apirealtimetx() {
// Load 10 transactions
$this->autoRender = false;
@ -625,8 +655,8 @@ class MainController extends AppController {
$this->_jsonResponse(['success' => true, 'txs' => $txs]);
}
protected function _gettxoutsetinfo() {
/*protected function _gettxoutsetinfo() {
$now = new \DateTime('now', new \DateTimeZone('UTC'));
$txOutSetInfo = new \stdClass();
$txOutSetInfo->time = $now->format('c');
@ -649,7 +679,6 @@ class MainController extends AppController {
}
if ($shouldRefreshSet) {
$req = ['method' => 'gettxoutsetinfo', 'params' => []];
try {
$res = json_decode(self::curl_json_post(self::$rpcurl, json_encode($req)));
@ -667,7 +696,7 @@ class MainController extends AppController {
}
return (isset($txOutSetInfo->tosi)) ? $txOutSetInfo->tosi : 'N/A';
}
}*/
public function apistatus() {
$this->autoRender = false;
@ -695,12 +724,9 @@ class MainController extends AppController {
public function apirecentblocks() {
$this->autoRender = false;
$this->loadModel('Blocks');
$blocks = $this->Blocks->find()->select(['Difficulty' => 'difficulty', 'Hash' => 'hash', 'Height' => 'height', 'transaction_hashes', 'BlockTime' => 'block_time', 'BlockSize' => 'block_size'])->order(['Height' => 'desc'])->limit(6)->toArray();
$blocks = $this->Blocks->find()->select(['Difficulty' => 'difficulty', 'Hash' => 'hash', 'Height' => 'height', 'BlockTime' => 'block_time', 'BlockSize' => 'block_size', 'TransactionCount' => 'tx_count'])->order(['Height' => 'desc'])->limit(6)->toArray();
for ($i = 0; $i < count($blocks); $i++) {
$tx_hashes = preg_split('#,#', $blocks[$i]->transaction_hashes);
$blocks[$i]->TransactionCount = count($tx_hashes);
$blocks[$i]->Difficulty = number_format($blocks[$i]->Difficulty, 2, '.', '');
unset($blocks[$i]->transaction_hashes);
}
return $this->_jsonResponse(['success' => true, 'blocks' => $blocks]);
}
@ -775,12 +801,12 @@ class MainController extends AppController {
if (!isset($base58address)) {
return $this->_jsonError('Base58 address not specified.', 400);
}
$address = $this->Addresses->find()->select(['id', 'balance'])->where(['address' => $base58address])->first();
if (!$address) {
return $this->_jsonError('Could not find address.', 400);
}
return $this->_jsonResponse(['success' => true, ['balance' => ['confirmed' => $address->balance, 'unconfirmed' => 0]]]);
}
@ -840,20 +866,30 @@ class MainController extends AppController {
$circulating = 0;
$txoutsetinfo = $this->_gettxoutsetinfo();
$reservedcommunity = ['rFLUohPG4tP3gZHYoyhvADCtrDMiaYb7Qd'];
$reservedoperational = ['r9PGXsejVJb9ZfMf3QVdDEJCzxkd9JLxzL'];
$reservedinstitutional = ['r9srwX7DEN7Mex3a8oR1mKSqQmLBizoJvi'];
$reservedaux = ['bRo4FEeqqxY7nWFANsZsuKEWByEgkvz8Qt', 'bU2XUzckfpdEuQNemKvhPT1gexQ3GG3SC2', 'bay3VA6YTQBL4WLobbG7CthmoGeUKXuXkD', 'bLPbiXBp6Vr3NSnsHzDsLNzoy5o36re9Cz', 'bMvUBo1h5WS46ThHtmfmXftz3z33VHL7wc', 'bVUrbCK8hcZ5XWti7b9eNxKEBxzc1rr393', 'bZja2VyhAC84a9hMwT8dwTU6rDRXowrjxH', 'bCrboXVztuSbZzVToCWSsu1pEr2oxKHu9v', 'bMgqQqYfwzWWYBk5o5dBMXtCndVAoeqy6h'];
$reservedcommunity = ['rEqocTgdPdoD8NEbrECTUPfpquJ4zPVCJ8'];
$reservedoperational = ['r7hj61jdbGXcsccxw8UmEFCReZoCWLRr7t'];
$reservedinstitutional = ['rKaAUDxr24hHNNTQuNtRvNt8SGYJMdLXo3'];
$reservedaux = [
'bRo4FEeqqxY7nWFANsZsuKEWByEgkvz8Qt',
'bU2XUzckfpdEuQNemKvhPT1gexQ3GG3SC2',
'bay3VA6YTQBL4WLobbG7CthmoGeUKXuXkD',
'bLPbiXBp6Vr3NSnsHzDsLNzoy5o36re9Cz',
'bMvUBo1h5WS46ThHtmfmXftz3z33VHL7wc',
'bVUrbCK8hcZ5XWti7b9eNxKEBxzc1rr393',
'bZja2VyhAC84a9hMwT8dwTU6rDRXowrjxH',
'bCrboXVztuSbZzVToCWSsu1pEr2oxKHu9v',
'bMgqQqYfwzWWYBk5o5dBMXtCndVAoeqy6h',
'bX6napXtY2nVTBRc8PwULBuGWn2i3SCtrN'
];
$allAddresses = array_merge($reservedcommunity, $reservedoperational, $reservedinstitutional, $reservedaux);
$reservedtotal = $this->Addresses->find()->select(['id', 'balance' => 'SUM(balance)'])->where(['Addresses.address IN' => $allAddresses])->first();
$circulating = $txoutsetinfo->total_amount - ($reservedtotal->balance);
$reservedtotal = $this->Addresses->find()->select(['balance' => 'SUM(balance)'])->where(['Addresses.address IN' => $allAddresses])->first();
return $this->_jsonResponse(['success' => true, 'utxosupply' => ['total' => $txoutsetinfo->total_amount, 'circulating' => $circulating]]);
$circulating = (isset($txoutsetinfo) ? $txoutsetinfo->total_amount : 0) - ($reservedtotal->balance);
return $this->_jsonResponse(['success' => true, 'utxosupply' => ['total' => isset($txoutsetinfo) ? $txoutsetinfo->total_amount : 0, 'circulating' => $circulating]]);
}
protected function _formatHashRate($value) {
if ($value === 'N/A') {
return $value;
@ -900,7 +936,7 @@ class MainController extends AppController {
private function _gethashrate() {
$req = ['method' => 'getnetworkhashps', 'params' => []];
try {
$res = json_decode(self::curl_json_post(self::$rpcurl, json_encode($req)));
$res = json_decode(self::curl_json_post($this->rpcurl, json_encode($req)));
if (!isset($res->result)) {
return 0;
}
@ -910,19 +946,6 @@ class MainController extends AppController {
}
}
// private function _gettxoutsetinfo() {
// $req = ['method' => 'gettxoutsetinfo', 'params' => []];
// try {
// $res = json_decode(self::curl_json_post(self::$rpcurl, json_encode($req)));
// if (!isset($res->result)) {
// return 0;
// }
// return $res->result;
// } catch (\Exception $e) {
// return 'N/A';
// }
// }
private static function curl_json_post($url, $data, $headers = []) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
@ -945,4 +968,67 @@ class MainController extends AppController {
// Close any open file handle
return $response;
}
private function _isClaimBlocked($claim, $claimChannel, $blockedList) {
if (!$blockedList || !isset($blockedList->data)) {
// invalid blockedList response
return false;
}
$blockedOutpoints = $blockedList->data->outpoints;
$claimIsBlocked = false;
foreach ($blockedOutpoints as $outpoint) {
// $parts[0] = txid
// $parts[1] = vout
$parts = explode(':', $outpoint);
if ($claim->transaction_hash_id == $parts[0] && $claim->vout == $parts[1]) {
$claimIsBlocked = true;
break;
}
// check if the publisher (channel) is blocked
// block the channel if that's the case
if ($claimChannel && $claimChannel->transaction_hash_id == $parts[0] && $claimChannel->vout == $parts[1]) {
$claimIsBlocked = true;
break;
}
}
return $claimIsBlocked;
}
private function _gettxoutsetinfo() {
$cachedOutsetInfo = Cache::read('gettxoutsetinfo', 'api_requests');
if ($cachedOutsetInfo !== false) {
$res = json_decode($cachedOutsetInfo);
if (isset($res->result)) {
return $res->result;
}
}
$req = ['method' => 'gettxoutsetinfo', 'params' => []];
try {
$response = self::curl_json_post($this->rpcurl, json_encode($req));
$res = json_decode($response);
if (!isset($res->result)) {
return null;
}
Cache::write('gettxoutsetinfo', $response, 'api_requests');
return $res->result;
} catch (\Exception $e) {
return null;
}
}
private function _getBlockedList() {
$cachedList = Cache::read('list_blocked', 'api_requests');
if ($cachedList !== false) {
return $cachedList;
}
// get the result from the api
$response = self::curl_get(self::blockedListUrl);
Cache::write('list_blocked', $response, 'api_requests');
return $response;
}
}

View file

@ -13,7 +13,7 @@ class AuxShell extends Shell {
public static $rpcurl;
const bittrex = 'https://bittrex.com/api/v1.1/public/getticker?market=BTC-LBC';
const bittrex = 'https://api.bittrex.com/v3/markets/LBC-BTC/ticker';
const blockchainticker = 'https://blockchain.info/ticker';
@ -150,13 +150,13 @@ class AuxShell extends Shell {
$btrxjson = json_decode(self::curl_get(self::bittrex));
$blckjson = json_decode(self::curl_get(self::blockchainticker));
if ($btrxjson->success) {
$btc = $btrxjson->result->Bid;
if ($btrxjson) {
$btc = $btrxjson->bidRate;
$usd = 0;
if (isset($blckjson->USD)) {
$usd = $btc * $blckjson->USD->buy;
$priceInfo = new \stdClass();
$priceInfo->price = number_format($usd, 2, '.', '');
$priceInfo->price = number_format($usd, 3, '.', '');
$priceInfo->time = $now->format('c');
if ($redis) {
$redis->set(self::lbcpricekey, json_encode($priceInfo));

View file

@ -29,12 +29,20 @@ $ctTag = $claim->getContentTag();
<div data-autothumb="<?php echo $autoThumbText ?>" class="thumbnail <?php echo $a[mt_rand(0, count($a) - 1)] ?>">
<?php if (!$claim->is_nsfw && strlen(trim($claim->thumbnail_url)) > 0): ?>
<img src="<?php echo htmlspecialchars($claim->thumbnail_url) ?>" alt="" />
<img src="<?php echo htmlspecialchars('https://thumbnails.odycdn.com/optimize/s:1280:720/quality:85/plain/'.$claim->thumbnail_url) ?>" alt="" />
<?php else: ?>
<div class="autothumb"><?php echo $autoThumbText ?></div>
<?php endif; ?>
</div>
<?php if ($claim->isBlocked): ?>
<div class="blocked-info">
In response to a complaint we received under the US Digital Millennium Copyright Act, we have blocked access to this content from our applications. For more information, please refer to <a href="https://lbry.com/faq/dmca" target="_blank">DMCA takedown requests</a>
</div>
<?php else: ?>
<div class="metadata">
<div class="title" title="<?php echo $claim->claim_type == 1 ? $claim->name : ((strlen(trim($claim->title)) > 0) ? $claim->title : '') ?>"><?php echo $claim->claim_type == 1 ? $claim->name : ((strlen(trim($claim->title)) > 0) ? $claim->title : '<em>No Title</em>') ?></div>
<div class="link" title="<?php echo $claim->getLbryLink() ?>"><a href="<?php echo $claim->getLbryLink() ?>" rel="nofollow"><?php echo $claim->getLbryLink() ?></a></div>
@ -61,10 +69,10 @@ $ctTag = $claim->getContentTag();
<!--<div class="label half-width">Author</div>
<div class="label half-width">License</div>-->
<!--<div class="value half-width" title="<?php echo strlen(trim($claim->author)) > 0 ? $claim->author : '<em>Unspecified</em>' ?>"><?php echo strlen(trim($claim->author)) > 0 ? $claim->author : '<em>Unspecified</em>' ?></div>
<div class="value half-width" title="<?php echo strlen(trim($claim->license)) > 0 ? $claim->license : '' ?>">
<?php if (strlen(trim($claim->LicenseUrl)) > 0): ?><a href="<?php echo $claim->LicenseUrl ?>" rel="nofollow" target="_blank"><?php endif; ?>
<?php echo strlen(trim($claim->License)) > 0 ? $claim->License : '<em>Unspecified</em>' ?>
@ -73,4 +81,5 @@ $ctTag = $claim->getContentTag();
-->
<?php endif; ?>
</div>
</div>
<?php endif; ?>
</div>

View file

@ -17,7 +17,7 @@
<script>try{Typekit.load({ async: true });}catch(e){}</script>
<!-- Analytics -->
<?php if ($_SERVER['HTTP_HOST'] === 'explorer.lbry.io'): ?>
<?php if ($_SERVER['HTTP_HOST'] === 'explorer.lbry.com'): ?>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="//www.googletagmanager.com/gtag/js?id=UA-60403362-1"></script>
<script>
@ -57,7 +57,7 @@
<?php echo $this->fetch('content') ?>
<footer>
<div class="content">
<a href="https://lbry.io">LBRY</a>
<a href="https://lbry.com">LBRY</a>
<div class="page-time">Page took <?php echo round((microtime(true) - TIME_START) * 1000, 0) ?>ms</div>
</div>

View file

@ -76,7 +76,7 @@
<div class="label">NameClaimRoot</div> <div class="value"><?php echo $block->name_claim_root ?></div>
<!--
<!--
<div class="spacer"></div>
<div class="label">Target</div> <div class="value"><?php echo $block->Target ?></div>
@ -184,7 +184,7 @@
<td class="right"><a href="/blocks/<?php echo $block->height ?>"><?php echo $block->height ?></a></td>
<td class="pad-left"><?php echo number_format($block->difficulty, 8, '.', '') ?></td>
<td class="right"><?php echo number_format((($currentBlock->height - $block->height) + 1), 0, '', ',') ?></td>
<td class="right"><?php echo count(preg_split('#,#', $block->transaction_hashes)) ?></td>
<td class="right"><?php echo $block->tx_count ?></td>
<td class="right"><?php echo round($block->block_size / 1024, 2) . 'KB' ?></td>
<td class="right pad-left"><?php echo $block->nonce ?></td>
<td class="pad-left"><?php echo \DateTime::createFromFormat('U', $block->block_time)->format('d M Y H:i:s') ?> UTC</td>
@ -195,4 +195,4 @@
</div>
<?php echo $this->element('pagination') ?>
<?php endif; ?>
<?php endif; ?>

View file

@ -65,10 +65,19 @@ if (strlen(trim($desc)) == 0) {
</div>
<div class="claims-body">
<?php if ($claimIsBlocked): ?>
<div class="blocked-claim-info">
<div class="content">
In response to a complaint we received under the US Digital Millennium Copyright Act, we have blocked access to this content from our applications. For more information, please refer to <a href="https://lbry.com/faq/dmca" target="_blank">DMCA takedown requests</a>.
</div>
</div>
<?php else: ?>
<div class="claim-info">
<div data-autothumb="<?php echo $autoThumbText ?>" class="thumbnail <?php echo $a[mt_rand(0, count($a) - 1)] ?>">
<?php if (!$claim->is_nsfw && strlen(trim($claim->thumbnail_url)) > 0): ?>
<img src="<?php echo htmlspecialchars($claim->thumbnail_url) ?>" alt="" />
<img src="<?php echo htmlspecialchars('https://thumbnails.odycdn.com/optimize/s:1280:720/quality:85/plain/'.$claim->thumbnail_url) ?>" alt="" />
<?php else: ?>
<div class="autothumb"><?php echo $autoThumbText ?></div>
<?php endif; ?>
@ -127,9 +136,7 @@ if (strlen(trim($desc)) == 0) {
<!--
<div class="value half-width"<?php if(strlen(trim($claim->license)) > 0): ?> title="<?php echo $claim->license ?>"<?php endif; ?>>
<?php if (strlen(trim($claim->license_url)) > 0): ?><a href="<?php echo $claim->LicenseUrl ?>" rel="nofollow" target="_blank"><?php endif; ?>
<?php echo strlen(trim($claim->License)) > 0 ? $claim->License : '<em>Unspecified</em>' ?>
<?php if (strlen(trim($claim->LicenseUrl))): ?></a><?php endif; ?>
</div>
-->
<div class="value half-width"><?php echo strlen(trim($claim->language)) > 0 ? ($claim->language == 'en' ? 'English' : '') : '<em>Unspecified</em>' ?></div>
@ -140,6 +147,7 @@ if (strlen(trim($desc)) == 0) {
<div class="clear"></div>
<?php endif; ?>
<?php if (count($moreClaims) > 0): ?>
@ -155,7 +163,7 @@ if (strlen(trim($desc)) == 0) {
$row++;
}
echo $this->element('claimbox', array('claim' => $claim, 'idx' => $idx, 'last_row' => $last_row));
$idx++;
$idx++;
endforeach; ?>
<div class="clear"></div>
</div>

View file

@ -171,7 +171,7 @@
<td><a href="/blocks/<?php echo $block->height ?>"><?php echo $block->height ?></a></td>
<td><?php echo \Carbon\Carbon::createFromTimestamp($block->block_time)->diffForHumans(); ?></td>
<td class="right"><?php echo round($block->block_size / 1024, 2) . 'KB' ?></td>
<td class="right"><?php echo $block->transaction_count ?></td>
<td class="right"><?php echo $block->tx_count ?></td>
<td class="right"><?php echo number_format($block->difficulty, 2, '.', '') ?></td>
<td class="last-cell"><?php echo DateTime::createFromFormat('U', $block->block_time)->format('d M Y H:i:s') . ' UTC' ?></td>
</tr>
@ -183,7 +183,7 @@
<div class="recent-claims">
<h3>Recent Claims</h3>
<a class="claim-explorer-link" href="/claims">Claims Explorer</a>
<?php $idx = 0; $a = ['purple', 'orange', 'blue', 'teal', 'green', 'yellow'];
<?php $idx = 0; $a = ['purple', 'orange', 'blue', 'teal', 'green', 'yellow'];
foreach ($recentClaims as $claim):
$idx++;
$autoThumbText = $claim->getAutoThumbText();
@ -203,7 +203,7 @@
<div data-autothumb="<?php echo $autoThumbText ?>" class="thumbnail <?php echo $a[mt_rand(0, count($a) - 1)] ?>">
<?php if (!$claim->is_nsfw && strlen(trim($claim->thumbnail_url)) > 0): ?>
<img src="<?php echo strip_tags($claim->thumbnail_url) ?>" alt="" />
<img src="<?php echo strip_tags('https://thumbnails.odycdn.com/optimize/s:1280:720/quality:85/plain/'.$claim->thumbnail_url) ?>" alt="" />
<?php else: ?>
<div class="autothumb"><?php echo $autoThumbText ?></div>
<?php endif; ?>

View file

@ -131,7 +131,7 @@
<tr data-height="<?php echo $block->height ?>" data-time="<?php echo $block->block_time ?>">
<td><a href="/blocks/<?php echo $block->height ?>" target="_blank"><?php echo $block->height ?></a></td>
<td><?php echo \Carbon\Carbon::createFromTimestamp($block->block_time)->diffForHumans(); ?></td>
<td class="right"><?php echo $block->transaction_count ?></td>
<td class="right"><?php echo $block->tx_count ?></td>
</tr>
<?php endforeach; ?>
</tbody>

View file

@ -83,6 +83,7 @@ border-radius: 0 8px 8px 0 }
.claims-grid .claim-grid-item .tags .nsfw { background: #e53935; text-align: center; color: #fff; position: relative; left: 1px }
.claims-grid .claim-grid-item .tags .bid-state { background: #551CA1; text-align: center; color: #fff; }
.claims-grid .claim-grid-item .tags .content-type { background: #880e4f; text-align: center; color: #fff; }
.claims-grid .claim-grid-item .blocked-info { padding: 24px; font-size: 90%; }
.claims-grid .claim-grid-item .metadata { padding: 24px; font-size: 90% }
.claims-grid .claim-grid-item .title { font-size: 120%; height: 25px; line-height: 25px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
.claims-grid .claim-grid-item .desc { font-size: 90%; font-weight: 300; height: 72px; overflow: hidden; text-overflow: ellipsis; margin: 8px 0 20px 0; line-height: 24px }
@ -95,6 +96,8 @@ border-radius: 0 8px 8px 0 }
.claims-grid .claim-grid-item .spacer { height: 16px }
.claims-body { width: 1200px; margin: 0 auto 0 auto; cursor: default }
.claims-body .blocked-claim-info { border: 1px solid rgba(0,0,0,.15); cursor: default }
.claims-body .blocked-claim-info .content { padding: 48px }
.claims-body .claim-info { width: 400px; float: left; /*box-shadow: 0 2px 4px rgba(0,0,0,.175);*/ border: 1px solid rgba(0,0,0,.15); cursor: default }
.claims-body .claim-info .thumbnail { width: 100%; height: 220px; background: #f0f0f0; display: block; position: relative; overflow: hidden }
.claims-body .claim-info .thumbnail img { width: 100% }

View file

@ -38,7 +38,7 @@ function buildChartData(claimsData) {
}
function loadChartData() {
var api_url = "https://chainquery.lbry.io/api/sql?query=";
var api_url = "https://chainquery.odysee.tv/api/sql?query=";
var query = "SELECT c1.claim_type, c1.bid_state, c1.effective_amount, c1.transaction_time, o.transaction_time AS 'spent_time' FROM claim c1 LEFT JOIN (SELECT output.claim_id, tx.transaction_time FROM output INNER JOIN input ON input.prevout_hash = output.transaction_hash AND input.prevout_n = output.vout INNER JOIN transaction tx ON tx.id = input.transaction_id) o ON o.claim_id=c1.claim_id AND c1.bid_state='Spent' ORDER BY c1.transaction_time ASC";
var url = api_url + query;
var loadProgress = $('.bids-chart-container .load-progress');
@ -167,4 +167,4 @@ divId: 'chart-export'
}
});
loadChartData();
});
});

View file

@ -97,7 +97,7 @@ function buildChartData(blockData) {
}
function loadChartData() {
var api_url = "https://chainquery.lbry.io/api/sql?query=";
var api_url = "https://chainquery.odysee.tv/api/sql?query=";
var query = "SELECT height, block_time FROM block WHERE confirmations > 0 ORDER BY height";
var url = api_url + query;
var loadProgress = $('.mining-inflation-chart-container .load-progress');
@ -261,4 +261,4 @@ divId: 'chart-export'
}
});
loadChartData();
});
});