def send_message(sender_key: GcPrivateKey, spend_from_txid, receiver_addr, op_ret_data): unspent = get_unspent_by_txid(sender_key, spend_from_txid) print(unspent) def chunk_data(data, size): return (data[i:i + size] for i in range(0, len(data), size)) messages = [] if op_ret_data: message_chunks = chunk_data(op_ret_data, MESSAGE_LIMIT) for message in message_chunks: messages.append((message, None)) fee_amount = get_fee_amount(op_ret_data, len(messages)) amount_back_to_sender = unspent.amount - fee_amount - MESSAGE_AMOUNT outputs = [ (sender_key.address, amount_back_to_sender), (receiver_addr, MESSAGE_AMOUNT), ] outputs.extend(messages) tx_hex = transaction.create_p2pkh_transaction(sender_key.bitcash_key, [unspent], outputs) tx_id = transaction.calc_txid(tx_hex) if which_net.is_testnet(): network.NetworkAPI.broadcast_tx_testnet(tx_hex) else: raise Exception("TX broadcasting only tested with testnet") return tx_id
async def build_tx( self, priv: str, addrs: List[Tuple[str, D]], split_fee=True ): # Todo: Need to break this up. key = self.KEY_CLASS(priv) addr_from = self.to_legacy_address(key.address) unspent_obj_list = await self._get_obj_unspent_list(addr_from) payables = [ (self.to_legacy_address(addr), amount * COIN) for addr, amount in addrs ] total_out = sum(amount for addr, amount in payables) total_unspent = sum(D(unspent.amount) for unspent in unspent_obj_list) remaining = total_unspent - total_out if total_out > total_unspent: raise NotEnoughAmountError() fee = self.calc_fee(len(unspent_obj_list), len(addrs)) fee_per_tx_out, extra_count = divmod(fee, len(addrs)) calc_addrs = [] for addr, amount in payables: amount -= fee_per_tx_out if extra_count > 0: amount -= 1 if amount < 1: raise NotEnoughAmountError() calc_addrs.append((addr, int(amount))) remaining = int(remaining) if remaining > 0: calc_addrs.append((addr_from, remaining)) return create_p2pkh_transaction(key, unspent_obj_list, calc_addrs)
def create_transaction( self, outputs, fee=None, leftover=None, combine=True, message=None, unspents=None, custom_pushdata=False, ): # pragma: no cover """Creates a signed P2PKH transaction. :param outputs: A sequence of outputs you wish to send in the form ``(destination, amount, currency)``. The amount can be either an int, float, or string as long as it is a valid input to ``decimal.Decimal``. The currency must be :ref:`supported <supported currencies>`. :type outputs: ``list`` of ``tuple`` :param fee: The number of satoshi per byte to pay to miners. By default Bitcash will poll `<https://bitcoincashfees.earn.com>`_ and use a fee that will allow your transaction to be confirmed as soon as possible. :type fee: ``int`` :param leftover: The destination that will receive any change from the transaction. By default Bitcash will send any change to the same address you sent from. :type leftover: ``str`` :param combine: Whether or not Bitcash should use all available UTXOs to make future transactions smaller and therefore reduce fees. By default Bitcash will consolidate UTXOs. :type combine: ``bool`` :param message: A message to include in the transaction. This will be stored in the blockchain forever. Due to size limits, each message will be stored in chunks of 220 bytes. :type message: ``str`` :param unspents: The UTXOs to use as the inputs. By default Bitcash will communicate with the blockchain itself. :type unspents: ``list`` of :class:`~bitcash.network.meta.Unspent` :returns: The signed transaction as hex. :rtype: ``str`` """ unspents, outputs = sanitize_tx_data( unspents or self.unspents, outputs, fee or DEFAULT_FEE, leftover or self.address, combine=combine, message=message, compressed=self.is_compressed(), custom_pushdata=custom_pushdata, ) return create_p2pkh_transaction(self, unspents, outputs, custom_pushdata=custom_pushdata)
def sign_transaction(self, tx_data): """Creates a signed P2PKH transaction using previously prepared transaction data. :param tx_data: Output of :func:`~bitcash.PrivateKeyTestnet.prepare_transaction`. :type tx_data: ``str`` :returns: The signed transaction as hex. :rtype: ``str`` """ data = json.loads(tx_data) unspents = [Unspent.from_dict(unspent) for unspent in data['unspents']] outputs = data['outputs'] return create_p2pkh_transaction(self, unspents, outputs)
def test_matching(self): private_key = PrivateKey(WALLET_FORMAT_MAIN) tx = create_p2pkh_transaction(private_key, UNSPENTS, OUTPUTS) print(tx) assert tx[-288:] == FINAL_TX_1[-288:]