cic-cli/cic/meta.py

142 lines
4.0 KiB
Python
Raw Normal View History

2021-10-09 19:56:29 +02:00
# standard imports
import os
import json
import logging
import base64
2021-10-09 19:56:29 +02:00
# external imports
from cic_types import MetadataPointer
from cic_types.processor import generate_metadata_pointer
2021-10-14 15:43:23 +02:00
from cic_types.ext.metadata import MetadataRequestsHandler
from hexathon import strip_0x
2021-10-09 19:56:29 +02:00
# local imports
2021-10-10 11:33:30 +02:00
from .base import (
Data,
data_dir,
)
2021-10-14 15:43:23 +02:00
from cic.output import OutputWriter
logg = logging.getLogger(__name__)
2021-10-09 19:56:29 +02:00
class Meta(Data):
2021-11-29 08:02:12 +01:00
"""Serialize and publish metadata for token.
2021-10-09 19:56:29 +02:00
2021-11-29 08:02:12 +01:00
The token metadata is any mutable data that is not part of the initial token proof, but published simultaneously as the token nonetheless.
:param path: Path to settings directory
:type path: str
:param writer: Writer interface receiving the output of the processor
:type writer: cic.output.OutputWriter
"""
def __init__(self, path='.', writer=None):
2021-10-09 19:56:29 +02:00
super(Meta, self).__init__()
self.name = None
2021-10-09 20:37:54 +02:00
self.contact = {}
2021-10-09 19:56:29 +02:00
self.path = path
self.writer = writer
2021-10-09 19:56:29 +02:00
self.meta_path = os.path.join(self.path, 'meta.json')
def load(self):
2021-11-29 08:02:12 +01:00
"""Load metadata from settings.
"""
2021-10-09 19:56:29 +02:00
super(Meta, self).load()
2021-10-09 20:37:54 +02:00
f = open(self.meta_path, 'r')
o = json.load(f)
2021-10-09 19:56:29 +02:00
f.close()
2021-10-09 20:37:54 +02:00
self.name = o['name']
self.contact = o['contact']
2021-10-09 19:56:29 +02:00
self.inited = True
def start(self):
2021-11-29 08:02:12 +01:00
"""Initialize metadata settings from template.
"""
2021-10-09 19:56:29 +02:00
super(Meta, self).start()
meta_template_file_path = os.path.join(data_dir, 'meta_template_v{}.json'.format(self.version()))
f = open(meta_template_file_path)
o = json.load(f)
f.close()
f = open(self.meta_path, 'w')
2021-10-18 10:47:48 +02:00
json.dump(o, f, sort_keys=True, indent="\t")
2021-10-09 19:56:29 +02:00
f.close()
2021-10-09 20:37:54 +02:00
def reference(self, token_address):
2021-11-29 08:02:12 +01:00
"""Calculate the mutable reference for the token metadata.
"""
token_address_bytes = bytes.fromhex(strip_0x(token_address))
return generate_metadata_pointer(token_address_bytes, MetadataPointer.TOKEN_META)
def asdict(self):
2021-11-29 08:02:12 +01:00
"""Output proof state to dict.
"""
return {
'name': self.name,
'contact': self.contact,
}
2021-10-21 15:11:05 +02:00
def process(self, token_address=None, token_symbol=None, writer=None):
2021-11-29 08:02:12 +01:00
"""Serialize and publish metadata.
See cic.processor.Processor.process
"""
if writer == None:
writer = self.writer
v = json.dumps(self.asdict())
2021-10-21 15:11:05 +02:00
token_address_bytes = bytes.fromhex(strip_0x(token_address))
k = generate_metadata_pointer(token_address_bytes, MetadataPointer.TOKEN_META)
writer.write(k, v.encode('utf-8'))
token_symbol_bytes = token_symbol.encode('utf-8')
k = generate_metadata_pointer(token_symbol_bytes, MetadataPointer.TOKEN_META_SYMBOL)
writer.write(k, v.encode('utf-8'))
return (k, v)
2021-10-09 20:37:54 +02:00
def __str__(self):
2021-10-10 14:49:22 +02:00
s = "contact.name = {}\n".format(self.name)
2021-10-09 20:37:54 +02:00
for k in self.contact.keys():
if self.contact[k] == '':
continue
2021-10-10 14:49:22 +02:00
s += "contact.{} = {}\n".format(k.lower(), self.contact[k])
2021-10-09 20:37:54 +02:00
return s
2021-10-14 15:43:23 +02:00
class MetadataWriter(OutputWriter):
2021-11-29 08:02:12 +01:00
"""Custom writer for publishing data under immutable content-addressed pointers in the cic-meta storage backend.
Data that is not utf-8 will be converted to base64 before publishing.
Implements cic.output.OutputWriter
"""
2021-10-21 15:11:05 +02:00
2021-10-14 15:43:23 +02:00
def write(self, k, v):
2021-10-21 15:11:05 +02:00
rq = MetadataRequestsHandler(MetadataPointer.NONE, bytes.fromhex(k))
try:
v = v.decode('utf-8')
v = json.loads(v)
logg.debug('metadatawriter bindecode {} {}'.format(k, v))
except UnicodeDecodeError:
v = base64.b64encode(v).decode('utf-8')
v = json.loads(json.dumps(v))
logg.debug('metadatawriter b64encode {} {}'.format(k, v))
r = rq.create(v)
logg.info('metadata submitted at {}'.format(k))
return r