import flask import pbc_client import pbcabi import base64 import dataclasses import requests_cache from collections.abc import Iterator HTML_INDEX = """ Hello from Flask
{% for notamon in notamons %}

{{ notamon.nickname }}

{{ notamon.species_name }}

{% endfor %}
""" @dataclasses.dataclass(frozen=True) class Notamon: image_src: str effect_css: str nickname: str species_name: str @dataclasses.dataclass(frozen=True) class NotamonNFTData: nickname: str owner: str species_id: int skin_id: int effect_id: int stat_hp: int stat_attack: int stat_defense: int @dataclasses.dataclass(frozen=True) class AssetVariable: variable_id: int asset_id: int opened: bytes | None app = flask.Flask(__name__) TEST_NOTAMON = Notamon( image_src = 'https://img.pokemondb.net/sprites/ruby-sapphire/normal/mudkip.png', effect_css = '', nickname = 'Dude', species_name = 'Mudkip', ) ADDRESS_NFTS = '02b82d36784146bd29415dbaa623a5f1cf6e6e1108' ADDRESS_ASSETS = '0338d039e3960426d0cfc590efbdbef70b049696a3' SESSION = requests_cache.CachedSession() def compress(b: bytes) -> bytes: l = [] for i in range(0, len(b)//8): derp = 0 for j in range(0, 8): derp |= b[i*8+j] << j del j l.append(derp) del i, derp return bytes(l) def decode_opened_variable(value: str) -> bytes: return compress(base64.b64decode(value))[4:] def get_asset_variables(client, address) -> Iterator[AssetVariable]: asset_contract_state, _ = client.get_contract_state(ADDRESS_ASSETS) for variable in asset_contract_state['variables']: print(variable) asset_id = int.from_bytes(base64.b64decode(variable['value']['information']['data'])) opened = decode_opened_variable(variable['value']['openValue']['data']) if variable['value']['openValue'] else None yield AssetVariable( variable_id = variable['key'], asset_id = asset_id, opened = opened, ) def to_base64_png(b: bytes) -> str: return f'data:image/png;base64,{base64.b64encode(b)}' def get_notamon_nfts(client: pbc_client.PbcClient) -> Iterator[NotamonNFTData]: asset_contract_state, _ = client.get_typed_contract_state(ADDRESS_NFTS) owners, _ = client.get_typed_contract_avl_tree(ADDRESS_NFTS, asset_contract_state['owners']) attributes, _ = client.get_typed_contract_avl_tree(ADDRESS_NFTS, asset_contract_state['notamon_attributes']) for notamon_id in owners: attr = attributes.get(notamon_id) yield NotamonNFTData( nickname = 'Dude', owner =owners.get(notamon_id), species_id= attr['species_id']['id'], skin_id = attr['skin_id']['id'], effect_id = attr['effect_id']['id'], stat_hp = attr['stat_hp'], stat_attack = attr['stat_attack'], stat_defense = attr['stat_defense'], ) def nft_to_notamon_view(nft: NotamonNFTData, assets) -> Notamon: return Notamon( image_src = to_base64_png(assets[nft.species_id]), effect_css = to_base64_png(assets[nft.effect_id]), nickname = nft.nickname, species_name = 'Mudkip', ) def select_notamons(): client = pbc_client.PbcClient(SESSION, pbc_client.HOSTNAME_TESTNET) nfts = list(get_notamon_nfts(client)) print(nfts) print(client) assets = list(get_asset_variables(client, ADDRESS_ASSETS)) print(assets ) return [nft_to_notamon_view(nft, assets) for nft in nfts] @app.route("/") def hello_world(): return flask.render_template_string(HTML_INDEX, notamons = select_notamons())