mirror of
https://github.com/logos-blockchain/lez-explorer-ui.git
synced 2026-04-08 04:23:18 +00:00
feat: live block streaming
This commit is contained in:
parent
578f0d2b15
commit
5b1d74f237
@ -47,6 +47,10 @@ ExplorerWidget::ExplorerWidget(QWidget* parent)
|
||||
connect(m_navBar, &NavigationBar::homeClicked, this, &ExplorerWidget::navigateHome);
|
||||
connect(m_searchBar, &SearchBar::searchRequested, this, &ExplorerWidget::onSearch);
|
||||
|
||||
connect(m_indexer.get(), &IndexerService::newBlockAdded, this, [this](const Block& block) {
|
||||
m_mainPage->onNewBlock(block);
|
||||
});
|
||||
|
||||
updateNavButtons();
|
||||
}
|
||||
|
||||
|
||||
@ -315,6 +315,19 @@ void MainPage::showSearchResults(const SearchResults& results)
|
||||
m_contentLayout->insertWidget(0, m_searchResultsWidget);
|
||||
}
|
||||
|
||||
void MainPage::onNewBlock(const Block& block)
|
||||
{
|
||||
if (!m_blocksLayout) return;
|
||||
|
||||
m_healthLabel->setText(QString("Chain height: %1").arg(block.blockId));
|
||||
|
||||
// Append to layout then move to top (index 0)
|
||||
addBlockRow(m_blocksLayout, block);
|
||||
auto* newRow = m_blocksLayout->itemAt(m_blocksLayout->count() - 1)->widget();
|
||||
m_blocksLayout->removeWidget(newRow);
|
||||
m_blocksLayout->insertWidget(0, newRow);
|
||||
}
|
||||
|
||||
void MainPage::clearSearchResults()
|
||||
{
|
||||
if (m_searchResultsWidget) {
|
||||
|
||||
@ -18,6 +18,7 @@ public:
|
||||
void refresh();
|
||||
void showSearchResults(const SearchResults& results);
|
||||
void clearSearchResults();
|
||||
void onNewBlock(const Block& block);
|
||||
|
||||
signals:
|
||||
void blockClicked(quint64 blockId);
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
#include "models/Transaction.h"
|
||||
#include "models/Account.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
#include <optional>
|
||||
|
||||
@ -13,9 +14,12 @@ struct SearchResults {
|
||||
QVector<Account> accounts;
|
||||
};
|
||||
|
||||
class IndexerService {
|
||||
class IndexerService : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
virtual ~IndexerService() = default;
|
||||
explicit IndexerService(QObject* parent = nullptr) : QObject(parent) {}
|
||||
~IndexerService() override = default;
|
||||
|
||||
virtual std::optional<Account> getAccount(const QString& accountId) = 0;
|
||||
virtual std::optional<Block> getBlockById(quint64 blockId) = 0;
|
||||
@ -25,4 +29,7 @@ public:
|
||||
virtual quint64 getLatestBlockId() = 0;
|
||||
virtual QVector<Transaction> getTransactionsByAccount(const QString& accountId, int offset, int limit) = 0;
|
||||
virtual SearchResults search(const QString& query) = 0;
|
||||
|
||||
signals:
|
||||
void newBlockAdded(Block block);
|
||||
};
|
||||
|
||||
@ -31,9 +31,68 @@ QString randomBase58String(int length)
|
||||
|
||||
} // namespace
|
||||
|
||||
MockIndexerService::MockIndexerService()
|
||||
MockIndexerService::MockIndexerService(QObject* parent)
|
||||
: IndexerService(parent)
|
||||
{
|
||||
generateData();
|
||||
|
||||
connect(&m_blockTimer, &QTimer::timeout, this, &MockIndexerService::onGenerateBlock);
|
||||
m_blockTimer.start(30000); // 30 seconds
|
||||
}
|
||||
|
||||
Block MockIndexerService::generateBlock(quint64 blockId, const QString& prevHash)
|
||||
{
|
||||
auto* rng = QRandomGenerator::global();
|
||||
|
||||
Block block;
|
||||
block.blockId = blockId;
|
||||
block.prevBlockHash = prevHash;
|
||||
block.hash = randomHash();
|
||||
block.timestamp = QDateTime::currentDateTimeUtc();
|
||||
block.signature = randomHexString(64);
|
||||
block.bedrockParentId = randomHexString(32);
|
||||
block.bedrockStatus = BedrockStatus::Pending;
|
||||
|
||||
int txCount = rng->bounded(1, 6);
|
||||
for (int t = 0; t < txCount; ++t) {
|
||||
Transaction tx;
|
||||
int typeRoll = rng->bounded(100);
|
||||
if (typeRoll < 60) {
|
||||
tx = generatePublicTransaction();
|
||||
} else if (typeRoll < 85) {
|
||||
tx = generatePrivacyPreservingTransaction();
|
||||
} else {
|
||||
tx = generateProgramDeploymentTransaction();
|
||||
}
|
||||
block.transactions.append(tx);
|
||||
m_transactionsByHash[tx.hash] = tx;
|
||||
|
||||
for (const auto& accRef : tx.accounts) {
|
||||
if (!m_accounts.contains(accRef.accountId)) {
|
||||
Account acc;
|
||||
acc.accountId = accRef.accountId;
|
||||
acc.programOwner = randomBase58String(44);
|
||||
acc.balance = QString::number(rng->bounded(0, 1000000));
|
||||
acc.nonce = accRef.nonce;
|
||||
acc.dataSizeBytes = rng->bounded(0, 4096);
|
||||
m_accounts[acc.accountId] = acc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
void MockIndexerService::onGenerateBlock()
|
||||
{
|
||||
quint64 newId = m_blocks.isEmpty() ? 1 : m_blocks.last().blockId + 1;
|
||||
QString prevHash = m_blocks.isEmpty() ? QString(64, '0') : m_blocks.last().hash;
|
||||
|
||||
Block block = generateBlock(newId, prevHash);
|
||||
m_blocks.append(block);
|
||||
m_blocksByHash[block.hash] = block;
|
||||
|
||||
emit newBlockAdded(block);
|
||||
}
|
||||
|
||||
QString MockIndexerService::randomHash()
|
||||
|
||||
@ -3,10 +3,13 @@
|
||||
#include "IndexerService.h"
|
||||
|
||||
#include <QMap>
|
||||
#include <QTimer>
|
||||
|
||||
class MockIndexerService : public IndexerService {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MockIndexerService();
|
||||
explicit MockIndexerService(QObject* parent = nullptr);
|
||||
|
||||
std::optional<Account> getAccount(const QString& accountId) override;
|
||||
std::optional<Block> getBlockById(quint64 blockId) override;
|
||||
@ -17,6 +20,9 @@ public:
|
||||
QVector<Transaction> getTransactionsByAccount(const QString& accountId, int offset, int limit) override;
|
||||
SearchResults search(const QString& query) override;
|
||||
|
||||
private slots:
|
||||
void onGenerateBlock();
|
||||
|
||||
private:
|
||||
void generateData();
|
||||
QString randomHash();
|
||||
@ -24,9 +30,11 @@ private:
|
||||
Transaction generatePublicTransaction();
|
||||
Transaction generatePrivacyPreservingTransaction();
|
||||
Transaction generateProgramDeploymentTransaction();
|
||||
Block generateBlock(quint64 blockId, const QString& prevHash);
|
||||
|
||||
QVector<Block> m_blocks;
|
||||
QMap<QString, Block> m_blocksByHash;
|
||||
QMap<QString, Transaction> m_transactionsByHash;
|
||||
QMap<QString, Account> m_accounts;
|
||||
QTimer m_blockTimer;
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user