def random_address_from_sil(address, sil_block_height=0, rng_block_height=0): if not valid_address(address): return {'error': 'Invalid address: %s' % address} return RandomAddress(address=address, sil_block_height=sil_block_height).get( source='SIL', rng_block_height=rng_block_height)
def configure(self, **config): super(ReceivedTrigger, self).configure(**config) if 'address' in config and valid_address(config['address']): self.address = config['address'] if 'amount' in config and valid_amount(config['amount']): self.amount = config['amount']
def get_sul(address, confirmations=1): if not valid_address(address): return {'error': 'Invalid address: ' + address} utxos_data = data.utxos(address=address, confirmations=confirmations) if 'utxos' in utxos_data: sul = utxos_to_sul(utxos_data['utxos']) return {'SUL': sul} if 'error' not in sul else {'error': sul['error']} else: return {'error': 'Unable to retrieve utxos of address %s' % address}
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 sign_message(**data): if not all(key in data for key in ['address', 'message']): return { 'success': False, 'error': 'Request data does not contain all required keys: address, message' } address = data['address'] message = data['message'] if not valid_address(address=address): return {'success': False, 'error': 'Invalid address: %s' % address} if len(message) > 255: return { 'success': False, 'error': 'Message is too long, can not be longer than 255 characters.' } account, index = find_address_in_wallet(address=address) if account is None or index is None: private_key = find_single_address_in_wallet(address=address) if private_key is None: return { 'success': False, 'error': 'Address %s not found in hot wallet' % address } else: private_key = get_private_key_from_wallet(account=account, index=index)[address] try: signature = sign_and_verify(private_key=private_key, address=address, message=message) except Exception as ex: return {'success': False, 'error': 'Unable to sign message: %s' % ex} return { 'success': True, 'signature': signature, 'address': address, 'message': message }
def get_sil(address, block_height=0): """ Get the Simplified Inputs List (SIL) :param address: The address that received the transactions :param block_height: A block height (optional) :return: A dictionary containing the SIL and the explorer that provided the data """ if not valid_address(address): return {'error': 'Invalid address: ' + address} txs_data = data.transactions(address) if 'transactions' in txs_data: return {'SIL': txs_2_sil(txs_data['transactions'], block_height)} else: return {'error': 'Unable to retrieve transactions of address %s' % address}
def get_profile(address, block_height=0): """ Get the profile of an address :param address: The address :param block_height: A block height (optional) :return: A dict containing the profile and the explorer that provided the data """ if not valid_address(address): return {'error': 'Invalid address: ' + address} txs_data = data.transactions(address) if 'transactions' in txs_data: return {'profile': txs_to_profile(txs_data['transactions'], address, block_height)} else: return {'error': 'Unable to retrieve transactions of address %s' % address}
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 __init__(self, *args, **kwargs): self.address = kwargs['address'] if 'address' in kwargs else None if self.address is not None and not valid_address(self.address): raise Exception('%s is not a valid address!' % self.address) self.message = kwargs['message'] if 'message' in kwargs else None self.signature = kwargs['signature'] if 'signature' in kwargs else None self.trigger_id = kwargs[ 'trigger_id'] if 'trigger_id' in kwargs else None self.trigger_type = kwargs[ 'trigger_type'] if 'trigger_type' in kwargs else None self.script = kwargs['script'] if 'script' in kwargs else None self.data = kwargs['data'] if 'data' in kwargs else None self.triggered = kwargs['triggered'] if 'triggered' in kwargs else None self.multi = kwargs['multi'] if 'multi' in kwargs else None self.description = kwargs[ 'description'] if 'description' in kwargs else None self.creator_name = kwargs[ 'creator_name'] if 'creator_name' in kwargs else None self.creator_email = kwargs[ 'creator_email'] if 'creator_email' in kwargs else None self.youtube = kwargs['youtube'] if 'youtube' in kwargs else None self.status = kwargs['status'] if 'status' in kwargs else None self.visibility = kwargs[ 'visibility'] if 'visibility' in kwargs else None self.created = kwargs['created'] if 'created' in kwargs else None self.actions = kwargs['actions'] if 'actions' in kwargs else None self.json = kwargs['json'] if 'json' in kwargs else None self.ipfs_hash = None self.ipfs_object = kwargs[ 'ipfs_object'] if 'ipfs_object' in kwargs else None self.text = None self.http_response = None self.new_actions = [] if self.message is not None: self.process_message()
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
# Create main parser parser = argparse.ArgumentParser( description='Bitcoin Wand command line interface', formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument('address', help='The address that is sending the message') parser.add_argument( 'message', help='The message itself OR name of the file that contains the message') parser.add_argument('url', help='The url to send the request to') # Parse arguments args = parser.parse_args() # Check if address is valid if not valid_address(args.address): print('Invalid address: %s' % args.address) sys.exit(1) data = {'address': args.address} # Find the private key of the address in the hot wallet account, index = find_address_in_wallet( address=data['address'], accounts=100 ) # Todo find better way to specify number of accounts to search if account is None or index is None: print('Can not find address in wallet!') sys.exit(1) else: private_key = get_private_key_from_wallet(account=account, index=index)[data['address']]
def test_valid_address_testnet(self, address, expected, description): helpers.configurationhelpers.get_use_testnet = mock.MagicMock(return_value=True) print(description) assert validators.valid_address(address) == expected, description
def configure(self, **config): super(SignedMessageTrigger, self).configure(**config) if 'address' in config and valid_address(config['address']): self.address = config['address'] elif 'address' in config and config['address'] == '': self.address = None