def find_card_bundles(provider: Provider, deck: Deck) -> Optional[Iterator]: '''each blockchain transaction can contain multiple cards, wrapped in bundles. This method finds and returns those bundles.''' if isinstance(provider, RpcNode): if deck.id is None: raise Exception("deck.id required to listtransactions") p2th_account = provider.getaccount(deck.p2th_address) batch_data = [('getrawtransaction', [i["txid"], 1]) for i in provider.listtransactions(p2th_account)] result = provider.batch(batch_data) if result is not None: raw_txns = [i['result'] for i in result if result] else: raise EmptyP2THDirectory({'error': 'No cards found on this deck.'}) else: if deck.p2th_address is None: raise Exception("deck.p2th_address required to listtransactions") try: raw_txns = (provider.getrawtransaction(i, 1) for i in provider.listtransactions(deck.p2th_address)) except TypeError: raise EmptyP2THDirectory({'error': 'No cards found on this deck.'}) return (card_bundler(provider, deck, i) for i in raw_txns)
def find_card_bundles(provider: Provider, deck: Deck) -> Optional[Iterator]: '''each blockchain transaction can contain multiple cards, wrapped in bundles. This method finds and returns those bundles.''' if isinstance(provider, RpcNode): if deck.id is None: raise Exception("deck.id required to listtransactions") batch_data = [('getrawtransaction', [i["txid"], 1]) for i in provider.listtransactions(deck.id)] result = provider.batch(batch_data) if result is not None: raw_txns = [i['result'] for i in result if result] else: raise EmptyP2THDirectory({'error': 'No cards found on this deck.'}) else: if deck.p2th_address is None: raise Exception("deck.p2th_address required to listtransactions") try: raw_txns = (provider.getrawtransaction(i, 1) for i in provider.listtransactions(deck.p2th_address)) except TypeError: raise EmptyP2THDirectory({'error': 'No cards found on this deck.'}) return (CardBundle(deck=deck, blockhash=i['blockhash'], txid=i['txid'], timestamp=i['time'], blockseq=tx_serialization_order(provider, i["blockhash"], i["txid"]), blocknum=provider.getblock(i["blockhash"])["height"], sender=find_tx_sender(provider, i), vouts=i['vout'], tx_confirmations=i['confirmations'] ) for i in raw_txns)
def get_card_transfers(provider: Provider, deck: Deck) -> Generator: '''get all <deck> card transfers, if cards match the protocol''' if isinstance(provider, RpcNode): if deck.id is None: raise Exception("deck.id required to listtransactions") batch_data = [('getrawtransaction', [i["txid"], 1]) for i in provider.listtransactions(deck.id)] result = provider.batch(batch_data) if result is not None: card_transfers = [i['result'] for i in result if result] else: if deck.p2th_address is None: raise Exception("deck.p2th_address required to listtransactions") if provider.listtransactions(deck.p2th_address): card_transfers = (provider.getrawtransaction( i, 1) for i in provider.listtransactions(deck.p2th_address)) else: raise EmptyP2THDirectory({'error': 'No cards found on this deck.'}) def card_parser(args: Tuple[Provider, Deck, dict]) -> list: '''this function wraps all the card transfer parsing''' provider = args[0] deck = args[1] raw_tx = args[2] try: validate_card_transfer_p2th(deck, raw_tx) # validate P2TH first card_metainfo = parse_card_transfer_metainfo( read_tx_opreturn(raw_tx), deck.version) vouts = raw_tx["vout"] sender = find_tx_sender(provider, raw_tx) try: # try to get block seq number blockseq = tx_serialization_order(provider, raw_tx["blockhash"], raw_tx["txid"]) except KeyError: blockseq = 0 try: # try to get block number of block when this tx was written blocknum = provider.getblock(raw_tx["blockhash"])["height"] except KeyError: blocknum = 0 try: # try to get tx confirmation count tx_confirmations = raw_tx["confirmations"] except KeyError: tx_confirmations = 0 cards = postprocess_card(card_metainfo, raw_tx, sender, vouts, blockseq, blocknum, tx_confirmations, deck) cards = [CardTransfer(**card) for card in cards] except (InvalidCardTransferP2TH, CardVersionMismatch, CardNumberOfDecimalsMismatch, InvalidVoutOrder, RecieverAmountMismatch, DecodeError, TypeError, InvalidNulldataOutput) as e: return [] return cards with concurrent.futures.ThreadPoolExecutor(max_workers=2) as th: for result in th.map(card_parser, ((provider, deck, i) for i in card_transfers)): if result: yield result