| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- #!/usr/bin/env python3
- #
- # MMGen Wallet, a terminal-based cryptocurrency wallet
- # Copyright (C)2013-2025 The MMGen Project <mmgen@tuta.io>
- # Licensed under the GNU General Public License, Version 3:
- # https://www.gnu.org/licenses
- # Public project repositories:
- # https://github.com/mmgen/mmgen-wallet
- # https://gitlab.com/mmgen/mmgen-wallet
- """
- proto.eth.tw.json: export and import tracking wallet to JSON format
- """
- from collections import namedtuple
- from ....tw.json import TwJSON
- from ....tw.shared import TwMMGenID
- class EthereumTwJSON(TwJSON):
- class Base(TwJSON.Base):
- def __init__(self, proto, *args, **kwargs):
- self.params_keys = ['symbol', 'decimals']
- self.params_tuple = namedtuple('params_tuple', self.params_keys)
- super().__init__(proto, *args, **kwargs)
- @property
- def mappings_json(self):
- def gen_mappings(data):
- for d in data:
- yield (d.mmgen_id, d.address) if hasattr(d, 'mmgen_id') else d
- return self.json_dump({
- 'accounts': list(gen_mappings(self.entries['accounts'])),
- 'tokens': {k: list(gen_mappings(v)) for k, v in self.entries['tokens'].items()}})
- @property
- def num_entries(self):
- return len(self.entries['accounts']) + len(self.entries['tokens'])
- class Import(TwJSON.Import, Base):
- info_msg = """
- This utility will recreate a new tracking wallet from the supplied JSON dump.
- If the dump contains address balances, balances will be updated from it.
- """
- @property
- async def tracking_wallet_exists(self):
- return bool(self.twctl.data['accounts'] or self.twctl.data['tokens'])
- async def create_tracking_wallet(self):
- return True
- async def get_entries(self):
- edata = self.data['data']['entries']
- def gen_entries(data):
- for d in data:
- if len(d) == 2:
- yield self.params_tuple(*d)
- else:
- e = self.entry_tuple_in(*d)
- yield self.entry_tuple(
- TwMMGenID(self.proto, e.mmgen_id),
- e.address,
- getattr(e, 'amount', '0'),
- e.comment)
- def gen_token_entries():
- for token_addr, token_data in edata['tokens'].items():
- yield (
- token_addr,
- list(gen_entries(token_data)),
- )
- return {
- 'accounts': list(gen_entries(edata['accounts'])),
- 'tokens': dict(list(gen_token_entries()))}
- async def do_import(self, batch):
- from ....obj import TwComment
- def gen_data(data):
- for d in data:
- if hasattr(d, 'address'):
- yield (
- d.address,
- {'mmid': d.mmgen_id, 'comment': TwComment(d.comment)}
- | ({} if d.amount is None else {'balance': d.amount}))
- else:
- yield ('params', {'symbol': d.symbol, 'decimals': d.decimals})
- self.twctl.data = { # keys must be in correct order
- 'coin': self.coin.upper(),
- 'network': self.network.upper(),
- 'accounts': dict(gen_data(self.entries['accounts'])),
- 'tokens': {k: dict(gen_data(v)) for k, v in self.entries['tokens'].items()}}
- self.twctl.write(quiet=False)
- class Export(TwJSON.Export, Base):
- async def get_entries(self, *, include_amts=True):
- def gen_data(data):
- for k, v in data.items():
- if k == 'params':
- yield self.params_tuple(**v)
- elif include_amts:
- yield self.entry_tuple(TwMMGenID(self.proto, v['mmid']), k, v.get('balance'), v['comment'])
- else:
- yield self.entry_tuple_in(TwMMGenID(self.proto, v['mmid']), k, v['comment'])
- def gen_token_data():
- for token_addr, token_data in self.twctl.data['tokens'].items():
- yield (
- token_addr,
- sorted(
- gen_data(token_data),
- key = lambda x: x.mmgen_id.sort_key if hasattr(x, 'mmgen_id') else '+'
- )
- )
- return {
- 'accounts': sorted(
- gen_data(self.twctl.data['accounts']),
- key = lambda x: x.mmgen_id.sort_key),
- 'tokens': dict(sorted(gen_token_data()))}
- @property
- async def entries_out(self):
- return await self.get_entries(include_amts='amount' in self.keys)
- @property
- async def total(self):
- return sum(self.proto.coin_amt(i.amount) for i in self.entries['accounts']) or self.proto.coin_amt('0')
|