code: def tx_extract(payload, senders, inputs, outputs, block_id, vtxindex, txid):
      
    
      sender_script = None
      sender_address = None
  
      recipient_script = None
      recipient_address = None
  
      try:
          # first two outputs matter to us
          assert check_tx_output_types(outputs[:2], block_id)
  
          assert len(senders) > 0
          assert 'script_pubkey' in senders[0].keys()
          assert 'addresses' in senders[0].keys()
  
          sender_script = str(senders[0]['script_pubkey'])
          sender_address = str(senders[0]['addresses'][0])
  
          assert sender_script is not None
          assert sender_address is not None
  
          recipient_script = get_token_transfer_recipient_from_outputs(outputs)
          recipient_address = virtualchain.script_hex_to_address(recipient_script)
  
          assert recipient_script is not None
          assert recipient_address is not None
  
      except Exception, e:
          log.exception(e)
          raise Exception("Failed to extract")
  
      parsed_payload = parse(payload, block_id)
      assert parsed_payload is not None 
     
      ret = {}
      ret.update(parsed_payload)
      ret.update({
          'address': sender_address,
          'sender': sender_script,
          'recipient_address': recipient_address,
          'recipient': recipient_script,
          'op': TOKEN_TRANSFER,
          'block_id': block_id,
          'txid': txid,
          'vtxindex': vtxindex
      })
  
      return ret
docs: Extract and return a dict of fields from the underlying blockchain transaction data
      that are useful to this operation.
  
      structure:
      inputs                                | outputs
      ------------------------------------------------------------------------------
      sender scriptsig + scriptPubkey       | OP_RETURN with token transfer payload
      ------------------------------------------------------------------------------
                                            | recipient script (DUST_MINIMUM)
                                            ----------------------------------------
                                            | sender's change address
  
      The recipient script identifies the recipient address.  This is its own output
      to ensure that the underlying blockchain can and will enforce signatures from
      the recipient on future spend transactions.  Also, it makes it straightforward
      to track blockstack transactions in existing block explorers.
  
      Any other inputs and outputs are allowed.