async def get_unspent_coins_for_wallet( self, wallet_id: int) -> Set[WalletCoinRecord]: """ Returns set of CoinRecords that have not been spent yet for a wallet. """ async with self.wallet_cache_lock: if wallet_id in self.coin_wallet_record_cache: wallet_coins: Dict[ bytes32, WalletCoinRecord] = self.coin_wallet_record_cache[ wallet_id] return set(wallet_coins.values()) coin_set = set() cursor = await self.db_connection.execute( "SELECT * from coin_record WHERE spent=0 and wallet_id=?", (wallet_id, ), ) rows = await cursor.fetchall() await cursor.close() cache_dict = {} for row in rows: 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]) coin_set.add(coin_record) cache_dict[coin.name()] = coin_record self.coin_wallet_record_cache[wallet_id] = cache_dict return coin_set
def farm_coin(self, puzzle_hash: bytes32, birthday: CoinTimestamp, amount: int = 1024) -> Coin: parent = birthday.height.to_bytes(32, "big") coin = Coin(parent, puzzle_hash, uint64(amount)) self._add_coin_entry(coin, birthday) return coin
def make_fake_coin(index: int, puzzle_hash_db: dict) -> Coin: """ Make a fake coin with parent id equal to the index (ie. a genesis block coin) """ parent = index.to_bytes(32, "big") puzzle_hash = puzzle_hash_for_index(index, puzzle_hash_db) amount = 100000 return Coin(parent, puzzle_hash, uint64(amount))
def coin_solution_for_lock_coin( prev_coin: Coin, subtotal: int, coin: Coin, ) -> CoinSolution: puzzle_reveal = LOCK_INNER_PUZZLE.curry(prev_coin.as_list(), subtotal) coin = Coin(coin.name(), puzzle_reveal.get_tree_hash(), uint64(0)) coin_solution = CoinSolution(coin, puzzle_reveal, Program.to(0)) return coin_solution
def generate_farmed_coin( block_index: int, puzzle_hash: bytes32, amount: int, ) -> Coin: """ Generate a (fake) coin which can be used as a starting point for a chain of coin tests. """ return Coin(int_as_bytes32(block_index), puzzle_hash, uint64(amount))
async def check_all_there(): spendable = await cc_wallet.get_cc_spendable_coins() spendable_name_set = set() for record in spendable: spendable_name_set.add(record.coin.name()) puzzle_hash = cc_puzzle_hash_for_inner_puzzle_hash(CC_MOD, cc_wallet.cc_info.my_genesis_checker, cc_2_hash) for i in range(1, 50): coin = Coin(spent_coint.name(), puzzle_hash, i) if coin.name() not in spendable_name_set: return False return True
async def get_unspent_coin_records(self) -> List[CoinRecord]: coins = set() cursor = await self.coin_record_db.execute( "SELECT * from coin_record WHERE spent=0") 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_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_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_coins_removed_at_height(self, height: uint32) -> List[CoinRecord]: cursor = await self.coin_record_db.execute( "SELECT * from coin_record WHERE spent_index=? and spent=1", (height, )) rows = await cursor.fetchall() await cursor.close() coins = [] for row in rows: coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), uint64.from_bytes(row[7])) coins.append( CoinRecord(coin, row[1], row[2], row[3], row[4], row[8])) return coins
async def get_all_coins(self) -> Set[WalletCoinRecord]: """ Returns set of all CoinRecords.""" coins = set() cursor = await self.db_connection.execute("SELECT * from coin_record") 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 coins
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)
def created_outputs_for_conditions_dict( conditions_dict: Dict[ConditionOpcode, List[ConditionVarPair]], input_coin_name: bytes32, ) -> List[Coin]: output_coins = [] for cvp in conditions_dict.get(ConditionOpcode.CREATE_COIN, []): # TODO: check condition very carefully # (ensure there are the correct number and type of parameters) # maybe write a type-checking framework for conditions # and don't just fail with asserts puzzle_hash, amount_bin = cvp.vars[0], cvp.vars[1] amount = int_from_bytes(amount_bin) coin = Coin(input_coin_name, puzzle_hash, amount) output_coins.append(coin) return output_coins
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, 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)
def create_pool_coin(block_index: uint32, puzzle_hash: bytes32, reward: uint64): block_index_as_hash = bytes32(block_index.to_bytes(32, "big")) return Coin(block_index_as_hash, puzzle_hash, reward)
def create_farmer_coin(block_index: uint32, puzzle_hash: bytes32, reward: uint64): block_index_as_hash = std_hash(std_hash(block_index.to_bytes(4, "big"))) return Coin(block_index_as_hash, puzzle_hash, reward)
async def generate_zero_val_coin(self, send=True, exclude: List[Coin] = None ) -> SpendBundle: if self.cc_info.my_genesis_checker is None: raise ValueError("My genesis checker is None") if exclude is None: exclude = [] coins = await self.standard_wallet.select_coins(0, exclude) assert coins != set() origin = coins.copy().pop() origin_id = origin.name() cc_inner = await self.get_new_inner_hash() cc_puzzle_hash: Program = cc_puzzle_hash_for_inner_puzzle_hash( CC_MOD, self.cc_info.my_genesis_checker, cc_inner) tx: TransactionRecord = await self.standard_wallet.generate_signed_transaction( uint64(0), cc_puzzle_hash, uint64(0), origin_id, coins) assert tx.spend_bundle is not None full_spend: SpendBundle = tx.spend_bundle self.log.info( f"Generate zero val coin: cc_puzzle_hash is {cc_puzzle_hash}") # generate eve coin so we can add future lineage_proofs even if we don't eve spend eve_coin = Coin(origin_id, cc_puzzle_hash, uint64(0)) await self.add_lineage( eve_coin.name(), Program.to(( 1, [eve_coin.parent_coin_info, cc_inner, eve_coin.amount], )), ) await self.add_lineage(eve_coin.parent_coin_info, Program.to((0, [origin.as_list(), 1]))) if send: regular_record = TransactionRecord( confirmed_at_height=uint32(0), created_at_time=uint64(int(time.time())), to_puzzle_hash=cc_puzzle_hash, amount=uint64(0), fee_amount=uint64(0), confirmed=False, sent=uint32(10), spend_bundle=full_spend, additions=full_spend.additions(), removals=full_spend.removals(), wallet_id=uint32(1), sent_to=[], trade_id=None, type=uint32(TransactionType.INCOMING_TX.value), name=token_bytes(), ) cc_record = TransactionRecord( confirmed_at_height=uint32(0), created_at_time=uint64(int(time.time())), to_puzzle_hash=cc_puzzle_hash, amount=uint64(0), fee_amount=uint64(0), confirmed=False, sent=uint32(0), spend_bundle=full_spend, additions=full_spend.additions(), removals=full_spend.removals(), wallet_id=self.id(), sent_to=[], trade_id=None, type=uint32(TransactionType.INCOMING_TX.value), name=full_spend.name(), ) await self.wallet_state_manager.add_transaction(regular_record) await self.wallet_state_manager.add_pending_transaction(cc_record) return full_spend
async def set_user_info( self, interval: uint64, limit: uint64, origin_parent_id: str, origin_puzzle_hash: str, origin_amount: uint64, admin_pubkey: str, ) -> None: admin_pubkey_bytes = hexstr_to_bytes(admin_pubkey) assert self.rl_info.user_pubkey is not None origin = Coin( hexstr_to_bytes(origin_parent_id), hexstr_to_bytes(origin_puzzle_hash), origin_amount, ) rl_puzzle = rl_puzzle_for_pk( pubkey=self.rl_info.user_pubkey, rate_amount=limit, interval_time=interval, origin_id=origin.name(), clawback_pk=admin_pubkey_bytes, ) rl_puzzle_hash = rl_puzzle.get_tree_hash() new_rl_info = RLInfo( "user", admin_pubkey_bytes, self.rl_info.user_pubkey, limit, interval, origin, origin.name(), rl_puzzle_hash, True, ) rl_puzzle_hash = rl_puzzle.get_tree_hash() if await self.wallet_state_manager.puzzle_store.puzzle_hash_exists(rl_puzzle_hash): raise ValueError( "Cannot create multiple Rate Limited wallets under the same keys. This will change in a future release." ) index = await self.wallet_state_manager.puzzle_store.index_for_pubkey( G1Element.from_bytes(self.rl_info.user_pubkey) ) assert index is not None record = DerivationRecord( index, rl_puzzle_hash, self.rl_info.user_pubkey, WalletType.RATE_LIMITED, self.id(), ) aggregation_puzzlehash = self.rl_get_aggregation_puzzlehash(new_rl_info.rl_puzzle_hash) record2 = DerivationRecord( index + 1, aggregation_puzzlehash, self.rl_info.user_pubkey, WalletType.RATE_LIMITED, self.id(), ) await self.wallet_state_manager.puzzle_store.add_derivation_paths([record, record2]) self.wallet_state_manager.set_coin_with_puzzlehash_created_callback( aggregation_puzzlehash, self.aggregate_this_coin ) data_str = json.dumps(new_rl_info.to_json_dict()) new_wallet_info = WalletInfo(self.id(), self.wallet_info.name, self.type(), data_str) await self.wallet_state_manager.user_store.update_wallet(new_wallet_info) await self.wallet_state_manager.add_new_wallet(self, self.id()) self.wallet_info = new_wallet_info self.rl_info = new_rl_info
def create_farmer_coin(block_height: uint32, puzzle_hash: bytes32, reward: uint64, genesis_challenge: bytes32): parent_id = farmer_parent_id(block_height, genesis_challenge) return Coin(parent_id, puzzle_hash, reward)