From 1e55e987b41420aea613af8279e97e4d55750bfd Mon Sep 17 00:00:00 2001 From: yhtiyar Date: Mon, 6 Sep 2021 15:56:21 +0300 Subject: [PATCH 1/5] added support of `nft` address metadata in `address_info/` --- backend/moonstream/actions.py | 22 +++++++++++++++++++++- backend/moonstream/data.py | 11 +++++++++-- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/backend/moonstream/actions.py b/backend/moonstream/actions.py index 4ecf8bd4..055f678b 100644 --- a/backend/moonstream/actions.py +++ b/backend/moonstream/actions.py @@ -57,6 +57,7 @@ def get_contract_source_info( class LabelNames(Enum): ETHERSCAN_SMARTCONTRACT = "etherscan_smartcontract" COINMARKETCAP_TOKEN = "coinmarketcap_token" + ERC721 = "erc721" def get_ethereum_address_info( @@ -71,6 +72,7 @@ def get_ethereum_address_info( address_info = data.EthereumAddressInfo(address=address) etherscan_address_url = f"https://etherscan.io/address/{address}" + etherscan_token_url = f"https://etherscan.io/token/{address}" blockchain_com_url = f"https://www.blockchain.com/eth/address/{address}" # Checking for token: coinmarketcap_label: Optional[EthereumLabel] = ( @@ -87,7 +89,7 @@ def get_ethereum_address_info( symbol=coinmarketcap_label.label_data["symbol"], external_url=[ coinmarketcap_label.label_data["coinmarketcap_url"], - etherscan_address_url, + etherscan_token_url, blockchain_com_url, ], ) @@ -107,6 +109,24 @@ def get_ethereum_address_info( external_url=[etherscan_address_url, blockchain_com_url], ) + # Checking for NFT + # Checking for smart contract + erc721_label: Optional[EthereumLabel] = ( + db_session.query(EthereumLabel) + .filter(EthereumLabel.address_id == id[0]) + .filter(EthereumLabel.label == LabelNames.ERC721.value) + .order_by(text("created_at desc")) + .limit(1) + .one_or_none() + ) + if erc721_label is not None: + address_info.nft = data.EthereumSmartContractDetails( + name=erc721_label.label_data.get("name"), + symbol=erc721_label.label_data.get("symbol"), + total_supplly=erc721_label.label_data.get("totalSupply"), + external_url=[etherscan_token_url, blockchain_com_url], + ) + return address_info diff --git a/backend/moonstream/data.py b/backend/moonstream/data.py index e8e36c5e..79ebc3ea 100644 --- a/backend/moonstream/data.py +++ b/backend/moonstream/data.py @@ -3,6 +3,8 @@ Pydantic schemas for the Moonstream HTTP API """ from typing import List, Optional, Dict, Any +from sqlalchemy.sql.selectable import alias + from pydantic import BaseModel, Field @@ -160,18 +162,23 @@ class EthereumSmartContractSourceInfo(BaseModel): class EthereumTokenDetails(BaseModel): name: Optional[str] symbol: Optional[str] - external_url: List[str] = [] + external_url: List[str] = Field(default_factory=list) class EthereumSmartContractDetails(BaseModel): name: Optional[str] - external_url: List[str] = [] + external_url: List[str] = Field(default_factory=list) + + +class EthereumNFTDetails(EthereumTokenDetails): + total_supply: Optional[int] = Field(alias="totalSupply") class EthereumAddressInfo(BaseModel): address: str token: Optional[EthereumTokenDetails] smart_contract: Optional[EthereumSmartContractDetails] + nft: Optional[EthereumNFTDetails] class TxinfoEthereumBlockchainResponse(BaseModel): From 8e27fb0a76adcf05193625227af091bd7dbb8212 Mon Sep 17 00:00:00 2001 From: yhtiyar Date: Mon, 6 Sep 2021 16:24:14 +0300 Subject: [PATCH 2/5] made it work --- backend/moonstream/actions.py | 6 +++--- backend/moonstream/data.py | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/backend/moonstream/actions.py b/backend/moonstream/actions.py index 055f678b..60242b13 100644 --- a/backend/moonstream/actions.py +++ b/backend/moonstream/actions.py @@ -120,13 +120,13 @@ def get_ethereum_address_info( .one_or_none() ) if erc721_label is not None: - address_info.nft = data.EthereumSmartContractDetails( + address_info.nft = data.EthereumNFTDetails( name=erc721_label.label_data.get("name"), symbol=erc721_label.label_data.get("symbol"), - total_supplly=erc721_label.label_data.get("totalSupply"), + total_supply=erc721_label.label_data.get("totalSupply"), external_url=[etherscan_token_url, blockchain_com_url], ) - + breakpoint() return address_info diff --git a/backend/moonstream/data.py b/backend/moonstream/data.py index 79ebc3ea..0f69f0cc 100644 --- a/backend/moonstream/data.py +++ b/backend/moonstream/data.py @@ -3,7 +3,6 @@ Pydantic schemas for the Moonstream HTTP API """ from typing import List, Optional, Dict, Any -from sqlalchemy.sql.selectable import alias from pydantic import BaseModel, Field @@ -171,7 +170,7 @@ class EthereumSmartContractDetails(BaseModel): class EthereumNFTDetails(EthereumTokenDetails): - total_supply: Optional[int] = Field(alias="totalSupply") + total_supply: Optional[int] class EthereumAddressInfo(BaseModel): From 0a2790b67842bc07f3198c93c30ae2d6652fb29b Mon Sep 17 00:00:00 2001 From: yhtiyar Date: Mon, 6 Sep 2021 19:55:33 +0300 Subject: [PATCH 3/5] removed breakpoint --- backend/moonstream/actions.py | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/moonstream/actions.py b/backend/moonstream/actions.py index 60242b13..1ddd67ae 100644 --- a/backend/moonstream/actions.py +++ b/backend/moonstream/actions.py @@ -126,7 +126,6 @@ def get_ethereum_address_info( total_supply=erc721_label.label_data.get("totalSupply"), external_url=[etherscan_token_url, blockchain_com_url], ) - breakpoint() return address_info From d6b135dbdaa0c66381d0d4140ed185cc6f8e57ee Mon Sep 17 00:00:00 2001 From: yhtiyar Date: Mon, 6 Sep 2021 19:59:55 +0300 Subject: [PATCH 4/5] added `None` default values where fields are `Optional` --- backend/moonstream/data.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/backend/moonstream/data.py b/backend/moonstream/data.py index 0f69f0cc..9107c74b 100644 --- a/backend/moonstream/data.py +++ b/backend/moonstream/data.py @@ -159,25 +159,25 @@ class EthereumSmartContractSourceInfo(BaseModel): class EthereumTokenDetails(BaseModel): - name: Optional[str] - symbol: Optional[str] + name: Optional[str] = None + symbol: Optional[str] = None external_url: List[str] = Field(default_factory=list) class EthereumSmartContractDetails(BaseModel): - name: Optional[str] + name: Optional[str] = None external_url: List[str] = Field(default_factory=list) class EthereumNFTDetails(EthereumTokenDetails): - total_supply: Optional[int] + total_supply: Optional[int] = None class EthereumAddressInfo(BaseModel): address: str - token: Optional[EthereumTokenDetails] - smart_contract: Optional[EthereumSmartContractDetails] - nft: Optional[EthereumNFTDetails] + token: Optional[EthereumTokenDetails] = None + smart_contract: Optional[EthereumSmartContractDetails] = None + nft: Optional[EthereumNFTDetails] = None class TxinfoEthereumBlockchainResponse(BaseModel): From 26d57b19699ddc7e4d76bcbb3de9de1e19ca364e Mon Sep 17 00:00:00 2001 From: yhtiyar Date: Wed, 15 Sep 2021 12:20:52 +0300 Subject: [PATCH 5/5] added error handling in address_info endpoint --- backend/moonstream/routes/address_info.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/backend/moonstream/routes/address_info.py b/backend/moonstream/routes/address_info.py index c985c683..a2bcbf65 100644 --- a/backend/moonstream/routes/address_info.py +++ b/backend/moonstream/routes/address_info.py @@ -53,7 +53,11 @@ async def addressinfo_handler( address: str, db_session: Session = Depends(yield_db_session), ) -> Optional[data.EthereumAddressInfo]: - response = actions.get_ethereum_address_info(db_session, address) + try: + response = actions.get_ethereum_address_info(db_session, address) + except Exception as e: + logger.error(f"Unable to get info about Ethereum address {e}") + raise MoonstreamHTTPException(status_code=500, internal_error=e) return response