def solution_for_rl( my_parent_id: bytes32, my_puzzlehash: bytes32, my_amount: uint64, out_puzzlehash: bytes32, out_amount: uint64, my_parent_parent_id: bytes32, parent_amount: uint64, interval, limit, fee, ): """ Solution is (1 my_parent_id, my_puzzlehash, my_amount, outgoing_puzzle_hash, outgoing_amount, min_block_time, parent_parent_id, parent_amount, fee) min block time = Math.ceil((new_amount * self.interval) / self.limit) """ min_block_count = math.ceil((out_amount * interval) / limit) solution = sexp( RATE_LIMITED_MODE, "0x" + my_parent_id.hex(), "0x" + my_puzzlehash.hex(), my_amount, "0x" + out_puzzlehash.hex(), out_amount, min_block_count, "0x" + my_parent_parent_id.hex(), parent_amount, fee, ) return Program.to(binutils.assemble(solution))
async def get_coin_record(self, coin_name: bytes32) -> Optional[CoinRecord]: if coin_name.hex() in self.coin_record_cache: return self.coin_record_cache[coin_name.hex()] cursor = await self.coin_record_db.execute( "SELECT * from coin_record WHERE coin_name=?", (coin_name.hex(), )) row = await cursor.fetchone() await cursor.close() if row is not None: coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), uint64.from_bytes(row[7])) return CoinRecord(coin, row[1], row[2], row[3], row[4], row[8]) return None
async def get_network_space( self, newer_block_header_hash: bytes32, older_block_header_hash: bytes32) -> Optional[uint64]: try: network_space_bytes_estimate = await self.fetch( "get_network_space", { "newer_block_header_hash": newer_block_header_hash.hex(), "older_block_header_hash": older_block_header_hash.hex(), }, ) except Exception: return None return network_space_bytes_estimate["space"]
async def get_mempool_item_by_tx_id(self, tx_id: bytes32) -> Optional[Dict]: try: response = await self.fetch("get_mempool_item_by_tx_id", {"tx_id": tx_id.hex()}) return response["mempool_item"] except Exception: return None
async def is_fully_compactified(self, header_hash: bytes32) -> Optional[bool]: cursor = await self.db.execute( "SELECT is_fully_compactified from full_blocks WHERE header_hash=?", (header_hash.hex(),) ) row = await cursor.fetchone() await cursor.close() if row is None: return None return bool(row[0])
async def get_block_record(self, header_hash: bytes32) -> Optional[BlockRecord]: cursor = await self.db.execute( "SELECT block from block_records WHERE header_hash=?", (header_hash.hex(),), ) row = await cursor.fetchone() await cursor.close() if row is not None: return BlockRecord.from_bytes(row[0]) return None
async def set_peak(self, header_hash: bytes32) -> None: cursor_1 = await self.db.execute( "UPDATE block_records SET is_peak=0 WHERE is_peak=1") await cursor_1.close() cursor_2 = await self.db.execute( "UPDATE block_records SET is_peak=1 WHERE header_hash=?", (header_hash.hex(), ), ) await cursor_2.close() await self.db.commit()
async def get_transaction(self, wallet_id: str, transaction_id: bytes32) -> TransactionRecord: res = await self.fetch( "get_transaction", { "walled_id": wallet_id, "transaction_id": transaction_id.hex() }, ) return TransactionRecord.from_json_dict(res["transaction"])
async def set_peak(self, header_hash: bytes32) -> None: # We need to be in a sqlite transaction here. # Note: we do not commit this to the database yet, as we need to also change the coin store cursor_1 = await self.db.execute("UPDATE block_records SET is_peak=0 WHERE is_peak=1") await cursor_1.close() cursor_2 = await self.db.execute( "UPDATE block_records SET is_peak=1 WHERE header_hash=?", (header_hash.hex(),), ) await cursor_2.close()
async def puzzle_hash_exists(self, puzzle_hash: bytes32) -> bool: """ Checks if passed puzzle_hash is present in the db. """ cursor = await self.db_connection.execute( "SELECT * from derivation_paths WHERE puzzle_hash=?", (puzzle_hash.hex(),) ) row = await cursor.fetchone() await cursor.close() return row is not None
async def get_header_block_record( self, header_hash: bytes32) -> Optional[HeaderBlockRecord]: """Gets a block record from the database, if present""" cursor = await self.db.execute( "SELECT block from header_blocks WHERE header_hash=?", (header_hash.hex(), )) row = await cursor.fetchone() await cursor.close() if row is not None: hbr = HeaderBlockRecord.from_bytes(row[0]) return hbr else: return None
async def get_full_block(self, header_hash: bytes32) -> Optional[FullBlock]: cached = self.block_cache.get(header_hash) if cached is not None: return cached cursor = await self.db.execute( "SELECT block from full_blocks WHERE header_hash=?", (header_hash.hex(), )) row = await cursor.fetchone() await cursor.close() if row is not None: return FullBlock.from_bytes(row[0]) return None
async def get_coin_records_by_puzzle_hash( self, puzzle_hash: bytes32) -> List[CoinRecord]: coins = set() cursor = await self.coin_record_db.execute( "SELECT * from coin_record WHERE puzzle_hash=?", (puzzle_hash.hex(), )) rows = await cursor.fetchall() await cursor.close() for row in rows: coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), uint64.from_bytes(row[7])) coins.add(CoinRecord(coin, row[1], row[2], row[3], row[4], row[8])) return list(coins)
async def is_transaction_in_mempool(api, tx_id: bytes32) -> bool: try: val = await api.get_transaction({ "wallet_id": user_wallet_id, "transaction_id": tx_id.hex() }) except ValueError: return False for _, mis, _ in val["transaction"].sent_to: if (MempoolInclusionStatus(mis) == MempoolInclusionStatus.SUCCESS or MempoolInclusionStatus(mis) == MempoolInclusionStatus.PENDING): return True return False
async def index_for_puzzle_hash(self, puzzle_hash: bytes32) -> Optional[uint32]: """ Returns the derivation path for the puzzle_hash. Returns None if not present. """ cursor = await self.db_connection.execute( "SELECT * from derivation_paths WHERE puzzle_hash=?", (puzzle_hash.hex(),) ) row = await cursor.fetchone() await cursor.close() if row is not None: return uint32(row[0]) return None
async def get_additions_and_removals( self, header_hash: bytes32) -> Tuple[List[CoinRecord], List[CoinRecord]]: try: response = await self.fetch("get_additions_and_removals", {"header_hash": header_hash.hex()}) except Exception: return [], [] removals = [] additions = [] for coin_record in response["removals"]: removals.append(CoinRecord.from_json_dict(coin_record)) for coin_record in response["additions"]: additions.append(CoinRecord.from_json_dict(coin_record)) return additions, removals
async def get_coin_record_by_coin_id( self, coin_id: bytes32) -> Optional[WalletCoinRecord]: """Returns a coin records with the given name, if it exists""" cursor = await self.db_connection.execute( "SELECT * from coin_record WHERE coin_name=?", (coin_id.hex(), )) row = await cursor.fetchone() await cursor.close() if row is None: return None coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), uint64.from_bytes(row[7])) coin_record = WalletCoinRecord(coin, row[1], row[2], row[3], row[4], WalletType(row[8]), row[9]) return coin_record
async def get_transaction_record( self, tx_id: bytes32) -> Optional[TransactionRecord]: """ Checks DB and cache for TransactionRecord with id: id and returns it. """ if tx_id in self.tx_record_cache: return self.tx_record_cache[tx_id] cursor = await self.db_connection.execute( "SELECT * from transaction_record WHERE bundle_id=?", (tx_id.hex(), )) row = await cursor.fetchone() await cursor.close() if row is not None: record = TransactionRecord.from_bytes(row[0]) return record return None
async def wallet_info_for_puzzle_hash(self, puzzle_hash: bytes32) -> Optional[Tuple[uint32, WalletType]]: """ Returns the derivation path for the puzzle_hash. Returns None if not present. """ cursor = await self.db_connection.execute( "SELECT * from derivation_paths WHERE puzzle_hash=?", (puzzle_hash.hex(),) ) row = await cursor.fetchone() await cursor.close() if row is not None: return row[4], WalletType(row[3]) return None
async def get_coin_record( self, coin_name: bytes32) -> Optional[WalletCoinRecord]: """ Returns CoinRecord with specified coin id. """ if coin_name in self.coin_record_cache: return self.coin_record_cache[coin_name] cursor = await self.db_connection.execute( "SELECT * from coin_record WHERE coin_name=?", (coin_name.hex(), )) row = await cursor.fetchone() await cursor.close() if row is not None: coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), uint64.from_bytes(row[7])) return WalletCoinRecord(coin, row[1], row[2], row[3], row[4], WalletType(row[8]), row[9]) return None
async def get_coin_records_by_puzzle_hash( self, puzzle_hash: bytes32) -> List[WalletCoinRecord]: """Returns a list of all coin records with the given puzzle hash""" coins = set() cursor = await self.db_connection.execute( "SELECT * from coin_record WHERE puzzle_hash=?", (puzzle_hash.hex(), )) rows = await cursor.fetchall() await cursor.close() for row in rows: coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), uint64.from_bytes(row[7])) coins.add( WalletCoinRecord(coin, row[1], row[2], row[3], row[4], WalletType(row[8]), row[9])) return list(coins)
async def get_coin_records_by_puzzle_hash( self, puzzle_hash: bytes32, include_spent_coins: bool = True, start_height: Optional[int] = None, end_height: Optional[int] = None, ) -> List: d = { "puzzle_hash": puzzle_hash.hex(), "include_spent_coins": include_spent_coins } if start_height is not None: d["start_height"] = start_height if end_height is not None: d["end_height"] = end_height return [ CoinRecord.from_json_dict(coin) for coin in ((await self.fetch( "get_coin_records_by_puzzle_hash", d))["coin_records"]) ]
async def get_coin_records_by_puzzle_hash( self, include_spent_coins: bool, puzzle_hash: bytes32, start_height: uint32 = uint32(0), end_height: uint32 = uint32((2**32) - 1), ) -> List[CoinRecord]: coins = set() cursor = await self.coin_record_db.execute( f"SELECT * from coin_record WHERE puzzle_hash=? AND confirmed_index>=? AND confirmed_index<? " f"{'' if include_spent_coins else 'AND spent=0'}", (puzzle_hash.hex(), start_height, end_height), ) rows = await cursor.fetchall() await cursor.close() for row in rows: coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), uint64.from_bytes(row[7])) coins.add(CoinRecord(coin, row[1], row[2], row[3], row[4], row[8])) return list(coins)
async def get_trade_record(self, trade_id: bytes32) -> Optional[TradeRecord]: """ Checks DB for TradeRecord with id: id and returns it. """ cursor = await self.db_connection.execute("SELECT * from trade_records WHERE trade_id=?", (trade_id.hex(),)) row = await cursor.fetchone() await cursor.close() if row is not None: record = TradeRecord.from_bytes(row[0]) return record return None
async def close_connection(self, node_id: bytes32) -> Dict: return await self.fetch("close_connection", {"node_id": node_id.hex()})
async def inner_puzzle_for_cc_puzhash(self, cc_hash: bytes32) -> Program: record: DerivationRecord = await self.wallet_state_manager.puzzle_store.get_derivation_record_for_puzzle_hash( cc_hash.hex()) inner_puzzle: Program = self.standard_wallet.puzzle_for_pk( bytes(record.pubkey)) return inner_puzzle
async def get_signage_point(self, sp_hash: bytes32) -> Optional[Dict]: try: return await self.fetch("get_signage_point", {"sp_hash": sp_hash.hex()}) except ValueError: return None
async def get_unspent_coins(self, puzzle_hash: bytes32) -> List: d = {"puzzle_hash": puzzle_hash.hex()} return [ CoinRecord.from_json_dict(coin) for coin in ((await self.fetch("get_unspent_coins", d))["coin_records"]) ]