Compare commits
122 commits
imgsrc-fix
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
4065389798 | ||
|
a252dc05e6 | ||
|
e8c58e8c15 | ||
|
e8e9346a70 | ||
|
fdecf39f93 | ||
|
d3cd0e13f6 | ||
|
f769cac5da | ||
|
9b554eec1b | ||
|
07d9521cfe | ||
|
820f20a479 | ||
|
0c84ba3fae | ||
|
e74d5b7b2d | ||
|
fc0abe8d33 | ||
|
7e9851ccfc | ||
|
d7fb718dd0 | ||
|
6f4fa32078 | ||
|
8873373465 | ||
|
a73d65b1c2 | ||
|
bb595d0027 | ||
|
52d13987e5 | ||
|
57219734c3 | ||
|
a7c1b9b346 | ||
|
77ca91757b | ||
|
a147665e96 | ||
|
0f197fc571 | ||
|
31d515e992 | ||
|
02551e98d7 | ||
|
007cf0d34c | ||
|
c18431394c | ||
|
04cbdbcaee | ||
|
9b3a1f4097 | ||
|
9582342a3a | ||
|
bbc07e8238 | ||
|
4a7be9d61d | ||
|
6054ddc6c0 | ||
|
a0dac9c35b | ||
|
5c5c7924af | ||
|
b8a685a8dc | ||
|
9f98c64d18 | ||
|
1b13f2711b | ||
|
55a3736233 | ||
|
fd8a6953f3 | ||
|
70069a29ec | ||
|
b96d40241d | ||
|
f3564d7809 | ||
|
2941698c2b | ||
|
0ca160336f | ||
|
e8eaf19490 | ||
|
9e984c94c1 | ||
|
19b35b0685 | ||
|
1ba751acb3 | ||
|
fae8b3e98a | ||
|
07d937d0ef | ||
|
a428ebdd73 | ||
|
262e90a2e1 | ||
|
17b0ef58a9 | ||
|
5064b86fc6 | ||
|
b99285cfa5 | ||
|
d61d9ff015 | ||
|
0d49e4d0c8 | ||
|
80e55f53e2 | ||
|
1edc128b61 | ||
|
8bef4e5cec | ||
|
9d88e2eaec | ||
|
3569fdb4ff | ||
|
4e0eeab3d1 | ||
|
f7318d64fc | ||
|
90eee866fc | ||
|
dfd7af81f9 | ||
|
cbee21c07c | ||
|
a09a0148c2 | ||
|
6c45f432de | ||
|
830df53d74 | ||
|
af39804ce7 | ||
|
fbfd5b8f39 | ||
|
edbc11db7f | ||
|
0bd3836b31 | ||
|
e5d16d0100 | ||
|
3cddd6ece1 | ||
|
e7a030ddf9 | ||
|
9a32c9a930 | ||
|
695f85262b | ||
|
5c681657cb | ||
|
25a50ca2aa | ||
|
b61a1545a7 | ||
|
86a1631144 | ||
|
94682cc4d4 | ||
|
6e8a651980 | ||
|
0df9658b87 | ||
|
5b7c9f7e72 | ||
|
aeceeec732 | ||
|
3884c74e7d | ||
|
3eab838967 | ||
|
e8d3ead2c7 | ||
|
5983c61820 | ||
|
d98e9a3fb2 | ||
|
c7c1e7299f | ||
|
9246952c08 | ||
|
59d23dc2a7 | ||
|
c58676cd69 | ||
|
b9917c89da | ||
|
26a79d8340 | ||
|
f903235c24 | ||
|
d8734c1b8e | ||
|
c13c06f74f | ||
|
ad82fc3975 | ||
|
4d0efbaff8 | ||
|
c8462afdee | ||
|
a8a956f2bc | ||
|
b91b3681d3 | ||
|
190d998e4c | ||
|
667097f35d | ||
|
8d552afe8f | ||
|
ad4615cc5a | ||
|
3ad5db032b | ||
|
e25cd7807e | ||
|
71c7834521 | ||
|
27ff22ff5a | ||
|
70032020f5 | ||
|
c8ca48220f | ||
|
c2a19d91c1 | ||
|
d3e542dd91 |
65 changed files with 4934 additions and 2544 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,7 +1,8 @@
|
|||
/vendor/*
|
||||
/config/app.php
|
||||
/tmp/*
|
||||
/config/lbry.php
|
||||
/logs/*
|
||||
lbryexplorer.zip
|
||||
lbryexplorer.komodoproject
|
||||
.komodotools
|
||||
/.gtm/
|
||||
|
|
|
@ -5,7 +5,6 @@ dist: trusty
|
|||
sudo: false
|
||||
|
||||
php:
|
||||
- 5.6
|
||||
- 7.0
|
||||
- 7.1
|
||||
|
||||
|
|
5
LICENSE
5
LICENSE
|
@ -1,10 +1,9 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2018 LBRY Inc
|
||||
Copyright (c) 2017-2018 LBRY Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish,distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
|
95
README.md
95
README.md
|
@ -0,0 +1,95 @@
|
|||
# LBRY Block Explorer
|
||||
|
||||
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.
|
||||
|
||||
## 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
|
||||
* MariaDB 10.2 or higher
|
||||
* Redis Server (optional, only required for the CakePHP redis cache engine, or to run `forevermempool`)
|
||||
* 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`
|
||||
* Change the working directory to the cloned directory and run composer.
|
||||
```
|
||||
cd block-explorer
|
||||
composer update
|
||||
```
|
||||
* Create the directories, `tmp` and `logs` in the `block-explorer` folder if they have not been created yet, and make sure that they are writable by the web server.
|
||||
* Copy `config/app.default.php` to `config/app.php`. Edit the database connection values to correspond to your environment.
|
||||
* Copy `config/lbry.default.php` to `config/lbry.php`. Update the values for LBRY RPC URL and the Redis URL to correspond to your environment.
|
||||
* Configure your web server with the host root folder set to `<path to>/block-explorer/webroot` where `<path to>` is the absolute path to the configuration. Here is a sample nginx configuration. You can make changes to this configuration to correspond to your environment.
|
||||
```
|
||||
server {
|
||||
listen 80;
|
||||
server_name my.explorer.com;
|
||||
|
||||
root /var/www/block-explorer/webroot;
|
||||
index index.php;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?$args;
|
||||
}
|
||||
|
||||
# pass the PHP scripts to FastCGI server listening on the php-fpm socket
|
||||
location ~ \.php$ {
|
||||
try_files $uri =404;
|
||||
include /etc/nginx/fastcgi_params;
|
||||
fastcgi_pass 127.0.0.1:9000;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_ignore_client_abort on;
|
||||
fastcgi_param PHP_AUTH_USER $remote_user;
|
||||
fastcgi_param PHP_AUTH_PW $http_authorization;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
}
|
||||
}
|
||||
```
|
||||
* Restart your web server.
|
||||
|
||||
|
||||
### Cron jobs
|
||||
There are a few scripts which can be set up as cron jobs or scheduled tasks.
|
||||
|
||||
#### blocks.sh
|
||||
Detect new LBRY blocks. Can also be configured to be triggered using the lbrycrd `blocknotify` flag. This cron will create new blocks obtained from lbrycrd starting from the highest block number in the database, and then create the corresponding block transactions. If there are pending transactions created by the forevermempool script, they will be automatically associated with the respective blocks.
|
||||
|
||||
#### claimindex.sh
|
||||
Create claims found on the LBRY blockchain in the database. This requires the Python decoder to be running in the background.
|
||||
|
||||
#### pricehistory.sh
|
||||
Get the current LBC price in USD and store the value in the `PriceHistory` table. This also caches the most recent price in Redis.
|
||||
|
||||
#### forever.sh
|
||||
Run the `forevermempool` script, and restart if necessary. The `forevermempool` script checks the LBRY blockchain mempool every second and creates transactions found in the database. The script makes use of Redis for caching the pending transaction IDs.
|
||||
|
||||
|
||||
## Usage
|
||||
Launch the URL for the configured web server root in a browser.
|
||||
|
||||
|
||||
## Contributing
|
||||
Contributions to this project are welcome, encouraged, and compensated. For more details, see https://lbry.tech/contribute
|
||||
|
||||
|
||||
## License
|
||||
This project is MIT licensed. For the full license, see [LICENSE](LICENSE).
|
||||
|
||||
|
||||
## Security
|
||||
We take security seriously. Please contact security@lbry.io regarding any security issues. Our PGP key is [here](https://keybase.io/lbry/key.asc) if you need it.
|
||||
|
||||
|
||||
## Contact
|
||||
The primary contact for this project is [@akinwale](https://github.com/akinwale) (akinwale@lbry.com)
|
|
@ -6,14 +6,15 @@
|
|||
"license": "MIT",
|
||||
"require": {
|
||||
"php": ">=5.6",
|
||||
"cakephp/cakephp": "3.4.*",
|
||||
"cakephp/cakephp": "3.7.7",
|
||||
"mobiledetect/mobiledetectlib": "2.*",
|
||||
"cakephp/migrations": "~1.0",
|
||||
"psr/simple-cache": "^1.0.0",
|
||||
"cakephp/plugin-installer": "~1.0",
|
||||
"mdanter/ecc": "^0.4.2",
|
||||
"mdanter/ecc": "^0.5.0",
|
||||
"nesbot/carbon": "~1.18",
|
||||
"endroid/qrcode": "^2.2.2",
|
||||
"predis/predis": "^1.1.1"
|
||||
"predis/predis": "^1.1.1",
|
||||
"endroid/qr-code": "^3.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"psy/psysh": "@stable",
|
||||
|
@ -40,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"
|
||||
|
@ -49,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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
3299
composer.lock
generated
3299
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -218,20 +218,20 @@ return [
|
|||
* See vendor\cakephp\cakephp\src\Database\Driver for complete list
|
||||
*/
|
||||
'Datasources' => [
|
||||
'default' => [
|
||||
'default' => [ // Chainquery database connection
|
||||
'className' => 'Cake\Database\Connection',
|
||||
'driver' => 'Cake\Database\Driver\Mysql',
|
||||
'persistent' => false,
|
||||
'host' => 'localhost',
|
||||
'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
|
||||
* the following line and set the port accordingly
|
||||
*/
|
||||
//'port' => 'non_standard_port_number',
|
||||
'username' => 'my_app',
|
||||
//'port' => '3000',
|
||||
'username' => 'username',
|
||||
'password' => 'secret',
|
||||
'database' => 'my_app',
|
||||
'database' => 'my_db',
|
||||
'encoding' => 'utf8',
|
||||
'timezone' => 'UTC',
|
||||
'flags' => [],
|
||||
|
@ -257,7 +257,28 @@ return [
|
|||
*/
|
||||
//'init' => ['SET GLOBAL innodb_stats_on_metadata = 0'],
|
||||
|
||||
'url' => env('DATABASE_URL', null),
|
||||
'url' => env('DATABASE_URL', 'chainquery.lbry.com:3600'),
|
||||
],
|
||||
|
||||
'localdb' => [ // Local db for price history
|
||||
'className' => 'Cake\Database\Connection',
|
||||
'driver' => 'Cake\Database\Driver\Mysql',
|
||||
'persistent' => false,
|
||||
'host' => 'localhost',
|
||||
/**
|
||||
* CakePHP will use the default DB port based on the driver selected
|
||||
* MySQL on MAMP uses port 8889, MAMP users will want to uncomment
|
||||
* the following line and set the port accordingly
|
||||
*/
|
||||
//'port' => '3306',
|
||||
'username' => 'username',
|
||||
'password' => 'secret',
|
||||
'database' => 'lbry',
|
||||
'encoding' => 'utf8',
|
||||
'timezone' => 'UTC',
|
||||
'flags' => [],
|
||||
'cacheMetadata' => true,
|
||||
'log' => false,
|
||||
],
|
||||
|
||||
/**
|
||||
|
|
|
@ -49,6 +49,7 @@ require __DIR__ . '/paths.php';
|
|||
*/
|
||||
require CORE_PATH . 'config' . DS . 'bootstrap.php';
|
||||
|
||||
use App\Application;
|
||||
use Cake\Cache\Cache;
|
||||
use Cake\Console\ConsoleErrorHandler;
|
||||
use Cake\Core\App;
|
||||
|
@ -60,7 +61,8 @@ use Cake\Datasource\ConnectionManager;
|
|||
use Cake\Error\ErrorHandler;
|
||||
use Cake\Log\Log;
|
||||
use Cake\Mailer\Email;
|
||||
use Cake\Network\Request;
|
||||
use Cake\Mailer\TransportFactory;
|
||||
use Cake\Http\ServerRequest;
|
||||
use Cake\Utility\Inflector;
|
||||
use Cake\Utility\Security;
|
||||
|
||||
|
@ -150,10 +152,12 @@ if (!Configure::read('App.fullBaseUrl')) {
|
|||
|
||||
Cache::setConfig(Configure::consume('Cache'));
|
||||
ConnectionManager::setConfig(Configure::consume('Datasources'));
|
||||
Email::setConfigTransport(Configure::consume('EmailTransport'));
|
||||
//Email::setConfigTransport(Configure::consume('EmailTransport'));
|
||||
TransportFactory::setConfig(Configure::consume('EmailTransport'));
|
||||
Email::setConfig(Configure::consume('Email'));
|
||||
Log::setConfig(Configure::consume('Log'));
|
||||
Security::salt(Configure::consume('Security.salt'));
|
||||
//Security::salt(Configure::consume('Security.salt'));
|
||||
Security::setSalt(Configure::consume('Security.salt'));
|
||||
|
||||
/*
|
||||
* The default crypto extension in 3.0 is OpenSSL.
|
||||
|
@ -165,12 +169,12 @@ Security::salt(Configure::consume('Security.salt'));
|
|||
/*
|
||||
* Setup detectors for mobile and tablet.
|
||||
*/
|
||||
Request::addDetector('mobile', function ($request) {
|
||||
ServerRequest::addDetector('mobile', function ($request) {
|
||||
$detector = new \Detection\MobileDetect();
|
||||
|
||||
return $detector->isMobile();
|
||||
});
|
||||
Request::addDetector('tablet', function ($request) {
|
||||
ServerRequest::addDetector('tablet', function ($request) {
|
||||
$detector = new \Detection\MobileDetect();
|
||||
|
||||
return $detector->isTablet();
|
||||
|
@ -218,5 +222,8 @@ Type::build('timestamp')
|
|||
* Debug Kit should not be installed on a production system
|
||||
*/
|
||||
if (Configure::read('debug')) {
|
||||
Plugin::load('DebugKit', ['bootstrap' => true]);
|
||||
//Plugin::load('DebugKit', ['bootstrap' => true]);
|
||||
Application::addPlugin('DebugKit', ['bootstrap' => true]);
|
||||
}
|
||||
|
||||
Configure::load('lbry', 'default');
|
||||
|
|
11
config/lbry.default.php
Normal file
11
config/lbry.default.php
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'Lbry' => [
|
||||
'RpcUrl' => 'http://user:password@127.0.0.1:9245',
|
||||
],
|
||||
|
||||
'Redis' => [
|
||||
'Url' => 'tcp://127.0.0.1:6379',
|
||||
]
|
||||
];
|
|
@ -72,9 +72,3 @@ Router::scope('/', function (RouteBuilder $routes) {
|
|||
|
||||
//$routes->fallbacks(DashedRoute::class);
|
||||
});
|
||||
|
||||
/**
|
||||
* Load all plugin routes. See the Plugin documentation on
|
||||
* how to customize the loading of plugin routes.
|
||||
*/
|
||||
Plugin::routes();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/sh
|
||||
cd /var/www/lbry.block.ng
|
||||
cd /home/lbry/explorer.lbry.io
|
||||
bin/cake block addrtxamounts
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/bin/sh
|
||||
cd /var/www/lbry.block.ng
|
||||
cd /home/lbry/explorer.lbry.io
|
||||
bin/cake block parsenewblocks
|
||||
rm tmp/lock/parsenewblocks
|
||||
rm tmp/lock/parsenewblocks 2>/dev/null
|
||||
bin/cake block parsetxs
|
||||
rm tmp/lock/parsetxs
|
||||
rm tmp/lock/parsetxs 2>/dev/null
|
||||
|
||||
|
|
|
@ -1,137 +0,0 @@
|
|||
<?php
|
||||
|
||||
define('TMP', '/tmp/');
|
||||
define('DS', '/');
|
||||
|
||||
class BlockSyncThread extends \Thread {
|
||||
private $_startHeight;
|
||||
private $_endHeight;
|
||||
private $_maxHeight;
|
||||
|
||||
public function __construct($startBlock, $endBlock, $maxHeight) {
|
||||
$this->_startHeight = $startBlock;
|
||||
$this->_endHeight = $endBlock;
|
||||
$this->_maxHeight = $maxHeight;
|
||||
}
|
||||
|
||||
public function run() {
|
||||
$conn = new \PDO("mysql:host=localhost;dbname=lbry", 'lbry-admin', '46D861aX#!yQ');
|
||||
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
$data_error = false;
|
||||
$conn->beginTransaction();
|
||||
|
||||
// TODO: Batch block synchronisation from memory to DB
|
||||
|
||||
for ($curr_height = $this->_startHeight; $curr_height <= $this->_endHeight; $curr_height++) {
|
||||
$idx_str = str_pad($curr_height, strlen($this->_maxHeight), '0', STR_PAD_LEFT);
|
||||
|
||||
// get the block hash
|
||||
$req = ['method' => 'getblockhash', 'params' => [$curr_height]];
|
||||
$response = BlockStuff::curl_json_post(BlockStuff::rpcurl, json_encode($req));
|
||||
$json = json_decode($response);
|
||||
$curr_block_hash = $json->result;
|
||||
|
||||
$req = ['method' => 'getblock', 'params' => [$curr_block_hash]];
|
||||
$response = BlockStuff::curl_json_post(BlockStuff::rpcurl, json_encode($req));
|
||||
$json = json_decode($response);
|
||||
$curr_block = $json->result;
|
||||
|
||||
$stmt = $conn->prepare('UPDATE Blocks SET Confirmations = ? WHERE Height = ?');
|
||||
try {
|
||||
$stmt->execute([$curr_block->confirmations, $curr_height]);
|
||||
echo "[$idx_str/$this->_maxHeight] Updated block height: $curr_height with confirmations $curr_block->confirmations.\n";
|
||||
} catch (Exception $e) {
|
||||
$data_error = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($data_error) {
|
||||
echo "Rolling back changes.\n";
|
||||
$conn->rollBack();
|
||||
return;
|
||||
}
|
||||
|
||||
echo "Committing data.\n";
|
||||
$conn->commit();
|
||||
}
|
||||
}
|
||||
|
||||
class BlockStuff {
|
||||
const rpcurl = 'http://lrpc:lrpc@127.0.0.1:9245';
|
||||
public static function blocksync() {
|
||||
self::lock('blocksync');
|
||||
|
||||
$conn = new \PDO("mysql:host=localhost;dbname=lbry", 'lbry-admin', '46D861aX#!yQ');
|
||||
|
||||
$stmt = $conn->prepare('SELECT Height FROM Blocks ORDER BY Height DESC LIMIT 1');
|
||||
$stmt->execute([]);
|
||||
$max_block = $stmt->fetch(PDO::FETCH_OBJ);
|
||||
if ($max_block) {
|
||||
$chunk_limit = 2;
|
||||
$curr_height = 0;
|
||||
$chunks = floor($max_block->Height / $chunk_limit);
|
||||
$threads = [];
|
||||
for ($i = 0; $i < $chunk_limit; $i++) {
|
||||
$start = $curr_height;
|
||||
$end = ($i == ($chunk_limit - 1)) ? $max_block->Height : $start + $chunks;
|
||||
$curr_height += $chunks + 1;
|
||||
$thread = new BlockSyncThread($start, $end, $max_block->Height);
|
||||
$threads[] = $thread;
|
||||
|
||||
$thread->start();
|
||||
}
|
||||
|
||||
for ($i = 0; $i < count($threads); $i++) {
|
||||
$threads[$i]->join();
|
||||
}
|
||||
}
|
||||
|
||||
self::unlock('blocksync');
|
||||
}
|
||||
|
||||
public static function curl_json_post($url, $data, $headers = []) {
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
//Log::debug('Request execution completed.');
|
||||
if ($response === false) {
|
||||
$error = curl_error($ch);
|
||||
$errno = curl_errno($ch);
|
||||
curl_close($ch);
|
||||
|
||||
throw new \Exception(sprintf('The request failed: %s', $error), $errno);
|
||||
} else {
|
||||
curl_close($ch);
|
||||
}
|
||||
|
||||
// Close any open file handle
|
||||
return $response;
|
||||
}
|
||||
|
||||
public static function lock($process_name) {
|
||||
if (!is_dir(TMP . 'lock')) {
|
||||
mkdir(TMP . 'lock');
|
||||
}
|
||||
$lock_file = TMP . 'lock' . DS . $process_name;
|
||||
if (file_exists($lock_file)) {
|
||||
echo "$process_name is already running.\n";
|
||||
exit(0);
|
||||
}
|
||||
file_put_contents($lock_file, '1');
|
||||
}
|
||||
|
||||
public static function unlock($process_name) {
|
||||
$lock_file = TMP . 'lock' . DS . $process_name;
|
||||
if (file_exists($lock_file)) {
|
||||
unlink($lock_file);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
BlockStuff::blocksync();
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/sh
|
||||
cd /var/www/lbry.block.ng
|
||||
cd /home/lbry/explorer.lbry.io
|
||||
bin/cake block parsetxs
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/sh
|
||||
cd /var/www/lbry.block.ng
|
||||
cd /home/lbry/explorer.lbry.io
|
||||
bin/cake block buildclaimindex
|
||||
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
#!/bin/sh
|
||||
cd /var/www/lbry.block.ng/cron
|
||||
php -d extension=pthreads.so blockstuff.php
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/sh
|
||||
cd /var/www/lbry.block.ng
|
||||
cd /home/lbry/explorer.lbry.io
|
||||
bin/cake block fixzerooutputs
|
||||
|
||||
|
|
5
cron/forever.sh
Executable file
5
cron/forever.sh
Executable file
|
@ -0,0 +1,5 @@
|
|||
#!/bin/sh
|
||||
pkill -f forevermempool
|
||||
rm -f /home/lbry/explorer.lbry.io/tmp/lock/forevermempool 2>/dev/null
|
||||
cd /home/lbry/explorer.lbry.io
|
||||
bin/cake block forevermempool &
|
|
@ -1,4 +0,0 @@
|
|||
#!/bin/sh
|
||||
cd /var/www/lbry.block.ng
|
||||
bin/cake block forevermempool &
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/sh
|
||||
cd /var/www/lbry.block.ng
|
||||
cd /home/lbry/explorer.lbry.io
|
||||
bin/cake block parsemempool
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/sh
|
||||
cd /var/www/lbry.block.ng
|
||||
cd /home/lbry/explorer.lbry.io
|
||||
bin/cake aux pricehistory
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/sh
|
||||
cd /var/www/lbry.block.ng
|
||||
cd /home/lbry/explorer.lbry.io
|
||||
bin/cake block updatespends
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/sh
|
||||
cd /var/www/lbry.block.ng
|
||||
cd /home/lbry/explorer.lbry.io
|
||||
bin/cake aux verifytags
|
||||
|
||||
|
|
23
dev.sh
Executable file
23
dev.sh
Executable file
|
@ -0,0 +1,23 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
PHPBIN=php7.4
|
||||
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
|
||||
if [ ! -e "config/app.php" ]; then
|
||||
cp "$DIR/config/app.default.php" "$DIR/config/app.php"
|
||||
fi
|
||||
|
||||
if ! which $PHPBIN 2>/dev/null; then
|
||||
PHPBIN=php
|
||||
fi
|
||||
|
||||
#Composer update
|
||||
composer update
|
||||
|
||||
#$PHPBIN composer.phar install
|
||||
|
||||
$PHPBIN --server localhost:8000 --docroot "$DIR/webroot" "$DIR/webroot/index.php"
|
|
@ -1,4 +1,4 @@
|
|||
l--DROP DATABASE IF EXISTS lbry;
|
||||
--DROP DATABASE IF EXISTS lbry;
|
||||
CREATE DATABASE lbry DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
USE lbry;
|
||||
|
||||
|
@ -74,7 +74,7 @@ CREATE TABLE `Addresses`
|
|||
`TotalReceived` DECIMAL(18,8) DEFAULT 0 NOT NULL,
|
||||
`TotalSent` DECIMAL(18,8) DEFAULT 0 NOT NULL,
|
||||
`Balance` DECIMAL(18,8) AS (`TotalReceived` - `TotalSent`) PERSISTENT,
|
||||
`Tag` VARCHAR(30) NOT NULL,
|
||||
`Tag` VARCHAR(30),
|
||||
`TagUrl` VARCHAR(200),
|
||||
`Created` DATETIME NOT NULL,
|
||||
`Modified` DATETIME NOT NULL,
|
||||
|
@ -163,11 +163,11 @@ CREATE TABLE `TransactionsAddresses`
|
|||
`AddressId` BIGINT UNSIGNED NOT NULL,
|
||||
`DebitAmount` DECIMAL(18,8) DEFAULT 0 NOT NULL COMMENT 'Sum of the inputs to this address for the tx',
|
||||
`CreditAmount` DECIMAL(18,8) DEFAULT 0 NOT NULL COMMENT 'Sum of the outputs to this address for the tx',
|
||||
`LatestTransactionTime` DATETIME DEFAULT UTC_TIMESTAMP() NOT NULL,
|
||||
`TransactionTime` DATETIME DEFAULT UTC_TIMESTAMP() NOT NULL,
|
||||
PRIMARY KEY `PK_TransactionAddress` (`TransactionId`, `AddressId`),
|
||||
FOREIGN KEY `Idx_TransactionsAddressesTransaction` (`TransactionId`) REFERENCES `Transactions` (`Id`),
|
||||
FOREIGN KEY `Idx_TransactionsAddressesAddress` (`AddressId`) REFERENCES `Addresses` (`Id`),
|
||||
INDEX `Idx_TransactionsAddressesLatestTransactionTime` (`LatestTransactionTime`),
|
||||
INDEX `Idx_TransactionsAddressesTransactionTime` (`TransactionTime`),
|
||||
INDEX `Idx_TransactionsAddressesDebit` (`DebitAmount`),
|
||||
INDEX `Idx_TransactionsAddressesCredit` (`CreditAmount`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4;
|
||||
|
|
|
@ -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;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -5,7 +5,46 @@ namespace App\Model\Entity;
|
|||
use Cake\ORM\Entity;
|
||||
|
||||
class Claim extends Entity {
|
||||
function getLbryLink() {
|
||||
$link = $this->name;
|
||||
if (isset($this->publisher)) {
|
||||
$link = $this->publisher . '/' . $link;
|
||||
}
|
||||
$link = 'lbry://' . $link;
|
||||
return $link;
|
||||
}
|
||||
|
||||
function getExplorerLink() {
|
||||
$link = '/claims/' . $this->claim_id;
|
||||
return $link;
|
||||
}
|
||||
|
||||
function getContentTag() {
|
||||
$ctTag = null;
|
||||
if (substr($this->content_type, 0, 5) === 'audio') {
|
||||
$ctTag = 'audio';
|
||||
} else if (substr($this->content_type, 0, 5) === 'video') {
|
||||
$ctTag = 'video';
|
||||
} else if (substr($this->content_type, 0, 5) === 'image') {
|
||||
$ctTag = 'image';
|
||||
}
|
||||
|
||||
if (!$ctTag && $this->claim_type == 2) {
|
||||
$ctTag = 'identity';
|
||||
}
|
||||
return $ctTag;
|
||||
}
|
||||
|
||||
function getAutoThumbText() {
|
||||
$autoThumbText = '';
|
||||
if ($this->claim_type == 2) {
|
||||
$autoThumbText = strtoupper(substr($this->name, 1, min(strlen($this->name), 10)));
|
||||
} else {
|
||||
$str = (strlen(trim($this->title)) > 0) ? $this->title : $this->name;
|
||||
$autoThumbText = strtoupper(substr($str, 0, min(strlen($str), 5)));
|
||||
}
|
||||
return $autoThumbText;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -5,7 +5,7 @@ namespace App\Model\Entity;
|
|||
use Cake\ORM\Entity;
|
||||
|
||||
class PriceHistory extends Entity {
|
||||
|
||||
public $useDbConfig = 'localdb';
|
||||
}
|
||||
|
||||
?>
|
|
@ -3,9 +3,9 @@
|
|||
namespace App\Model\Entity;
|
||||
|
||||
use Cake\ORM\Entity;
|
||||
use Cake\ORM\TableRegistry;
|
||||
|
||||
class Transaction extends Entity {
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -4,8 +4,7 @@ namespace App\Model\Entity;
|
|||
|
||||
use Cake\ORM\Entity;
|
||||
|
||||
class ClaimStream extends Entity {
|
||||
|
||||
class TransactionAddress extends Entity {
|
||||
}
|
||||
|
||||
?>
|
|
@ -8,8 +8,8 @@ class AddressesTable extends Table {
|
|||
public function initialize(array $config) {
|
||||
parent::initialize($config);
|
||||
|
||||
$this->primaryKey('Id');
|
||||
$this->table('Addresses');
|
||||
$this->setPrimaryKey('id');
|
||||
$this->setTable('address');
|
||||
|
||||
$this->addBehavior('SimpleAudit');
|
||||
}
|
||||
|
|
|
@ -8,8 +8,8 @@ class BlocksTable extends Table {
|
|||
public function initialize(array $config) {
|
||||
parent::initialize($config);
|
||||
|
||||
$this->primaryKey('Id');
|
||||
$this->table('Blocks');
|
||||
$this->setPrimaryKey('id');
|
||||
$this->setTable('block');
|
||||
|
||||
$this->addBehavior('SimpleAudit');
|
||||
}
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Model\Table;
|
||||
|
||||
use Cake\ORM\Table;
|
||||
|
||||
class ClaimStreamsTable extends Table {
|
||||
public function initialize(array $config) {
|
||||
parent::initialize($config);
|
||||
|
||||
$this->primaryKey('Id');
|
||||
$this->table('ClaimStreams');
|
||||
|
||||
//$this->addBehavior('SimpleAudit');
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -8,29 +8,20 @@ class ClaimsTable extends Table {
|
|||
public function initialize(array $config) {
|
||||
parent::initialize($config);
|
||||
|
||||
$this->primaryKey('Id');
|
||||
$this->table('Claims');
|
||||
$this->setPrimaryKey('id');
|
||||
$this->setTable('claim');
|
||||
|
||||
//$this->addBehavior('SimpleAudit');
|
||||
$this->addAssociations([
|
||||
'belongsTo' => [
|
||||
'Publisher' => [
|
||||
'publisher' => [
|
||||
'className' => 'App\Model\Table\ClaimsTable',
|
||||
'foreignKey' => 'PublisherId',
|
||||
'bindingKey' => 'ClaimId',
|
||||
'propertyName' => 'Publisher'
|
||||
]
|
||||
],
|
||||
'hasOne' => [
|
||||
'Stream' => [
|
||||
'className' => 'App\Model\Table\ClaimStreamsTable',
|
||||
'foreignKey' => 'Id',
|
||||
'bindingKey' => 'Id',
|
||||
'propertyName' => 'Stream'
|
||||
'foreignKey' => 'publisher_id',
|
||||
'bindingKey' => 'claim_id',
|
||||
'propertyName' => 'publisher'
|
||||
]
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -8,19 +8,19 @@ class InputsTable extends Table {
|
|||
public function initialize(array $config) {
|
||||
parent::initialize($config);
|
||||
|
||||
$this->primaryKey('Id');
|
||||
$this->table('Inputs');
|
||||
$this->setPrimaryKey('id');
|
||||
$this->setTable('input');
|
||||
|
||||
$this->addBehavior('SimpleAudit');
|
||||
|
||||
$this->addAssociations([
|
||||
'belongsToMany' => [
|
||||
'InputAddresses' => [
|
||||
'input_addresses' => [
|
||||
'className' => 'App\Model\Table\AddressesTable',
|
||||
'joinTable' => 'InputsAddresses',
|
||||
'foreignKey' => 'InputId',
|
||||
'targetForeignKey' => 'AddressId',
|
||||
'propertyName' => 'InputAddresses'
|
||||
'joinTable' => 'input_addresses',
|
||||
'foreignKey' => 'input_id',
|
||||
'targetForeignKey' => 'address_id',
|
||||
'propertyName' => 'input_addresses'
|
||||
]
|
||||
]
|
||||
]);
|
||||
|
|
|
@ -8,26 +8,26 @@ class OutputsTable extends Table {
|
|||
public function initialize(array $config) {
|
||||
parent::initialize($config);
|
||||
|
||||
$this->primaryKey('Id');
|
||||
$this->table('Outputs');
|
||||
$this->setPrimaryKey('id');
|
||||
$this->setTable('output');
|
||||
|
||||
$this->addBehavior('SimpleAudit');
|
||||
|
||||
$this->addAssociations([
|
||||
'belongsTo' => [
|
||||
'SpendInput' => [
|
||||
'spend_input' => [
|
||||
'className' => 'App\Model\Table\InputsTable',
|
||||
'foreignKey' => 'SpentByInputId',
|
||||
'propertyName' => 'SpendInput'
|
||||
'foreignKey' => 'spent_by_input_id',
|
||||
'propertyName' => 'spend_input'
|
||||
]
|
||||
],
|
||||
'belongsToMany' => [
|
||||
'OutputAddresses' => [
|
||||
'output_addresses' => [
|
||||
'className' => 'App\Model\Table\AddressesTable',
|
||||
'joinTable' => 'OutputsAddresses',
|
||||
'foreignKey' => 'OutputId',
|
||||
'targetForeignKey' => 'AddressId',
|
||||
'propertyName' => 'OutputAddresses'
|
||||
'joinTable' => 'output_addresses',
|
||||
'foreignKey' => 'output_id',
|
||||
'targetForeignKey' => 'address_id',
|
||||
'propertyName' => 'output_addresses'
|
||||
]
|
||||
]
|
||||
]);
|
||||
|
|
|
@ -8,8 +8,8 @@ class PriceHistoryTable extends Table {
|
|||
public function initialize(array $config) {
|
||||
parent::initialize($config);
|
||||
|
||||
$this->primaryKey('Id');
|
||||
$this->table('PriceHistory');
|
||||
$this->setPrimaryKey('Id');
|
||||
$this->setTable('PriceHistory');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@ class TagAddressRequestsTable extends Table {
|
|||
public function initialize(array $config) {
|
||||
parent::initialize($config);
|
||||
|
||||
$this->primaryKey('Id');
|
||||
$this->table('TagAddressRequests');
|
||||
$this->setPrimaryKey('Id');
|
||||
$this->setTable('TagAddressRequests');
|
||||
|
||||
$this->addBehavior('SimpleAudit');
|
||||
}
|
||||
|
|
16
src/Model/Table/TransactionAddressesTable.php
Normal file
16
src/Model/Table/TransactionAddressesTable.php
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace App\Model\Table;
|
||||
|
||||
use Cake\ORM\Table;
|
||||
|
||||
class TransactionAddressesTable extends Table {
|
||||
public function initialize(array $config) {
|
||||
parent::initialize($config);
|
||||
|
||||
$this->setTable('transaction_address');
|
||||
$this->addBehavior('SimpleAudit');
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -8,8 +8,8 @@ class TransactionsTable extends Table {
|
|||
public function initialize(array $config) {
|
||||
parent::initialize($config);
|
||||
|
||||
$this->primaryKey('Id');
|
||||
$this->table('Transactions');
|
||||
$this->setPrimaryKey('id');
|
||||
$this->setTable('transaction');
|
||||
|
||||
$this->addBehavior('SimpleAudit');
|
||||
}
|
||||
|
|
|
@ -4,13 +4,16 @@ namespace App\Shell;
|
|||
|
||||
use Cake\Console\ConsoleOutput;
|
||||
use Cake\Console\Shell;
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Datasource\ConnectionManager;
|
||||
use Cake\Log\Log;
|
||||
use Mdanter\Ecc\EccFactory;
|
||||
|
||||
class AuxShell extends Shell {
|
||||
|
||||
const bittrex = 'https://bittrex.com/api/v1.1/public/getticker?market=BTC-LBC';
|
||||
public static $rpcurl;
|
||||
|
||||
const bittrex = 'https://api.bittrex.com/v3/markets/LBC-BTC/ticker';
|
||||
|
||||
const blockchainticker = 'https://blockchain.info/ticker';
|
||||
|
||||
|
@ -20,12 +23,11 @@ class AuxShell extends Shell {
|
|||
|
||||
const scriptAddress = [5, 122];
|
||||
|
||||
const rpcurl = 'http://lrpc:lrpc@127.0.0.1:9245';
|
||||
|
||||
const tagrcptaddress = 'bLockNgmfvnnnZw7bM6SPz6hk5BVzhevEp';
|
||||
|
||||
public function initialize() {
|
||||
parent::initialize();
|
||||
self::$rpcurl = Configure::read('Lbry.RpcUrl');
|
||||
$this->loadModel('Addresses');
|
||||
$this->loadModel('Inputs');
|
||||
$this->loadModel('Outputs');
|
||||
|
@ -125,8 +127,8 @@ class AuxShell extends Shell {
|
|||
public function pricehistory() {
|
||||
self::lock('pricehistory');
|
||||
|
||||
$conn = ConnectionManager::get('default');
|
||||
$redis = new \Predis\Client('tcp://127.0.0.1:6379');
|
||||
$conn = ConnectionManager::get('localdb');
|
||||
$redis = new \Predis\Client(Configure::read('Redis.Url'));
|
||||
|
||||
try {
|
||||
// Only allow 5-minute update intervals
|
||||
|
@ -148,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));
|
||||
|
|
|
@ -4,24 +4,27 @@ namespace App\Shell;
|
|||
|
||||
use Cake\Console\ConsoleOutput;
|
||||
use Cake\Console\Shell;
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Datasource\ConnectionManager;
|
||||
use Cake\Log\Log;
|
||||
use Mdanter\Ecc\EccFactory;
|
||||
|
||||
class BlockShell extends Shell {
|
||||
|
||||
public static $rpcurl;
|
||||
|
||||
public static $redisurl;
|
||||
|
||||
const mempooltxkey = 'lbc.mempooltx';
|
||||
|
||||
const pubKeyAddress = [0, 85];
|
||||
|
||||
const scriptAddress = [5, 122];
|
||||
|
||||
const rpcurl = 'http://lrpc:lrpc@127.0.0.1:9245';
|
||||
|
||||
const redisurl = 'tcp://127.0.0.1:6379';
|
||||
|
||||
public function initialize() {
|
||||
parent::initialize();
|
||||
self::$rpcurl = Configure::read('Lbry.RpcUrl');
|
||||
self::$redisurl = Configure::read('Redis.Url');
|
||||
$this->loadModel('Blocks');
|
||||
$this->loadModel('Addresses');
|
||||
$this->loadModel('Claims');
|
||||
|
@ -42,7 +45,7 @@ class BlockShell extends Shell {
|
|||
$txid = $otx->TransactionId;
|
||||
$tx = $this->Transactions->find()->select(['Hash'])->where(['Id' => $txid])->first();
|
||||
$req = ['method' => 'getrawtransaction', 'params' => [$tx->Hash]];
|
||||
$response = self::curl_json_post(self::rpcurl, json_encode($req));
|
||||
$response = self::curl_json_post(self::$rpcurl, json_encode($req));
|
||||
$json = json_decode($response);
|
||||
$tx_result = $json->result;
|
||||
$raw_tx = $tx_result;
|
||||
|
@ -160,7 +163,7 @@ class BlockShell extends Shell {
|
|||
$req = ['method' => 'getvalueforname', 'params' => [$claim_name]];
|
||||
$json = null;
|
||||
try {
|
||||
$json = json_decode(self::curl_json_post(self::rpcurl, json_encode($req)));
|
||||
$json = json_decode(self::curl_json_post(self::$rpcurl, json_encode($req)));
|
||||
if (!$json) {
|
||||
echo "[$idx_str/$count] getvalueforname failed for [$out->Hash:$vout]. Skipping.\n";
|
||||
continue;
|
||||
|
@ -271,6 +274,7 @@ class BlockShell extends Shell {
|
|||
self::unlock('buildindex');
|
||||
}
|
||||
|
||||
// TODO: Refactor for unique claim identification by claim_id instead of using the claim name.
|
||||
protected function _getclaimfortxout($pubkeyasm, $tx_hash, $vout, $tx_time = null) {
|
||||
$claim_data = null;
|
||||
$claim_stream_data = null;
|
||||
|
@ -292,10 +296,14 @@ class BlockShell extends Shell {
|
|||
if ($json) {
|
||||
$claim = json_decode($json);
|
||||
if ($claim) {
|
||||
if (strpos($claim_name, '#') !== false) {
|
||||
$claim_name = substr($claim_name, 0, strpos($claim_name, '#'));
|
||||
}
|
||||
|
||||
$req = ['method' => 'getvalueforname', 'params' => [$claim_name]];
|
||||
$json = null;
|
||||
try {
|
||||
$json = json_decode(self::curl_json_post(self::rpcurl, json_encode($req)));
|
||||
$json = json_decode(self::curl_json_post(self::$rpcurl, json_encode($req)));
|
||||
if ($json) {
|
||||
$claim_data = [];
|
||||
$claim_id = $json->result->claimId;
|
||||
|
@ -391,7 +399,7 @@ class BlockShell extends Shell {
|
|||
// getraw
|
||||
$req = ['method' => 'getrawtransaction', 'params' => [$tx->Hash]];
|
||||
$start_ms = round(microtime(true) * 1000);
|
||||
$response = self::curl_json_post(self::rpcurl, json_encode($req));
|
||||
$response = self::curl_json_post(self::$rpcurl, json_encode($req));
|
||||
$diff_ms = (round(microtime(true) * 1000)) - $start_ms;
|
||||
$total_diff += $diff_ms;
|
||||
echo "getrawtx took {$diff_ms}ms. ";
|
||||
|
@ -673,7 +681,7 @@ class BlockShell extends Shell {
|
|||
private function processtx($tx_hash, $block_ts, $block_data, &$data_error) {
|
||||
// Get the raw transaction (Use getrawtx daemon instead (for speed!!!)
|
||||
$req = ['method' => 'getrawtransaction', 'params' => [$tx_hash]];
|
||||
$response = self::curl_json_post(self::rpcurl, json_encode($req));
|
||||
$response = self::curl_json_post(self::$rpcurl, json_encode($req));
|
||||
$json = json_decode($response);
|
||||
$tx_result = $json->result;
|
||||
$raw_tx = $tx_result;
|
||||
|
@ -1075,12 +1083,13 @@ class BlockShell extends Shell {
|
|||
try {
|
||||
// Get the best block hash
|
||||
$req = ['method' => 'getbestblockhash', 'params' => []];
|
||||
$response = self::curl_json_post(self::rpcurl, json_encode($req));
|
||||
$response = self::curl_json_post(self::$rpcurl, json_encode($req));
|
||||
$json = json_decode($response);
|
||||
print_r($response); print_r($json);
|
||||
$best_hash = $json->result;
|
||||
|
||||
$req = ['method' => 'getblock', 'params' => [$best_hash]];
|
||||
$response = self::curl_json_post(self::rpcurl, json_encode($req));
|
||||
$response = self::curl_json_post(self::$rpcurl, json_encode($req));
|
||||
$json = json_decode($response);
|
||||
$best_block = $json->result;
|
||||
|
||||
|
@ -1103,20 +1112,20 @@ class BlockShell extends Shell {
|
|||
for ($curr_height = $min_height; $curr_height <= $max_height; $curr_height++) {
|
||||
// get the block hash
|
||||
$req = ['method' => 'getblockhash', 'params' => [$curr_height]];
|
||||
$response = self::curl_json_post(self::rpcurl, json_encode($req));
|
||||
$response = self::curl_json_post(self::$rpcurl, json_encode($req));
|
||||
$json = json_decode($response);
|
||||
$curr_block_hash = $json->result;
|
||||
|
||||
$next_block_hash = null;
|
||||
if ($curr_height < $max_height) {
|
||||
$req = ['method' => 'getblockhash', 'params' => [$curr_height + 1]];
|
||||
$response = self::curl_json_post(self::rpcurl, json_encode($req));
|
||||
$response = self::curl_json_post(self::$rpcurl, json_encode($req));
|
||||
$json = json_decode($response);
|
||||
$next_block_hash = $json->result;
|
||||
}
|
||||
|
||||
$req = ['method' => 'getblock', 'params' => [$curr_block_hash]];
|
||||
$response = self::curl_json_post(self::rpcurl, json_encode($req));
|
||||
$response = self::curl_json_post(self::$rpcurl, json_encode($req));
|
||||
$json = json_decode($response);
|
||||
$curr_block = $json->result;
|
||||
|
||||
|
@ -1127,7 +1136,7 @@ class BlockShell extends Shell {
|
|||
$next_block = null;
|
||||
if ($next_block_hash != null) {
|
||||
$req = ['method' => 'getblock', 'params' => [$next_block_hash]];
|
||||
$response = self::curl_json_post(self::rpcurl, json_encode($req));
|
||||
$response = self::curl_json_post(self::$rpcurl, json_encode($req));
|
||||
$json = json_decode($response);
|
||||
$next_block = $json->result;
|
||||
}
|
||||
|
@ -1243,7 +1252,7 @@ class BlockShell extends Shell {
|
|||
while (true) {
|
||||
try {
|
||||
$data = ['method' => 'getrawmempool', 'params' => []];
|
||||
$res = self::curl_json_post(self::rpcurl, json_encode($data));
|
||||
$res = self::curl_json_post(self::$rpcurl, json_encode($data));
|
||||
$json = json_decode($res);
|
||||
$txs = $json->result;
|
||||
$now = new \DateTime('now', new \DateTimeZone('UTC'));
|
||||
|
@ -1852,7 +1861,7 @@ class BlockShell extends Shell {
|
|||
// Other standard: pay to pubkey hash
|
||||
$define['p2pk'] = array('type' => 'pubkeyhash',
|
||||
'reqSigs' => 1,
|
||||
'data_index_for_hash' => 1);
|
||||
'data_index_for_hash' => 0);
|
||||
$rule['p2pk'] = [
|
||||
'0' => '/^[0-9a-f]+$/i',
|
||||
'1' => '/^OP_CHECKSIG/'
|
||||
|
@ -2070,7 +2079,7 @@ class BlockShell extends Shell {
|
|||
}
|
||||
|
||||
public static function _init_redis() {
|
||||
$redis = new \Predis\Client(self::redisurl);
|
||||
$redis = new \Predis\Client(self::$redisurl);
|
||||
try {
|
||||
$redis->info('mem');
|
||||
} catch (\Predis\Connection\ConnectionException $e) {
|
||||
|
|
85
src/Template/Element/claimbox.ctp
Normal file
85
src/Template/Element/claimbox.ctp
Normal file
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
$autoThumbText = $claim->getAutoThumbText();
|
||||
$cost = '';
|
||||
if (isset($claim->price) && $claim->price > 0) {
|
||||
$cost = $this->Amount->formatCurrency($claim->price) . ' LBC';
|
||||
} else if (isset($claim->fee) && strtolower($claim->fee_currency) === 'lbc') {
|
||||
$cost = $this->Amount->formatCurrency($claim->fee) . ' LBC';
|
||||
}
|
||||
$a = ['purple', 'orange', 'blue', 'teal', 'green', 'yellow'];
|
||||
// content type
|
||||
$ctTag = $claim->getContentTag();
|
||||
?>
|
||||
<div data-id="<?php echo $claim->claim_id ?>" class="claim-grid-item<?php if ($idx % 3 == 0): ?> last-item<?php endif; ?><?php if ($last_row): ?> last-row<?php endif; ?>">
|
||||
<?php if (strlen(trim($cost)) > 0): ?>
|
||||
<div class="price-tag"><?php echo $cost ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="tags">
|
||||
<?php if ($claim->bid_state == 'Controlling'): ?>
|
||||
<div class="bid-state">Controlling</div>
|
||||
<?php endif; ?>
|
||||
<?php if ($ctTag): ?>
|
||||
<div class="content-type"><?php echo strtoupper($ctTag) ?></div>
|
||||
<?php endif; ?>
|
||||
<?php if ($claim->is_nsfw): ?>
|
||||
<div class="nsfw">NSFW</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<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('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>
|
||||
|
||||
<div class="desc"><?php echo strlen(trim($claim->description)) > 0 ? $claim->description : '<em>No description available</em>' ?></div>
|
||||
|
||||
<div class="label half-width">Transaction</div>
|
||||
<div class="label half-width">Created</div>
|
||||
|
||||
<div class="value half-width"><a href="/tx/<?php echo $claim->transaction_hash_id ?>#output-<?php echo $claim->vout ?>" title="<?php echo $claim->transaction_hash_id ?>"><?php echo $claim->transaction_hash_id ?></a></div>
|
||||
<div class="value half-width" title="<?php echo $claim->created_at->format('j M Y H:i:s') ?> UTC">
|
||||
<?php echo \Carbon\Carbon::createFromTimestamp($claim->created_at->format('U'))->diffForHumans(); ?>
|
||||
</div>
|
||||
<div class="clear spacer"></div>
|
||||
|
||||
<?php if ($claim->claim_type == 1): ?>
|
||||
<div class="label half-width">Content Type</div>
|
||||
<div class="label half-width">Language</div>
|
||||
|
||||
<div class="value half-width" title="<?php echo $claim->content_type ?>"><?php echo $claim->content_type ?></div>
|
||||
<div class="value half-width" title="<?php echo $claim->language == 'en' ? 'English' : $claim->language ?>"><?php echo $claim->language == 'en' ? 'English' : $claim->language ?></div>
|
||||
|
||||
<div class="clear spacer"></div>
|
||||
|
||||
<!--<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>' ?>
|
||||
<?php if (strlen(trim($claim->LicenseUrl))): ?></a><?php endif; ?>
|
||||
</div>
|
||||
-->
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
|
@ -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>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<?php $this->assign('title', 'Address ' . $address->Address) ?>
|
||||
<?php $this->assign('title', 'Address ' . $address->address) ?>
|
||||
|
||||
<?php $this->start('script') ?>
|
||||
<script type="text/javascript">
|
||||
|
@ -40,7 +40,7 @@
|
|||
|
||||
var btnClose = $('.btn-close');
|
||||
$.ajax({
|
||||
url: '/api/v1/address/<?php echo $address->Address ?>/tag',
|
||||
url: '/api/v1/address/<?php echo $address->address ?>/tag',
|
||||
type: 'post',
|
||||
dataType: 'json',
|
||||
data: req,
|
||||
|
@ -87,41 +87,15 @@
|
|||
|
||||
<div class="address-head">
|
||||
<h3>LBRY Address</h3>
|
||||
<h4><?php echo $address->Address ?></h4> <div class="tag">
|
||||
<h4><?php echo $address->address ?></h4>
|
||||
<?php if (isset($address->Tag) && strlen(trim($address->Tag)) > 0): ?>
|
||||
<?php if (strlen(trim($address->TagUrl)) > 0): ?><a href="<?php echo $address->TagUrl ?>" target="_blank" rel="nofollow"><?php echo $address->Tag ?></a><?php else: echo $address->Tag; endif; ?>
|
||||
<?php else: ?><a href="#" class="tag-link">Tag this address</a><?php endif; ?></div>
|
||||
|
||||
<div class="tag-address-container">
|
||||
<h4>Tag adddress</h4>
|
||||
<?php if ($pending): ?>
|
||||
<div class="desc">This address has a pending tag request. If you made this request, please send exactly <strong><?php echo $pending->VerificationAmount ?> LBC</strong> from <strong><?php echo $address->Address ?></strong> to <strong><a href="/address/bLockNgmfvnnnZw7bM6SPz6hk5BVzhevEp" target="_blank">bLockNgmfvnnnZw7bM6SPz6hk5BVzhevEp</a></strong>. Incomplete requests will be automatically deleted 7 days from the request creation date.</div>
|
||||
<?php else: ?>
|
||||
<div class="desc">Label your public LBRY address with a name and an optional link. In order to tag this address, please send exactly <strong><?php echo $tagRequestAmount ?> LBC</strong>
|
||||
from <strong><?php echo $address->Address ?></strong> to <strong><a href="/address/bLockNgmfvnnnZw7bM6SPz6hk5BVzhevEp" target="_blank">bLockNgmfvnnnZw7bM6SPz6hk5BVzhevEp</a></strong>
|
||||
and then specify the desired tag (maximum 30 characters) and link in the fields below. The transaction will be verified after at least 1 confirmation. The <strong><?php echo $tagRequestAmount ?> LBC</strong> fee is a measure to prevent spam and low-effort submissions. Verification is an automatic process, but any tags or URLs that may be considered illegal when brought to attention will be removed.</div>
|
||||
<div class="form-group">
|
||||
<input type="hidden" name="tag_verify_amount" value="<?php echo $tagRequestAmount ?>" />
|
||||
<div class="error-message"></div>
|
||||
<div class="col">
|
||||
<input name="tag_value" maxlength="30" placeholder="Tag (max. 30 characters)" />
|
||||
</div>
|
||||
<div class="col">
|
||||
<input name="tag_url" maxlength="200" placeholder="Link (max. 200 characters)" />
|
||||
</div>
|
||||
<div class="col buttons">
|
||||
<button class="btn btn-tag">Tag address</button>
|
||||
<button class="btn btn-close">Close</button>
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="address-subhead">
|
||||
<div class="address-qr">
|
||||
<img src="/qr/lbry%3A<?php echo $address->Address ?>" alt="lbry:<?php echo $address->Address ?>" />
|
||||
<img src="/qr/lbry%3A<?php echo $address->address ?>" alt="lbry:<?php echo $address->address ?>" />
|
||||
</div>
|
||||
|
||||
<div class="address-summary">
|
||||
|
@ -178,19 +152,14 @@
|
|||
|
||||
<?php foreach ($recentTxs as $tx): ?>
|
||||
<tr>
|
||||
<td class="w125"><?php if ($tx->Height === null): ?><em>Unconfirmed</em><?php else: ?><a href="/blocks/<?php echo $tx->Height ?>"><?php echo $tx->Height ?></a><?php endif; ?></td>
|
||||
<td class="w250"><div><a href="/tx/<?php echo $tx->Hash ?>?address=<?php echo $address->Address ?>#<?php echo $address->Address ?>"><?php echo $tx->Hash ?></a></div></td>
|
||||
<td><?php echo \DateTime::createFromFormat('U', $tx->TxTime)->format('d M Y H:i:s') . ' UTC'; ?></td>
|
||||
<td class="right"><?php echo number_format($tx->Confirmations, 0, '', ',') ?></td>
|
||||
<td class="right"><?php echo $tx->InputCount ?></td>
|
||||
<td class="right"><?php echo $tx->OutputCount ?></td>
|
||||
<td class="right<?php echo ' ' . (($tx->DebitAmount > 0 && $tx->CreditAmount > 0) ? '' : (($tx->DebitAmount > 0) ? 'debit' : 'credit')) ?>">
|
||||
<?php if ($tx->DebitAmount > 0 && $tx->CreditAmount > 0): ?>
|
||||
<div class="credit">+<?php echo number_format($tx->CreditAmount, 8, '.', ',') ?> LBC</div>
|
||||
<div class="debit">-<?php echo number_format($tx->DebitAmount, 8, '.', ',') ?> LBC</div>
|
||||
<?php else: ?>
|
||||
<?php echo (($tx->DebitAmount > 0) ? '-' : '+'); ?><?php echo number_format((($tx->DebitAmount > 0) ? $tx->DebitAmount : $tx->CreditAmount), 8, '.', ',') ?> LBC
|
||||
<?php endif; ?>
|
||||
<td class="w125"><?php if ($tx->height === null): ?><em>Unconfirmed</em><?php else: ?><a href="/blocks/<?php echo $tx->height ?>"><?php echo $tx->height ?></a><?php endif; ?></td>
|
||||
<td class="w250"><div><a href="/tx/<?php echo $tx->hash ?>?address=<?php echo $address->address ?>#<?php echo $address->address ?>"><?php echo $tx->hash ?></a></div></td>
|
||||
<td><?php echo \DateTime::createFromFormat('U', $tx->transaction_time)->format('d M Y H:i:s') . ' UTC'; ?></td>
|
||||
<td class="right"><?php echo number_format($tx->confirmations, 0, '', ',') ?></td>
|
||||
<td class="right"><?php echo $tx->input_count ?></td>
|
||||
<td class="right"><?php echo $tx->output_count ?></td>
|
||||
<td class="right<?php echo ' ' . ($tx->debit_amount > 0 && $tx->credit_amount > 0 ? 'diff' : ($tx->debit_amount > 0 ? 'debit' : 'credit')) ?>">
|
||||
<?php echo number_format($tx->credit_amount - $tx->debit_amount, 8, '.', ',') ?> LBC
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
|
|
|
@ -21,21 +21,19 @@
|
|||
</script>
|
||||
<?php $this->end(); ?>
|
||||
|
||||
<?php $this->assign('title', 'Block Height ' . $block->Height) ?>
|
||||
<?php $this->assign('title', 'Block Height ' . $block->height) ?>
|
||||
|
||||
<div class="block-head">
|
||||
<h3>LBRY Block <?php echo $block->Height ?></h3>
|
||||
<h4><?php echo $block->Hash ?></h4>
|
||||
<h3>LBRY Block <?php echo $block->height ?></h3>
|
||||
<h4><?php echo $block->hash ?></h4>
|
||||
</div>
|
||||
|
||||
<div class="block-nav">
|
||||
<?php if (strlen(trim($block->PreviousBlockHash)) > 0): ?>
|
||||
<a class="btn btn-prev" href="/blocks/<?php echo ($block->Height - 1); ?>">« Previous Block</a>
|
||||
<?php if ($block->height > 0): ?>
|
||||
<a class="btn btn-prev" href="/blocks/<?php echo ($block->height - 1); ?>">« Previous Block</a>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (strlen(trim($block->NextBlockHash)) > 0): ?>
|
||||
<a class="btn btn-next" href="/blocks/<?php echo ($block->Height + 1); ?>">Next Block »</a>
|
||||
<?php endif; ?>
|
||||
<a class="btn btn-next" href="/blocks/<?php echo ($block->height + 1); ?>">Next Block »</a>
|
||||
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
@ -47,44 +45,46 @@
|
|||
<div class="label half-width">Block Size (bytes)</div>
|
||||
<div class="label half-width">Block Time</div>
|
||||
|
||||
<div class="value half-width"><?php echo number_format($block->BlockSize, 0, '', ',') ?></div>
|
||||
<div class="value half-width"><?php echo \DateTime::createFromFormat('U', $block->BlockTime)->format('j M Y H:i:s') . ' UTC' ?></div>
|
||||
<div class="value half-width"><?php echo number_format($block->block_size, 0, '', ',') ?></div>
|
||||
<div class="value half-width"><?php echo \DateTime::createFromFormat('U', $block->block_time)->format('j M Y H:i:s') . ' UTC' ?></div>
|
||||
|
||||
<div class="clear spacer"></div>
|
||||
|
||||
<div class="label half-width">Bits</div>
|
||||
<div class="label half-width">Confirmations</div>
|
||||
|
||||
<div class="value half-width"><?php echo $block->Bits ?></div>
|
||||
<div class="value half-width"><?php echo number_format($block->Confirmations, 0, '', ',') ?></div>
|
||||
<div class="value half-width"><?php echo $block->bits ?></div>
|
||||
<div class="value half-width"><?php echo $confirmations ?></div>
|
||||
|
||||
<div class="clear spacer"></div>
|
||||
|
||||
<div class="label half-width">Difficulty</div>
|
||||
<div class="label half-width">Nonce</div>
|
||||
|
||||
<div class="value half-width"><?php echo $this->Amount->format($block->Difficulty, '') ?></div>
|
||||
<div class="value half-width"><?php echo $block->Nonce ?></div>
|
||||
<div class="value half-width"><?php echo $this->Amount->format($block->difficulty, '') ?></div>
|
||||
<div class="value half-width"><?php echo $block->nonce ?></div>
|
||||
|
||||
<div class="clear spacer"></div>
|
||||
|
||||
<div class="label">Chainwork</div> <div class="value"><?php echo $block->Chainwork ?></div>
|
||||
<div class="label">Chainwork</div> <div class="value"><?php echo $block->chainwork ?></div>
|
||||
|
||||
<div class="spacer"></div>
|
||||
|
||||
<div class="label">MerkleRoot</div> <div class="value"><?php echo $block->MerkleRoot ?></div>
|
||||
<div class="label">MerkleRoot</div> <div class="value"><?php echo $block->merkle_root ?></div>
|
||||
|
||||
<div class="spacer"></div>
|
||||
|
||||
<div class="label">NameClaimRoot</div> <div class="value"><?php echo $block->NameClaimRoot ?></div>
|
||||
<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>
|
||||
-->
|
||||
|
||||
<div class="spacer"></div>
|
||||
|
||||
<div class="label">Version</div> <div class="value"><?php echo $block->Version ?></div>
|
||||
<div class="label">Version</div> <div class="value"><?php echo $block->version ?></div>
|
||||
</div>
|
||||
|
||||
<div class="block-transactions">
|
||||
|
@ -109,10 +109,10 @@
|
|||
|
||||
<?php foreach ($blockTxs as $tx): ?>
|
||||
<tr>
|
||||
<td class="w300"><div><a href="/tx/<?php echo $tx->Hash ?>"><?php echo $tx->Hash ?></a></div></td>
|
||||
<td class="right"><?php echo $tx->InputCount ?></td>
|
||||
<td class="right"><?php echo $tx->OutputCount ?></td>
|
||||
<td class="right"><div title="<?php echo $tx->Value ?> LBC"><?php echo $this->Amount->formatCurrency($tx->Value) ?> LBC</div></td>
|
||||
<td class="w300"><div><a href="/tx/<?php echo $tx->hash ?>"><?php echo $tx->hash ?></a></div></td>
|
||||
<td class="right"><?php echo $tx->input_count ?></td>
|
||||
<td class="right"><?php echo $tx->output_count ?></td>
|
||||
<td class="right"><div title="<?php echo $tx->value ?> LBC"><?php echo $this->Amount->formatCurrency($tx->value) ?> LBC</div></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
|
@ -134,236 +134,7 @@
|
|||
<script type="text/javascript" src="/amcharts/amcharts.js"></script>
|
||||
<script type="text/javascript" src="/amcharts/serial.js"></script>
|
||||
<script type="text/javascript" src="/amcharts/plugins/export/export.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
var chart;
|
||||
var chartData = [];
|
||||
var chartLoadInProgress = false;
|
||||
var minPeriod = 'hh';
|
||||
var validPeriods = ['24h', '72h', '168h', '30d', '90d', '1y'];
|
||||
var defaultPeriod = (validPeriods.indexOf(localStorage.getItem('chartPeriod')) > -1) ? localStorage.getItem('chartPeriod') : '24h';
|
||||
var periodGridCounts = {'24h': 24, '72h': 24, '168h': 14, '30d': 30, '90d': 45, '1y': 12 };
|
||||
AmCharts.ready(function() {
|
||||
chart = AmCharts.makeChart('block-size-chart', {
|
||||
type: 'serial',
|
||||
theme: 'light',
|
||||
mouseWheelZoomEnabled: true,
|
||||
categoryField: 'date',
|
||||
synchronizeGrid: true,
|
||||
dataProvider: chartData,
|
||||
valueAxes: [
|
||||
{
|
||||
id: 'v-block-size',
|
||||
axisColor: '#1e88e5',
|
||||
axisThickness: 2,
|
||||
labelFunction: function(value) {
|
||||
return (Math.round((value / 1000) * 100)/100).toFixed(2) + ' KB';
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'v-price',
|
||||
axisColor: '#00e676',
|
||||
offset: 75,
|
||||
gridAlpha: 0,
|
||||
axisThickness: 2,
|
||||
labelFunction: function(value) {
|
||||
return '$' + value.toFixed(2);
|
||||
}
|
||||
}
|
||||
],
|
||||
categoryAxis: {
|
||||
parseDates: true,
|
||||
minPeriod: minPeriod, // DD for daily
|
||||
autoGridCount: false,
|
||||
minorGridEnabled: true,
|
||||
minorGridAlpha: 0.04,
|
||||
axisColor: '#dadada',
|
||||
twoLineMode: true,
|
||||
dateFormats: [{
|
||||
period: 'fff',
|
||||
format: 'JJ:NN:SS'
|
||||
}, {
|
||||
period: 'ss',
|
||||
format: 'JJ:NN:SS'
|
||||
}, {
|
||||
period: 'mm',
|
||||
format: 'JJ:NN'
|
||||
}, {
|
||||
period: 'hh',
|
||||
format: 'JJ:NN'
|
||||
}, {
|
||||
period: 'DD',
|
||||
format: 'DD'
|
||||
}, {
|
||||
period: 'WW',
|
||||
format: 'DD MMM'
|
||||
}, {
|
||||
period: 'MM',
|
||||
format: 'MMM'
|
||||
}, {
|
||||
period: 'YYYY',
|
||||
format: 'YYYY'
|
||||
}]
|
||||
},
|
||||
graphs: [
|
||||
{
|
||||
id: 'g-block-size',
|
||||
valueAxis: 'v-block-size', // we have to indicate which value axis should be used
|
||||
title: 'Avg Block Size',
|
||||
valueField: 'AvgBlockSize',
|
||||
bullet: 'round',
|
||||
bulletBorderThickness: 1,
|
||||
bulletBorderAlpha: 1,
|
||||
bulletColor: '#ffffff',
|
||||
bulletSize: 5,
|
||||
useLineColorForBulletBorder: true,
|
||||
lineColor: '#1e88e5',
|
||||
hideBulletsCount: 101,
|
||||
balloonText: '[[AvgBlockSize]] KB',
|
||||
switchable: false,
|
||||
balloonFunction: function(item, graph) {
|
||||
var result = graph.balloonText;
|
||||
return result.replace('[[AvgBlockSize]]', (Math.round((item.dataContext.AvgBlockSize / 1000) * 100)/100).toFixed(2));
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'g-price',
|
||||
valueAxis: 'v-price',
|
||||
title: 'Average Price',
|
||||
valueField: 'AvgUSD',
|
||||
bullet: 'round',
|
||||
bulletBorderThickness: 1,
|
||||
bulletBorderAlpha: 1,
|
||||
bulletColor: '#ffffff',
|
||||
bulletSize: 5,
|
||||
useLineColorForBulletBorder: true,
|
||||
lineColor: '#00e676',
|
||||
balloonText: '$[[AvgUSD]]',
|
||||
balloonFunction: function(item, graph) {
|
||||
var result = graph.balloonText;
|
||||
if (!item.dataContext.AvgUSD) {
|
||||
return '';
|
||||
}
|
||||
return result.replace('[[AvgUSD]]', item.dataContext.AvgUSD.toFixed(2));
|
||||
},
|
||||
hideBulletsCount: 101,
|
||||
labelFunction: function(value) {
|
||||
return '$' + value;
|
||||
},
|
||||
}
|
||||
],
|
||||
chartCursor: {
|
||||
cursorAlpha: 0.1,
|
||||
fullWidth: true,
|
||||
valueLineBalloonEnabled: true,
|
||||
categoryBalloonColor: '#333333',
|
||||
cursorColor: '#1e88e5',
|
||||
categoryBalloonDateFormat: minPeriod === 'hh' ? 'D MMM HH:NN ' : 'D MMM'
|
||||
},
|
||||
chartScrollbar: {
|
||||
scrollbarHeight: 36,
|
||||
color: '#888888',
|
||||
gridColor: '#bbbbbb'
|
||||
},
|
||||
legend: {
|
||||
marginLeft: 110,
|
||||
useGraphSettings: true,
|
||||
valueAlign: 'right',
|
||||
valueWidth: 60,
|
||||
spacing: 64,
|
||||
valueFunction: function(item, formatted) {
|
||||
if (item.dataContext) {
|
||||
var g = item.graph;
|
||||
if (g.id === 'g-block-size' && item.dataContext.AvgBlockSize > 0) {
|
||||
return g.balloonText.replace('[[AvgBlockSize]]', (Math.round((item.dataContext.AvgBlockSize / 1000) * 100)/100).toFixed(2) );
|
||||
}
|
||||
if (g.id === 'g-price' && item.dataContext.AvgUSD) {
|
||||
return g.balloonText.replace('[[AvgUSD]]', item.dataContext.AvgUSD.toFixed(2));
|
||||
}
|
||||
}
|
||||
|
||||
return formatted;
|
||||
}
|
||||
},
|
||||
export: {
|
||||
enabled: true,
|
||||
fileName: 'lbry-block-size-chart',
|
||||
position: 'bottom-right',
|
||||
divId: 'chart-export'
|
||||
}
|
||||
});
|
||||
|
||||
loadChartData(defaultPeriod);
|
||||
});
|
||||
|
||||
var loadChartData = function(dataPeriod) {
|
||||
var loadProgress = $('.block-size-chart-container .load-progress');
|
||||
// clear previous chart data
|
||||
$.ajax({
|
||||
url: '/api/v1/charts/blocksize/' + dataPeriod,
|
||||
type: 'get',
|
||||
dataType: 'json',
|
||||
beforeSend: function() {
|
||||
chartLoadInProgress = true;
|
||||
loadProgress.css({ display: 'block' });
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
chartData = [];
|
||||
var data = response.data;
|
||||
for (var period in data) {
|
||||
if (data.hasOwnProperty(period)) {
|
||||
chartData.push({
|
||||
date: Date.parse(period),
|
||||
AvgBlockSize: data[period].AvgBlockSize,
|
||||
AvgUSD: data[period].AvgUSD
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// save selcted period to localStorage
|
||||
localStorage.setItem('chartPeriod', dataPeriod);
|
||||
|
||||
if (chart) {
|
||||
var isHourly = (dataPeriod.indexOf('h') > -1);
|
||||
var gridCount = periodGridCounts[dataPeriod];
|
||||
chart.categoryAxis.minPeriod = isHourly ? 'hh' : 'DD';
|
||||
chart.categoryAxis.dateFormats[4].format = isHourly ? 'DD MMM' : 'DD';
|
||||
chart.chartCursor.categoryBalloonDateFormat = isHourly ? 'D MMM HH:NN ' : 'D MMM YYYY';
|
||||
chart.categoryAxis.gridCount = gridCount;
|
||||
chart.chartScrollbar.gridCount = gridCount;
|
||||
chart.dataProvider = chartData;
|
||||
chart.validateNow();
|
||||
chart.validateData();
|
||||
}
|
||||
}
|
||||
},
|
||||
complete: function() {
|
||||
chartLoadInProgress = false;
|
||||
loadProgress.css({ display: 'none' });
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$(document).ready(function() {
|
||||
$('.block-size-data-links a').on('click', function(evt) {
|
||||
evt.preventDefault();
|
||||
if (chartLoadInProgress) {
|
||||
return;
|
||||
}
|
||||
|
||||
var link = $(this);
|
||||
if (link.hasClass('active')) {
|
||||
return;
|
||||
}
|
||||
|
||||
link.addClass('active').siblings().removeClass('active');
|
||||
var period = link.attr('data-period');
|
||||
loadChartData(period);
|
||||
});
|
||||
|
||||
$('a[data-period="' + defaultPeriod + '"]').addClass('active').siblings().removeClass('active');
|
||||
});
|
||||
</script>
|
||||
<script type="text/javascript" src="/js/block-size-chart.js"></script>
|
||||
<?php $this->end(); ?>
|
||||
|
||||
<div class="block-head">
|
||||
|
@ -410,13 +181,13 @@
|
|||
<tbody>
|
||||
<?php foreach ($blocks as $block): ?>
|
||||
<tr>
|
||||
<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($block->Confirmations, 0, '', ',') ?></td>
|
||||
<td class="right"><?php echo count(json_decode($block->TransactionHashes)) ?></td>
|
||||
<td class="right"><?php echo round($block->BlockSize / 1024, 2) . 'KB' ?></td>
|
||||
<td class="right pad-left"><?php echo $block->Nonce ?></td>
|
||||
<td class="pad-left"><?php echo \DateTime::createFromFormat('U', $block->BlockTime)->format('d M Y H:i:s') ?> UTC</td>
|
||||
<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 $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>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
|
|
|
@ -39,28 +39,15 @@
|
|||
<?php if (isset($claim)):
|
||||
|
||||
$a = ['purple', 'orange', 'blue', 'teal', 'green', 'yellow'];
|
||||
$autoThumbText = '';
|
||||
$link = $claim->Name;
|
||||
$rawLink = $claim->Name;
|
||||
if (isset($claim->Publisher->Name)) {
|
||||
$link = urlencode($claim->Publisher->Name) . '/' . $link;
|
||||
$rawLink = $claim->Publisher->Name . '/' . $rawLink;
|
||||
}
|
||||
$link = 'lbry://' . $link;
|
||||
$rawLink = 'lbry://' . $rawLink;
|
||||
if ($claim->ClaimType == 1) { $autoThumbText = strtoupper(substr($claim->Name, 1, min( strlen($claim->Name), 10 ))); } else {
|
||||
$str = str_replace(' ', '', (strlen(trim($claim->Title)) > 0) ? $claim->Title : $claim->Name);
|
||||
$autoThumbText = strtoupper(mb_substr($str, 0, min( strlen($str), 10 )));
|
||||
}
|
||||
|
||||
$autoThumbText = $claim->getAutoThumbText();
|
||||
$cost = 'Free';
|
||||
if (isset($claim->Price) && $claim->Price > 0) {
|
||||
$cost = $this->Amount->formatCurrency($claim->Price) . ' LBC';
|
||||
} else if (isset($claim->Fee) && strtolower($claim->FeeCurrency) === 'lbc') {
|
||||
$cost = $this->Amount->formatCurrency($claim->Fee) . ' LBC';
|
||||
if (isset($claim->price) && $claim->price > 0) {
|
||||
$cost = $this->Amount->formatCurrency($claim->price) . ' LBC';
|
||||
} else if (isset($claim->fee) && strtolower($claim->fee_currency) === 'lbc') {
|
||||
$cost = $this->Amount->formatCurrency($claim->fee) . ' LBC';
|
||||
}
|
||||
|
||||
$desc = $claim->Description;
|
||||
$desc = $claim->description;
|
||||
if (strlen(trim($desc)) == 0) {
|
||||
$desc = '<em>No description available.</em>';
|
||||
} else {
|
||||
|
@ -70,29 +57,38 @@ if (strlen(trim($desc)) == 0) {
|
|||
|
||||
?>
|
||||
|
||||
<?php $this->assign('title', 'Claim • ' . $claim->Name) ?>
|
||||
<?php $this->assign('title', 'Claim • ' . $claim->name) ?>
|
||||
|
||||
<div class="claims-head">
|
||||
<h3><a href="/claims">LBRY Claims</a> • <?php echo $claim->Name ?></h3>
|
||||
<h4><?php echo $claim->ClaimId ?></h4>
|
||||
<h3><a href="/claims">LBRY Claims</a> • <?php echo $claim->name ?></h3>
|
||||
<h4><?php echo $claim->claim_id ?></h4>
|
||||
</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->IsNSFW && strlen(trim($claim->ThumbnailUrl)) > 0): ?>
|
||||
<img src="<?php echo $claim->ThumbnailUrl ?>" alt="" />
|
||||
<?php if (!$claim->is_nsfw && strlen(trim($claim->thumbnail_url)) > 0): ?>
|
||||
<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>
|
||||
|
||||
<div class="content">
|
||||
<?php if ($claim->ClaimType == 2): ?>
|
||||
<?php if ($claim->claim_type == 1): ?>
|
||||
<div class="label">Published By</div>
|
||||
<div class="value">
|
||||
<?php if (isset($claim->Publisher)): ?>
|
||||
<a href="lbry://<?php echo $claim->Publisher->Name ?>"><?php echo $claim->Publisher->Name ?></a>
|
||||
<?php if (isset($claim->publisher)): ?>
|
||||
<a href="lbry://<?php echo $claim->publisher ?>"><?php echo $claim->publisher ?></a>
|
||||
<?php else: ?>
|
||||
<em>Anonymous</em>
|
||||
<?php endif; ?>
|
||||
|
@ -100,17 +96,17 @@ if (strlen(trim($desc)) == 0) {
|
|||
<?php endif; ?>
|
||||
|
||||
<div class="label">Created On</div>
|
||||
<div class="value"><?php echo \DateTime::createFromFormat('U', $claim->TransactionTime > 0 ? $claim->TransactionTime : $claim->Created->format('U'))->format('j M Y H:i:s') ?> UTC</div>
|
||||
<div class="value"><?php echo \DateTime::createFromFormat('U', $claim->transaction_time > 0 ? $claim->transaction_time : $claim->created_at->format('U'))->format('j M Y H:i:s') ?> UTC</div>
|
||||
|
||||
<div class="label">Transaction ID</div>
|
||||
<div class="value"><a href="/tx/<?php echo $claim->TransactionHash ?>#output-<?php echo $claim->Vout ?>"><?php echo $claim->TransactionHash ?></a></div>
|
||||
<div class="value"><a href="/tx/<?php echo $claim->transaction_hash_id ?>#output-<?php echo $claim->vout ?>"><?php echo $claim->transaction_hash_id ?></a></div>
|
||||
|
||||
<?php if ($claim->ClaimType == 2): ?>
|
||||
<?php if ($claim->claim_type == 1): ?>
|
||||
<div class="label half-width">Cost</div>
|
||||
<div class="label half-width">Safe for Work</div>
|
||||
|
||||
<div class="value half-width"><?php echo $cost ?></div>
|
||||
<div class="value half-width"><?php echo $claim->IsNSFW ? 'No' : 'Yes' ?></div>
|
||||
<div class="value half-width"><?php echo $claim->is_nsfw ? 'No' : 'Yes' ?></div>
|
||||
|
||||
<div class="clear"></div>
|
||||
<?php endif; ?>
|
||||
|
@ -118,11 +114,11 @@ if (strlen(trim($desc)) == 0) {
|
|||
</div>
|
||||
|
||||
<div class="claim-metadata">
|
||||
<?php if ($claim->ClaimType == 1): ?>
|
||||
<?php if ($claim->claim_type == 2): ?>
|
||||
<div class="title">Identity Claim</div>
|
||||
<div class="desc">This is an identity claim.</div>
|
||||
<?php else: ?>
|
||||
<div class="title"><?php echo $claim->Title ?></div>
|
||||
<div class="title"><?php echo $claim->title ?></div>
|
||||
<div class="desc"><?php echo str_replace("\n", '<br />', $desc) ?></div>
|
||||
|
||||
<div class="details">
|
||||
|
@ -130,30 +126,33 @@ if (strlen(trim($desc)) == 0) {
|
|||
<div class="label half-width">Content Type</div>
|
||||
|
||||
|
||||
<div class="value half-width"><?php echo strlen(trim($claim->Author)) > 0 ? $claim->Author : '<em>Unspecified</em>' ?></div>
|
||||
<div class="value half-width"><?php echo strlen(trim($claim->ContentType)) > 0 ? $claim->ContentType : '<em>Unspecified</em>' ?></div>
|
||||
<div class="value half-width"><?php echo strlen(trim($claim->author)) > 0 ? $claim->author : '<em>Unspecified</em>' ?></div>
|
||||
<div class="value half-width"><?php echo strlen(trim($claim->content_type)) > 0 ? $claim->content_type : '<em>Unspecified</em>' ?></div>
|
||||
|
||||
<!--
|
||||
<div class="label half-width">License</div>
|
||||
<div class="label half-width">Language</div>
|
||||
-->
|
||||
<div class="label">Language</div>
|
||||
|
||||
<div class="value half-width"<?php if(strlen(trim($claim->License)) > 0): ?> title="<?php echo $claim->License ?>"<?php endif; ?>>
|
||||
<?php if (strlen(trim($claim->LicenseUrl)) > 0): ?><a href="<?php echo $claim->LicenseUrl ?>" rel="nofollow" target="_blank"><?php endif; ?>
|
||||
<!--
|
||||
<div class="value half-width"<?php if(strlen(trim($claim->license)) > 0): ?> title="<?php echo $claim->license ?>"<?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>
|
||||
-->
|
||||
<div class="value half-width"><?php echo strlen(trim($claim->language)) > 0 ? ($claim->language == 'en' ? 'English' : '') : '<em>Unspecified</em>' ?></div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<a href="<?php echo $link ?>" class="open-lbry-link">Open in LBRY</a>
|
||||
<a href="<?php echo $claim->getLbryLink() ?>" class="open-lbry-link">Open in LBRY</a>
|
||||
</div>
|
||||
|
||||
<div class="clear"></div>
|
||||
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (count($moreClaims) > 0): ?>
|
||||
|
||||
<div class="more-claims">
|
||||
<h4><?php echo isset($claim->Publisher) ? 'More from the publisher' : 'Published by this identity' ?></h4>
|
||||
<h4><?php echo isset($claim->publisher) ? 'More from the publisher' : 'Published by this identity' ?></h4>
|
||||
|
||||
<div class="claims-grid">
|
||||
<?php $idx = 1; $row = 1; $rowCount = ceil(count($moreClaims) / 3);
|
||||
|
@ -163,105 +162,9 @@ if (strlen(trim($desc)) == 0) {
|
|||
if ($idx % 3 == 0) {
|
||||
$row++;
|
||||
}
|
||||
|
||||
$autoThumbText = '';
|
||||
$link = $claim->Name;
|
||||
$rawLink = $claim->Name;
|
||||
if (isset($claim->Publisher->Name)) {
|
||||
$link = urlencode($claim->Publisher->Name) . '/' . $link;
|
||||
$rawLink = $claim->Publisher->Name . '/' . $rawLink;
|
||||
}
|
||||
$link = 'lbry://' . $link;
|
||||
$rawLink = 'lbry://' . $rawLink;
|
||||
$cost = '';
|
||||
if (isset($claim->Price) && $claim->Price > 0) {
|
||||
$cost = $this->Amount->formatCurrency($claim->Price) . ' LBC';
|
||||
} else if (isset($claim->Fee) && strtolower($claim->FeeCurrency) === 'lbc') {
|
||||
$cost = $this->Amount->formatCurrency($claim->Fee) . ' LBC';
|
||||
}
|
||||
|
||||
// content type
|
||||
$ctTag = null;
|
||||
if (substr($claim->ContentType, 0, 5) === 'audio') {
|
||||
$ctTag = 'audio';
|
||||
} else if (substr($claim->ContentType, 0, 5) === 'video') {
|
||||
$ctTag = 'video';
|
||||
} else if (substr($claim->ContentType, 0, 5) === 'image') {
|
||||
$ctTag = 'image';
|
||||
}
|
||||
|
||||
if (!$ctTag && $claim->ClaimType == 1) {
|
||||
$ctTag = 'identity';
|
||||
}
|
||||
|
||||
if ($claim->ClaimType == 1) { $autoThumbText = strtoupper(substr($claim->Name, 1, min( strlen($claim->Name), 10 ))); } else {
|
||||
$str = str_replace(' ', '', (strlen(trim($claim->Title)) > 0) ? $claim->Title : $claim->Name);
|
||||
$autoThumbText = strtoupper(mb_substr($str, 0, min( strlen($str), 10 )));
|
||||
}
|
||||
|
||||
?>
|
||||
<div data-id="<?php echo $claim->ClaimId ?>" class="claim-grid-item<?php if ($idx % 3 == 0): ?> last-item<?php endif; ?><?php if ($last_row): ?> last-row<?php endif; ?>">
|
||||
<?php if (strlen(trim($cost)) > 0): ?>
|
||||
<div class="price-tag"><?php echo $cost ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="tags">
|
||||
<?php if ($ctTag): ?>
|
||||
<div class="content-type"><?php echo strtoupper($ctTag) ?></div>
|
||||
<?php endif; ?>
|
||||
<?php if ($claim->IsNSFW): ?>
|
||||
<div class="nsfw">NSFW</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div data-autothumb="<?php echo $autoThumbText ?>" class="thumbnail <?php echo $a[mt_rand(0, count($a) - 1)] ?>">
|
||||
<?php if (!$claim->IsNSFW && strlen(trim($claim->ThumbnailUrl)) > 0): ?>
|
||||
<img src="<?php echo $claim->ThumbnailUrl ?>" alt="" />
|
||||
<?php else: ?>
|
||||
<div class="autothumb"><?php echo $autoThumbText ?></div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="metadata">
|
||||
<div class="title" title="<?php echo $claim->ClaimType == 1 ? $claim->Name : ((strlen(trim($claim->Title)) > 0) ? $claim->Title : '') ?>"><?php echo $claim->ClaimType == 1 ? $claim->Name : ((strlen(trim($claim->Title)) > 0) ? $claim->Title : '<em>No Title</em>') ?></div>
|
||||
<div class="link" title="<?php echo $rawLink ?>"><a href="<?php echo $link ?>" rel="nofollow"><?php echo $rawLink ?></a></div>
|
||||
|
||||
<div class="desc"><?php echo strlen(trim($claim->Description)) > 0 ? $claim->Description : '<em>No description available</em>' ?></div>
|
||||
|
||||
<div class="label half-width">Transaction</div>
|
||||
<div class="label half-width">Created</div>
|
||||
|
||||
<div class="value half-width"><a href="/tx/<?php echo $claim->TransactionHash ?>#output-<?php echo $claim->Vout ?>" title="<?php echo $claim->TransactionHash ?>"><?php echo $claim->TransactionHash ?></a></div>
|
||||
<div class="value half-width" title="<?php echo $claim->Created->format('j M Y H:i:s') ?> UTC">
|
||||
<?php echo \Carbon\Carbon::createFromTimestamp($claim->Created->format('U'))->diffForHumans(); ?>
|
||||
</div>
|
||||
|
||||
<div class="clear spacer"></div>
|
||||
|
||||
<?php if ($claim->ClaimType == 2): ?>
|
||||
<div class="label half-width">Content Type</div>
|
||||
<div class="label half-width">Language</div>
|
||||
|
||||
<div class="value half-width" title="<?php echo $claim->ContentType ?>"><?php echo $claim->ContentType ?></div>
|
||||
<div class="value half-width" title="<?php echo $claim->Language == 'en' ? 'English' : $claim->Language ?>"><?php echo $claim->Language == 'en' ? 'English' : $claim->Language ?></div>
|
||||
|
||||
<div class="clear spacer"></div>
|
||||
|
||||
<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>' ?>
|
||||
<?php if (strlen(trim($claim->LicenseUrl))): ?></a><?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<?php $idx++; endforeach; ?>
|
||||
|
||||
echo $this->element('claimbox', array('claim' => $claim, 'idx' => $idx, 'last_row' => $last_row));
|
||||
$idx++;
|
||||
endforeach; ?>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -290,103 +193,9 @@ if (strlen(trim($desc)) == 0) {
|
|||
if ($idx % 3 == 0) {
|
||||
$row++;
|
||||
}
|
||||
$autoThumbText = '';
|
||||
$link = $claim->Name;
|
||||
$rawLink = $claim->Name;
|
||||
if (isset($claim->Publisher->Name)) {
|
||||
$link = urlencode($claim->Publisher->Name) . '/' . $link;
|
||||
$rawLink = $claim->Publisher->Name . '/' . $rawLink;
|
||||
}
|
||||
$link = 'lbry://' . $link;
|
||||
$rawLink = 'lbry://' . $rawLink;
|
||||
$cost = '';
|
||||
if (isset($claim->Price) && $claim->Price > 0) {
|
||||
$cost = $this->Amount->formatCurrency($claim->Price) . ' LBC';
|
||||
} else if (isset($claim->Fee) && strtolower($claim->FeeCurrency) === 'lbc') {
|
||||
$cost = $this->Amount->formatCurrency($claim->Fee) . ' LBC';
|
||||
}
|
||||
|
||||
// content type
|
||||
$ctTag = null;
|
||||
if (substr($claim->ContentType, 0, 5) === 'audio') {
|
||||
$ctTag = 'audio';
|
||||
} else if (substr($claim->ContentType, 0, 5) === 'video') {
|
||||
$ctTag = 'video';
|
||||
} else if (substr($claim->ContentType, 0, 5) === 'image') {
|
||||
$ctTag = 'image';
|
||||
}
|
||||
|
||||
if (!$ctTag && $claim->ClaimType == 1) {
|
||||
$ctTag = 'identity';
|
||||
}
|
||||
|
||||
if ($claim->ClaimType == 1) { $autoThumbText = strtoupper(substr($claim->Name, 1, min( strlen($claim->Name), 10 ))); } else {
|
||||
$str = str_replace(' ', '', (strlen(trim($claim->Title)) > 0) ? $claim->Title : $claim->Name);
|
||||
$autoThumbText = strtoupper(mb_substr($str, 0, min( strlen($str), 10 )));
|
||||
}
|
||||
|
||||
?>
|
||||
<div data-id="<?php echo $claim->ClaimId ?>" class="claim-grid-item<?php if ($idx % 3 == 0): ?> last-item<?php endif; ?><?php if ($last_row): ?> last-row<?php endif; ?>">
|
||||
<?php if (strlen(trim($cost)) > 0): ?>
|
||||
<div class="price-tag"><?php echo $cost ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="tags">
|
||||
<?php if ($ctTag): ?>
|
||||
<div class="content-type"><?php echo strtoupper($ctTag) ?></div>
|
||||
<?php endif; ?>
|
||||
<?php if ($claim->IsNSFW): ?>
|
||||
<div class="nsfw">NSFW</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div data-autothumb="<?php echo $autoThumbText ?>" class="thumbnail <?php echo $a[mt_rand(0, count($a) - 1)] ?>">
|
||||
<?php if (!$claim->IsNSFW && strlen(trim($claim->ThumbnailUrl)) > 0): ?>
|
||||
<img src="<?php echo $claim->ThumbnailUrl ?>" alt="" />
|
||||
<?php else: ?>
|
||||
<div class="autothumb"><?php echo $autoThumbText ?></div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="metadata">
|
||||
<div class="title" title="<?php echo $claim->ClaimType == 1 ? $claim->Name : ((strlen(trim($claim->Title)) > 0) ? $claim->Title : '') ?>"><?php echo $claim->ClaimType == 1 ? $claim->Name : ((strlen(trim($claim->Title)) > 0) ? $claim->Title : '<em>No Title</em>') ?></div>
|
||||
<div class="link" title="<?php echo $rawLink ?>"><a href="<?php echo $link ?>" rel="nofollow"><?php echo $rawLink ?></a></div>
|
||||
|
||||
<div class="desc"><?php echo strlen(trim($claim->Description)) > 0 ? $claim->Description : '<em>No description available</em>' ?></div>
|
||||
|
||||
<div class="label half-width">Transaction</div>
|
||||
<div class="label half-width">Created</div>
|
||||
|
||||
<div class="value half-width"><a href="/tx/<?php echo $claim->TransactionHash ?>#output-<?php echo $claim->Vout ?>" title="<?php echo $claim->TransactionHash ?>"><?php echo $claim->TransactionHash ?></a></div>
|
||||
<div class="value half-width" title="<?php echo $claim->Created->format('j M Y H:i:s') ?> UTC">
|
||||
<?php echo \Carbon\Carbon::createFromTimestamp($claim->TransactionTime > 0 ? $claim->TransactionTime : $claim->Created->format('U'))->diffForHumans(); ?>
|
||||
</div>
|
||||
|
||||
<div class="clear spacer"></div>
|
||||
|
||||
<?php if ($claim->ClaimType == 2): ?>
|
||||
<div class="label half-width">Content Type</div>
|
||||
<div class="label half-width">Language</div>
|
||||
|
||||
<div class="value half-width" title="<?php echo $claim->ContentType ?>"><?php echo $claim->ContentType ?></div>
|
||||
<div class="value half-width" title="<?php echo $claim->Language == 'en' ? 'English' : $claim->Language ?>"><?php echo $claim->Language == 'en' ? 'English' : $claim->Language ?></div>
|
||||
|
||||
<div class="clear spacer"></div>
|
||||
|
||||
<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>' ?>
|
||||
<?php if (strlen(trim($claim->LicenseUrl))): ?></a><?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php $idx++; endforeach; ?>
|
||||
|
||||
echo $this->element('claimbox', array('claim' => $claim, 'idx' => $idx, 'last_row' => $last_row));
|
||||
$idx++;
|
||||
endforeach; ?>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
||||
|
|
66
src/Template/Main/find.ctp
Normal file
66
src/Template/Main/find.ctp
Normal file
|
@ -0,0 +1,66 @@
|
|||
<?php $this->start('script'); ?>
|
||||
<script type="text/javascript">
|
||||
var resizeCards = function() {
|
||||
var claimInfo = $('.claim-info');
|
||||
var claimMtdt = $('.claim-metadata');
|
||||
if (claimMtdt.outerHeight() < claimInfo.outerHeight()) {
|
||||
claimMtdt.outerHeight(claimInfo.outerHeight());
|
||||
} else if (claimInfo.outerHeight() < claimMtdt.outerHeight()) {
|
||||
claimInfo.outerHeight(claimMtdt.outerHeight());
|
||||
}
|
||||
};
|
||||
|
||||
window.onload = function() {
|
||||
resizeCards();
|
||||
};
|
||||
|
||||
$(document).ready(function() {
|
||||
resizeCards();
|
||||
|
||||
$('.claim-grid-item img,.claim-info img').on('error', function() {
|
||||
var img = $(this);
|
||||
var parent = img.parent();
|
||||
var text = parent.attr('data-autothumb');
|
||||
img.remove();
|
||||
parent.append(
|
||||
$('<div></div>').attr({'class': 'autothumb' }).text(text)
|
||||
);
|
||||
});
|
||||
|
||||
$(document).on('click', '.claim-grid-item', function() {
|
||||
var id = $(this).attr('data-id');
|
||||
location.href = '/claims/' + id;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?php $this->end(); ?>
|
||||
<?php echo $this->element('header') ?>
|
||||
|
||||
<?php $this->assign('title', 'Search Results') ?>
|
||||
|
||||
<div class="claims-head">
|
||||
<h3>Search results</h3>
|
||||
</div>
|
||||
|
||||
<div class="claims-grid">
|
||||
<?php if (isset($claims) && count($claims) > 0): ?>
|
||||
<?php
|
||||
$idx = 1;
|
||||
$row = 1;
|
||||
$rowCount = ceil(count($claims) / 3);
|
||||
$a = ['purple', 'orange', 'blue', 'teal', 'green', 'yellow'];
|
||||
foreach ($claims as $claim):
|
||||
$last_row = ($row == $rowCount);
|
||||
if ($idx % 3 == 0) {
|
||||
$row++;
|
||||
}
|
||||
echo $this->element('claimbox', array('claim' => $claim, 'idx' => $idx, 'last_row' => $last_row));
|
||||
$idx++;
|
||||
endforeach; ?>
|
||||
<?php else: ?>
|
||||
<div class="no-results">No results were found.</div>
|
||||
<?php endif; ?>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
||||
<?php echo $this->element('pagination') ?>
|
|
@ -127,22 +127,22 @@
|
|||
</div>
|
||||
|
||||
<div class="stats">
|
||||
<div class="box">
|
||||
<div class="box box-20">
|
||||
<div class="title">Block Height</div>
|
||||
<div class="value"><?php echo $recentBlocks[0]->Height ?></div>
|
||||
<div class="value"><?php echo $recentBlocks[0]->height ?></div>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<div class="box box-30">
|
||||
<div class="title">Difficulty</div>
|
||||
<div class="value" title="<?php echo $recentBlocks[0]->Difficulty ?>"><?php echo number_format($recentBlocks[0]->Difficulty, 2, '.', '') ?></div>
|
||||
<div class="value" title="<?php echo $recentBlocks[0]->difficulty ?>"><?php echo number_format($recentBlocks[0]->difficulty, 2, '.', '') ?></div>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<div class="box box-30">
|
||||
<div class="title">Network</div>
|
||||
<div class="value"><?php echo $hashRate ?></div>
|
||||
</div>
|
||||
|
||||
<div class="box last">
|
||||
<div class="box box-20 last">
|
||||
<div class="title">Price</div>
|
||||
<div class="value"><?php echo $lbcUsdPrice ?></div>
|
||||
</div>
|
||||
|
@ -167,13 +167,13 @@
|
|||
|
||||
<tbody>
|
||||
<?php foreach ($recentBlocks as $block): ?>
|
||||
<tr data-height="<?php echo $block->Height ?>" data-time="<?php echo $block->BlockTime ?>">
|
||||
<td><a href="/blocks/<?php echo $block->Height ?>"><?php echo $block->Height ?></a></td>
|
||||
<td><?php echo \Carbon\Carbon::createFromTimestamp($block->BlockTime)->diffForHumans(); ?></td>
|
||||
<td class="right"><?php echo round($block->BlockSize / 1024, 2) . 'KB' ?></td>
|
||||
<td class="right"><?php echo $block->TransactionCount ?></td>
|
||||
<td class="right"><?php echo number_format($block->Difficulty, 2, '.', '') ?></td>
|
||||
<td class="last-cell"><?php echo DateTime::createFromFormat('U', $block->BlockTime)->format('d M Y H:i:s') . ' UTC' ?></td>
|
||||
<tr data-height="<?php echo $block->height ?>" data-time="<?php echo $block->block_time ?>">
|
||||
<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->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>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
|
@ -183,66 +183,43 @@
|
|||
<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']; foreach ($recentClaims as $claim):
|
||||
<?php $idx = 0; $a = ['purple', 'orange', 'blue', 'teal', 'green', 'yellow'];
|
||||
foreach ($recentClaims as $claim):
|
||||
$idx++;
|
||||
$autoThumbText = '';
|
||||
$link = $claim->Name;
|
||||
$rawLink = $claim->Name;
|
||||
if (isset($claim->Publisher->Name)) {
|
||||
$link = urlencode($claim->Publisher->Name) . '/' . $link;
|
||||
$rawLink = $claim->Publisher->Name . '/' . $link;
|
||||
}
|
||||
$link = 'lbry://' . $link;
|
||||
$rawLink = 'lbry://' . $rawLink;
|
||||
$autoThumbText = $claim->getAutoThumbText();
|
||||
|
||||
// content type
|
||||
$ctTag = null;
|
||||
if (substr($claim->ContentType, 0, 5) === 'audio') {
|
||||
$ctTag = 'audio';
|
||||
} else if (substr($claim->ContentType, 0, 5) === 'video') {
|
||||
$ctTag = 'video';
|
||||
} else if (substr($claim->ContentType, 0, 5) === 'image') {
|
||||
$ctTag = 'image';
|
||||
}
|
||||
|
||||
if (!$ctTag && $claim->ClaimType == 1) {
|
||||
$ctTag = 'identity';
|
||||
}
|
||||
|
||||
if ($claim->ClaimType == 1) { $autoThumbText = strtoupper(substr($claim->Name, 1, min( strlen($claim->Name), 3 ))); } else {
|
||||
$str = (strlen(trim($claim->Title)) > 0) ? $claim->Title : $claim->Name;
|
||||
$autoThumbText = strtoupper(substr($str, 0, min (strlen($str), 2 )));
|
||||
}
|
||||
$ctTag = $claim->getContentTag();
|
||||
?>
|
||||
<div data-id="<?php echo $claim->ClaimId ?>" class="claim-box<?php if ($idx == 5): ?> last<?php endif; ?>">
|
||||
<div data-id="<?php echo $claim->claim_id ?>" class="claim-box<?php if ($idx == 5): ?> last<?php endif; ?>">
|
||||
<div class="tags">
|
||||
<?php if ($ctTag): ?>
|
||||
<div class="content-type"><?php echo strtoupper($ctTag) ?></div>
|
||||
<?php endif; ?>
|
||||
<?php if ($claim->IsNSFW): ?>
|
||||
<?php if ($claim->is_nsfw): ?>
|
||||
<div class="nsfw">NSFW</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div data-autothumb="<?php echo $autoThumbText ?>" class="thumbnail <?php echo $a[mt_rand(0, count($a) - 1)] ?>">
|
||||
<?php if (!$claim->IsNSFW && strlen(trim($claim->ThumbnailUrl)) > 0): ?>
|
||||
<img src="<?php echo strip_tags($claim->ThumbnailUrl) ?>" alt="" />
|
||||
<?php if (!$claim->is_nsfw && strlen(trim($claim->thumbnail_url)) > 0): ?>
|
||||
<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; ?>
|
||||
</div>
|
||||
|
||||
<div class="metadata">
|
||||
<div class="title" title="<?php echo $claim->ClaimType == 1 ? $claim->Name : ((strlen(trim($claim->Title)) > 0) ? $claim->Title : ''); ?>"><?php echo $claim->ClaimType == 1 ? $claim->Name : ((strlen(trim($claim->Title)) > 0) ? $claim->Title : '<em>No Title</em>') ?></div>
|
||||
<div class="link" title="<?php echo $rawLink ?>"><a href="<?php echo $link ?>"><?php echo $rawLink ?></a></div>
|
||||
<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() ?>"><?php echo $claim->getLbryLink() ?></a></div>
|
||||
|
||||
<div class="clear"></div>
|
||||
<?php if ($claim->ClaimType == 2 && strlen(trim($claim->Description)) > 0): ?>
|
||||
<div class="desc"><?php echo $claim->Description ?></div>
|
||||
<?php if ($claim->claim_type == 2 && strlen(trim($claim->description)) > 0): ?>
|
||||
<div class="desc"><?php echo $claim->description ?></div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<a class="tx-link" href="/tx/<?php echo $claim->TransactionHash ?>#output-<?php echo $claim->Vout ?>" target="_blank">Transaction</a>
|
||||
<a class="tx-link" href="/tx/<?php echo $claim->transaction_hash_id ?>#output-<?php echo $claim->vout ?>" target="_blank">Transaction</a>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
|
||||
|
|
|
@ -128,10 +128,10 @@
|
|||
|
||||
<tbody>
|
||||
<?php foreach ($blocks as $block): ?>
|
||||
<tr data-height="<?php echo $block->Height ?>" data-time="<?php echo $block->BlockTime ?>">
|
||||
<td><a href="/blocks/<?php echo $block->Height ?>" target="_blank"><?php echo $block->Height ?></a></td>
|
||||
<td><?php echo \Carbon\Carbon::createFromTimestamp($block->BlockTime)->diffForHumans(); ?></td>
|
||||
<td class="right"><?php echo $block->TransactionCount ?></td>
|
||||
<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->tx_count ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
|
@ -153,12 +153,12 @@
|
|||
|
||||
<tbody>
|
||||
<?php foreach ($txs as $tx): ?>
|
||||
<tr data-hash="<?php echo $tx->Hash ?>" data-time="<?php echo $tx->TxTime ?>">
|
||||
<td class="w200"><div><a href="/tx/<?php echo $tx->Hash ?>" target="_blank"><?php echo $tx->Hash ?></a></div></td>
|
||||
<td><?php echo \Carbon\Carbon::createFromTimestamp($tx->TxTime)->diffForHumans(); ?></td>
|
||||
<td class="right"><?php echo $tx->InputCount ?></td>
|
||||
<td class="right"><?php echo $tx->OutputCount ?></td>
|
||||
<td class="right"><?php echo number_format($tx->Value, 8, '.', '') ?> LBC</td>
|
||||
<tr data-hash="<?php echo $tx->hash ?>" data-time="<?php echo $tx->transaction_time ?>">
|
||||
<td class="w200"><div><a href="/tx/<?php echo $tx->hash ?>" target="_blank"><?php echo $tx->hash ?></a></div></td>
|
||||
<td><?php echo $tx->created_at->diffForHumans(); ?></td>
|
||||
<td class="right"><?php echo $tx->input_count ?></td>
|
||||
<td class="right"><?php echo $tx->output_count ?></td>
|
||||
<td class="right"><?php echo number_format($tx->value, 8, '.', '') ?> LBC</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
|
|
|
@ -1,19 +1,34 @@
|
|||
<?php $this->assign('title', 'Stats & Rich List') ?>
|
||||
|
||||
<?php $this->start('script'); ?>
|
||||
<script type="text/javascript">
|
||||
|
||||
</script>
|
||||
<?php $this->end(); ?>
|
||||
|
||||
<?php echo $this->element('header') ?>
|
||||
|
||||
<?php $this->start('script'); ?>
|
||||
<script src="https://www.amcharts.com/lib/3/amcharts.js"></script>
|
||||
<script src="https://www.amcharts.com/lib/3/serial.js"></script>
|
||||
<script src="https://www.amcharts.com/lib/3/plugins/export/export.min.js"></script>
|
||||
<script src="https://www.amcharts.com/lib/3/plugins/responsive/responsive.min.js" type="text/javascript"></script>
|
||||
<script type="text/javascript" src="/js/mining-inflation-chart.js"></script>
|
||||
<?php $this->end(); ?>
|
||||
|
||||
<?php
|
||||
$this->start('css');
|
||||
echo $this->Html->css('/css/mining-inflation-chart.css');
|
||||
echo $this->Html->css('https://www.amcharts.com/lib/3/plugins/export/export.css');
|
||||
$this->end();
|
||||
?>
|
||||
<div class="stats-head">
|
||||
<h3>LBRY Stats</h3>
|
||||
</div>
|
||||
|
||||
<div class="stats-main">
|
||||
|
||||
<div class="mining-inflation-chart-container">
|
||||
<div class="load-progress inc"></div>
|
||||
<h3>Mining Inflation Chart</h3>
|
||||
<div id="mining-inflation-chart" class="chart"></div>
|
||||
<div id="chart-export" class="btn-chart-export"></div>
|
||||
</div>
|
||||
|
||||
<div class="richlist">
|
||||
<h3>LBRY Rich List (Top 500)</h3>
|
||||
<table class="table">
|
||||
|
@ -32,22 +47,25 @@
|
|||
<?php $rank = 0; foreach ($richList as $item): $rank++; ?>
|
||||
<tr>
|
||||
<td class="right topvalign"><?php echo $rank ?></td>
|
||||
<td class="topvalign"><a href="/address/<?php echo $item->Address ?>" target="_blank"><?php echo $item->Address ?></a>
|
||||
<td class="topvalign"><a href="/address/<?php echo $item->address ?>" target="_blank"><?php echo $item->address ?></a>
|
||||
<?php if(in_array($item->address, $lbryAddresses)): ?>
|
||||
<span class="lbry-address">
|
||||
<img src="/img/lbry.png" height="18px" width="18px" title="Address owned by LBRY Inc."/>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
<?php if (isset($item->Tag) && strlen(trim($item->Tag)) > 0): ?>
|
||||
<div class="tag">
|
||||
<?php if (strlen(trim($item->TagUrl)) > 0): ?><a href="<?php echo $item->TagUrl ?>" target="_blank" rel="nofollow"><?php echo $tiem->Tag ?></a><?php else: echo $item->Tag; endif; ?>
|
||||
</div>
|
||||
<?php endif; ?></td>
|
||||
<td class="right topvalign"><?php echo number_format($item->Balance, 8, '.', ',') ?></td>
|
||||
<td class="right topvalign">$<?php echo number_format(bcmul($item->Balance, $rate, 8), 2, '.', ',') ?></td>
|
||||
<td class="med-pad-left topvalign"><?php echo $item->FirstSeen->format('d M Y H:i:s') . ' UTC'; ?></td>
|
||||
<td class="right topvalign"><?php echo number_format($item->balance, 8, '.', ',') ?></td>
|
||||
<td class="right topvalign">$<?php echo number_format(bcmul($item->balance, $rate, 8), 2, '.', ',') ?></td>
|
||||
<td class="med-pad-left topvalign"><?php echo $item->first_seen->format('d M Y H:i:s') . ' UTC'; ?></td>
|
||||
<td class="w150 center top500-percent-cell"><div class="top500-percent" style="width: <?php echo $item->MinMaxPercent ?>%"></div><div class="text"><?php echo number_format($item->Top500Percent, 5, '.', '') ?>%</div></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="clear"></div>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -14,22 +14,22 @@
|
|||
|
||||
<div class="tx-head">
|
||||
<h3>LBRY Transaction</h3>
|
||||
<h4><?php echo $tx->Hash ?></h4>
|
||||
<h4><?php echo $tx->hash ?></h4>
|
||||
</div>
|
||||
|
||||
<div class="tx-time">
|
||||
<div class="created-time">
|
||||
<h3 title="Represents the time this transaction was created on the explorer">Time Created</h3>
|
||||
<div><?php echo $tx->Created->format('j M Y H:i:s') . ' UTC '; ?></div>
|
||||
<div><?php echo $tx->created_at->format('j M Y H:i:s') . ' UTC '; ?></div>
|
||||
</div>
|
||||
|
||||
<div class="conf-time">
|
||||
<h3 title="The time the first confirmation of this transaction happened on the blockchain">Block Time</h3>
|
||||
<div><?php echo ($tx->TransactionTime == null || strlen(trim($tx->TransactionTime)) == 0) ? '<em>Not yet confirmed</em>' :
|
||||
\DateTime::createFromFormat('U', $tx->TransactionTime)->format('j M Y H:i:s') . ' UTC' ?>
|
||||
<div><?php echo ($tx->transaction_time == null || strlen(trim($tx->transaction_time)) == 0) ? '<em>Not yet confirmed</em>' :
|
||||
\DateTime::createFromFormat('U', $tx->transaction_time)->format('j M Y H:i:s') . ' UTC' ?>
|
||||
|
||||
<?php if ($tx->TransactionTime > $tx->Created->getTimestamp()):
|
||||
$diffSeconds = $tx->TransactionTime - $tx->Created->getTimestamp();
|
||||
<?php if ($tx->transaction_time > $tx->created_at->getTimestamp()):
|
||||
$diffSeconds = $tx->transaction_time - $tx->created_at->getTimestamp();
|
||||
if ($diffSeconds <= 60) {
|
||||
echo sprintf(' (+%s second%s)', $diffSeconds, $diffSeconds == 1 ? '' : 's');
|
||||
} else {
|
||||
|
@ -47,15 +47,15 @@
|
|||
<div class="tx-summary">
|
||||
<div class="box p25">
|
||||
<div class="title">Amount (LBC)</div>
|
||||
<div class="value"><?php echo $this->Amount->format($tx->Value) ?></div>
|
||||
<div class="value"><?php echo $this->Amount->format($tx->value) ?></div>
|
||||
</div>
|
||||
|
||||
<div class="box p15">
|
||||
<div class="title">Block Height</div>
|
||||
<?php if (!isset($tx->BlockHash) || strlen(trim($tx->BlockHash)) === 0): ?>
|
||||
<?php if (!isset($tx->block_hash_id) || strlen(trim($tx->block_hash_id)) === 0): ?>
|
||||
<div class="value" title="Unconfirmed">Unconf.</div>
|
||||
<?php else: ?>
|
||||
<div class="value" title="<?php echo $tx->BlockHash ?>"><a href="/blocks/<?php echo $block->Height ?>"><?php echo $block->Height ?></a></div>
|
||||
<div class="value" title="<?php echo $tx->block_hash_id ?>"><a href="/blocks/<?php echo $block->height ?>"><?php echo $block->height ?></a></div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
|
@ -66,17 +66,17 @@
|
|||
|
||||
<div class="box p15">
|
||||
<div class="title">Size (bytes)</div>
|
||||
<div class="value"><?php echo number_format($tx->TransactionSize, 0, '', ',') ?></div>
|
||||
<div class="value"><?php echo number_format($tx->transaction_size, 0, '', ',') ?></div>
|
||||
</div>
|
||||
|
||||
<div class="box p15">
|
||||
<div class="title">Inputs</div>
|
||||
<div class="value"><?php echo $tx->InputCount ?></div>
|
||||
<div class="value"><?php echo $tx->input_count ?></div>
|
||||
</div>
|
||||
|
||||
<div class="box p15 last">
|
||||
<div class="title">Outputs</div>
|
||||
<div class="value"><?php echo $tx->OutputCount ?></div>
|
||||
<div class="value"><?php echo $tx->output_count ?></div>
|
||||
</div>
|
||||
|
||||
<div class="clear"></div>
|
||||
|
@ -86,28 +86,29 @@
|
|||
<h3>Details</h3>
|
||||
<div class="tx-details-layout">
|
||||
<div class="inputs">
|
||||
<div class="subtitle"><?php echo $tx->InputCount ?> input<?php echo $tx->InputCount === 1 ? '' : 's'; ?></div>
|
||||
<div class="subtitle"><?php echo $tx->input_count ?> input<?php echo $tx->input_count === 1 ? '' : 's'; ?></div>
|
||||
|
||||
<?php
|
||||
$setAddressIds = [];
|
||||
foreach ($inputs as $in):
|
||||
?>
|
||||
<div id="input-<?php echo $in->Id ?>" class="input <?php if (isset($in['InputAddresses']) && count($in['InputAddresses']) > 0 && $in['InputAddresses'][0]->Address == $sourceAddress): ?>is-source<?php endif; ?>">
|
||||
<?php if ($in['IsCoinbase']): ?>
|
||||
<div id="input-<?php echo $in->id ?>" class="input <?php if (isset($in->input_addresses) && count($in->input_addresses) > 0 && $in->input_addresses[0]->address == $sourceAddress): ?>is-source<?php endif; ?>">
|
||||
<?php if ($in->is_coinbase): ?>
|
||||
<div>Block Reward (New Coins)</div>
|
||||
<?php else: ?>
|
||||
<?php if (strlen(trim($in->Value)) == 0): ?>
|
||||
<?php if (strlen(trim($in->value)) == 0): ?>
|
||||
<div>Incomplete data</div>
|
||||
<?php else:
|
||||
$addr = $in['InputAddresses'][0];
|
||||
$addr = $in->input_addresses[0];
|
||||
|
||||
if (!isset($setAddressIds[$addr->Address])):
|
||||
$setAddressIds[$addr->Address] = 1; ?>
|
||||
<a id="<?php echo $addr->Address ?>"></a>
|
||||
if (!isset($setAddressIds[$addr->address])):
|
||||
$setAddressIds[$addr->address] = 1; ?>
|
||||
<a id="<?php echo $addr->address ?>"></a>
|
||||
<?php endif; ?>
|
||||
<div><span class="value"><?php echo $this->Amount->format($in['Value']) ?> LBC</span> from</div>
|
||||
<div class="address"><a href="/address/<?php echo $addr->Address ?>"><?php echo $addr->Address ?></a>
|
||||
(<a class="output-link" href="/tx/<?php echo $in->PrevoutHash ?>#output-<?php echo $in->PrevoutN ?>">output</a>)
|
||||
<div><span class="value"><?php echo $this->Amount->format($in->value) ?> LBC</span> from</div>
|
||||
<div class="address"><a href="/address/<?php echo $addr->address ?>"><?php echo $addr->address ?></a>
|
||||
(<a class="output-link" href="/tx/<?php echo $in->prevout_hash ?>#output-<?php echo $in->prevout_n ?>">output</a>)
|
||||
|
||||
<?php if (isset($addr->Tag) && strlen(trim($addr->Tag)) > 0): ?>
|
||||
<div class="tag">
|
||||
<?php if (strlen(trim($addr->TagUrl)) > 0): ?><a href="<?php echo $addr->TagUrl ?>" target="_blank" rel="nofollow"><?php echo $addr->Tag ?></a><?php else: echo $addr->Tag; endif; ?>
|
||||
|
@ -125,7 +126,7 @@
|
|||
</div>
|
||||
|
||||
<div class="outputs">
|
||||
<div class="subtitle"><?php echo $tx->OutputCount ?> output<?php echo $tx->OutputCount === 1 ? '' : 's'; ?>
|
||||
<div class="subtitle"><?php echo $tx->output_count ?> output<?php echo $tx->output_count === 1 ? '' : 's'; ?>
|
||||
|
||||
<?php if ($fee > 0): ?>
|
||||
<span class="fee"><span class="label">Fee</span> <span class="value"><?php echo $this->Amount->format($fee) ?> LBC</span></span>
|
||||
|
@ -134,26 +135,27 @@
|
|||
|
||||
<?php
|
||||
foreach ($outputs as $out): ?>
|
||||
<div id="output-<?php echo $out->Vout ?>" class="output <?php if (isset($out['OutputAddresses']) && count($out['OutputAddresses']) > 0 && $out['OutputAddresses'][0]->Address == $sourceAddress): ?>is-source<?php endif; ?>">
|
||||
<div id="output-<?php echo $out->vout ?>" class="output <?php if (isset($out->output_addresses) && count($out->output_addresses) > 0 && $out->output_addresses[0]->address == $sourceAddress): ?>is-source<?php endif; ?>">
|
||||
<div class="labels">
|
||||
<?php if($out->Claim && ($out->IsClaim or $out->IsSupportClaim or $out->IsUpdateClaim)): ?><a class="view-claim" href="<?php echo $out->Claim->getExplorerLink() ?>">View</a><?php endif; ?>
|
||||
<?php if($out->IsSupportClaim): ?><div class="support">SUPPORT</div><?php endif; ?>
|
||||
<?php if($out->IsUpdateClaim): ?><div class="update">UPDATE</div><?php endif; ?>
|
||||
<?php if($out->IsClaim): ?><div class="claim">CLAIM</div><?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php if (strlen(trim($out['Value'])) == 0): ?>
|
||||
<?php if (strlen(trim($out->value)) == 0): ?>
|
||||
<div>Incomplete data</div>
|
||||
<?php else:
|
||||
$addr = $out['OutputAddresses'][0];
|
||||
$addr = $out->output_addresses[0];
|
||||
|
||||
if (!isset($setAddressIds[$addr->Address])):
|
||||
$setAddressIds[$addr->Address] = 1; ?>
|
||||
<a id="<?php echo $addr->Address ?>"></a>
|
||||
if (!isset($setAddressIds[$addr->address])):
|
||||
$setAddressIds[$addr->address] = 1; ?>
|
||||
<a id="<?php echo $addr->address ?>"></a>
|
||||
<?php endif; ?>
|
||||
<div><span class="value"><?php echo $this->Amount->format($out['Value']) ?> LBC</span> to</div>
|
||||
<div class="address"><a href="/address/<?php echo $addr->Address ?>"><?php echo $addr->Address ?></a>
|
||||
<div><span class="value"><?php echo $this->Amount->format($out->value) ?> LBC</span> to</div>
|
||||
<div class="address"><a href="/address/<?php echo $addr->address ?>"><?php echo $addr->address ?></a>
|
||||
|
||||
<?php if ($out->IsSpent): ?>(<a href="/tx/<?php echo $out->SpendInput->TransactionHash ?>#input-<?php echo $out->SpendInput->Id ?>">spent</a>)<?php else: ?>(unspent)<?php endif; ?>
|
||||
<?php if ($out->is_spent): ?>(<a href="/tx/<?php if(isset($out->spend_input_id)) { echo $out->spend_input_hash; } ?>#input-<?php if(isset($out->spend_input_id)) {echo $out->spend_input_id; } ?>">spent</a>)<?php else: ?>(unspent)<?php endif; ?>
|
||||
|
||||
<?php if (isset($addr->Tag) && strlen(trim($addr->Tag)) > 0): ?>
|
||||
<div class="tag">
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
namespace App\View;
|
||||
|
||||
use Cake\Event\EventManager;
|
||||
use Cake\Network\Request;
|
||||
use Cake\Http\ServerRequest;
|
||||
use Cake\Network\Response;
|
||||
|
||||
/**
|
||||
|
|
4
tmp/.gitignore
vendored
Normal file
4
tmp/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
*
|
||||
!*/
|
||||
!.git*
|
||||
|
|
@ -5,7 +5,7 @@ Version: 1.1.2
|
|||
|
||||
## Description
|
||||
|
||||
Smoothly animates the `dataProvider`
|
||||
Smoothly animates the `dataProvider`.
|
||||
|
||||
It works with serial, pie, XY, funnel, and radar.
|
||||
|
||||
|
@ -96,13 +96,13 @@ http://www.apache.org/licenses/LICENSE-2.0
|
|||
## Changelog
|
||||
|
||||
### 1.1.2
|
||||
* Fixing a bug with the minimum/maximum
|
||||
* Fixing a bug with the minimum/maximum.
|
||||
|
||||
### 1.1.1
|
||||
* It now automatically sets the minimum/maximum on the value axes while animating
|
||||
* It now automatically sets the minimum/maximum on the value axes while animating.
|
||||
|
||||
### 1.1.0
|
||||
* Adding in support for XY charts
|
||||
* Adding in support for XY charts.
|
||||
|
||||
### 1.0.0
|
||||
* Initial release
|
||||
* Initial release.
|
||||
|
|
|
@ -5,13 +5,13 @@ Version: 1.0.16
|
|||
|
||||
## Description
|
||||
|
||||
By default all amCharts libraries accept data in JSON format. It needs to be
|
||||
By default, all amCharts libraries accept data in JSON format. It needs to be
|
||||
there when the web page loads, defined in-line or loaded via custom code.
|
||||
|
||||
This plugin introduces are native wrapper that enables automatic loading of data
|
||||
from external data data sources in CSV and JSON formats.
|
||||
This plugin introduces our native wrapper that enables automatic loading of data
|
||||
from external data sources in CSV and JSON formats.
|
||||
|
||||
Most of the times you will just need to provide a URL of the external data
|
||||
Most of the time, you will just need to provide a URL of the external data
|
||||
source - static file or dynamically generated - and it will do the rest.
|
||||
|
||||
|
||||
|
@ -25,7 +25,7 @@ So, any of the examples loaded locally (file:///) will not work.
|
|||
|
||||
The page needs to be loaded via web server (http://) in order to work properly.
|
||||
|
||||
Loading data from another domain than the web page is loaded is possible but is
|
||||
Loading data from another domain than the web page is loaded is possible, but is
|
||||
a subject for `Access-Control-Allow-Origin` policies defined by the web server
|
||||
you are loading data from.
|
||||
|
||||
|
@ -78,7 +78,7 @@ AmCharts.makeChart( "chartdiv", {
|
|||
That's it. The plugin will make sure the files are loaded and dataProvider is
|
||||
populated with their content *before* the chart is built.
|
||||
|
||||
Some formats, like CSV, will require additional parameters needed to parse the
|
||||
Some formats like CSV, will require additional parameters needed to parse the
|
||||
data, such as "separator".
|
||||
|
||||
If the "format" is omitted, the plugin will assume JSON.
|
||||
|
@ -104,32 +104,32 @@ chart["dataLoader"] = {
|
|||
|
||||
Property | Default | Description
|
||||
-------- | ------- | -----------
|
||||
async | true | If set to false (not recommended) everything will wait until data is fully loaded
|
||||
complete | | Callback function to execute when loader is done
|
||||
delimiter | , | [CSV only] a delimiter for columns (use \t for tab delimiters)
|
||||
emptyAs | undefined | [CSV only] replace empty columns with whatever is set here
|
||||
error | | Callback function to execute if file load fails
|
||||
init | | Callback function to execute when Data Loader is initialized, before any loading starts
|
||||
format | json | Type of data: json, csv
|
||||
headers | | An array of objects with two properties (key and value) to attach to HTTP request
|
||||
load | | Callback function to execute when file is successfully loaded (might be invoked multiple times)
|
||||
noStyles | false | If set to true no styles will be applied to "Data loading" curtain
|
||||
numberFields | | [CSV only] An array of fields in data to treat as numbers
|
||||
postProcess | | If set to function reference, that function will be called to "post-process" loaded data before passing it on to chart. The handler function will receive two parameters: loaded data, Data Loader options
|
||||
async | true | If set to false (not recommended), everything will wait until data is fully loaded.
|
||||
complete | | Callback function to execute when loader is done.
|
||||
delimiter | , | [CSV only] a delimiter for columns (use \t for tab delimiters).
|
||||
emptyAs | undefined | [CSV only] replace empty columns with whatever is set here.
|
||||
error | | Callback function to execute if file load fails.
|
||||
init | | Callback function to execute when Data Loader is initialized, before any loading starts.
|
||||
format | json | Type of data: json, csv.
|
||||
headers | | An array of objects with two properties (key and value) to attach to HTTP request.
|
||||
load | | Callback function to execute when file is successfully loaded (might be invoked multiple times).
|
||||
noStyles | false | If set to true, no styles will be applied to "Data loading" curtain.
|
||||
numberFields | | [CSV only] An array of fields in data to treat as numbers.
|
||||
postProcess | | If set to function reference, that function will be called to "post-process" loaded data before passing it on to chart. The handler function will receive two parameters: loaded data, Data Loader options.
|
||||
progress | | Set this to function reference to track progress of the load. The function will be passed in three parameters: global progress, individual file progress, file URL.
|
||||
showErrors | true | Show loading errors in a chart curtain
|
||||
showCurtain | true| Show curtain over the chart area when loading data
|
||||
reload | 0 | Reload data every X seconds
|
||||
reverse | false | [CSV only] add data points in revers order
|
||||
skip | 0 | [CSV only] skip X first rows in data (includes first row if useColumnNames is used)
|
||||
skipEmpty | true | [CSV only] Ignore empty lines in data
|
||||
timestamp | false | Add current timestamp to data URLs (to avoid caching)
|
||||
useColumnNames | false | [CSV only] Use first row in data as column names when parsing
|
||||
showErrors | true | Show loading errors in a chart curtain.
|
||||
showCurtain | true| Show curtain over the chart area when loading data.
|
||||
reload | 0 | Reload data every X seconds.
|
||||
reverse | false | [CSV only] add data points in revers order.
|
||||
skip | 0 | [CSV only] skip X first rows in data (includes first row if useColumnNames is used).
|
||||
skipEmpty | true | [CSV only] Ignore empty lines in data.
|
||||
timestamp | false | Add current timestamp to data URLs (to avoid caching).
|
||||
useColumnNames | false | [CSV only] Use first row in data as column names when parsing.
|
||||
|
||||
|
||||
## Using in JavaScript Stock Chart
|
||||
|
||||
In JavaScript Stock Chart it works exactly the same as in other chart types,
|
||||
In JavaScript Stock Chart, it works exactly the same as in other chart types,
|
||||
with the exception that `dataLoader` is set as a property to the data set
|
||||
definition. I.e.:
|
||||
|
||||
|
@ -251,9 +251,9 @@ The three available functions are as follows:
|
|||
|
||||
Function | Parameters | Description
|
||||
-------- | ---------- | -----------
|
||||
AmCharts.loadFile() | url, options, callback | Loads the file and passes it into callback function (unparsed)
|
||||
AmCharts.parseCSV() | data, options | Parses data in string CSV format and returns JavaScript Array
|
||||
AmCharts.parseJSON() | data | Parses data in string JSON format and returns JavaScript Array
|
||||
AmCharts.loadFile() | url, options, callback | Loads the file and passes it into callback function (unparsed).
|
||||
AmCharts.parseCSV() | data, options | Parses data in string CSV format and returns JavaScript Array.
|
||||
AmCharts.parseJSON() | data | Parses data in string JSON format and returns JavaScript Array.
|
||||
|
||||
The options passed into standalone functions are the same as discussed in [Complete list of available dataLoader settings](#complete-list-of-available-dataloader-settings) chapter.
|
||||
|
||||
|
@ -280,7 +280,7 @@ AmCharts.loadFile(dataset_url, {}, function(data) {
|
|||
|
||||
## Translating into other languages
|
||||
|
||||
Depending on configuration options the plugin will display a small number of
|
||||
Depending on configuration options, the plugin will display a small number of
|
||||
text prompts, like 'Data loading...'.
|
||||
|
||||
Plugin will try matching chart's `language` property and display text prompts in
|
||||
|
@ -354,72 +354,72 @@ http://www.apache.org/licenses/LICENSE-2.0
|
|||
## Changelog
|
||||
|
||||
### 1.0.16
|
||||
* Added "numberFields" config array
|
||||
* Added "numberFields" config array.
|
||||
|
||||
### 1.0.15
|
||||
* Added "emptyAs" config property. Empty CSV values will be set to this (default `undefined`)
|
||||
* Added "emptyAs" config property. Empty CSV values will be set to this (default `undefined`).
|
||||
|
||||
### 1.0.14
|
||||
* Added "init" event handler, which is called **before** loading starts
|
||||
* Added "init" event handler, which is called **before** loading starts.
|
||||
|
||||
### 1.0.13
|
||||
* Added "progress" handler, which can be used to monitor data load progress
|
||||
* Added "progress" handler, which can be used to monitor data load progress.
|
||||
|
||||
### 1.0.12
|
||||
* Better default options handling in external calls to AmCharts.loadFile
|
||||
* Fixed the latest version of Stock Chart not resetting to default pre-defined period
|
||||
* New example: Using Data Loader functions externally (map_json_external_function.html)
|
||||
* Better default options handling in external calls to AmCharts.loadFile.
|
||||
* Fixed the latest version of Stock Chart not resetting to default pre-defined period.
|
||||
* New example: Using Data Loader functions externally (map_json_external_function.html).
|
||||
|
||||
### 1.0.11
|
||||
* New translation: Added French translation. Thanks Remy!
|
||||
* Tweaks to allow better animation after data load on Pie chart
|
||||
* Tweaks to allow better animation after data load on Pie chart.
|
||||
|
||||
### 1.0.10
|
||||
* Fixed error related to headers not being set when using standalone data load functions
|
||||
* Fixed error related to headers not being set when using standalone data load functions.
|
||||
|
||||
### 1.0.9
|
||||
* Plugin will now ignore empty CSV lines by default (configurable with `skipEmpty` property)
|
||||
* Plugin will now ignore empty CSV lines by default (configurable with `skipEmpty` property).
|
||||
|
||||
### 1.0.8
|
||||
* Added `headers` config variable which allows adding custom headers to HTTP requests
|
||||
* Added `headers` config variable which allows adding custom headers to HTTP requests.
|
||||
|
||||
### 1.0.7
|
||||
* Fixed an issue with the Pie chart when it is being loaded in inactive tab
|
||||
* Fixed an issue with the Pie chart when it is being loaded in inactive tab.
|
||||
|
||||
### 1.0.6
|
||||
* Added support for Gauge chart (loads `arrows` array)
|
||||
* Added support for Gauge chart (loads `arrows` array).
|
||||
|
||||
### 1.0.5
|
||||
* Fixed JS error if periodSelector was not defined in chart config
|
||||
* Now all callback functions (complete, error, load) receive additional parameter: chart
|
||||
* postProcess function will now have "this" context set to Data Loader object as well as receive chart reference as third paramater
|
||||
* Fixed JS error if periodSelector was not defined in chart config.
|
||||
* Now all callback functions (complete, error, load) receive additional parameter: chart.
|
||||
* postProcess function will now have "this" context set to Data Loader object as well as receive chart reference as third parameter.
|
||||
|
||||
### 1.0.4
|
||||
* Added `chart.dataLoader.loadData()` function which can be used to manually trigger all data reload
|
||||
* Added `chart.dataLoader.loadData()` function which can be used to manually trigger all data reload.
|
||||
|
||||
### 1.0.3
|
||||
* Fixed the bug where defaults were not being applied properly
|
||||
* Fixed the bug with translations not being applied properly
|
||||
* Cleaned up the code (to pass JSHint validation)
|
||||
* Fixed the bug where defaults were not being applied properly.
|
||||
* Fixed the bug with translations not being applied properly.
|
||||
* Cleaned up the code (to pass JSHint validation).
|
||||
|
||||
### 1.0.2
|
||||
* Fixed the issue with modified Array prototypes
|
||||
* Fixed the issue with modified Array prototypes.
|
||||
|
||||
### 1.0.1
|
||||
* Added `complete`, `load` and `error` properties that can be set with function handlers to be invoked on load completion, successful file load or failed load respectively
|
||||
* Fixed language container initialization bug
|
||||
* Fixed bug that was causing parse errors not be displayed
|
||||
* Added `complete`, `load` and `error` properties that can be set with function handlers to be invoked on load completion, successful file load or failed load respectively.
|
||||
* Fixed language container initialization bug.
|
||||
* Fixed bug that was causing parse errors not be displayed.
|
||||
|
||||
### 1.0
|
||||
* Added GANTT chart support
|
||||
* Added GANTT chart support.
|
||||
|
||||
### 0.9.2
|
||||
* Added global data load methods that can be used to load and parse data by code outside plugin
|
||||
* Trim CSV column names
|
||||
* Translation added: Lithuanian
|
||||
* Added global data load methods that can be used to load and parse data by code outside plugin.
|
||||
* Trim CSV column names.
|
||||
* Translation added: Lithuanian.
|
||||
|
||||
### 0.9.1
|
||||
* Fix chart animations not playing after asynchronous load
|
||||
* Fix chart animations not playing after asynchronous load.
|
||||
|
||||
### 0.9
|
||||
* Initial release
|
||||
* Initial release.
|
||||
|
|
File diff suppressed because it is too large
Load diff
8
webroot/css/bids-chart.css
Normal file
8
webroot/css/bids-chart.css
Normal file
|
@ -0,0 +1,8 @@
|
|||
.bids-chart-container { width: 1200px; margin: 0 auto 48px auto; box-shadow: 0 2px 6px rgba(0,0,0,.175); border: 1px solid rgba(0,0,0,.15); padding: 24px 36px; position: relative; overflow: hidden }
|
||||
.bids-chart-container .load-progress { position: absolute; top: 0; left: 0; width: 100%; height: 3px; background: #1e88e5; animation: indeterminate 4s linear infinite; }
|
||||
.bids-chart-container .chart { height: 414px }
|
||||
.bids-chart-container .btn-chart-export { position: absolute; right: 40px; bottom: 36px }
|
||||
@keyframes indeterminate {
|
||||
from { left: -70%; }
|
||||
to { left: 100% }
|
||||
}
|
|
@ -81,18 +81,23 @@ border-radius: 0 8px 8px 0 }
|
|||
.claims-grid .claim-grid-item .thumbnail .autothumb { display: block; margin: 73px auto 0 auto; text-align: center; font-size: 240%; color: #fff; line-height: 54px }
|
||||
.claims-grid .claim-grid-item .tags > div { display: inline-block; padding: 4px 12px; margin-left: 2px }
|
||||
.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 }
|
||||
.claims-grid .claim-grid-item .link { font-size: 95%; font-weight: 300; margin-top: 3px; overflow: hidden; text-overflow: ellipsis; line-height: 20px; height: 20px; margin-top: 6px }
|
||||
|
||||
.claims-grid .claim-grid-item .label { font-size: 80%; color: #1e88e5 }
|
||||
.claims-grid .no-results {font-style: italic; width: 100%; height: 300px; text-align: center; font-size: 90%; color: grey; }
|
||||
.claims-grid .claim-grid-item .value { font-weight: 300; word-break: break-word; word-wrap: break-word; font-size: 95%; line-height: 24px; height: 24px }
|
||||
.claims-grid .claim-grid-item .half-width { width: 155px; float: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding-right: 12px }
|
||||
.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% }
|
||||
|
@ -219,7 +224,9 @@ footer .content .page-time { position: absolute; right: 12px; bottom: 0px; paddi
|
|||
.stats-main h3 { font-weight: 300; margin: 0 0 12px 0 }
|
||||
|
||||
.stats { width: 1000px; margin: 0 auto 48px auto; box-shadow: 0 2px 6px rgba(0,0,0,.175); border: 1px solid rgba(0,0,0,.15); padding: 24px; cursor: default }
|
||||
.stats .box { padding: 24px 0; border-right: 1px solid #ccc; float: left; text-align: center; width: 25% }
|
||||
.stats .box { padding: 24px 0; border-right: 1px solid #ccc; float: left; text-align: center }
|
||||
.stats .box-20 { width: 20% }
|
||||
.stats .box-30 { width: 30% }
|
||||
.stats .box .title { color: #1e88e5; font-size: 90% }
|
||||
.stats .box .value { font-size: 180%; font-weight: 300; margin-top: 8px }
|
||||
.stats .box.last { border-color: transparent }
|
||||
|
@ -252,6 +259,7 @@ footer .content .page-time { position: absolute; right: 12px; bottom: 0px; paddi
|
|||
.tx-details-layout .outputs .output .labels .support { background: #ffeb3b }
|
||||
.tx-details-layout .outputs .output .labels .update { background: #ea80fc }
|
||||
.tx-details-layout .outputs .output .labels .claim { background: #76ff03 }
|
||||
.tx-details-layout .outputs .output .view-claim { font-size: 80%; }
|
||||
.tx-details-layout .inputs .input .value, .tx-details-layout .outputs .output .value { font-weight: normal }
|
||||
.tx-details-layout .inputs .input.is-source, .tx-details-layout .outputs .output.is-source { border-right-width: 18px; border-right-color: #1e88e5; background: #e3f2fd }
|
||||
.tx-details-layout .inputs .input.highlighted, .tx-details-layout .outputs .output.highlighted { background: #f1f8e9 }
|
||||
|
@ -295,6 +303,7 @@ footer .content .page-time { position: absolute; right: 12px; bottom: 0px; paddi
|
|||
.tx-table td { vertical-align: top; line-height: 24px }
|
||||
.tx-table td.credit, .tx-table td div.credit { color: #00e676 }
|
||||
.tx-table td.debit, .tx-table td div.debit { color: #ff0000 }
|
||||
.tx-table td.diff, .tx-table td div.diff{ color: #337ab7 }
|
||||
.tx-table td div.debit { padding-top: 8px }
|
||||
|
||||
.pagination { width: 1200px; margin: 36px auto 0 auto; cursor: default }
|
||||
|
|
8
webroot/css/mining-inflation-chart.css
Normal file
8
webroot/css/mining-inflation-chart.css
Normal file
|
@ -0,0 +1,8 @@
|
|||
.mining-inflation-chart-container { width: 1200px; margin: 0 auto 48px auto; box-shadow: 0 2px 6px rgba(0,0,0,.175); border: 1px solid rgba(0,0,0,.15); padding: 24px 36px; position: relative; overflow: hidden }
|
||||
.mining-inflation-chart-container .load-progress { position: absolute; top: 0; left: 0; width: 100%; height: 3px; background: #1e88e5; animation: indeterminate 4s linear infinite; }
|
||||
.mining-inflation-chart-container .chart { height: 414px }
|
||||
.mining-inflation-chart-container .btn-chart-export { position: absolute; right: 40px; bottom: 36px }
|
||||
@keyframes indeterminate {
|
||||
from { left: -70%; }
|
||||
to { left: 100% }
|
||||
}
|
BIN
webroot/img/lbry.png
Normal file
BIN
webroot/img/lbry.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.6 KiB |
170
webroot/js/bids-chart.js
Normal file
170
webroot/js/bids-chart.js
Normal file
|
@ -0,0 +1,170 @@
|
|||
function buildChartData(claimsData) {
|
||||
var chartData = [];
|
||||
var lastDate = 0;
|
||||
var nbClaimsDay = 0;
|
||||
var nbClaimsTotal = 0;
|
||||
var bidClaimsDay = 0;
|
||||
var bidClaimsTotal = 0;
|
||||
var nbChannelsDay = 0;
|
||||
var nbChannelsTotal = 0;
|
||||
for(var i = 0; i < claimsData.length; i++) {
|
||||
if(claimsData[i].transaction_time == 0) {
|
||||
continue;
|
||||
}
|
||||
var transactionDate = new Date(claimsData[i].transaction_time * 1000);
|
||||
transactionDate.setHours(0,0,0,0)
|
||||
if(lastDate == 0) {
|
||||
lastDate = transactionDate;
|
||||
}
|
||||
if(transactionDate.toString() != lastDate.toString()) {
|
||||
nbClaimsTotal += nbClaimsDay;
|
||||
bidClaimsTotal += bidClaimsDay;
|
||||
var dateData = {
|
||||
date: lastDate,
|
||||
NumberClaims: nbClaimsTotal,
|
||||
BidsClaims: bidClaimsTotal,
|
||||
};
|
||||
chartData.push(dateData);
|
||||
nbClaimsDay = 0;
|
||||
bidClaimsDay = 0;
|
||||
lastDate = transactionDate;
|
||||
}
|
||||
if(claimsData[i].claim_type == 1) {
|
||||
nbClaimsDay += 1;
|
||||
bidClaimsDay += claimsData[i].effective_amount/100000000;
|
||||
}
|
||||
}
|
||||
return chartData;
|
||||
}
|
||||
|
||||
function loadChartData() {
|
||||
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');
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: 'get',
|
||||
dataType: 'json',
|
||||
beforeSend: function() {
|
||||
chartLoadInProgress = true;
|
||||
loadProgress.css({ display: 'block' });
|
||||
},
|
||||
success: function(response) {
|
||||
if(response.success) {
|
||||
chartData = buildChartData(response.data);
|
||||
if(chart) {
|
||||
chart.dataProvider = chartData;
|
||||
chart.validateNow();
|
||||
chart.validateData();
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.log("Could not fetch block data.");
|
||||
}
|
||||
},
|
||||
complete: function() {
|
||||
chartLoadInProgress = false;
|
||||
loadProgress.css({ display: 'none' });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var chart;
|
||||
var chartData = [];
|
||||
var chartLoadInProgress = false;
|
||||
AmCharts.ready(function() {
|
||||
chart = AmCharts.makeChart('bids-chart', {
|
||||
type: 'serial',
|
||||
theme: 'light',
|
||||
mouseWheelZoomEnabled: true,
|
||||
height: '100%',
|
||||
categoryField: 'date',
|
||||
synchronizeGrid: true,
|
||||
dataProvider: chartData,
|
||||
responsive: {
|
||||
enabled: true,
|
||||
},
|
||||
valueAxes: [
|
||||
{
|
||||
id: 'v-number-claims',
|
||||
axisColor: '#1e88e5',
|
||||
axisThickness: 2,
|
||||
position: 'left',
|
||||
},
|
||||
{
|
||||
id: 'v-bids-claims',
|
||||
axisColor: '#0b7a06',
|
||||
axisThickness: 2,
|
||||
position: 'left',
|
||||
offset: 75,
|
||||
},
|
||||
],
|
||||
categoryAxis: {
|
||||
parseDates: true,
|
||||
autoGridCount: false,
|
||||
minorGridEnabled: true,
|
||||
minorGridAlpha: 0.04,
|
||||
axisColor: '#dadada',
|
||||
twoLineMode: true
|
||||
},
|
||||
graphs: [
|
||||
{
|
||||
id: 'g-number-claims',
|
||||
valueAxis: 'v-number-claims',
|
||||
title: 'Number of claims',
|
||||
valueField: 'NumberClaims',
|
||||
bullet: 'round',
|
||||
bulletBorderThickness: 1,
|
||||
bulletBorderAlpha: 1,
|
||||
bulletColor: '#ffffff',
|
||||
bulletSize: 5,
|
||||
useLineColorForBulletBorder: true,
|
||||
lineColor: '#1e88e5',
|
||||
hideBulletsCount: 101,
|
||||
balloonText: '[[NumberClaims]]',
|
||||
},
|
||||
{
|
||||
id: 'g-bids-claims',
|
||||
valueAxis: 'v-bids-claims',
|
||||
title: 'Bids for claims (LBC)',
|
||||
valueField: 'BidsClaims',
|
||||
bullet: 'round',
|
||||
bulletBorderThickness: 1,
|
||||
bulletBorderAlpha: 1,
|
||||
bulletColor: '#ffffff',
|
||||
bulletSize: 5,
|
||||
useLineColorForBulletBorder: true,
|
||||
lineColor: '#0b7a06',
|
||||
balloonText: '[[BidsClaims]] LBC',
|
||||
hideBulletsCount: 101
|
||||
},
|
||||
],
|
||||
chartCursor: {
|
||||
cursorAlpha: 0.1,
|
||||
fullWidth: true,
|
||||
valueLineBalloonEnabled: true,
|
||||
categoryBalloonColor: '#333333',
|
||||
cursorColor: '#1e88e5'
|
||||
},
|
||||
chartScrollbar: {
|
||||
scrollbarHeight: 36,
|
||||
color: '#888888',
|
||||
gridColor: '#bbbbbb'
|
||||
},
|
||||
legend: {
|
||||
marginLeft: 110,
|
||||
useGraphSettings: true,
|
||||
valueText: "",
|
||||
spacing: 64,
|
||||
|
||||
},
|
||||
export: {
|
||||
enabled: true,
|
||||
fileName: 'lbry-bids-chart',
|
||||
position: 'bottom-right',
|
||||
divId: 'chart-export'
|
||||
}
|
||||
});
|
||||
loadChartData();
|
||||
});
|
228
webroot/js/block-size-chart.js
Normal file
228
webroot/js/block-size-chart.js
Normal file
|
@ -0,0 +1,228 @@
|
|||
var chart;
|
||||
var chartData = [];
|
||||
var chartLoadInProgress = false;
|
||||
var minPeriod = 'hh';
|
||||
var validPeriods = ['24h', '72h', '168h', '30d', '90d', '1y'];
|
||||
var defaultPeriod = (validPeriods.indexOf(localStorage.getItem('chartPeriod')) > -1) ? localStorage.getItem('chartPeriod') : '24h';
|
||||
var periodGridCounts = {'24h': 24, '72h': 24, '168h': 14, '30d': 30, '90d': 45, '1y': 12 };
|
||||
AmCharts.ready(function() {
|
||||
chart = AmCharts.makeChart('block-size-chart', {
|
||||
type: 'serial',
|
||||
theme: 'light',
|
||||
mouseWheelZoomEnabled: true,
|
||||
categoryField: 'date',
|
||||
synchronizeGrid: true,
|
||||
dataProvider: chartData,
|
||||
valueAxes: [
|
||||
{
|
||||
id: 'v-block-size',
|
||||
axisColor: '#1e88e5',
|
||||
axisThickness: 2,
|
||||
labelFunction: function(value) {
|
||||
return (Math.round((value / 1000) * 100)/100).toFixed(2) + ' KB';
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'v-price',
|
||||
axisColor: '#00e676',
|
||||
offset: 75,
|
||||
gridAlpha: 0,
|
||||
axisThickness: 2,
|
||||
labelFunction: function(value) {
|
||||
return '$' + value.toFixed(2);
|
||||
}
|
||||
}
|
||||
],
|
||||
categoryAxis: {
|
||||
parseDates: true,
|
||||
minPeriod: minPeriod, // DD for daily
|
||||
autoGridCount: false,
|
||||
minorGridEnabled: true,
|
||||
minorGridAlpha: 0.04,
|
||||
axisColor: '#dadada',
|
||||
twoLineMode: true,
|
||||
dateFormats: [{
|
||||
period: 'fff',
|
||||
format: 'JJ:NN:SS'
|
||||
}, {
|
||||
period: 'ss',
|
||||
format: 'JJ:NN:SS'
|
||||
}, {
|
||||
period: 'mm',
|
||||
format: 'JJ:NN'
|
||||
}, {
|
||||
period: 'hh',
|
||||
format: 'JJ:NN'
|
||||
}, {
|
||||
period: 'DD',
|
||||
format: 'DD'
|
||||
}, {
|
||||
period: 'WW',
|
||||
format: 'DD MMM'
|
||||
}, {
|
||||
period: 'MM',
|
||||
format: 'MMM'
|
||||
}, {
|
||||
period: 'YYYY',
|
||||
format: 'YYYY'
|
||||
}]
|
||||
},
|
||||
graphs: [
|
||||
{
|
||||
id: 'g-block-size',
|
||||
valueAxis: 'v-block-size', // we have to indicate which value axis should be used
|
||||
title: 'Avg Block Size',
|
||||
valueField: 'AvgBlockSize',
|
||||
bullet: 'round',
|
||||
bulletBorderThickness: 1,
|
||||
bulletBorderAlpha: 1,
|
||||
bulletColor: '#ffffff',
|
||||
bulletSize: 5,
|
||||
useLineColorForBulletBorder: true,
|
||||
lineColor: '#1e88e5',
|
||||
hideBulletsCount: 101,
|
||||
balloonText: '[[AvgBlockSize]] KB',
|
||||
switchable: false,
|
||||
balloonFunction: function(item, graph) {
|
||||
var result = graph.balloonText;
|
||||
return result.replace('[[AvgBlockSize]]', (Math.round((item.dataContext.AvgBlockSize / 1000) * 100)/100).toFixed(2));
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'g-price',
|
||||
valueAxis: 'v-price',
|
||||
title: 'Average Price',
|
||||
valueField: 'AvgUSD',
|
||||
bullet: 'round',
|
||||
bulletBorderThickness: 1,
|
||||
bulletBorderAlpha: 1,
|
||||
bulletColor: '#ffffff',
|
||||
bulletSize: 5,
|
||||
useLineColorForBulletBorder: true,
|
||||
lineColor: '#00e676',
|
||||
balloonText: '$[[AvgUSD]]',
|
||||
balloonFunction: function(item, graph) {
|
||||
var result = graph.balloonText;
|
||||
if (!item.dataContext.AvgUSD) {
|
||||
return '';
|
||||
}
|
||||
return result.replace('[[AvgUSD]]', item.dataContext.AvgUSD.toFixed(2));
|
||||
},
|
||||
hideBulletsCount: 101,
|
||||
labelFunction: function(value) {
|
||||
return '$' + value;
|
||||
},
|
||||
}
|
||||
],
|
||||
chartCursor: {
|
||||
cursorAlpha: 0.1,
|
||||
fullWidth: true,
|
||||
valueLineBalloonEnabled: true,
|
||||
categoryBalloonColor: '#333333',
|
||||
cursorColor: '#1e88e5',
|
||||
categoryBalloonDateFormat: minPeriod === 'hh' ? 'D MMM HH:NN ' : 'D MMM'
|
||||
},
|
||||
chartScrollbar: {
|
||||
scrollbarHeight: 36,
|
||||
color: '#888888',
|
||||
gridColor: '#bbbbbb'
|
||||
},
|
||||
legend: {
|
||||
marginLeft: 110,
|
||||
useGraphSettings: true,
|
||||
valueAlign: 'right',
|
||||
valueWidth: 60,
|
||||
spacing: 64,
|
||||
valueFunction: function(item, formatted) {
|
||||
if (item.dataContext) {
|
||||
var g = item.graph;
|
||||
if (g.id === 'g-block-size' && item.dataContext.AvgBlockSize > 0) {
|
||||
return g.balloonText.replace('[[AvgBlockSize]]', (Math.round((item.dataContext.AvgBlockSize / 1000) * 100)/100).toFixed(2) );
|
||||
}
|
||||
if (g.id === 'g-price' && item.dataContext.AvgUSD) {
|
||||
return g.balloonText.replace('[[AvgUSD]]', item.dataContext.AvgUSD.toFixed(2));
|
||||
}
|
||||
}
|
||||
|
||||
return formatted;
|
||||
}
|
||||
},
|
||||
export: {
|
||||
enabled: true,
|
||||
fileName: 'lbry-block-size-chart',
|
||||
position: 'bottom-right',
|
||||
divId: 'chart-export'
|
||||
}
|
||||
});
|
||||
|
||||
loadChartData(defaultPeriod);
|
||||
});
|
||||
|
||||
var loadChartData = function(dataPeriod) {
|
||||
var loadProgress = $('.block-size-chart-container .load-progress');
|
||||
// clear previous chart data
|
||||
$.ajax({
|
||||
url: '/api/v1/charts/blocksize/' + dataPeriod,
|
||||
type: 'get',
|
||||
dataType: 'json',
|
||||
beforeSend: function() {
|
||||
chartLoadInProgress = true;
|
||||
loadProgress.css({ display: 'block' });
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
chartData = [];
|
||||
var data = response.data;
|
||||
for (var period in data) {
|
||||
if (data.hasOwnProperty(period)) {
|
||||
chartData.push({
|
||||
date: Date.parse(period),
|
||||
AvgBlockSize: data[period].AvgBlockSize,
|
||||
AvgUSD: data[period].AvgUSD
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// save selcted period to localStorage
|
||||
localStorage.setItem('chartPeriod', dataPeriod);
|
||||
|
||||
if (chart) {
|
||||
var isHourly = (dataPeriod.indexOf('h') > -1);
|
||||
var gridCount = periodGridCounts[dataPeriod];
|
||||
chart.categoryAxis.minPeriod = isHourly ? 'hh' : 'DD';
|
||||
chart.categoryAxis.dateFormats[4].format = isHourly ? 'DD MMM' : 'DD';
|
||||
chart.chartCursor.categoryBalloonDateFormat = isHourly ? 'D MMM HH:NN ' : 'D MMM YYYY';
|
||||
chart.categoryAxis.gridCount = gridCount;
|
||||
chart.chartScrollbar.gridCount = gridCount;
|
||||
chart.dataProvider = chartData;
|
||||
chart.validateNow();
|
||||
chart.validateData();
|
||||
}
|
||||
}
|
||||
},
|
||||
complete: function() {
|
||||
chartLoadInProgress = false;
|
||||
loadProgress.css({ display: 'none' });
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$(document).ready(function() {
|
||||
$('.block-size-data-links a').on('click', function(evt) {
|
||||
evt.preventDefault();
|
||||
if (chartLoadInProgress) {
|
||||
return;
|
||||
}
|
||||
|
||||
var link = $(this);
|
||||
if (link.hasClass('active')) {
|
||||
return;
|
||||
}
|
||||
|
||||
link.addClass('active').siblings().removeClass('active');
|
||||
var period = link.attr('data-period');
|
||||
loadChartData(period);
|
||||
});
|
||||
|
||||
$('a[data-period="' + defaultPeriod + '"]').addClass('active').siblings().removeClass('active');
|
||||
});
|
264
webroot/js/mining-inflation-chart.js
Normal file
264
webroot/js/mining-inflation-chart.js
Normal file
|
@ -0,0 +1,264 @@
|
|||
function getReward(blockHeight) {
|
||||
if (blockHeight == 0) {
|
||||
return 400000000;
|
||||
}
|
||||
else if (blockHeight <= 5100) {
|
||||
return 1;
|
||||
}
|
||||
else if (blockHeight <= 55000) {
|
||||
return 1 + Math.floor((blockHeight - 5001) / 100);
|
||||
}
|
||||
else {
|
||||
var level = Math.floor((blockHeight - 55001) / 32);
|
||||
var reduction = Math.floor((Math.floor(Math.sqrt((8 * level) + 1)) - 1) / 2);
|
||||
while(!(withinLevelBounds(reduction, level))) {
|
||||
if(Math.floor((reduction * reduction + reduction) / 2) > level) {
|
||||
reduction--;
|
||||
}
|
||||
else {
|
||||
reduction++;
|
||||
}
|
||||
}
|
||||
return Math.max(0, 500 - reduction);
|
||||
}
|
||||
}
|
||||
|
||||
function withinLevelBounds(reduction, level) {
|
||||
if(Math.floor((reduction * reduction + reduction) / 2) > level) {
|
||||
return false;
|
||||
}
|
||||
reduction += 1;
|
||||
if(Math.floor((reduction * reduction + reduction) / 2) <= level) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function getAverageBlockTime(blocks) {
|
||||
var numBlocks = blocks.length;
|
||||
var windowSize = 100;
|
||||
var sum = 0;
|
||||
for(i = numBlocks - windowSize; i < numBlocks; i++) {
|
||||
sum += blocks[i].block_time - blocks[i-1].block_time;
|
||||
}
|
||||
return sum / windowSize;
|
||||
}
|
||||
|
||||
function buildChartData(blockData) {
|
||||
var chartData = [];
|
||||
var supply = 0;
|
||||
var reward = 0;
|
||||
var averageBlockTime = getAverageBlockTime(blockData);
|
||||
var blockTime = 0;
|
||||
var lastBlock = 4071017; // Last block with reward
|
||||
var skip = 100;
|
||||
var blocksPerYear = Math.floor((3600*24*365) / averageBlockTime);
|
||||
var historicalSupply = {};
|
||||
var lastYearSupply = 0;
|
||||
var lastYearBlock = 0;
|
||||
var inflationRate = 0;
|
||||
for(var i = 0; i < lastBlock; i++) {
|
||||
reward = getReward(i);
|
||||
supply += reward;
|
||||
historicalSupply[i + 1] = supply;
|
||||
if(i == 0) { // Reward for 1st block set to 0 for scale
|
||||
reward = 0;
|
||||
}
|
||||
if(i < blockData.length) {
|
||||
// Historical Data
|
||||
var b = blockData[i];
|
||||
blockTime = b.block_time;
|
||||
}
|
||||
else {
|
||||
// Future blocks
|
||||
skip = 1000;
|
||||
blockTime += averageBlockTime;
|
||||
}
|
||||
// Inflation Rate
|
||||
if(i + 1 - blocksPerYear <= 0) {
|
||||
lastYearBlock = 1;
|
||||
}
|
||||
else {
|
||||
lastYearBlock = i + 1 - blocksPerYear;
|
||||
}
|
||||
lastYearSupply = historicalSupply[lastYearBlock];
|
||||
inflationRate = ((supply - lastYearSupply) / lastYearSupply) * 100;
|
||||
if(i % skip == 0) { // Only push 1/<skip> of all blocks to optimize data loading
|
||||
chartData.push({
|
||||
date: new Date(blockTime * 1000),
|
||||
AvailableSupply: supply,
|
||||
RewardLBC: reward,
|
||||
InflationRate: inflationRate,
|
||||
BlockId: i + 1
|
||||
});
|
||||
}
|
||||
}
|
||||
return chartData;
|
||||
}
|
||||
|
||||
function loadChartData() {
|
||||
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');
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: 'get',
|
||||
dataType: 'json',
|
||||
beforeSend: function() {
|
||||
chartLoadInProgress = true;
|
||||
loadProgress.css({ display: 'block' });
|
||||
},
|
||||
success: function(response) {
|
||||
if(response.success) {
|
||||
chartData = buildChartData(response.data);
|
||||
if(chart) {
|
||||
chart.dataProvider = chartData;
|
||||
chart.validateNow();
|
||||
chart.validateData();
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.log("Could not fetch block data.");
|
||||
}
|
||||
},
|
||||
complete: function() {
|
||||
chartLoadInProgress = false;
|
||||
loadProgress.css({ display: 'none' });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var chart;
|
||||
var chartData = [];
|
||||
var chartLoadInProgress = false;
|
||||
AmCharts.ready(function() {
|
||||
chart = AmCharts.makeChart('mining-inflation-chart', {
|
||||
type: 'serial',
|
||||
theme: 'light',
|
||||
mouseWheelZoomEnabled: true,
|
||||
height: '100%',
|
||||
categoryField: 'date',
|
||||
synchronizeGrid: true,
|
||||
dataProvider: chartData,
|
||||
responsive: {
|
||||
enabled: true,
|
||||
},
|
||||
valueAxes: [
|
||||
{
|
||||
id: 'v-supply',
|
||||
axisColor: '#1e88e5',
|
||||
axisThickness: 2,
|
||||
position: 'left',
|
||||
labelFunction: function(value) {
|
||||
return (Math.round((value / 1000000) * 1000000)/1000000).toFixed(2);
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'v-reward',
|
||||
axisColor: '#0b7a06',
|
||||
axisThickness: 2,
|
||||
position: 'left',
|
||||
offset: 75,
|
||||
},
|
||||
{
|
||||
id: 'v-inflation-rate',
|
||||
axisColor: '#ff9900',
|
||||
axisThickness: 2,
|
||||
position: 'right',
|
||||
labelFunction: function(value) {
|
||||
return value.toFixed(2);
|
||||
}
|
||||
},
|
||||
],
|
||||
categoryAxis: {
|
||||
parseDates: true,
|
||||
autoGridCount: false,
|
||||
minorGridEnabled: true,
|
||||
minorGridAlpha: 0.04,
|
||||
axisColor: '#dadada',
|
||||
twoLineMode: true
|
||||
},
|
||||
graphs: [
|
||||
{
|
||||
id: 'g-supply',
|
||||
valueAxis: 'v-supply', // we have to indicate which value axis should be used
|
||||
title: 'Available supply (millions LBC)',
|
||||
valueField: 'AvailableSupply',
|
||||
bullet: 'round',
|
||||
bulletBorderThickness: 1,
|
||||
bulletBorderAlpha: 1,
|
||||
bulletColor: '#ffffff',
|
||||
bulletSize: 5,
|
||||
useLineColorForBulletBorder: true,
|
||||
lineColor: '#1e88e5',
|
||||
hideBulletsCount: 101,
|
||||
balloonText: '[[AvailableSupply]]',
|
||||
balloonFunction: function(item, graph) {
|
||||
var result = graph.balloonText;
|
||||
return result.replace('[[AvailableSupply]]', (Math.round((item.dataContext.AvailableSupply / 1000000) * 1000000)/1000000).toFixed(2));
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'g-reward',
|
||||
valueAxis: 'v-reward',
|
||||
title: 'Block Reward (LBC)',
|
||||
valueField: 'RewardLBC',
|
||||
bullet: 'round',
|
||||
bulletBorderThickness: 1,
|
||||
bulletBorderAlpha: 1,
|
||||
bulletColor: '#ffffff',
|
||||
bulletSize: 5,
|
||||
useLineColorForBulletBorder: true,
|
||||
lineColor: '#0b7a06',
|
||||
balloonText: '[[RewardLBC]] LBC<br>Block [[BlockId]]',
|
||||
hideBulletsCount: 101
|
||||
},
|
||||
{
|
||||
id: 'g-inflation-rate',
|
||||
valueAxis: 'v-inflation-rate',
|
||||
title: 'Annualized Inflation Rate',
|
||||
valueField: 'InflationRate',
|
||||
bullet: 'round',
|
||||
bulletBorderThickness: 1,
|
||||
bulletBorderAlpha: 1,
|
||||
bulletColor: '#ffffff',
|
||||
bulletSize: 5,
|
||||
useLineColorForBulletBorder: true,
|
||||
lineColor: '#ff9900',
|
||||
balloonText: '[[InflationRate]]%',
|
||||
hideBulletsCount: 101,
|
||||
balloonFunction: function(item, graph) {
|
||||
var result = graph.balloonText;
|
||||
return result.replace('[[InflationRate]]', item.dataContext.InflationRate.toFixed(2));
|
||||
}
|
||||
}
|
||||
],
|
||||
chartCursor: {
|
||||
cursorAlpha: 0.1,
|
||||
fullWidth: true,
|
||||
valueLineBalloonEnabled: true,
|
||||
categoryBalloonColor: '#333333',
|
||||
cursorColor: '#1e88e5'
|
||||
},
|
||||
chartScrollbar: {
|
||||
scrollbarHeight: 36,
|
||||
color: '#888888',
|
||||
gridColor: '#bbbbbb'
|
||||
},
|
||||
legend: {
|
||||
marginLeft: 110,
|
||||
useGraphSettings: true,
|
||||
valueText: "",
|
||||
spacing: 64,
|
||||
|
||||
},
|
||||
export: {
|
||||
enabled: true,
|
||||
fileName: 'lbry-supply-chart',
|
||||
position: 'bottom-right',
|
||||
divId: 'chart-export'
|
||||
}
|
||||
});
|
||||
loadChartData();
|
||||
});
|
Loading…
Reference in a new issue