Example #1
0
 def _from_json_data_object(self, data):
     self._botid = int(data.get('id', 0) or 0)
     addresses = data.get('addresses', {}) or {}
     self._addresses_to_add = [
         NetworkAddress.from_json(address)
         for address in addresses.get('add', []) or []
     ]
     self._addresses_to_remove = [
         NetworkAddress.from_json(address)
         for address in addresses.get('remove', []) or []
     ]
     names = data.get('names', {}) or {}
     self._names_to_add = [
         BotName.from_json(name) for name in names.get('add', []) or []
     ]
     self._names_to_remove = [
         BotName.from_json(name) for name in names.get('remove', []) or []
     ]
     self._number_of_months = int(data.get('nrofmonths', 0) or 0)
     if 'txfee' in data:
         self._transaction_fee = Currency.from_json(data['txfee'])
     else:
         self._transaction_fee = None
     self._coin_inputs = [
         CoinInput.from_json(ci) for ci in data.get('coininputs', []) or []
     ]
     if 'refundcoinoutput' in data:
         self._refund_coin_output = CoinOutput.from_json(
             data['refundcoinoutput'])
     else:
         self._refund_coin_output = None
     self._signature = ED25519Signature.from_json(
         data.get('signature', None) or None)
    def fund(self, amount, source=None):
        """
        Fund the specified amount with the available outputs of this wallet's balance.
        """
        # collect addresses and multisig addresses
        addresses = set()
        refund = None
        if source == None:
            for co in self.outputs_available:
                addresses.add(co.condition.unlockhash.__str__())
            for co in self.outputs_unconfirmed_available:
                addresses.add(co.condition.unlockhash.__str__())
        else:
            # if only one address is given, transform it into an acceptable list
            if not isinstance(source, list) and not jsobj.is_js_arr(source):
                if isinstance(source, str):
                    source = UnlockHash.from_json(source)
                elif not isinstance(source, UnlockHash):
                    raise TypeError(
                        "cannot add source address from type {}".format(
                            type(source)))
                source = [source]
            # add one or multiple personal/multisig addresses
            for value in source:
                if isinstance(value, str):
                    value = UnlockHash.from_json(value)
                elif not isinstance(value, UnlockHash):
                    raise TypeError(
                        "cannot add source address from type {}".format(
                            type(value)))
                elif value.uhtype.__eq__(UnlockHashType.PUBLIC_KEY):
                    addresses.add(value)
                else:
                    raise TypeError(
                        "cannot add source address with unsupported UnlockHashType {}"
                        .format(value.uhtype))
            if len(source) == 1:
                if source[0].uhtype.__eq__(UnlockHashType.PUBLIC_KEY):
                    refund = ConditionTypes.unlockhash_new(
                        unlockhash=source[0])

        # ensure at least one address is defined
        if len(addresses) == 0:
            raise tferrors.InsufficientFunds(
                "insufficient funds in this wallet")

        # if personal addresses are given, try to use these first
        # as these are the easiest kind to deal with
        if len(addresses) == 0:
            outputs, collected = ([], Currency())  # start with nothing
        else:
            outputs, collected = self._fund_individual(amount, addresses)

        if collected.greater_than_or_equal_to(amount):
            # if we already have sufficient, we stop now
            return ([CoinInput.from_coin_output(co)
                     for co in outputs], collected.minus(amount), refund)
        raise tferrors.InsufficientFunds(
            "not enough funds available in the wallet to fund the requested amount"
        )
Example #3
0
 def _from_json_data_object(self, data):
     self._addresses = [
         NetworkAddress.from_json(address)
         for address in data.get('addresses', []) or []
     ]
     self._names = [
         BotName.from_json(name) for name in data.get('names', []) or []
     ]
     self._number_of_months = int(data.get('nrofmonths', 0) or 0)
     if 'txfee' in data:
         self._transaction_fee = Currency.from_json(data['txfee'])
     else:
         self._transaction_fee = None
     self._coin_inputs = [
         CoinInput.from_json(ci) for ci in data.get('coininputs', []) or []
     ]
     if 'refundcoinoutput' in data:
         self._refund_coin_output = CoinOutput.from_json(
             data['refundcoinoutput'])
     else:
         self._refund_coin_output = None
     if 'identification' not in data or data['identification'] in (None,
                                                                   {}):
         self._public_key = None
         self._signature = None
     else:
         identification = data['identification']
         self._public_key = PublicKey.from_json(identification['publickey'])
         self._signature = ED25519Signature.from_json(
             identification['signature'], as_array=True)
    def fund(self, amount, source=None):
        """
        Fund the specified amount with the available outputs of this wallet's balance.
        """
        refund = self.condition
        address = refund.unlockhash.__str__()
        if source == None:
            source = address
        else:
            if not isinstance(source, str):
                raise TypeError("invalid source: {} ({})".format(
                    source, type(source)))
            if source != address:
                raise ValueError(
                    "source is of an address different than this multisig' balance' address: {} != {}"
                    .format(source, address))

        outputs, collected = self._fund_individual(amount, [source])
        if collected.greater_than_or_equal_to(amount):
            # if we already have sufficient, we stop now
            return ([CoinInput.from_coin_output(co)
                     for co in outputs], collected.minus(amount), refund)
        raise tferrors.InsufficientFunds(
            "not enough funds available in the wallet to fund the requested amount"
        )
Example #5
0
 def _from_json_data_object(self, data):
     # decode public key
     if 'pubkey' in data:
         self._public_key = PublicKey.from_json(data['pubkey'])
     else:
         self._public_key = None
     # decode signature
     if 'signature' in data:
         self._signature = ED25519Signature.from_json(data['signature'])
     else:
         self._signature = None
     # decode registration fee
     if 'regfee' in data:
         self.registration_fee = Currency.from_json(data['regfee'])
     else:
         self.registration_fee = None
     # decode transaction fee
     if 'txfee' in data:
         self._transaction_fee = Currency.from_json(data['txfee'])
     else:
         self._transaction_fee = None
     # decode coin inputs
     self._coin_inputs = [
         CoinInput.from_json(ci) for ci in data.get('coininputs', []) or []
     ]
     # decode refund coin output (if it exists)
     if 'refundcoinoutput' in data:
         self._refund_coin_output = CoinOutput.from_json(
             data['refundcoinoutput'])
     else:
         self._refund_coin_output = None
Example #6
0
 def _from_json_data_object(self, data):
     # decode address
     if 'address' in data:
         self._address = ERC20Address.from_json(data['address'])
     else:
         self._address = None
     # decode value
     if 'value' in data:
         self._value = Currency.from_json(data['value'])
     else:
         self._value = None
     # decode transaction fee
     if 'txfee' in data:
         self._transaction_fee = Currency.from_json(data['txfee'])
     else:
         self._transaction_fee = None
     # decode coin inputs
     self._coin_inputs = [
         CoinInput.from_json(ci) for ci in data.get('coininputs', []) or []
     ]
     # decode refund coin output (if it exists)
     if 'refundcoinoutput' in data:
         self._refund_coin_output = CoinOutput.from_json(
             data['refundcoinoutput'])
     else:
         self._refund_coin_output = None
    def drain(self,
              recipient,
              miner_fee,
              unconfirmed=False,
              data=None,
              lock=None):
        """
        add all available outputs into as many transactions as required,
        by default only confirmed outputs are used, if unconfirmed=True
        it will use unconfirmed available outputs as well.

        Result can be an empty list if no outputs were available.

        @param recipient: required recipient towards who the drained coins will be sent
        @param the miner fee to be added to all sent transactions
        @param unconfirmed: optionally drain unconfirmed (available) outputs as well
        @param data: optional data that can be attached ot the created transactions (str or bytes), with a max length of 83
        @param lock: optional lock that can be attached to the sent coin outputs
        """
        # define recipient
        recipient = ConditionTypes.from_recipient(recipient, lock=lock)

        # validate miner fee
        if not isinstance(miner_fee, Currency):
            raise TypeError("miner fee has to be a currency")
        if miner_fee.__eq__(0):
            raise ValueError("a non-zero miner fee has to be defined")

        # collect all transactions in one list
        txns = []

        # collect all confirmed (available) outputs
        outputs = self.outputs_available
        if unconfirmed:
            # if also the unconfirmed_avaialble) outputs are desired, let's add them as well
            outputs += self.outputs_unconfirmed_available
        # drain all outputs
        while len(outputs) > 0:
            txn = transactions.new()
            txn.data = data
            txn.miner_fee_add(miner_fee)
            # select maximum _MAX_RIVINE_TRANSACTION_INPUTS outputs
            n = min(len(outputs), _MAX_RIVINE_TRANSACTION_INPUTS)
            used_outputs = outputs[:n]
            outputs = outputs[
                n:]  # and update our output list, so we do not double spend
            # compute amount, minus minimum fee and add our only output
            amount = sum([co.value for co in used_outputs]) - miner_fee
            txn.coin_output_add(condition=recipient, value=amount)
            # add the coin inputs
            txn.coin_inputs = [
                CoinInput.from_coin_output(co) for co in used_outputs
            ]
            # append the transaction
            txns.append(txn)

        # return all created transactions, if any
        return txns
Example #8
0
 def _from_json_data_object(self, data):
     self._coin_inputs = [CoinInput.from_json(
         ci) for ci in data.get('coininputs', []) or []]
     self._coin_outputs = [CoinOutput.from_json(
         co) for co in data.get('coinoutputs', []) or []]
     self._blockstake_inputs = [BlockstakeInput.from_json(
         bsi) for bsi in data.get('blockstakeinputs', []) or []]
     self._blockstake_outputs = [BlockstakeOutput.from_json(
         bso) for bso in data.get('blockstakeoutputs', []) or []]
     self._miner_fees = [Currency.from_json(
         fee) for fee in data.get('minerfees', []) or []]
     self._data = BinaryData.from_json(
         data.get('arbitrarydata', None) or '', strencoding='base64')
Example #9
0
 def _from_json_data_object(self, data):
     # decode sender info
     if 'sender' in data:
         bot_data = data['sender']
         self._sender_botid = int(bot_data.get('id', 0) or 0)
         self._sender_signature = ED25519Signature.from_json(
             bot_data.get('signature', None) or None)
     else:
         self._sender_botid = None
         self._sender_signature = None
     # decode receiver info
     if 'receiver' in data:
         bot_data = data['receiver']
         self._receiver_botid = int(bot_data.get('id', 0) or 0)
         self._receiver_signature = ED25519Signature.from_json(
             bot_data.get('signature', None) or None)
     else:
         self._receiver_botid = None
         self._receiver_signature = None
     # decode names
     self._names = [
         BotName.from_json(name) for name in data.get('names', []) or []
     ]
     # decode transaction fee
     if 'txfee' in data:
         self._transaction_fee = Currency.from_json(data['txfee'])
     else:
         self._transaction_fee = None
     # decode coin inputs
     self._coin_inputs = [
         CoinInput.from_json(ci) for ci in data.get('coininputs', []) or []
     ]
     # decode refund coin output
     if 'refundcoinoutput' in data:
         self._refund_coin_output = CoinOutput.from_json(
             data['refundcoinoutput'])
     else:
         self._refund_coin_output = None
Example #10
0
 def coin_input_add(self, parentid, fulfillment, parent_output=None):
     ci = CoinInput(parentid=parentid, fulfillment=fulfillment)
     ci.parent_output = parent_output
     self._coin_inputs.append(ci)
Example #11
0
    def legacy_from_json(cls, obj):
        """
        Class method to decode v1 Tx from a legacy v0 Tx.
        """

        tv = obj.get('version', -1)
        if TransactionVersion.LEGACY != tv:
            raise ValueError("legacy v0 transaction is expected to be of version {}, not version {}".format(
                TransactionVersion.LEGACY, tv))
        txn = cls()

        if 'data' not in obj:
            raise ValueError("no data object found in Legacy Transaction (v{})".format(
                TransactionVersion.LEGACY))
        txn_data = obj['data']
        if 'coininputs' in txn_data:
            for legacy_ci_info in (txn_data['coininputs'] or []):
                unlocker = legacy_ci_info.get('unlocker', {})
                ci_info = {
                    'parentid': legacy_ci_info.get('parentid', ''),
                    'fulfillment': {
                        'type': 1,
                        'data': {
                            'publickey': unlocker.get('condition', {}).get('publickey'),
                            'signature': unlocker.get('fulfillment', {}).get('signature'),
                        }
                    }
                }
                ci = CoinInput.from_json(ci_info)
                txn._coin_inputs.append(ci)
        if 'coinoutputs' in txn_data:
            for legacy_co_info in (txn_data['coinoutputs'] or []):
                co_info = {
                    'value': legacy_co_info.get('value', '0'),
                    'condition': {
                        'type': 1,
                        'data': {
                            'unlockhash': legacy_co_info.get('unlockhash', ''),
                        }
                    }
                }
                co = CoinOutput.from_json(co_info)
                txn._coin_outputs.append(co)
        if 'blockstakeinputs' in txn_data:
            for legacy_bsi_info in (txn_data['blockstakeinputs'] or []):
                unlocker = legacy_bsi_info.get('unlocker', {})
                bsi_info = {
                    'parentid': legacy_bsi_info.get('parentid', ''),
                    'fulfillment': {
                        'type': 1,
                        'data': {
                            'publickey': unlocker.get('condition', {}).get('publickey'),
                            'signature': unlocker.get('fulfillment', {}).get('signature'),
                        }
                    }
                }
                bsi = BlockstakeInput.from_json(bsi_info)
                txn._blockstake_inputs.append(bsi)
        if 'blockstakeoutputs' in txn_data:
            for legacy_bso_info in (txn_data['blockstakeoutputs'] or []):
                bso_info = {
                    'value': legacy_bso_info.get('value', '0'),
                    'condition': {
                        'type': 1,
                        'data': {
                            'unlockhash': legacy_bso_info.get('unlockhash', ''),
                        }
                    }
                }
                bso = BlockstakeOutput.from_json(bso_info)
                txn._blockstake_outputs.append(bso)

        if 'minerfees' in txn_data:
            for miner_fee in (txn_data['minerfees'] or []):
                txn._miner_fees.append(Currency.from_json(miner_fee))
        if 'arbitrarydata' in txn_data:
            txn._data = BinaryData.from_json(txn_data.get(
                'arbitrarydata', None) or '', strencoding='base64')

        txn._legacy = True
        return txn