Switch to chainquery

This commit is contained in:
Ben van Hartingsveldt 2025-06-27 16:22:05 +02:00
parent aa6f86b014
commit 09800ab844
No known key found for this signature in database
GPG key ID: 261AA214130CE7AB
36 changed files with 230 additions and 3337 deletions

View file

@ -1,258 +0,0 @@
<?php
namespace App\Console\Commands;
use DateInterval;
use DateTime;
use DateTimeZone;
use Exception;
use PDO;
use App\Models\Address;
use App\Models\TagAddressRequest;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;
class AuxCommand extends Command{
const bittrex = 'https://api.bittrex.com/v3/markets/LBC-BTC/ticker';
const coingeckoURL = 'https://api.coingecko.com/api/v3/simple/price?ids=lbry-credits&vs_currencies=btc';
const blockchainticker = 'https://blockchain.info/ticker';
const lbcpricekey = 'lbc.price';
const pubKeyAddress = [0, 85];
const scriptAddress = [5, 122];
const tagrcptaddress = 'bLockNgmfvnnnZw7bM6SPz6hk5BVzhevEp';
public static string $rpcurl;
/**
* The console command description.
* @var string
*/
protected $description = 'LBRY Block Explorer - Block auxiliary command';
/**
* The name and signature of the console command.
* @var string
*/
protected $signature = 'explorer:aux {function?}';
/**
* Execute the console command.
*/
public function handle(): void{
self::$rpcurl = config('lbry.rpc_url');
$function = $this->argument('function');
if($function){
$this->$function();
}else{
$this->warn('No arguments specified');
}
}
/**
* @throws \Throwable
*/
public function verifytags(): void{
self::lock('auxverify');
$conn = DB::connection();
$requests = TagAddressRequest::query()->where('IsVerified','<>',1)->get();
foreach ($requests AS $req) {
echo "Verifying tag for $req->Address, amount: $req->VerificationAmount... ";
$req_date = $req->Created;
$src_addr = $req->Address;
$dst_addr = self::tagrcptaddress;
// find a transaction with the corresponding inputs created on or after the date
// look for the address ids
$address = Address::query()->select(['Id'])->where('Address',$src_addr)->first();
$veri_address = Address::query()->select(['Id'])->where('Address',$dst_addr)->first(); // TODO: Redis cache?
if (!$address || !$veri_address) {
echo "could not find source nor verification addresses. Skipping.\n";
continue;
}
$src_addr_id = $address->Id;
$dst_addr_id = $veri_address->Id;
// find the inputs for the source address that were created after $req->Created - 1 hour
$req_date->sub(new DateInterval('PT1H'));
$stmt = $conn->getPdo()->query('SELECT DISTINCT I.TransactionId FROM Inputs I ' .
'RIGHT JOIN (SELECT IIA.InputId FROM InputsAddresses IIA WHERE IIA.AddressId = ?) IA ON IA.InputId = I.Id ' .
'JOIN Transactions T ON T.Id = I.TransactionId ' .
'LEFT JOIN Blocks B ON B.Hash = T.BlockHash ' .
'WHERE B.Confirmations > 0 AND DATE(I.Created) >= ?', [$src_addr_id, $req_date->format('Y-m-d')]);
$tx_inputs = $stmt->fetchAll(PDO::FETCH_OBJ);
$param_values = [$dst_addr_id];
$params = [];
foreach ($tx_inputs as $in) {
$params[] = '?';
$param_values[] = $in->TransactionId;
}
$num_inputs = count($tx_inputs);
echo "***found $num_inputs inputs from address $src_addr.\n";
if ($num_inputs == 0) {
continue;
}
try {
// check the outputs with the dst address
$total_amount = 0;
$stmt = $conn->getPdo()->query(sprintf('SELECT O.Value FROM Outputs O ' .
'RIGHT JOIN (SELECT IOA.OutputId, IOA.AddressId FROM OutputsAddresses IOA WHERE IOA.AddressId = ?) OA ON OA.OutputId = O.Id ' .
'WHERE O.TransactionId IN (%s)', implode(', ', $params)), $param_values);
$tx_outputs = $stmt->fetchAll(PDO::FETCH_OBJ);
foreach ($tx_outputs as $out) {
echo "***found output to verification address with value " . $out->Value . "\n";
$total_amount = bcadd($total_amount, $out->Value, 8);
}
if ($total_amount >= $req->VerificationAmount) {
$conn->beginTransaction();
echo "***$total_amount is gte verification amount: $req->VerificationAmount.\n";
// Update the tag in the DB
$conn->statement('UPDATE Addresses SET Tag = ?, TagUrl = ? WHERE Address = ?', [$req->Tag, $req->TagUrl, $src_addr]);
// Set the request as verified
$conn->statement('UPDATE TagAddressRequests SET IsVerified = 1 WHERE Id = ?', [$req->Id]);
$conn->commit();
echo "Data committed.\n";
} else {
echo "***$total_amount is NOT up to verification amount: $req->VerificationAmount.\n";
}
} catch (Exception $e) {
print_r($e);
echo "Rolling back.\n";
$conn->rollback();
}
}
self::unlock('auxverify');
}
public function pricehistory(): void{
self::lock('pricehistory');
$conn = DB::connection('localdb');
$redis = Redis::connection();
try {
// Only allow 5-minute update intervals
$stmt = $conn->getPdo()->query('SELECT MAX(Created) AS LastUpdate FROM PriceHistory');
$res = $stmt->fetch(PDO::FETCH_OBJ);
$now = new DateTime('now', new DateTimeZone('UTC'));
if ($res && strlen(trim($res->LastUpdate)) > 0) {
$dt = new DateTime($res->LastUpdate, new DateTimeZone('UTC'));
$diff = $now->diff($dt);
$diffMinutes = $diff->i;
if ($diffMinutes < 5) {
echo "Last update is less than 5 minutes ago. Quitting.\n";
self::unlock('pricehistory');
return;
}
}
$coingeckoJSON = Cache::remember('coingecko',60,static function(){
return json_decode(self::curl_get(self::coingeckoURL));
});
$blckjson = json_decode(self::curl_get(self::blockchainticker));
if ($coingeckoJSON) {
$btc = $coingeckoJSON->{'lbry-credits'}->btc;
$usd = 0;
if (isset($blckjson->USD)) {
$usd = $btc * $blckjson->USD->buy;
$priceInfo = [
'price' => number_format($usd, 3, '.', ''),
'time' => $now->format('c'),
];
if ($redis) {
$redis->client()->set(self::lbcpricekey, json_encode($priceInfo));
}
// save the price history if both prices are > 0
if ($usd > 0 && $btc > 0) {
$conn->statement('INSERT INTO PriceHistory (USD, BTC, Created) VALUES (?, ?, UTC_TIMESTAMP())', [$usd, $btc]);
echo "Inserted price history item. USD: $usd, BTC: $btc.\n";
} else {
echo "Could not insert price history item. USD: $usd, BTC: $btc.\n";
}
}
} else {
echo "CoinGecko requrest returned an invalid result.\n";
}
} catch (Exception $e) {
print_r($e);
}
self::unlock('pricehistory');
}
/**
* Lock
* @param $process_name
* @return void
*/
public static function lock($process_name): void{
$lock = Cache::lock($process_name);
if(!$lock->get()){
echo $process_name." is already running.\n";
exit(0);
}
}
/**
* Unlock
* @param $process_name
* @return bool
*/
public static function unlock($process_name): bool{
return Cache::lock($process_name)->release();
}
/**
* @param $url
* @return string
* @throws Exception
*/
public static function curl_get($url): string{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
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);
}
return $response;
}
}

File diff suppressed because it is too large Load diff

View file

@ -22,11 +22,11 @@ class ClaimsController extends Controller{
$order = 'RAND() ASC';
break;
case 'oldest':
$order = 'Created ASC';
$order = 'created_at ASC';
break;
case 'newest':
default:
$order = 'Created DESC';
$order = 'created_at DESC';
break;
}
@ -39,22 +39,22 @@ class ClaimsController extends Controller{
}
$conditions = [
['ThumbnailUrl','IS','NOT NULL'],
['LENGTH(TRIM(ThumbnailUrl))','>',0],
['IsFiltered','<>',1],
['thumbnail_url','IS','NOT NULL'],
['LENGTH(TRIM(thumbnail_url))','>',0],
['is_filtered','<>',1],
];
if ($afterId > 0) {
$conditions[] = ['Id','>',$afterId];
$conditions[] = ['id','>',$afterId];
} else if ($beforeId) {
$conditions[] = ['Id','<',$beforeId];
$conditions[] = ['id','<',$beforeId];
}
if ($nsfw !== 'true') {
$conditions[] = ['IsNSFW','<>',1];
$conditions[] = ['is_nsfw','<>',1];
}
//->contain(['Stream', 'Publisher' => ['fields' => ['Name']]])
$claims = Claim::query()->distinct(['ClaimId'])->where($conditions)->limit($pageLimit)->orderByRaw($order)->get();
$claims = Claim::query()->distinct(['claim_id'])->where($conditions)->limit($pageLimit)->orderByRaw($order)->get();
return [
'success' => true,

View file

@ -127,9 +127,8 @@ class MainController extends Controller{
*/
public function index(): JsonResponse|Response|View{
$lbcUsdPrice = $this->_getLatestPrice();
$blocks = Block::query()->select(['Chainwork','Confirmations','Difficulty','Hash','Height','BlockTime','BlockSize'])->selectRaw('JSON_LENGTH(`TransactionHashes`) AS tx_count')->orderByDesc('Height')->limit(6)->get();
$claims = Claim::query()->limit(5)->get();
//$claims = $this->Claims->find()->select($this->Claims)->select(['publisher' => 'C.name'])->leftJoin(['C' => 'claim'], ['C.claim_id = Claims.publisher_id'])->order(['Claims.created_at' => 'DESC'])->limit(5)->toArray();
$blocks = Block::query()->select(['chainwork', 'confirmations', 'difficulty', 'hash', 'height', 'block_time', 'block_size','tx_count'])->orderByDesc('height')->limit(6)->get();
$claims = Claim::query()->leftJoin('claim AS c','c.claim_id','=','claim.publisher_id')->orderByDesc('claim.created_at')->limit(5)->get();
$hashRate = $this->_formatHashRate($this->_gethashrate());
return self::generateResponse('main.index',[
@ -166,7 +165,7 @@ class MainController extends Controller{
// $count = $stmt->fetch(\PDO::FETCH_OBJ);
$numClaims = 20000000;
$stmt = $conn->getPdo()->query('SELECT MAX(Id) AS MaxId FROM Claims');
$stmt = $conn->getPdo()->query('SELECT MAX(Id) AS MaxId FROM claim');
$res = $stmt->fetch(PDO::FETCH_OBJ);
$maxClaimId = $res->MaxId;
@ -185,7 +184,7 @@ class MainController extends Controller{
}
$blockedList = json_decode($this->_getBlockedList());
$claims = [];//Claim::query()->selectRaw('Name AS Publisher')->addSelect(['publisher' => 'C.name', 'publisher_transaction_hash_id' => 'C.transaction_hash_id', 'publisher_vout' => 'C.vout'])->leftJoin('Claims','claim_id','=','Claims.publisher_id')->where('Claims.id','>',$startLimitId)->where( 'Claims.Id','<=',$endLimitId)->orderByDesc('Id')->get();
$claims = Claim::query()->select(['claim.*'])->addSelect(['c.name AS publisher','c.transaction_hash_id AS publisher_transaction_hash_id','c.vout AS publisher_vout'])->leftJoin('claim AS c','c.claim_id','=','claim.publisher_id')->where('claim.id','>',$startLimitId)->where('claim.id','<=',$endLimitId)->orderByDesc('claim.id')->get();
for ($i = 0; $i < count($claims); $i++) {
if ($canConvert && $claims[$i]->fee > 0 && $claims[$i]->fee_currency == 'USD') {
@ -222,7 +221,7 @@ class MainController extends Controller{
'claims' => $claims,
]);
} else {
$claim = Claim::query()->addSelect(['publisher' => 'C.name'])->leftJoin('Claims','claim_id','=','Claims.publisher_id')->where('Claims.claim_id',$id)->orderByDesc('Claims.created_at')->first();
$claim = Claim::query()->select('claim.*')->where('claim.claim_id',$id)->leftJoin('claim AS c','c.claim_id','=','claim.publisher_id')->orderByDesc('claim.created_at')->first();
if (!$claim) {
return Redirect::to('/');
}
@ -285,8 +284,8 @@ class MainController extends Controller{
public function realtime(): JsonResponse|Response|View{
// Load 10 blocks and transactions
$blocks = Block::query()->select(['Height','BlockTime'])->selectRaw('JSON_LENGTH(`TransactionHashes`) AS tx_count')->orderByDesc('Height')->limit(10)->get();
$transactions = Transaction::query()->select(['Id','Hash','Value','InputCount','OutputCount','TransactionTime','Created'])->orderByDesc('Created')->limit(10)->get();
$blocks = Block::query()->select(['height','block_time','tx_count'])->orderByDesc('height')->limit(10)->get();
$transactions = Transaction::query()->select(['id','hash','value','input_count','output_count','transaction_time','created_at'])->orderByDesc('created_at')->limit(10)->get();
return self::generateResponse('main.realtime',[
'blocks' => $blocks,
@ -299,38 +298,38 @@ class MainController extends Controller{
if(is_numeric($criteria)){
$height = (int) $criteria;
$block = Block::query()->select(['Id'])->where('Height',$height)->first();
$block = Block::query()->select(['id'])->where('height',$height)->first();
if($block){
return Redirect::to('/blocks/'.$height);
}
}elseif(strlen(trim($criteria)) === 34){
// Address
$address = Address::query()->select(['Id','Address'])->where('Address',$criteria)->first();
$address = Address::query()->select(['id','address'])->where('address',$criteria)->first();
if($address){
return Redirect::to('/address/'.$address->Address);
return Redirect::to('/address/'.$address->address);
}
}elseif(strlen(trim($criteria)) === 40){
// Claim ID
$claim = Claim::query()->select(['ClaimId'])->where('ClaimId',$criteria)->first();
$claim = Claim::query()->select(['claim_id'])->where('claim_id',$criteria)->first();
if($claim){
return Redirect::to('/claims/'.$claim->ClaimId);
return Redirect::to('/claims/'.$claim->claim_id);
}
}elseif(strlen(trim($criteria)) === 64) { // block or tx hash
// Try block hash first
$block = Block::query()->select(['Height'])->where('Hash',$criteria)->first();
$block = Block::query()->select(['height'])->where('hash',$criteria)->first();
if($block){
return Redirect::to('/blocks/'.$block->Height);
return Redirect::to('/blocks/'.$block->height);
}else{
$tx = Transaction::query()->select(['Hash'])->where('Hash',$criteria)->first();
$tx = Transaction::query()->select(['hash'])->where('hash',$criteria)->first();
if($tx){
return Redirect::to('/tx/'.$tx->Hash);
return Redirect::to('/tx/'.$tx->hash);
}
}
}else{
// finally, try exact claim name match
$claims = Claim::query()->distinct('ClaimId')->where('Name',$criteria)->orderByDesc('CreatedAt')->limit(10)->get(); //TODO Fix ordering by BidState (Controlling)
$claims = Claim::query()->distinct('claim_id')->where('name',$criteria)->orderByDesc('FIELD(bid_state,"Controlling")')->limit(10)->get();
if(count($claims)===1){
return Redirect::to('/claims/'.$claims[0]->ClaimId);
return Redirect::to('/claims/'.$claims[0]->claim_id);
}
return self::generateResponse('main.find',[
'claims' => $claims,
@ -348,7 +347,7 @@ class MainController extends Controller{
$page = intval(request()->query('page'));
$conn = DB::connection();
$stmt = $conn->getPdo()->query('SELECT Height AS Total FROM Blocks order by Id desc limit 1');
$stmt = $conn->getPdo()->query('SELECT height AS Total FROM block order by id desc limit 1');
$count = $stmt->fetch(PDO::FETCH_OBJ);
$numBlocks = $count->Total;
@ -361,8 +360,8 @@ class MainController extends Controller{
}
$offset = ($page - 1) * $pageLimit;
$currentBlock = Block::query()->select(['Height'])->orderByDesc('Height')->first();
$blocks = Block::query()->select(['Height', 'Difficulty', 'BlockSize', 'Nonce', 'BlockTime'])->offset($offset)->limit($pageLimit)->orderByDesc('Height')->get();//'tx_count'
$currentBlock = Block::query()->select(['height'])->orderByDesc('height')->first();
$blocks = Block::query()->select(['height', 'difficulty', 'block_size', 'nonce', 'block_time','tx_count'])->offset($offset)->limit($pageLimit)->orderByDesc('height')->get();
return self::generateResponse('main.blocks',[
'currentBlock' => $currentBlock,
@ -384,7 +383,7 @@ class MainController extends Controller{
}
// Get the basic block transaction info
$txs = Transaction::query()->select(['Transactions.id', 'Transactions.value', 'Transactions.input_count', 'Transactions.output_count', 'Transactions.hash', 'Transactions.version'])->where('Transactions.block_hash_id',$block->hash)->get();
$txs = Transaction::query()->select(['id','value','input_count','output_count','hash','version'])->where('block_hash_id',$block->hash)->get();
$last_block = Block::query()->select(['height'])->orderByDesc('height')->first();
$confirmations = $last_block->height - $block->height + 1;
@ -399,7 +398,7 @@ class MainController extends Controller{
public function tx($hash = null): JsonResponse|Response|RedirectResponse|View{
$sourceAddress = request()->query('address');
$tx = Transaction::query()->where('Transactions.hash',$hash)->first();
$tx = Transaction::query()->where('hash',$hash)->first();
if (!$tx) {
return Redirect::to('/');
}
@ -636,8 +635,8 @@ class MainController extends Controller{
$conn = DB::connection();
// get avg block sizes for the time period
$stmt = $conn->getPdo()->prepare("SELECT AVG(BlockSize) AS AvgBlockSize, DATE_FORMAT(FROM_UNIXTIME(BlockTime), '$sqlDateFormat') AS TimePeriod " .
"FROM Blocks WHERE DATE_FORMAT(FROM_UNIXTIME(BlockTime), '$sqlDateFormat') >= ? GROUP BY TimePeriod ORDER BY TimePeriod ASC");
$stmt = $conn->getPdo()->prepare("SELECT AVG(block_size) AS AvgBlockSize, DATE_FORMAT(FROM_UNIXTIME(block_time), '$sqlDateFormat') AS TimePeriod " .
"FROM block WHERE DATE_FORMAT(FROM_UNIXTIME(block_time), '$sqlDateFormat') >= ? GROUP BY TimePeriod ORDER BY TimePeriod ASC");
$stmt->execute([$start->format($dateFormat)]);
$avgBlockSizes = $stmt->fetchAll(PDO::FETCH_OBJ);
foreach ($avgBlockSizes as $size) {

View file

@ -1,19 +0,0 @@
<?php
namespace App\Jobs;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Support\Facades\Artisan;
class AddrTXJob implements ShouldQueue{
use Queueable;
/**
* Execute the job.
*/
public function handle(): void{
Artisan::call('explorer:block addrtxamounts');
}
}

View file

@ -1,19 +0,0 @@
<?php
namespace App\Jobs;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Support\Facades\Artisan;
class BlockTXJob implements ShouldQueue{
use Queueable;
/**
* Execute the job.
*/
public function handle(): void{
Artisan::call('explorer:block parsetxs');
}
}

View file

@ -1,23 +0,0 @@
<?php
namespace App\Jobs;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Cache;
class BlocksJob implements ShouldQueue{
use Queueable;
/**
* Execute the job.
*/
public function handle(): void{
Artisan::call('explorer:block parsenewblocks');
Cache::lock('parsenewblocks')->forceRelease();
Artisan::call('explorer:block parsetxs');
Cache::lock('parsetxs')->forceRelease();
}
}

View file

@ -1,19 +0,0 @@
<?php
namespace App\Jobs;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Support\Facades\Artisan;
class ClaimIndexJob implements ShouldQueue{
use Queueable;
/**
* Execute the job.
*/
public function handle(): void{
Artisan::call('explorer:block buildclaimindex');
}
}

View file

@ -1,19 +0,0 @@
<?php
namespace App\Jobs;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Support\Facades\Artisan;
class FixZeroJob implements ShouldQueue{
use Queueable;
/**
* Execute the job.
*/
public function handle(): void{
Artisan::call('explorer:block fixzerooutputs');
}
}

View file

@ -1,22 +0,0 @@
<?php
namespace App\Jobs;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Cache;
class ForeverJob implements ShouldQueue{
use Queueable;
/**
* Execute the job.
*/
public function handle(): void{
//TODO: What is this? `pkill -f forevermempool`
Cache::lock('forevermempool')->forceRelease();
Artisan::call('explorer:block forevermempool');
}
}

View file

@ -1,19 +0,0 @@
<?php
namespace App\Jobs;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Support\Facades\Artisan;
class LiveTXJob implements ShouldQueue{
use Queueable;
/**
* Execute the job.
*/
public function handle(): void{
Artisan::call('explorer:block parsemempool');
}
}

View file

@ -1,19 +0,0 @@
<?php
namespace App\Jobs;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Support\Facades\Artisan;
class PriceHistoryJob implements ShouldQueue{
use Queueable;
/**
* Execute the job.
*/
public function handle(): void{
Artisan::call('explorer:aux pricehistory');
}
}

View file

@ -1,19 +0,0 @@
<?php
namespace App\Jobs;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Support\Facades\Artisan;
class SpendsJob implements ShouldQueue{
use Queueable;
/**
* Execute the job.
*/
public function handle(): void{
Artisan::call('explorer:block updatespends');
}
}

View file

@ -1,19 +0,0 @@
<?php
namespace App\Jobs;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Support\Facades\Artisan;
class VerifyTagsJob implements ShouldQueue{
use Queueable;
/**
* Execute the job.
*/
public function handle(): void{
Artisan::call('explorer:aux verifytags');
}
}

View file

@ -6,34 +6,16 @@ use Illuminate\Database\Eloquent\Model;
/**
* @mixin Model
* @property int Id
* @property string Address
* @property datetime FirstSeen
* @property decimal TotalReceived
* @property decimal TotalSent
* @property decimal Balance
* @property string Tag
* @property string TagUrl
* @property datetime Created
* @property datetime Modified
* @property mixed id
* @property mixed address
* @property mixed first_seen
* @property mixed created_at
* @property mixed modified_at
* @property mixed balance
*/
class Address extends Model{
protected $fillable = [
'Address',
'FirstSeen',
];
protected $table = 'Addresses';
protected $table = 'address';
public $timestamps = false;
public function __construct(array $attributes = []){
parent::__construct($attributes);
//TODO Fix default non-null attributes
$this->Tag = '';
$this->TagUrl = '';
$this->Created = Carbon::now();
$this->Modified = Carbon::now();
}
}

View file

@ -5,55 +5,36 @@ use Illuminate\Database\Eloquent\Model;
/**
* @mixin Model
* @property mixed Bits
* @property mixed Chainwork
* @property mixed Confirmations
* @property mixed Difficulty
* @property mixed Hash
* @property mixed Height
* @property mixed MedianTime
* @property mixed MerkleRoot
* @property mixed NameClaimRoot
* @property mixed Nonce
* @property mixed PreviousBlockHash
* @property mixed NextBlockHash
* @property mixed BlockSize
* @property mixed Target
* @property mixed BlockTime
* @property mixed TransactionHashes
* @property mixed Version
* @property mixed VersionHex
* @property mixed id
* @property mixed bits
* @property mixed chainwork
* @property mixed confirmations
* @property mixed difficulty
* @property mixed hash
* @property mixed height
* @property mixed merkle_root
* @property mixed name_claim_root
* @property mixed nonce
* @property mixed previous_block_hash
* @property mixed next_block_hash
* @property mixed block_size
* @property mixed block_time
* @property mixed version
* @property mixed version_hex
* @property mixed tx_count
* @property mixed created_at
* @property mixed modified_at
*/
class Block extends Model{
protected $fillable = [
'Bits',
'Chainwork',
'Confirmations',
'Difficulty',
'Hash',
'Height',
'MedianTime',
'MerkleRoot',
'NameClaimRoot',
'Nonce',
'PreviousBlockHash',
'NextBlockHash',
'BlockSize',
'Target',
'BlockTime',
'TransactionHashes',
'Version',
'VersionHex',
];
protected $table = 'Blocks';
protected $table = 'block';
public $timestamps = false;
public function jsonSerialize(): array{
return [
'height' => $this->Height,
'block_time' => $this->BlockTime,
'tx_count' => -1,//TODO
'height' => $this->height,
'block_time' => $this->block_time,
'tx_count' => $this->tx_count,
];
}

View file

@ -6,18 +6,74 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
/**
* @mixin Model
* @property mixed id
* @property mixed transaction_hash_id
* @property mixed vout
* @property mixed name
* @property mixed claim_id
* @property mixed claim_type
* @property mixed publisher_id
* @property mixed publisher_sig
* @property mixed certificate
* @property mixed sd_hash
* @property mixed transaction_time
* @property mixed version
* @property mixed value_as_hex
* @property mixed value_as_json
* @property mixed valid_at_height
* @property mixed height
* @property mixed effective_amount
* @property mixed author
* @property mixed description
* @property mixed content_type
* @property mixed is_nsfw
* @property mixed language
* @property mixed thumbnail_url
* @property mixed title
* @property mixed fee
* @property mixed fee_currency
* @property mixed fee_address
* @property mixed is_filtered
* @property mixed bid_state
* @property mixed created_at
* @property mixed modified_at
* @property mixed claim_address
* @property mixed is_cert_valid
* @property mixed is_cert_processed
* @property mixed license
* @property mixed type
* @property mixed release_time
* @property mixed source_hash
* @property mixed source_name
* @property mixed source_size
* @property mixed source_media_type
* @property mixed source_url
* @property mixed frame_width
* @property mixed frame_height
* @property mixed duration
* @property mixed audio_duration
* @property mixed email
* @property mixed has_claim_list
* @property mixed claim_reference
* @property mixed list_type
* @property mixed claim_id_list
* @property mixed transaction_hash_update
* @property mixed vout_update
* @property mixed claim_count
*/
class Claim extends Model{
protected $fillable = [];
protected $table = 'Claims';
protected $casts = [
'created_at' => 'datetime',
];
protected $table = 'claim';
public $timestamps = false;
public function publisher(): BelongsTo{
return $this->belongsTo(Claim::class, 'PublisherId','ClaimId');
}
// public function publisher(): BelongsTo{
// return $this->belongsTo(Claim::class, 'publisher_id','claim_id');
// }
function getLbryLink() {
public function getLbryLink(): string{
$link = $this->name;
if (isset($this->publisher)) {
$link = $this->publisher . '/' . $link;
@ -26,12 +82,12 @@ class Claim extends Model{
return $link;
}
function getExplorerLink() {
public function getExplorerLink(): string{
$link = '/claims/' . $this->claim_id;
return $link;
}
function getContentTag() {
public function getContentTag(): ?string{
$ctTag = null;
if (substr($this->content_type, 0, 5) === 'audio') {
$ctTag = 'audio';
@ -47,7 +103,7 @@ class Claim extends Model{
return $ctTag;
}
function getAutoThumbText() {
public function getAutoThumbText(): string{
$autoThumbText = '';
if ($this->claim_type == 2) {
$autoThumbText = strtoupper(substr($this->name, 1, min(strlen($this->name), 10)));

View file

@ -1,15 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
/**
* @mixin Model
*/
class ClaimStream extends Model{
protected $fillable = [];
protected $table = 'ClaimStreams';
public $timestamps = false;
}

View file

@ -6,11 +6,26 @@ use Illuminate\Database\Eloquent\Relations\BelongsToMany;
/**
* @mixin Model
* @property mixed id
* @property mixed transaction_id
* @property mixed transaction_hash
* @property mixed input_address_id
* @property mixed is_coinbase
* @property mixed coinbase
* @property mixed prevout_hash
* @property mixed prevout_n
* @property mixed sequence
* @property mixed value
* @property mixed script_sig_asm
* @property mixed script_sig_hex
* @property mixed created
* @property mixed modified
* @property mixed vin
* @property mixed witness
*/
class Input extends Model{
protected $fillable = [];
protected $table = 'Inputs';
protected $table = 'input';
public $timestamps = false;
public function input_addresses(): BelongsToMany{

View file

@ -7,11 +7,25 @@ use Illuminate\Database\Eloquent\Relations\BelongsToMany;
/**
* @mixin Model
* @property mixed id
* @property mixed transaction_id
* @property mixed transaction_hash
* @property mixed value
* @property mixed vout
* @property mixed type
* @property mixed script_pub_key_asm
* @property mixed script_pub_key_hex
* @property mixed required_signatures
* @property mixed address_list
* @property mixed is_spent
* @property mixed spent_by_input_id
* @property mixed created_at
* @property mixed modified_at
* @property mixed claim_id
*/
class Output extends Model{
protected $fillable = [];
protected $table = 'Outputs';
protected $table = 'output';
public $timestamps = false;
public function output_addresses(): BelongsToMany{

View file

@ -1,13 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
/**
* @mixin Model
*/
class PriceHistory extends Model{
protected $connection = 'localdb';
}

View file

@ -5,6 +5,7 @@ use Illuminate\Database\Eloquent\Model;
/**
* @mixin Model
* @deprecated
*/
class TagAddressRequest extends Model{

View file

@ -5,13 +5,23 @@ use Illuminate\Database\Eloquent\Model;
/**
* @mixin Model
* @property mixed id
* @property mixed block_hash_id
* @property mixed input_count
* @property mixed output_count
* @property mixed transaction_time
* @property mixed transaction_size
* @property mixed hash
* @property mixed version
* @property mixed lock_time
* @property mixed created_at
* @property mixed modified_at
* @property mixed created_time
* @property mixed value
*/
class Transaction extends Model{
protected $fillable = [
'Version',
];
protected $table = 'Transactions';
protected $table = 'transaction';
public $timestamps = false;
}

View file

@ -5,11 +5,14 @@ use Illuminate\Database\Eloquent\Model;
/**
* @mixin Model
* @property mixed transaction_id
* @property mixed address_id
* @property mixed debit_amount
* @property mixed credit_amount
*/
class TransactionAddress extends Model{
protected $fillable = [];
protected $table = 'TransactionAddresses';
protected $table = 'transaction_address';
public $timestamps = false;
}

View file

@ -1,16 +1,4 @@
<?php
use App\Jobs\AddrTXJob;
use App\Jobs\BlocksJob;
use App\Jobs\BlockTXJob;
use App\Jobs\ClaimIndexJob;
use App\Jobs\FixZeroJob;
use App\Jobs\ForeverJob;
use App\Jobs\LiveTXJob;
use App\Jobs\PriceHistoryJob;
use App\Jobs\SpendsJob;
use App\Jobs\VerifyTagsJob;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Middleware;
@ -26,16 +14,4 @@ return Application::configure(basePath: dirname(__DIR__))
commands: __DIR__.'/../routes/console.php',
health: '/up',
)
->withSchedule(static function(Schedule $schedule){
$schedule->job(new AddrTXJob)->everyMinute();
$schedule->job(new BlocksJob)->everyMinute();
$schedule->job(new BlockTXJob)->everyMinute();
$schedule->job(new ClaimIndexJob)->everyMinute();
$schedule->job(new FixZeroJob)->everyMinute();
$schedule->job(new ForeverJob)->everyMinute();
$schedule->job(new LiveTXJob)->everyMinute();
$schedule->job(new PriceHistoryJob)->everyMinute();
$schedule->job(new SpendsJob)->everyMinute();
$schedule->job(new VerifyTagsJob)->everyMinute();
})
->create();

View file

@ -15,7 +15,7 @@ return [
|
*/
'default' => 'default',
'default' => 'chainquery',
/*
|--------------------------------------------------------------------------
@ -29,31 +29,13 @@ return [
*/
'connections' => [
'default' => [
'chainquery' => [
'driver' => 'mysql',
'host' => env('DB_DEFAULT_HOST', '127.0.0.1'),
'port' => env('DB_DEFAULT_PORT', '3306'),
'database' => env('DB_DEFAULT_DATABASE', 'laravel'),
'username' => env('DB_DEFAULT_USERNAME', 'root'),
'password' => env('DB_DEFAULT_PASSWORD', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
'localdb' => [
'driver' => 'mysql',
'host' => env('DB_LOCAL_HOST', '127.0.0.1'),
'port' => env('DB_LOCAL_PORT', '3306'),
'database' => env('DB_LOCAL_DATABASE', 'laravel'),
'username' => env('DB_LOCAL_USERNAME', 'root'),
'password' => env('DB_LOCAL_PASSWORD', ''),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'laravel'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',

View file

@ -1,44 +0,0 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User>
*/
class UserFactory extends Factory
{
/**
* The current password being used by the factory.
*/
protected static ?string $password;
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'name' => fake()->name(),
'email' => fake()->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => static::$password ??= Hash::make('password'),
'remember_token' => Str::random(10),
];
}
/**
* Indicate that the model's email address should be unverified.
*/
public function unverified(): static
{
return $this->state(fn (array $attributes) => [
'email_verified_at' => null,
]);
}
}

View file

@ -1,288 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration{
protected $connection = 'default';
/**
* Run the migrations.
*/
public function up(): void{
Schema::create('Blocks',static function(Blueprint $table): void{
$table->rawColumn('Id','SERIAL');
$table->string('Bits',20);
$table->string('Chainwork',70);
$table->unsignedInteger('Confirmations');
$table->decimal('Difficulty',18,2);
$table->string('Hash',70);
$table->bigInteger('Height');
$table->bigInteger('MedianTime');
$table->string('MerkleRoot',70);
$table->string('NameClaimRoot',70);
$table->bigInteger('Nonce');
$table->string('PreviousBlockHash',70);
$table->string('NextBlockHash',70);
$table->bigInteger('BlockSize');
$table->string('Target',70);
$table->bigInteger('BlockTime');
$table->bigInteger('Version');
$table->string('VersionHex',10);
$table->text('TransactionHashes');
$table->tinyInteger('TransactionsProcessed')->default(0);
$table->dateTime('Created');
$table->dateTime('Modified');
$table->primary(['Id'],'PK_Block');
$table->unique(['Hash'],'Idx_BlockHash');
//TODO: CONSTRAINT `Cnt_TransactionHashesValidJson` CHECK(`TransactionHashes` IS NULL OR JSON_VALID(`TransactionHashes`))
$table->index(['Height'],'Idx_BlockHeight');
$table->index(['BlockTime'],'Idx_BlockTime');
$table->index(['MedianTime'],'Idx_MedianTime');
$table->index(['PreviousBlockHash'],'Idx_PreviousBlockHash');
$table->index(['Created'],'Idx_BlockCreated');
$table->index(['Modified'],'Idx_BlockModified');
});
Schema::create('Transactions',static function(Blueprint $table): void{
$table->rawColumn('Id','SERIAL');
$table->string('BlockHash',70);
$table->unsignedInteger('InputCount');
$table->unsignedInteger('OutputCount');
$table->decimal('Value',18,8);
$table->decimal('Fee',18,8)->default(0);
$table->unsignedBigInteger('TransactionTime');
$table->unsignedBigInteger('TransactionSize');
$table->string('Hash',70);
$table->integer('Version');
$table->unsignedInteger('LockTime');
$table->text('Raw');
$table->dateTime('Created');
$table->dateTime('Modified');
$table->rawColumn('CreatedTime','INT UNSIGNED DEFAULT UNIX_TIMESTAMP() NOT NULL');
//$table->unsignedInteger('CreatedTime')->default('UNIX_TIMESTAMP()');
$table->primary(['Id'],'PK_Transaction');
$table->foreign(['BlockHash'],'FK_TransactionBlockHash')->references(['Hash'])->on('Blocks');
$table->unique(['Hash'],'Idx_TransactionHash');
$table->index(['TransactionTime'],'Idx_TransactionTime');
$table->index(['CreatedTime'],'Idx_TransactionCreatedTime');
$table->index(['Created'],'Idx_TransactionCreated');
$table->index(['Modified'],'Idx_TransactionModified');
});
Schema::create('Addresses',static function(Blueprint $table): void{
$table->rawColumn('Id','SERIAL');
$table->string('Address',40);
$table->dateTime('FirstSeen');
$table->decimal('TotalReceived',18,8)->default(0);
$table->decimal('TotalSent',18,8)->default(0);
$table->decimal('Balance',18,8)->virtualAs('TotalReceived - TotalSent')->persisted();
$table->string('Tag',30);
$table->string('TagUrl',200);
$table->dateTime('Created');
$table->dateTime('Modified');
$table->primary(['Id'],'PK_Address');
$table->unique(['Address'],'Idx_AddressAddress');
$table->unique(['Tag'],'Idx_AddressTag');
$table->index(['TotalReceived'],'Idx_AddressTotalReceived');
$table->index(['TotalSent'],'Idx_AddressTotalSent');
$table->index(['Balance'],'Idx_AddressBalance');
$table->index(['Created'],'Idx_AddressCreated');
$table->index(['Modified'],'Idx_AddressModified');
});
Schema::create('Inputs',static function(Blueprint $table): void{
$table->rawColumn('Id','SERIAL');
$table->unsignedBigInteger('TransactionId');
$table->string('TransactionHash',70);
$table->unsignedBigInteger('AddressId');
$table->tinyInteger('IsCoinbase')->default(0);
$table->string('Coinbase',70);
$table->string('PrevoutHash',70);
$table->unsignedInteger('PrevoutN');
$table->tinyInteger('PrevoutSpendUpdated')->default(0);
$table->unsignedInteger('Sequence');
$table->decimal('Value',18,8);
$table->text('ScriptSigAsm');
$table->text('ScriptSigHex');
$table->dateTime('Created');
$table->dateTime('Modified');
$table->primary(['Id'],'PK_Input');
$table->foreign(['AddressId'],'FK_InputAddress')->references(['Id'])->on('Addresses');
$table->foreign(['TransactionId'],'FK_InputTransaction')->references(['Id'])->on('Transactions');
$table->index(['Value'],'Idx_InputValue');
$table->index(['PrevoutHash'],'Idx_PrevoutHash');
$table->index(['Created'],'Idx_InputCreated');
$table->index(['Modified'],'Idx_InputModified');
});
Schema::create('InputsAddresses',static function(Blueprint $table): void{
$table->unsignedBigInteger('InputId');
$table->unsignedBigInteger('AddressId');
$table->primary(['InputId','AddressId'],'PK_InputAddress');
$table->foreign(['InputId'],'Idx_InputsAddressesInput')->references('Id')->on('Inputs');
$table->foreign(['AddressId'],'Idx_InputsAddressesAddress')->references('Id')->on('Addresses');
});
Schema::create('Outputs',static function(Blueprint $table): void{
$table->rawColumn('Id','SERIAL');
$table->unsignedBigInteger('TransactionId');
$table->decimal('Value',18,8);
$table->unsignedInteger('Vout');
$table->string('Type',20);
$table->text('ScriptPubKeyAsm');
$table->text('ScriptPubKeyHex');
$table->unsignedInteger('RequiredSignatures');
$table->string('Hash160',50);
$table->text('Addresses');
$table->tinyInteger('IsSpent')->default(0);
$table->unsignedBigInteger('SpentByInputId');
$table->dateTime('Created');
$table->dateTime('Modified');
$table->primary(['Id'],'PK_Output');
$table->foreign(['TransactionId'],'FK_OutputTransaction')->references(['Id'])->on('Transactions');
$table->foreign(['SpentByInputId'],'FK_OutputSpentByInput')->references(['Id'])->on('Inputs');
//TODO CONSTRAINT `Cnt_AddressesValidJson` CHECK(`Addresses` IS NULL OR JSON_VALID(`Addresses`))
$table->index(['Value'],'Idx_OutputValue');
$table->index(['Created'],'Idx_OuptutCreated');
$table->index(['Modified'],'Idx_OutputModified');
});
Schema::create('OutputsAddresses',static function(Blueprint $table): void{
$table->unsignedBigInteger('OutputId');
$table->unsignedBigInteger('AddressId');
$table->primary(['OutputId','AddressId'],'PK_OutputAddress');
$table->foreign(['OutputId'],'Idx_OutputsAddressesOutput')->references('Id')->on('Outputs');
$table->foreign(['AddressId'],'Idx_OutputsAddressesAddress')->references('Id')->on('Addresses');
});
Schema::create('TransactionsAddresses',static function(Blueprint $table): void{
$table->unsignedBigInteger('TransactionId');
$table->unsignedBigInteger('AddressId');
$table->decimal('DebitAmount',18,8)->default(0)->comment('Sum of the inputs to this address for the tx');
$table->decimal('CreditAmount',18,8)->default(0)->comment('Sum of the outputs to this address for the tx');
//$table->dateTime('TransactionTime')->default('UTC_TIMESTAMP()');
$table->rawColumn('TransactionTime','DATETIME DEFAULT UTC_TIMESTAMP() NOT NULL');
$table->primary(['TransactionId','AddressId'],'PK_TransactionAddress');
$table->foreign(['TransactionId'],'Idx_TransactionsAddressesTransaction')->references('Id')->on('Transactions');
$table->foreign(['AddressId'],'Idx_TransactionsAddressesAddress')->references('Id')->on('Addresses');
$table->index(['TransactionTime'],'Idx_TransactionsAddressesTransactionTime');
$table->index(['DebitAmount'],'Idx_TransactionsAddressesDebit');
$table->index(['CreditAmount'],'Idx_TransactionsAddressesCredit');
});
Schema::create('Claims',static function(Blueprint $table): void{
$table->rawColumn('Id','SERIAL');
$table->string('TransactionHash',70);
$table->unsignedInteger('Vout');
$table->string('Name',1024);
$table->char('ClaimId',40);
$table->tinyInteger('ClaimType'); // 1 - CertificateType, 2 - StreamType
$table->char('PublisherId',40)->comment('references a ClaimId with CertificateType');
$table->string('PublisherSig',200);
$table->text('Certificate');
$table->unsignedInteger('TransactionTime');
$table->string('Version',10);
//Additional fields for easy indexing of stream types
$table->string('Author',512);
$table->mediumText('Description');
$table->string('ContentType',162);
$table->tinyInteger('IsNSFW')->default(0);
$table->string('Language',20);
$table->text('ThumbnailUrl');
$table->text('Title');
$table->decimal('Fee',18,8)->default(0);
$table->char('FeeCurrency',3);
$table->tinyInteger('IsFiltered')->default(0);
$table->dateTime('Created');
$table->dateTime('Modified');
$table->primary(['Id'],'PK_Claim');
$table->foreign(['TransactionHash'],'FK_ClaimTransaction')->references(['Hash'])->on('Transactions');
//TODO $table->foreign(['PublisherId'],'FK_ClaimPublisher')->references(['ClaimId'])->on('Claims');
$table->unique(['TransactionHash','Vout','ClaimId'],'Idx_ClaimUnique');
//TODO CONSTRAINT `Cnt_ClaimCertificate` CHECK(`Certificate` IS NULL OR JSON_VALID(`Certificate`)) // certificate type
$table->index(['ClaimId'],'Idx_Claim');
$table->index(['TransactionTime'],'Idx_ClaimTransactionTime');
$table->index(['Created'],'Idx_ClaimCreated');
$table->index(['Modified'],'Idx_ClaimModified');
//$table->index(['Author(191)'],'Idx_ClaimAuthor');
$table->rawIndex('Author(191)','Idx_ClaimAuthor');
$table->index(['ContentType'],'Idx_ClaimContentType');
$table->index(['Language'],'Idx_ClaimLanguage');
//$table->index(['Title(191)'],'Idx_ClaimTitle');
$table->rawIndex('Title(191)','Idx_ClaimTitle');
});
Schema::create('ClaimStreams',static function(Blueprint $table): void{
$table->unsignedBigInteger('Id');
$table->mediumText('Stream');
$table->primary(['Id'],'PK_ClaimStream');
$table->foreign(['Id'],'PK_ClaimStreamClaim')->references('Id')->on('Claims');
});
Schema::create('PriceHistory',static function(Blueprint $table): void{
$table->rawColumn('Id','SERIAL');
$table->decimal('BTC',18,8)->default(0);
$table->decimal('USD',18,2)->default(0);
$table->dateTime('Created');
$table->primary(['Id'],'PK_PriceHistory');
$table->unique(['Created'],'Idx_PriceHistoryCreated');
});
}
/**
* Reverse the migrations.
*/
public function down(): void{
Schema::dropIfExists('Blocks');
Schema::dropIfExists('Transactions');
Schema::dropIfExists('Addresses');
Schema::dropIfExists('Inputs');
Schema::dropIfExists('InputsAddresses');
Schema::dropIfExists('Outputs');
Schema::dropIfExists('OutputsAddresses');
Schema::dropIfExists('TransactionsAddresses');
Schema::dropIfExists('Claims');
Schema::dropIfExists('ClaimStreams');
Schema::dropIfExists('PriceHistory');
}
};

View file

@ -1,42 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration{
protected $connection = 'localdb';
/**
* Run the migrations.
*/
public function up(): void{
Schema::create('TagAddressRequests',static function(Blueprint $table): void{
$table->integer('Id');
$table->string('Address',35);
$table->decimal('VerificationAmount',18,8);
$table->string('Tag',30);
$table->string('TagUrl',200);
$table->tinyInteger('IsVerified')->default(0);
$table->dateTime('Created');
$table->dateTime('Modified');
$table->primary(['Id'],'PK_TagAddressRequest');
$table->unique(['Address','VerificationAmount'],'Idx_TagAddressRequestId');
$table->index(['VerificationAmount'],'Idx_TagAddressRequestVerificationAmount');
$table->index(['Address'],'Idx_TagAddressRequestAddress');
$table->index(['Created'],'Idx_TagAddressRequestCreated');
$table->index(['Modified'],'Idx_TagAddressRequestModified');
});
}
/**
* Reverse the migrations.
*/
public function down(): void{
Schema::dropIfExists('TagAddressRequests');
}
};

View file

@ -1,23 +0,0 @@
<?php
namespace Database\Seeders;
use App\Models\User;
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*/
public function run(): void
{
// User::factory(10)->create();
User::factory()->create([
'name' => 'Test User',
'email' => 'test@example.com',
]);
}
}

View file

@ -1,4 +1,5 @@
@extends('layout.default')
{{ /**@var \App\Models\Address $address*/'' }}
@section('title','Address '.$address->address)

View file

@ -1,7 +1,7 @@
@extends('layout.default')
{{ /**@var \App\Models\Block $block*/'' }}
@section('title',isset($block)?('Block Height '.$block->Height):'Blocks')
@section('title',isset($block)?('Block Height '.$block->height):'Blocks')
@section('script')
@if(isset($block))
@ -42,16 +42,16 @@
@if(isset($block))
<div class="block-head">
<h3>LBRY Block {{ $block->Height }}</h3>
<h4>{{ $block->Hash }}</h4>
<h3>LBRY Block {{ $block->height }}</h3>
<h4>{{ $block->hash }}</h4>
</div>
<div class="block-nav">
@if($block->Height > 0)
<a class="btn btn-prev" href="/blocks/{{ ($block->Height - 1) }}">&laquo; Previous Block</a>
@if($block->height > 0)
<a class="btn btn-prev" href="/blocks/{{ ($block->height - 1) }}">&laquo; Previous Block</a>
@endif
<a class="btn btn-next" href="/blocks/{{ $block->Height + 1 }}">Next Block &raquo;</a>
<a class="btn btn-next" href="/blocks/{{ $block->height + 1 }}">Next Block &raquo;</a>
<div class="clear"></div>
</div>
@ -63,15 +63,15 @@
<div class="label half-width">Block Size (bytes)</div>
<div class="label half-width">Block Time</div>
<div class="value half-width">{{ number_format($block->BlockSize, 0, '', ',') }}</div>
<div class="value half-width">{{ \DateTime::createFromFormat('U', $block->BlockTime)->format('j M Y H:i:s') . ' UTC' }}</div>
<div class="value half-width">{{ number_format($block->block_size, 0, '', ',') }}</div>
<div class="value half-width">{{ \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">{{ $block->Bits }}</div>
<div class="value half-width">{{ $block->bits }}</div>
<div class="value half-width">{{ $confirmations }}</div>
<div class="clear spacer"></div>
@ -79,20 +79,20 @@
<div class="label half-width">Difficulty</div>
<div class="label half-width">Nonce</div>
<div class="value half-width">{{ \App\Helpers\AmountHelper::format($block->Difficulty,'') }}</div>
<div class="value half-width">{{ $block->Nonce }}</div>
<div class="value half-width">{{ \App\Helpers\AmountHelper::format($block->difficulty,'') }}</div>
<div class="value half-width">{{ $block->nonce }}</div>
<div class="clear spacer"></div>
<div class="label">Chainwork</div> <div class="value">{{ $block->Chainwork }}</div>
<div class="label">Chainwork</div> <div class="value">{{ $block->chainwork }}</div>
<div class="spacer"></div>
<div class="label">MerkleRoot</div> <div class="value">{{ $block->MerkleRoot }}</div>
<div class="label">MerkleRoot</div> <div class="value">{{ $block->merkle_root }}</div>
<div class="spacer"></div>
<div class="label">NameClaimRoot</div> <div class="value">{{ $block->NameClaimRoot }}</div>
<div class="label">NameClaimRoot</div> <div class="value">{{ $block->name_claim_root }}</div>
<!--
<div class="spacer"></div>
@ -102,7 +102,7 @@
<div class="spacer"></div>
<div class="label">Version</div> <div class="value">{{ $block->Version }}</div>
<div class="label">Version</div> <div class="value">{{ $block->version }}</div>
</div>
<div class="block-transactions">
@ -184,13 +184,13 @@
<tbody>
@foreach($blocks as $block)
<tr>
<td class="right"><a href="/blocks/{{ $block->Height }}">{{ $block->Height }}</a></td>
<td class="pad-left">{{ number_format($block->Difficulty, 8, '.', '') }}</td>
<td class="right">{{ number_format((($currentBlock->Height - $block->Height) + 1), 0, '', ',') }}</td>
<td class="right"><a href="/blocks/{{ $block->height }}">{{ $block->height }}</a></td>
<td class="pad-left">{{ number_format($block->difficulty, 8, '.', '') }}</td>
<td class="right">{{ number_format((($currentBlock->height - $block->height) + 1), 0, '', ',') }}</td>
<td class="right">{{ $block->tx_count }}</td>
<td class="right">{{ round($block->BlockSize / 1024, 2) . 'KB' }}</td>
<td class="right pad-left">{{ $block->Nonce }}</td>
<td class="pad-left">{{ \DateTime::createFromFormat('U', $block->BlockTime)->format('d M Y H:i:s') }} UTC</td>
<td class="right">{{ round($block->block_size / 1024, 2) . 'KB' }}</td>
<td class="right pad-left">{{ $block->nonce }}</td>
<td class="pad-left">{{ \DateTime::createFromFormat('U', $block->block_time)->format('d M Y H:i:s') }} UTC</td>
</tr>
@endforeach
</tbody>

View file

@ -56,7 +56,7 @@
$desc = $claim->description;
if (strlen(trim($desc)) == 0) {
$desc = '<em>No description available.</em>';
$desc = null;
} else {
$desc = preg_replace('#((https?|ftp|lbry)://([A-Za-z0-9\-\/]+|\S*?\.\S*?))([\s)\[\]{},;"\':<]|\.\s|$)#i','<a href="$1" target="_blank" rel="nofollow">$1</a>$4', $desc);
$desc = preg_replace('/(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/is', '<a href="mailto:$0" rel="nofollow">$0</a>', $desc);
@ -121,7 +121,7 @@
<div class="desc">This is an identity claim.</div>
@else
<div class="title">{{ $claim->title }}</div>
<div class="desc">{{ str_replace("\n", '<br />', $desc) }}</div>
<div class="desc">@if($desc===null)<em>No description available.</em>@else{{ str_replace("\n", '<br />', $desc) }}@endif</div>
<div class="details">
<div class="label half-width">Author</div>

View file

@ -132,12 +132,12 @@
<div class="stats">
<div class="box box-20">
<div class="title">Block Height</div>
<div class="value">{{ $recentBlocks[0]->Height }}</div>
<div class="value">{{ $recentBlocks[0]->height }}</div>
</div>
<div class="box box-30">
<div class="title">Difficulty</div>
<div class="value" title="{{ $recentBlocks[0]->Difficulty }}">{{ number_format($recentBlocks[0]->Difficulty, 2, '.', '') }}</div>
<div class="value" title="{{ $recentBlocks[0]->difficulty }}">{{ number_format($recentBlocks[0]->difficulty, 2, '.', '') }}</div>
</div>
<div class="box box-30">
@ -170,13 +170,13 @@
<tbody>
@foreach($recentBlocks as $block)
<tr data-height="{{ $block->Height }}" data-time="{{ $block->BlockTime }}">
<td><a href="/blocks/{{ $block->Height }}">{{ $block->Height }}</a></td>
<td>{{ \Carbon\Carbon::createFromTimestamp($block->BlockTime)->diffForHumans() }}</td>
<td class="right">{{ round($block->BlockSize / 1024, 2) . 'KB' }}</td>
<tr data-height="{{ $block->height }}" data-time="{{ $block->block_time }}">
<td><a href="/blocks/{{ $block->height }}">{{ $block->height }}</a></td>
<td>{{ \Carbon\Carbon::createFromTimestamp($block->block_time)->diffForHumans() }}</td>
<td class="right">{{ round($block->block_size / 1024, 2) . 'KB' }}</td>
<td class="right">{{ $block->tx_count }}</td>
<td class="right">{{ number_format($block->Difficulty, 2, '.', '') }}</td>
<td class="last-cell">{{ DateTime::createFromFormat('U', $block->BlockTime)->format('d M Y H:i:s') . ' UTC' }}</td>
<td class="right">{{ number_format($block->difficulty, 2, '.', '') }}</td>
<td class="last-cell">{{ DateTime::createFromFormat('U', $block->block_time)->format('d M Y H:i:s') . ' UTC' }}</td>
</tr>
@endforeach
</tbody>
@ -193,7 +193,7 @@
@php($autoThumbText = $claim->getAutoThumbText())
{{--content type--}}
@php($ctTag = $claim->getContentTag())
<div data-id="{{ $claim->claim_id }}" class="claim-box@if($idx == 5) last@endif">
<div data-id="{{ $claim->claim_id }}" class="{{ 'claim-box' }}@if($idx == 5){{ ' last' }}@endif">
<div class="tags">
@if($ctTag)
<div class="content-type">{{ strtoupper($ctTag) }}</div>
@ -212,7 +212,9 @@
</div>
<div class="metadata">
<div class="title" title="{{ $claim->claim_type == 1 ? $claim->name : ((strlen(trim($claim->title)) > 0) ? $claim->title : '') }}">{{ $claim->claim_type == 1 ? $claim->name : ((strlen(trim($claim->title)) > 0) ? $claim->title : '<em>No Title</em>') }}</div>
<div class="title" title="{{ $claim->claim_type == 1 ? $claim->name : ((strlen(trim($claim->title)) > 0) ? $claim->title : '') }}">
@if($claim->claim_type == 1){{ $claim->name }}@else{{ '' }}@if(strlen(trim($claim->title)) > 0){{ $claim->title }}@else<em>No Title</em>@endif{{ '' }}@endif
</div>
<div class="link" title="{{ $claim->getLbryLink() }}"><a href="{{ $claim->getLbryLink() }}">{{ $claim->getLbryLink() }}</a></div>
<div class="clear"></div>

View file

@ -133,9 +133,9 @@
<tbody>
@foreach($blocks as $block)
<tr data-height="{{ $block->Height }}" data-time="{{ $block->BlockTime }}">
<td><a href="/blocks/{{ $block->Height }}" target="_blank">{{ $block->Height }}</a></td>
<td>{{ \Carbon\Carbon::createFromTimestamp($block->BlockTime)->diffForHumans() }}</td>
<tr data-height="{{ $block->height }}" data-time="{{ $block->block_time }}">
<td><a href="/blocks/{{ $block->height }}" target="_blank">{{ $block->height }}</a></td>
<td>{{ \Carbon\Carbon::createFromTimestamp($block->block_time)->diffForHumans() }}</td>
<td class="right">{{ $block->tx_count }}</td>
</tr>
@endforeach

View file

@ -1,6 +1,6 @@
@extends('layout.default')
@section('title','Transaction '.$tx->Hash)
@section('title','Transaction '.$tx->hash)
@section('script')
<script type="text/javascript">
@ -111,7 +111,7 @@
<a id="{{ $addr->address }}"></a>
@endif
<div><span class="value">{{ $this->Amount->format($in->value) }} LBC</span> from</div>
<div><span class="value">{{ \App\Helpers\AmountHelper::format($in->value) }} LBC</span> from</div>
<div class="address">
<a href="/address/{{ $addr->address }}">{{ $addr->address }}</a>
(<a class="output-link" href="/tx/{{ $in->prevout_hash }}#output-{{ $in->prevout_n }}">output</a>)