Exemplo n.º 1
0
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
Exemplo n.º 2
0
    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)
Exemplo n.º 3
0
    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)
Exemplo n.º 4
0
    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)
Exemplo n.º 5
0
 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:]