Skip to content

Commit

Permalink
chore: merge staging into master (#557)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexbarnsley authored Sep 25, 2023
2 parents 6399eda + d4fffbd commit 5e70933
Show file tree
Hide file tree
Showing 54 changed files with 3,076 additions and 341 deletions.
6 changes: 4 additions & 2 deletions app/Console/Commands/CacheDelegateVoterCounts.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ final class CacheDelegateVoterCounts extends Command
*/
public function handle(): void
{
$walletCache = new WalletCache();
$walletCache = new WalletCache();
$delegateCache = new DelegateCache();

$select = [
'wallets.public_key',
Expand All @@ -54,7 +55,8 @@ public function handle(): void

$results->each(fn ($total, $publicKey) => $walletCache->setVoterCount($publicKey, $total));

(new DelegateCache())->setTotalVoted(function () {
$delegateCache->setAllVoterCounts($results->toArray());
$delegateCache->setTotalVoted(function () {
$wallets = Wallet::select('balance')
->whereRaw("\"attributes\"->>'vote' is not null")
->get();
Expand Down
12 changes: 12 additions & 0 deletions app/Enums/SortDirection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace App\Enums;

enum SortDirection: string
{
case ASC = 'asc';

case DESC = 'desc';
}
69 changes: 69 additions & 0 deletions app/Http/Livewire/Concerns/HasTableSorting.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

declare(strict_types=1);

namespace App\Http\Livewire\Concerns;

use App\Enums\SortDirection;

trait HasTableSorting
{
public string $sortKey;

public SortDirection $sortDirection;

public function bootHasTableSorting(): void
{
$this->sortKey = static::defaultSortKey();

if (request()->has('sort-direction')) {
$sortDirection = request()->get('sort-direction');
if ($sortDirection === SortDirection::DESC->value) {
$this->sortDirection = SortDirection::DESC;
} else {
$this->sortDirection = SortDirection::ASC;
}
} else {
$this->sortDirection = static::defaultSortDirection();
}
}

public function queryStringHasTableSorting(): array
{
return [
'sortKey' => ['as' => 'sort', 'except' => static::defaultSortKey()],
'sortDirectionQuery' => ['as' => 'sort-direction', 'except' => static::defaultSortDirection()->value],
];
}

public function sortBy(string $key): void
{
if ($this->sortKey === $key) {
if ($this->sortDirection === SortDirection::ASC) {
$this->sortDirection = SortDirection::DESC;
} else {
$this->sortDirection = SortDirection::ASC;
}
} else {
$this->sortKey = $key;
$this->sortDirection = SortDirection::ASC;
}

$this->gotoPage(1);
}

public static function defaultSortKey(): string
{
return constant(static::class.'::INITIAL_SORT_KEY');
}

public static function defaultSortDirection(): SortDirection
{
return constant(static::class.'::INITIAL_SORT_DIRECTION');
}

public function getSortDirectionQueryProperty(): string
{
return $this->sortDirection->value;
}
}
89 changes: 77 additions & 12 deletions app/Http/Livewire/Delegates/Delegates.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,20 @@

namespace App\Http\Livewire\Delegates;

use App\Enums\SortDirection;
use App\Facades\Network;
use App\Http\Livewire\Abstracts\TabbedTableComponent;
use App\Http\Livewire\Concerns\DeferLoading;
use App\Http\Livewire\Concerns\HasTableFilter;
use App\Models\Scopes\OrderByBalanceScope;
use App\Http\Livewire\Concerns\HasTableSorting;
use App\Models\ForgingStats;
use App\Models\Wallet;
use App\Services\Cache\DelegateCache;
use App\ViewModels\ViewModelFactory;
use Illuminate\Contracts\View\View;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\DB;

/**
* @property bool $isAllSelected
Expand All @@ -23,9 +27,14 @@ final class Delegates extends TabbedTableComponent
{
use DeferLoading;
use HasTableFilter;
use HasTableSorting;

public const PER_PAGE = 51;

public const INITIAL_SORT_KEY = 'rank';

public const INITIAL_SORT_DIRECTION = SortDirection::ASC;

public array $filter = [
'active' => true,
'standby' => true,
Expand Down Expand Up @@ -85,19 +94,9 @@ public function getDelegatesProperty(): LengthAwarePaginator
}

return $this->getDelegatesQuery()
->withScope(OrderByBalanceScope::class)
->paginate($this->perPage);
}

public function getShowMissedBlocksProperty(): bool
{
if ($this->filter['active'] === false) {
return false;
}

return ($this->page - 1) * $this->perPage < Network::delegateCount();
}

public static function perPageOptions(): array
{
return trans('tables.delegates.delegate_per_page_options');
Expand All @@ -118,6 +117,11 @@ private function hasFilters(): bool

private function getDelegatesQuery(): Builder
{
$sortDirection = SortDirection::ASC;
if ($this->sortDirection === SortDirection::DESC) {
$sortDirection = SortDirection::DESC;
}

return Wallet::query()
->whereNotNull('attributes->delegate->username')
->where(fn ($query) => $query->when($this->hasFilters(), function ($query) {
Expand All @@ -133,6 +137,67 @@ private function getDelegatesQuery(): Builder
})))
->orWhere(fn ($query) => $query->when($this->filter['resigned'] === true, fn ($query) => $query->where('attributes->delegate->resigned', true)));
}))
->orderByRaw("(\"attributes\"->'delegate'->>'rank')::numeric ASC");
->when($this->sortKey === 'rank', fn ($query) => $query->orderByRaw("(\"attributes\"->'delegate'->>'rank')::numeric ".$sortDirection->value))
->when($this->sortKey === 'name', fn ($query) => $query->orderByRaw("(\"attributes\"->'delegate'->>'username')::text ".$sortDirection->value.', ("attributes"->\'delegate\'->>\'rank\')::numeric ASC'))
->when($this->sortKey === 'votes' || $this->sortKey === 'percentage_votes', function ($query) use ($sortDirection) {
$query->selectRaw('("attributes"->\'delegate\'->>\'voteBalance\')::numeric AS vote_count')
->selectRaw('wallets.*')
->orderByRaw('CASE WHEN NULLIF(("attributes"->\'delegate\'->>\'voteBalance\')::numeric, 0) IS NULL THEN 1 ELSE 0 END ASC')
->orderByRaw(sprintf(
'("attributes"->\'delegate\'->>\'voteBalance\')::numeric %s',
$sortDirection->value
))
->orderByRaw('("attributes"->\'delegate\'->>\'rank\')::numeric ASC');
})
->when($this->sortKey === 'no_of_voters', function ($query) use ($sortDirection) {
$voterCounts = (new DelegateCache())->getAllVoterCounts();
if (count($voterCounts) === 0) {
$query->selectRaw('0 AS no_of_voters')
->selectRaw('wallets.*');

return;
}

$query->selectRaw('voting_stats.count AS no_of_voters')
->selectRaw('wallets.*')
->join(DB::raw(sprintf(
'(values %s) as voting_stats (public_key, count)',
collect($voterCounts)
->map(fn ($count, $publicKey) => sprintf('(\'%s\',%d)', $publicKey, $count))
->join(','),
)), 'wallets.public_key', '=', 'voting_stats.public_key', 'left outer')
->orderByRaw(sprintf('no_of_voters %s NULLS LAST', $sortDirection->value))
->orderByRaw('("attributes"->\'delegate\'->>\'rank\')::numeric ASC');
})
->when($this->sortKey === 'missed_blocks', function ($query) use ($sortDirection) {
$missedBlocks = ForgingStats::selectRaw('public_key, COUNT(*) as count')
->groupBy('public_key')
->whereNot('missed_height', null)
->get();

if (count($missedBlocks) === 0) {
$query->selectRaw('0 AS missed_blocks')
->selectRaw('wallets.*');

return;
}

$query->selectRaw('COALESCE(forging_stats.count, 0) AS missed_blocks')
->selectRaw('wallets.*')
->join(DB::raw(sprintf(
'(values %s) as forging_stats (public_key, count)',
$missedBlocks->map(fn ($forgingStat) => sprintf('(\'%s\',%d)', $forgingStat->public_key, $forgingStat->count))
->join(','),
)), 'wallets.public_key', '=', 'forging_stats.public_key', 'left outer')
->when($sortDirection === SortDirection::ASC, fn ($query) => $query->orderByRaw(sprintf(
'CASE WHEN ("attributes"->\'delegate\'->>\'rank\')::numeric <= %d THEN 0 ELSE 1 END ASC',
Network::delegateCount(),
)))
->orderByRaw(sprintf(
'missed_blocks %s',
$sortDirection->value,
))
->orderByRaw('("attributes"->\'delegate\'->>\'rank\')::numeric ASC');
});
}
}
83 changes: 82 additions & 1 deletion app/Http/Livewire/Delegates/MissedBlocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,30 @@

namespace App\Http\Livewire\Delegates;

use App\Enums\SortDirection;
use App\Http\Livewire\Abstracts\TabbedTableComponent;
use App\Http\Livewire\Concerns\DeferLoading;
use App\Http\Livewire\Concerns\HasTableSorting;
use App\Models\ForgingStats;
use App\Models\Wallet;
use App\Services\Cache\DelegateCache;
use App\ViewModels\ViewModelFactory;
use Illuminate\Contracts\View\View;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\DB;

/**
* @property LengthAwarePaginator $missedBlocks
* */
final class MissedBlocks extends TabbedTableComponent
{
use DeferLoading;
use HasTableSorting;

public const INITIAL_SORT_KEY = 'age';

public const INITIAL_SORT_DIRECTION = SortDirection::DESC;

/** @var mixed */
protected $listeners = [
Expand Down Expand Up @@ -59,8 +69,79 @@ public function getMissedBlocksProperty(): LengthAwarePaginator

private function getMissedBlocksQuery(): Builder
{
$sortDirection = SortDirection::ASC;
if ($this->sortDirection === SortDirection::DESC) {
$sortDirection = SortDirection::DESC;
}

return ForgingStats::query()
->orderBy('missed_height', 'desc')
->when($this->sortKey === 'height', fn ($query) => $query->orderByRaw('missed_height '.$sortDirection->value.', timestamp DESC'))
->when($this->sortKey === 'age', fn ($query) => $query->orderByRaw('timestamp '.$sortDirection->value.', timestamp DESC'))
->when($this->sortKey === 'name', function ($query) use ($sortDirection) {
$missedBlockPublicKeys = ForgingStats::groupBy('public_key')->pluck('public_key');

$delegateNames = Wallet::whereIn('public_key', $missedBlockPublicKeys)
->get()
->pluck('attributes.delegate.username', 'public_key');

if (count($delegateNames) === 0) {
$query->selectRaw('NULL AS delegate_name')
->selectRaw('forging_stats.*');

return;
}

$query->selectRaw('wallets.name AS delegate_name')
->selectRaw('forging_stats.*')
->join(DB::raw(sprintf(
'(values %s) as wallets (public_key, name)',
$delegateNames->map(fn ($name, $publicKey) => sprintf('(\'%s\',\'%s\')', $publicKey, $name))
->join(','),
)), 'forging_stats.public_key', '=', 'wallets.public_key', 'left outer')
->orderByRaw('delegate_name '.$sortDirection->value.', timestamp DESC');
})
->when($this->sortKey === 'votes' || $this->sortKey === 'percentage_votes', function ($query) use ($sortDirection) {
$missedBlockPublicKeys = ForgingStats::groupBy('public_key')->pluck('public_key');

$delegateVotes = Wallet::whereIn('public_key', $missedBlockPublicKeys)
->get()
->pluck('attributes.delegate.voteBalance', 'public_key');

if (count($delegateVotes) === 0) {
$query->selectRaw('0 AS votes')
->selectRaw('forging_stats.*');

return;
}

$query->selectRaw('wallets.votes AS votes')
->selectRaw('forging_stats.*')
->join(DB::raw(sprintf(
'(values %s) as wallets (public_key, votes)',
$delegateVotes->map(fn ($votes, $publicKey) => sprintf('(\'%s\',%d)', $publicKey, $votes))
->join(','),
)), 'forging_stats.public_key', '=', 'wallets.public_key', 'left outer')
->orderByRaw('votes '.$sortDirection->value.', timestamp DESC');
})
->when($this->sortKey === 'no_of_voters', function ($query) use ($sortDirection) {
$voterCounts = (new DelegateCache())->getAllVoterCounts();
if (count($voterCounts) === 0) {
$query->selectRaw('0 AS no_of_voters')
->selectRaw('forging_stats.*');

return;
}

$query->selectRaw('voting_stats.count AS no_of_voters')
->selectRaw('forging_stats.*')
->join(DB::raw(sprintf(
'(values %s) as voting_stats (public_key, count)',
collect($voterCounts)
->map(fn ($count, $publicKey) => sprintf('(\'%s\',%d)', $publicKey, $count))
->join(','),
)), 'forging_stats.public_key', '=', 'voting_stats.public_key', 'left outer')
->orderByRaw(sprintf('no_of_voters %s NULLS LAST, timestamp DESC', $sortDirection->value));
})
->whereNotNull('missed_height');
}
}
Loading

0 comments on commit 5e70933

Please sign in to comment.