Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add tui explorer #487

Merged
merged 6 commits into from
Mar 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -61,19 +61,12 @@ RUN . ~/.bash_profile \
&& poetry config virtualenvs.create false

# install python packages
USER apl
COPY pyproject.toml /app/pyproject.toml
COPY poetry.lock /app/poetry.lock
RUN . ~/.bash_profile \
&& poetry install --directory /app --only main --no-root \
&& rm -f /app/pyproject.toml \
&& rm -f /app/poetry.lock

# app deploy
USER root
COPY --chown=apl:apl LICENSE /app/ibet-Prime/
RUN mkdir -p /app/ibet-Prime/bin/
COPY --chown=apl:apl bin/ /app/ibet-Prime/bin/
RUN mkdir -p /app/ibet-Prime/cmd/
COPY --chown=apl:apl cmd/ /app/ibet-Prime/cmd/
RUN mkdir -p /app/ibet-Prime/contracts/
COPY --chown=apl:apl contracts/ /app/ibet-Prime/contracts/
RUN mkdir -p /app/ibet-Prime/conf/
Expand All @@ -88,6 +81,15 @@ COPY --chown=apl:apl app/ /app/ibet-Prime/app/
RUN find /app/ibet-Prime/ -type d -name __pycache__ | xargs rm -fr \
&& chmod -R 755 /app/ibet-Prime/

USER apl
COPY pyproject.toml /app/ibet-Prime/pyproject.toml
COPY poetry.lock /app/ibet-Prime/poetry.lock
RUN . ~/.bash_profile \
&& cd /app/ibet-Prime \
&& poetry install --only main --no-root -E ibet-explorer \
&& rm -f /app/ibet-Prime/pyproject.toml \
&& rm -f /app/ibet-Prime/poetry.lock

# command deploy
USER apl
COPY run.sh healthcheck.sh /app/
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ English | [日本語](./README_JA.md)

Install python packages with:
```bash
$ pip install -r requirements.txt
$ poetry install --no-root --only main -E explorer
```

### Setting environment variables
Expand All @@ -68,13 +68,13 @@ The main environment variables are as follows.
<td>DATABASE_URL</td>
<td>False</td>
<td nowrap>Database URL</td>
<td>postgresql://issuerapi:issuerapipass@localhost:5432/issuerapidb</td>
<td>postgresql+psycopg://issuerapi:issuerapipass@localhost:5432/issuerapidb</td>
</tr>
<tr>
<td>TEST_DATABASE_URL</td>
<td>False</td>
<td nowrap>Test database URL</td>
<td>postgresql://issuerapi:issuerapipass@localhost:5432/issuerapidb</td>
<td>postgresql+psycopg://issuerapi:issuerapipass@localhost:5432/issuerapidb</td>
</tr>
<tr>
<td>DATABASE_SCHEMA</td>
Expand Down
6 changes: 3 additions & 3 deletions README_JA.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@

以下のコマンドで Python パッケージをインストールします。
```bash
$ pip install -r requirements.txt
$ poetry install --no-root --only main -E explorer
```

### 環境変数の設定
Expand All @@ -69,13 +69,13 @@ $ pip install -r requirements.txt
<td>DATABASE_URL</td>
<td>False</td>
<td nowrap>データベース URL</td>
<td>postgresql://issuerapi:issuerapipass@localhost:5432/issuerapidb</td>
<td>postgresql+psycopg://issuerapi:issuerapipass@localhost:5432/issuerapidb</td>
</tr>
<tr>
<td>TEST_DATABASE_URL</td>
<td>False</td>
<td nowrap>テスト用データベース URL</td>
<td>postgresql://issuerapi:issuerapipass@localhost:5432/issuerapidb</td>
<td>postgresql+psycopg://issuerapi:issuerapipass@localhost:5432/issuerapidb</td>
</tr>
<tr>
<td>DATABASE_SCHEMA</td>
Expand Down
4 changes: 3 additions & 1 deletion app/model/schema/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@
# Response
BlockDataResponse,
BlockDataListResponse,
BlockDataDetail,
TxDataResponse,
TxDataListResponse
TxDataListResponse,
TxDataDetail
)
from .bulk_transfer import (
# Response
Expand Down
15 changes: 14 additions & 1 deletion app/model/schema/bc_explorer.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@
from pydantic.dataclasses import dataclass
from web3 import Web3

from .types import ResultSet
from .types import (
ResultSet,
SortOrder
)


############################
Expand All @@ -44,6 +47,7 @@ class BlockData(BaseModel):
gas_used: int
size: NonNegativeInt


class BlockDataDetail(BaseModel):
number: NonNegativeInt = Field(description="Block number")
parent_hash: str
Expand All @@ -64,6 +68,7 @@ class BlockDataDetail(BaseModel):
size: NonNegativeInt
transactions: list[str] = Field(description="Transaction list")


class TxData(BaseModel):
hash: str = Field(description="Transaction hash")
block_hash: str
Expand All @@ -72,6 +77,7 @@ class TxData(BaseModel):
from_address: str
to_address: Optional[str]


class TxDataDetail(BaseModel):
hash: str = Field(description="Transaction hash")
block_hash: str
Expand All @@ -87,6 +93,7 @@ class TxDataDetail(BaseModel):
value: NonNegativeInt
nonce: NonNegativeInt


############################
# REQUEST
############################
Expand All @@ -97,6 +104,8 @@ class ListBlockDataQuery:
limit: Optional[NonNegativeInt] = Query(default=None, description="number of set")
from_block_number: Optional[NonNegativeInt] = Query(default=None)
to_block_number: Optional[NonNegativeInt] = Query(default=None)
sort_order: Optional[SortOrder] = Query(default=SortOrder.ASC, description="sort order(0: ASC, 1: DESC)")


@dataclass
class ListTxDataQuery:
Expand All @@ -120,20 +129,24 @@ def to_address_is_valid_address(cls, v):
raise ValueError("to_address is not a valid address")
return v


############################
# RESPONSE
############################

class BlockDataResponse(BaseModel):
__root__: BlockDataDetail


class BlockDataListResponse(BaseModel):
result_set: ResultSet
block_data: list[BlockData]


class TxDataResponse(BaseModel):
__root__: TxDataDetail


class TxDataListResponse(BaseModel):
result_set: ResultSet
tx_data: list[TxData]
35 changes: 30 additions & 5 deletions app/routers/bc_explorer.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,20 @@

SPDX-License-Identifier: Apache-2.0
"""
from pathlib import Path
from typing import Tuple, Dict, Any, Type

from eth_utils import to_checksum_address
from fastapi import (
APIRouter,
Depends, HTTPException
Depends,
HTTPException,
Path
)
from pydantic import NonNegativeInt
from sqlalchemy import desc
from sqlalchemy.orm import Session
from web3.contract import ContractFunction
import config

from app import log
from app.database import db_session
Expand All @@ -36,7 +38,9 @@
)
from app.model.db import (
IDXBlockData,
IDXTxData, Token
IDXTxData,
Token,
IDXBlockDataBlockNumber
)
from app.model.schema import (
ListBlockDataQuery,
Expand Down Expand Up @@ -90,9 +94,27 @@ def list_block_data(
limit = request_query.limit
from_block_number = request_query.from_block_number
to_block_number = request_query.to_block_number
sort_order = request_query.sort_order # default: asc

# NOTE: The more data, the slower the SELECT COUNT(1) query becomes.
# To get total number of block data, latest block number where block data synced is used here.
idx_block_data_block_number = (
session.query(IDXBlockDataBlockNumber).filter(IDXBlockDataBlockNumber.chain_id == str(config.CHAIN_ID)).first()
)
if idx_block_data_block_number is None:
return json_response({
"result_set": {
"count": 0,
"offset": offset,
"limit": limit,
"total": 0
},
"block_data": []
})

total = idx_block_data_block_number.latest_block_number + 1

query = session.query(IDXBlockData)
total = query.count()

# Search Filter
if from_block_number is not None and to_block_number is not None:
Expand All @@ -105,7 +127,10 @@ def list_block_data(
count = query.count()

# Sort
query = query.order_by(IDXBlockData.number)
if sort_order == 0:
query = query.order_by(IDXBlockData.number)
else:
query = query.order_by(desc(IDXBlockData.number))

# Pagination
if limit is not None:
Expand Down
21 changes: 21 additions & 0 deletions cmd/explorer/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
.PHONY: isort black test run

format: isort black

isort:
isort src/.

black:
poetry run black src

test:
pytest .

console:
textual console

dev:
TEXTUAL=devtools poetry run python src/main.py

run:
poetry run python src/main.py
44 changes: 44 additions & 0 deletions cmd/explorer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# ibet-Prime BC-Explorer

## Run

### with container

```bash
> docker exec -it -e "TERM=xterm-256color" ibet-prime-app bash --login
> apl@2e5a80e06fcb:/$ ibet-explorer --help

Usage: ibet-explorer [OPTIONS]

╭─ Options ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ --url TEXT ibet-Prime server URL to connect [default: http://localhost:5000] │
│ --lot-size INTEGER Lot size to fetch Block Data list [default: 100] │
│ --install-completion [bash|zsh|fish|powershell|pwsh] Install completion for the specified shell. [default: None] │
│ --show-completion [bash|zsh|fish|powershell|pwsh] Show completion for the specified shell, to copy it or customize the installation. [default: None] │
│ --help Show this message and exit. │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
```

- **URL**: ibet-Prime URL.
- You can run this on pythonic way in local.

### Poetry
```bash
> poetry install
> poetry run python src/main.py --url http://localhost:5000
```

### Pip
```bash
> pip install -e ./
> python src/main.py --url http://localhost:5000
```

## Screenshots 👀

![query-setting](https://user-images.githubusercontent.com/15183665/222354993-0c11eedc-fb22-472a-8c9f-f9bc8be4d173.png)

![block](https://user-images.githubusercontent.com/15183665/222355008-0c893524-2a80-4975-9c44-537649b11fc7.png)

![transaction](https://user-images.githubusercontent.com/15183665/222355025-24b72685-8d27-48e5-9ea1-b265c4365629.png)

7 changes: 7 additions & 0 deletions cmd/explorer/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions cmd/explorer/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
[tool.poetry]
name = "ibet-prime-explorer"
version = "0.1.0"
description = "ibet-Prime Terminal UI for Block Chain Explorer"
authors = ["BOOSTRY Co., Ltd. <dev@boostry.co.jp>"]
readme = "README.md"
packages = [
{ include = "src" },
]

[tool.poetry.dependencies]
python = "3.10.4"

[tool.poetry.scripts]
ibet-explorer = "src.main:app"

[tool.mypy]
python_version = "3.10"
no_strict_optional = true
ignore_missing_imports = true
check_untyped_defs = true

[tool.black]
includes = "src"
target-version = ['py310']
line-length = 120

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
18 changes: 18 additions & 0 deletions cmd/explorer/src/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"""
Copyright BOOSTRY Co., Ltd.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

See the License for the specific language governing permissions and
limitations under the License.

SPDX-License-Identifier: Apache-2.0
"""
Loading