async def _send_block_create(self, amount: int, destination: str, id: str = None, work: str = None) -> dict: """Create a state block (send)""" # Get account info is_open = True account_info = await RPCClient.instance().account_info( self.account.address) if account_info is None: return None # Check balance if amount > int(account_info['balance']): # Auto-receive blocks if they have it pending if config.Config.instance().auto_receive_on_send and int( account_info['balance']) + int( account_info['pending']) >= amount: await self._receive_all() account_info = await RPCClient.instance().account_info( self.account.address) if account_info is None: return None if amount > int(account_info['balance']): raise InsufficientBalance(account_info['balance']) else: raise InsufficientBalance(account_info['balance']) workbase = account_info['frontier'] # Build other fields previous = account_info['frontier'] representative = account_info['representative'] balance = str(int(account_info['balance']) - amount) # Generate work if work is None: try: work = await WorkClient.instance().work_generate(workbase) if work is None: raise WorkFailed(workbase) except Exception: raise WorkFailed(workbase) # Build final state block state_block = nanopy.state_block() state_block['account'] = self.account.address state_block['previous'] = previous state_block['representative'] = representative state_block['balance'] = balance state_block['link'] = nanopy.account_key(destination) state_block['work'] = work # Sign block pk = self.private_key() state_block['signature'] = await nano_util.NanoUtil.instance( ).sign_block(pk, block=state_block) return state_block
async def _receive_block_create(self, hash: str, work: str = None) -> dict: """Build a state block (receive)""" # Get block info block_info = await RPCClient.instance().block_info(hash) if block_info is None or block_info['contents'][ 'link_as_account'] != self.account.address: return None # Get account info is_open = True try: account_info = await RPCClient.instance().account_info( self.account.address) if account_info is None: return None except AccountNotFound: is_open = False # Different workbase for open/receive if is_open: workbase = account_info['frontier'] else: workbase = nanopy.account_key(self.account.address) # Build other fields previous = '0000000000000000000000000000000000000000000000000000000000000000' if not is_open else account_info[ 'frontier'] representative = self.get_representative( ) if not is_open else account_info['representative'] balance = block_info['amount'] if not is_open else str( int(account_info['balance']) + int(block_info['amount'])) # Generate work if work is None: try: work = await WorkClient.instance().work_generate( workbase, DifficultyModel.instance().receive_difficulty) if work is None: log.server_logger.error("WORK FAILED") raise WorkFailed(workbase) except Exception: log.server_logger.exception("work failed") raise WorkFailed(workbase) # Build final state block state_block = nanopy.state_block() state_block['account'] = self.account.address state_block['previous'] = previous state_block['representative'] = representative state_block['balance'] = balance state_block['link'] = hash state_block['work'] = work # Sign block pk = self.private_key() state_block['signature'] = await nano_util.NanoUtil.instance( ).sign_block(pk, block=state_block) return state_block
async def _change_block_create(self, representative: str, work: str = None, only_if_different: bool = False) -> dict: """Create a state block (change)""" # Get account info account_info = await RPCClient.instance().account_info( self.account.address) if account_info is None: return None elif only_if_different and account_info[ 'representative'] == representative: return None workbase = account_info['frontier'] # Build other fields previous = account_info['frontier'] representative = representative balance = account_info['balance'] # Generate work if work is None: try: work = await WorkClient.instance().work_generate( workbase, DifficultyModel.instance().send_difficulty) if work is None: raise WorkFailed(workbase) except Exception: raise WorkFailed(workbase) # Build final state block state_block = nanopy.state_block() state_block['account'] = self.account.address state_block['previous'] = previous state_block['representative'] = representative state_block['balance'] = balance state_block[ 'link'] = '0000000000000000000000000000000000000000000000000000000000000000' state_block['work'] = work # Sign block pk = self.private_key() state_block['signature'] = await nano_util.NanoUtil.instance( ).sign_block(pk, block=state_block) return state_block