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())