def random_address_from_lsl(address, xpub, sil_block_height=0, rng_block_height=0): if not valid_address(address): return {'error': 'Invalid address: %s' % address} if not valid_xpub(xpub): return {'error': 'Invalid xpub: %s' % xpub} return RandomAddress(address=address, xpub=xpub, sil_block_height=sil_block_height).get( source='LSL', rng_block_height=rng_block_height)
def get_lal(address, xpub, block_height=0): if not valid_address(address): return {'error': 'Invalid address: %s' % address} if not valid_xpub(xpub): return {'error': 'Invalid xpub: %s' % xpub} sil_data = get_sil(address, block_height) if 'SIL' in sil_data: sil = sil_data['SIL'] linked_addresses = get_addresses_from_xpub(xpub, len(sil)) lal = [] for i in range(0, len(sil)): lal.append([sil[i][0], linked_addresses[i]]) return {'LAL': lal} else: return {'error': 'Received invalid SIL data: %s' % sil_data}
def configure(self, **config): """ Configure the action with given config settings :param config: A dict containing the configuration settings - config['fee_address'] : An address to send the spellbook fee to - config['fee_percentage'] : The percentage to calculate the spellbook fee - config['wallet_type'] : The type of wallet (Single or BIP44) - config['sending_address'] : The address that will be sending the transaction - config['bip44_account'] : An account number of a BIP44 wallet - config['bip44_index'] : An index number of a BIP44 account - config['receiving_address'] : The address to receive the transaction - config['receiving_xpub'] : The xpub key to derive the receiving addresses from - config['amount'] : The amount to send - config['minimum_amount'] : The minimum amount that needs to be available - config['registration_address'] : An address used for the registration of a SIL, LBL, LRL or LSL - config['registration_block_height'] : An block height used for the registration of a SIL - config['registration_xpub'] : An xpub key used for the registration of a LBL, LRL or LSL - config['distribution'] : A dict containing a distribution (each address should be a key in the dict with the value being the share) """ super(SendTransactionAction, self).configure(**config) if 'fee_address' in config and valid_address(config['fee_address']): self.fee_address = config['fee_address'] if 'fee_percentage' in config and valid_percentage( config['fee_percentage']): self.fee_percentage = config['fee_percentage'] if 'wallet_type' in config and config['wallet_type'] in [ 'Single', 'BIP44' ]: self.wallet_type = config['wallet_type'] if 'sending_address' in config and valid_address( config['sending_address']): self.sending_address = config['sending_address'] if 'bip44_account' in config: self.bip44_account = config['bip44_account'] if 'bip44_index' in config: self.bip44_index = config['bip44_index'] if 'receiving_address' in config and valid_address( config['receiving_address']): self.receiving_address = config['receiving_address'] if 'receiving_xpub' in config and valid_xpub(config['receiving_xpub']): self.receiving_xpub = config['receiving_xpub'] if 'amount' in config and valid_amount(config['amount']): self.amount = config['amount'] if 'minimum_amount' in config and valid_amount( config['minimum_amount']): self.minimum_amount = config['minimum_amount'] if 'op_return_data' in config and valid_op_return( config['op_return_data']): self.op_return_data = config['op_return_data'] if 'change_address' in config and valid_address( config['change_address']): self.receiving_address = config['change_address'] if 'transaction_type' in config and valid_transaction_type( config['transaction_type']): self.transaction_type = config['transaction_type'] if 'minimum_output_value' in config and valid_amount( config['minimum_output_value']): self.minimum_output_value = config['minimum_output_value'] if 'registration_address' in config and valid_address( config['registration_address']): self.registration_address = config['registration_address'] if 'registration_block_height' in config and valid_block_height( config['registration_block_height']): self.registration_block_height = config[ 'registration_block_height'] if 'registration_xpub' in config and valid_xpub( config['registration_xpub']): self.registration_xpub = config['registration_xpub'] if 'distribution' in config and valid_distribution( config['distribution']): self.distribution = config['distribution'] if 'tx_fee_type' in config and config['tx_fee_type'] in [ 'High', 'Medium', 'Low', 'Fixed' ]: self.tx_fee_type = config['tx_fee_type'] if 'tx_fee' in config and valid_amount( config['tx_fee']) and self.tx_fee_type == 'Fixed': self.tx_fee = config['tx_fee'] if 'utxo_confirmations' in config and valid_amount( config['utxo_confirmations']): self.utxo_confirmations = config['utxo_confirmations'] if 'private_key' in config and valid_private_key( private_key=config['private_key']): self.private_key = config['private_key'] # fill in the address in case of a BIP44 hot wallet if self.wallet_type == 'BIP44': self.sending_address = get_address_from_wallet( self.bip44_account, self.bip44_index)
def get_distribution(self, transaction_type, sending_amount): if not valid_amount(sending_amount) or sending_amount == 0: LOG.error( 'Unable to get distribution: invalid sending_amount: %s' % sending_amount) raise Exception( 'Unable to get distribution: invalid sending_amount: %s' % sending_amount) if transaction_type == 'Send2Single': if not valid_address(self.receiving_address): LOG.error( 'Unable to get distribution: invalid receiving_address: %s' % self.receiving_address) raise Exception( 'Unable to get distribution: invalid receiving_address: %s' % self.receiving_address) distribution = {self.receiving_address: sending_amount} elif transaction_type == 'Send2Many': if not valid_distribution(self.distribution): LOG.error( 'Unable to get distribution: invalid distribution: %s' % self.distribution) raise Exception( 'Unable to get distribution: invalid distribution: %s' % self.distribution) distribution = self.distribution elif transaction_type == 'Send2SIL': if not valid_address(self.registration_address): LOG.error( 'Unable to get distribution: invalid registration_address: %s' % self.registration_address) raise Exception( 'Unable to get distribution: invalid registration_address: %s' % self.registration_address) if not valid_block_height(self.registration_block_height): LOG.error( 'Unable to get distribution: invalid registration_block_height: %s' % self.registration_block_height) raise Exception( 'Unable to get distribution: invalid registration_block_height: %s' % self.registration_block_height) data = get_sil(address=self.registration_address, block_height=self.registration_block_height) if 'SIL' not in data: LOG.error('Unable to get distribution: invalid SIL data: %s' % data) raise Exception('Unable to get distribution: invalid SIL: %s' % data) distribution = { recipient[0]: recipient[1] for recipient in data['SIL'] } elif transaction_type == 'Send2LBL': if not valid_address(self.registration_address): LOG.error( 'Unable to get distribution: invalid registration_address: %s' % self.registration_address) raise Exception( 'Unable to get distribution: invalid registration_address: %s' % self.registration_address) if not valid_xpub(self.registration_xpub): LOG.error( 'Unable to get distribution: invalid registration_xpub: %s' % self.registration_xpub) raise Exception( 'Unable to get distribution: invalid registration_xpub: %s' % self.registration_xpub) if not valid_block_height(self.registration_block_height): LOG.error( 'Unable to get distribution: invalid registration_block_height: %s' % self.registration_block_height) raise Exception( 'Unable to get distribution: invalid registration_block_height: %s' % self.registration_block_height) data = get_lbl(address=self.registration_address, xpub=self.registration_xpub, block_height=self.registration_block_height) if 'LBL' not in data: LOG.error('Unable to get distribution: invalid LBL data: %s' % data) raise Exception('Unable to get distribution: invalid LBL: %s' % data) distribution = { recipient[0]: recipient[1] for recipient in data['LBL'] } elif transaction_type == 'Send2LRL': if not valid_address(self.registration_address): LOG.error( 'Unable to get distribution: invalid registration_address: %s' % self.registration_address) raise Exception( 'Unable to get distribution: invalid registration_address: %s' % self.registration_address) if not valid_xpub(self.registration_xpub): LOG.error( 'Unable to get distribution: invalid registration_xpub: %s' % self.registration_xpub) raise Exception( 'Unable to get distribution: invalid registration_xpub: %s' % self.registration_xpub) if not valid_block_height(self.registration_block_height): LOG.error( 'Unable to get distribution: invalid registration_block_height: %s' % self.registration_block_height) raise Exception( 'Unable to get distribution: invalid registration_block_height: %s' % self.registration_block_height) data = get_lrl(address=self.registration_address, xpub=self.registration_xpub, block_height=self.registration_block_height) if 'LRL' not in data: LOG.error('Unable to get distribution: invalid LRL data: %s' % data) raise Exception('Unable to get distribution: invalid LRL: %s' % data) distribution = { recipient[0]: recipient[1] for recipient in data['LRL'] } elif transaction_type == 'Send2LSL': if not valid_address(self.registration_address): LOG.error( 'Unable to get distribution: invalid registration_address: %s' % self.registration_address) raise Exception( 'Unable to get distribution: invalid registration_address: %s' % self.registration_address) if not valid_xpub(self.registration_xpub): LOG.error( 'Unable to get distribution: invalid registration_xpub: %s' % self.registration_xpub) raise Exception( 'Unable to get distribution: invalid registration_xpub: %s' % self.registration_xpub) if not valid_block_height(self.registration_block_height): LOG.error( 'Unable to get distribution: invalid registration_block_height: %s' % self.registration_block_height) raise Exception( 'Unable to get distribution: invalid registration_block_height: %s' % self.registration_block_height) data = get_lsl(address=self.registration_address, xpub=self.registration_xpub, block_height=self.registration_block_height) if 'LSL' not in data: LOG.error('Unable to get distribution: invalid LSL data: %s' % data) raise Exception('Unable to get distribution: invalid LSL: %s' % data) distribution = { recipient[0]: recipient[1] for recipient in data['LSL'] } elif transaction_type == 'Send2LAL': if not valid_address(self.sending_address): LOG.error( 'Unable to get distribution: invalid sending_address: %s' % self.sending_address) raise Exception( 'Unable to get distribution: invalid sending_address: %s' % self.sending_address) if not valid_xpub(self.registration_xpub): LOG.error( 'Unable to get distribution: invalid registration_xpub: %s' % self.registration_xpub) raise Exception( 'Unable to get distribution: invalid registration_xpub: %s' % self.registration_xpub) if not valid_block_height(self.registration_block_height): LOG.error( 'Unable to get distribution: invalid registration_block_height: %s' % self.registration_block_height) raise Exception( 'Unable to get distribution: invalid registration_block_height: %s' % self.registration_block_height) # The registration address of a LAL must always be the sending address data = get_lal(address=self.sending_address, xpub=self.registration_xpub, block_height=self.registration_block_height) if 'LAL' not in data: LOG.error('Unable to get distribution: invalid LAL data: %s' % data) raise Exception('Unable to get distribution: invalid LAL: %s' % data) LOG.info('LAL: %s' % data['LAL']) distribution = {} for utxo in self.unspent_outputs: prime_input_address_data = prime_input_address( utxo.output_hash) prime_input_address_of_utxo = prime_input_address_data[ 'prime_input_address'] if 'prime_input_address' in prime_input_address_data else None LOG.info('Prime input address of %s is %s' % (utxo.output_hash, prime_input_address_of_utxo)) linked_address = [ linked_address for input_address, linked_address in data['LAL'] if input_address == prime_input_address_of_utxo ] # There should be exactly 1 linked address if len(linked_address) == 1: distribution[linked_address[0]] = utxo.value else: LOG.error( 'Something went wrong with the LAL: found %s linked addresses, should be exactly 1!' % len(linked_address)) raise Exception( 'Something went wrong with the LAL: found %s linked addresses, should be exactly 1!' % len(linked_address)) else: raise NotImplementedError('Unknown transaction type %s' % transaction_type) LOG.info('distribution: %s' % distribution) return distribution
def test_valid_xpub_testnet(self, xpub, expected, description): helpers.configurationhelpers.get_use_testnet = mock.MagicMock(return_value=True) print(description) assert validators.valid_xpub(xpub) == expected, description