async def get_next_puzzle_hash(self, request: Dict) -> Dict: """ Returns a new puzzlehash """ if self.service is None: return {"success": False} wallet_id = uint32(int(request["wallet_id"])) if self.service.wallet_state_manager is None: return {"success": False} wallet = self.service.wallet_state_manager.wallets[wallet_id] if wallet.wallet_info.type == WalletType.STANDARD_WALLET.value: raw_puzzle_hash = await wallet.get_new_puzzlehash() puzzle_hash = encode_puzzle_hash(raw_puzzle_hash) elif wallet.wallet_info.type == WalletType.COLOURED_COIN.value: raw_puzzle_hash = await wallet.get_new_inner_hash() puzzle_hash = encode_puzzle_hash(raw_puzzle_hash) else: return { "success": False, "reason": "Wallet type cannnot create puzzle hashes", } response = { "success": True, "wallet_id": wallet_id, "puzzle_hash": puzzle_hash, } return response
async def setup_farmer( port, consensus_constants: ConsensusConstants, full_node_port: Optional[uint16] = None, ): config = bt.config["farmer"] config_pool = bt.config["pool"] config["xch_target_address"] = encode_puzzle_hash(bt.farmer_ph) config["pool_public_keys"] = [bytes(pk).hex() for pk in bt.pool_pubkeys] config["port"] = port config_pool["xch_target_address"] = encode_puzzle_hash(bt.pool_ph) if full_node_port: config["full_node_peer"]["host"] = self_hostname config["full_node_peer"]["port"] = full_node_port else: del config["full_node_peer"] kwargs = service_kwargs_for_farmer(bt.root_path, config, config_pool, bt.keychain, consensus_constants) kwargs.update(parse_cli_args=False, ) service = Service(**kwargs) await service.start() yield service._api, service._api.server service.stop() await service.wait_closed()
def show_all_keys(): """ Prints all keys and mnemonics (if available). """ private_keys = keychain.get_all_private_keys() if len(private_keys) == 0: print("There are no saved private keys.") return print("Showing all private keys:") for sk, seed in private_keys: print("") print("Fingerprint:", sk.get_g1().get_fingerprint()) print("Master public key (m):", sk.get_g1()) print("Master private key (m):", bytes(sk).hex()) print( "Farmer public key (m/12381/8444/0/0)::", master_sk_to_farmer_sk(sk).get_g1(), ) print("Pool public key (m/12381/8444/1/0):", master_sk_to_pool_sk(sk).get_g1()) print( "First wallet key (m/12381/8444/2/0):", master_sk_to_wallet_sk(sk, uint32(0)).get_g1(), ) print( "First wallet address:", encode_puzzle_hash( create_puzzlehash_for_pk( master_sk_to_wallet_sk(sk, uint32(0)).get_g1())), ) assert seed is not None mnemonic = bytes_to_mnemonic(seed) print(" Mnemonic seed (24 secret words):") print(mnemonic)
async def setup_farmer( port, consensus_constants: ConsensusConstants, full_node_port: Optional[uint16] = None, ): config = load_config(bt.root_path, "config.yaml", "farmer") config_pool = load_config(bt.root_path, "config.yaml", "pool") config["xch_target_address"] = encode_puzzle_hash(bt.farmer_ph) config["pool_public_keys"] = [bytes(pk).hex() for pk in bt.pool_pubkeys] config_pool["xch_target_address"] = encode_puzzle_hash(bt.pool_ph) if full_node_port: connect_peers = [PeerInfo(self_hostname, full_node_port)] else: connect_peers = [] api = Farmer(config, config_pool, bt.keychain, consensus_constants) started = asyncio.Event() async def start_callback(): nonlocal started started.set() service = Service( root_path=bt.root_path, api=api, node_type=NodeType.FARMER, advertised_port=port, service_name="farmer", server_listen_ports=[port], on_connect_callback=api._on_connect, connect_peers=connect_peers, auth_connect_peers=False, start_callback=start_callback, parse_cli_args=False, ) run_task = asyncio.create_task(service.run()) await started.wait() yield api, api.server service.stop() await run_task
async def get_next_address(self, request: Dict) -> Dict: """ Returns a new address """ assert self.service.wallet_state_manager is not None wallet_id = uint32(int(request["wallet_id"])) wallet = self.service.wallet_state_manager.wallets[wallet_id] if wallet.type() == WalletType.STANDARD_WALLET: raw_puzzle_hash = await wallet.get_new_puzzlehash() address = encode_puzzle_hash(raw_puzzle_hash) elif wallet.type() == WalletType.COLOURED_COIN: raw_puzzle_hash = await wallet.get_new_inner_hash() address = encode_puzzle_hash(raw_puzzle_hash) else: raise ValueError(f"Wallet type {wallet.type()} cannot create puzzle hashes") return { "wallet_id": wallet_id, "address": address, }
async def get_transactions(self, request): wallet_id = int(request["wallet_id"]) transactions = await self.service.wallet_state_manager.get_all_transactions( wallet_id) formatted_transactions = [] for tx in transactions: formatted = tx.to_json_dict() formatted["to_puzzle_hash"] = encode_puzzle_hash(tx.to_puzzle_hash) formatted_transactions.append(formatted) response = { "success": True, "txs": formatted_transactions, "wallet_id": wallet_id, } return response
async def get_transactions(self, request: Dict) -> Dict: assert self.service.wallet_state_manager is not None wallet_id = int(request["wallet_id"]) transactions = await self.service.wallet_state_manager.get_all_transactions( wallet_id ) formatted_transactions = [] for tx in transactions: formatted = tx.to_json_dict() formatted["to_address"] = encode_puzzle_hash(tx.to_puzzle_hash) formatted_transactions.append(formatted) return { "transactions": formatted_transactions, "wallet_id": wallet_id, }
async def test_create_rl_coin(self, three_wallet_nodes): num_blocks = 4 full_nodes, wallets = three_wallet_nodes full_node_1, server_1 = full_nodes[0] wallet_node, server_2 = wallets[0] wallet_node_1, wallet_server_1 = wallets[1] wallet_node_2, wallet_server_2 = wallets[2] wallet = wallet_node.wallet_state_manager.main_wallet ph = await wallet.get_new_puzzlehash() await server_2.start_client( PeerInfo("localhost", uint16(server_1._port)), None) await wallet_server_1.start_client( PeerInfo("localhost", uint16(server_1._port)), None) await wallet_server_2.start_client( PeerInfo("localhost", uint16(server_1._port)), None) for i in range(0, num_blocks): await full_node_1.farm_new_block(FarmNewBlockProtocol(ph)) api_user = WalletRpcApi(wallet_node_1) val = await api_user.create_new_wallet({ "wallet_type": "rl_wallet", "rl_type": "user" }) assert isinstance(val, dict) assert val["success"] assert val["id"] assert val["type"] == WalletType.RATE_LIMITED.value pubkey = val["pubkey"] api_admin = WalletRpcApi(wallet_node) val = await api_admin.create_new_wallet({ "wallet_type": "rl_wallet", "rl_type": "admin", "interval": 2, "limit": 1, "pubkey": pubkey, "amount": 100, }) assert isinstance(val, dict) assert val["success"] assert val["id"] assert val["type"] == WalletType.RATE_LIMITED.value assert val["origin"] assert val["pubkey"] admin_pubkey = val["pubkey"] origin: Coin = val["origin"] val = await api_user.rl_set_user_info({ "wallet_id": 2, "interval": 2, "limit": 1, "origin": { "parent_coin_info": origin.parent_coin_info.hex(), "puzzle_hash": origin.puzzle_hash.hex(), "amount": origin.amount, }, "admin_pubkey": admin_pubkey, }) assert val["success"] assert (await api_user.get_wallet_balance( {"wallet_id": 2}))["wallet_balance"]["confirmed_wallet_balance"] == 0 for i in range(0, 2 * num_blocks): await full_node_1.farm_new_block(FarmNewBlockProtocol(32 * b"\0")) async def check_balance(api, wallet_id): balance_response = await api.get_wallet_balance( {"wallet_id": wallet_id}) balance = balance_response["wallet_balance"][ "confirmed_wallet_balance"] return balance await time_out_assert(15, check_balance, 100, api_user, 2) receiving_wallet = wallet_node_2.wallet_state_manager.main_wallet puzzle_hash = encode_puzzle_hash(await receiving_wallet.get_new_puzzlehash()) assert await receiving_wallet.get_spendable_balance() == 0 val = await api_user.send_transaction({ "wallet_id": 2, "amount": 3, "fee": 0, "puzzle_hash": puzzle_hash }) assert val["status"] == "SUCCESS" for i in range(0, 2 * num_blocks): await full_node_1.farm_new_block(FarmNewBlockProtocol(32 * b"\0")) await time_out_assert(15, check_balance, 97, api_user, 2) await time_out_assert(15, receiving_wallet.get_spendable_balance, 3)
async def test_wallet_make_transaction(self, two_wallet_nodes): test_rpc_port = uint16(21529) num_blocks = 5 full_nodes, wallets = two_wallet_nodes full_node_1, server_1 = full_nodes[0] wallet_node, server_2 = wallets[0] wallet_node_2, server_3 = wallets[1] wallet = wallet_node.wallet_state_manager.main_wallet wallet_2 = wallet_node_2.wallet_state_manager.main_wallet ph = await wallet.get_new_puzzlehash() ph_2 = await wallet_2.get_new_puzzlehash() await server_2.start_client( PeerInfo("localhost", uint16(server_1._port)), None) for i in range(0, num_blocks): await full_node_1.farm_new_block(FarmNewBlockProtocol(ph)) initial_funds = sum([ calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i)) for i in range(1, num_blocks - 1) ]) initial_funds_eventually = sum([ calculate_base_fee(uint32(i)) + calculate_block_reward(uint32(i)) for i in range(1, num_blocks + 1) ]) wallet_rpc_api = WalletRpcApi(wallet_node) config = load_config(bt.root_path, "config.yaml") hostname = config["self_hostname"] daemon_port = config["daemon_port"] def stop_node_cb(): pass rpc_cleanup = await start_rpc_server( wallet_rpc_api, hostname, daemon_port, test_rpc_port, stop_node_cb, connect_to_daemon=False, ) await time_out_assert(5, wallet.get_confirmed_balance, initial_funds) await time_out_assert(5, wallet.get_unconfirmed_balance, initial_funds) client = await WalletRpcClient.create("localhost", test_rpc_port) try: addr = encode_puzzle_hash(await wallet_node_2.wallet_state_manager. main_wallet.get_new_puzzlehash()) tx_amount = 15600000 try: await client.send_transaction("1", 100000000000000000, addr) raise Exception("Should not create high value tx") except ValueError: pass tx = await client.send_transaction("1", tx_amount, addr) transaction_id = tx.name() async def tx_in_mempool(): tx = await client.get_transaction("1", transaction_id) return tx.is_in_mempool() await time_out_assert(5, tx_in_mempool, True) await time_out_assert(5, wallet.get_unconfirmed_balance, initial_funds - tx_amount) assert ( await client.get_wallet_balance("1") )["unconfirmed_wallet_balance"] == initial_funds - tx_amount assert (await client.get_wallet_balance("1") )["confirmed_wallet_balance"] == initial_funds for i in range(0, 5): await client.farm_block(encode_puzzle_hash(ph_2)) await asyncio.sleep(1) async def eventual_balance(): return ( await client.get_wallet_balance("1"))["confirmed_wallet_balance"] await time_out_assert(5, eventual_balance, initial_funds_eventually - tx_amount) address = await client.get_next_address("1") assert len(address) > 10 transactions = await client.get_transactions("1") assert len(transactions) > 1 pks = await client.get_public_keys() assert len(pks) == 1 assert (await client.get_height_info()) > 0 sk_dict = await client.get_private_key(pks[0]) assert sk_dict["fingerprint"] == pks[0] assert sk_dict["sk"] is not None assert sk_dict["pk"] is not None assert sk_dict["seed"] is not None mnemonic = await client.generate_mnemonic() assert len(mnemonic) == 24 await client.add_key(mnemonic) pks = await client.get_public_keys() assert len(pks) == 2 await client.log_in_and_skip(pks[1]) sk_dict = await client.get_private_key(pks[1]) assert sk_dict["fingerprint"] == pks[1] await client.delete_key(pks[0]) await client.log_in_and_skip(pks[1]) assert len(await client.get_public_keys()) == 1 assert not (await client.get_sync_status()) wallets = await client.get_wallets() assert len(wallets) == 1 balance = await client.get_wallet_balance(wallets[0]["id"]) assert balance["unconfirmed_wallet_balance"] == 0 test_wallet_backup_path = Path("test_wallet_backup_file") await client.create_backup(test_wallet_backup_path) assert test_wallet_backup_path.exists() test_wallet_backup_path.unlink() try: await client.send_transaction(wallets[0]["id"], 100, addr) raise Exception("Should not create tx if no balance") except ValueError: pass await client.delete_all_keys() assert len(await client.get_public_keys()) == 0 except Exception: # Checks that the RPC manages to stop the node client.close() await client.await_closed() await rpc_cleanup() raise client.close() await client.await_closed() await rpc_cleanup()
def check_keys(new_root): keychain: Keychain = Keychain() all_sks = keychain.get_all_private_keys() if len(all_sks) == 0: print( "No keys are present in the keychain. Generate them with 'chia keys generate'" ) return config: Dict = load_config(new_root, "config.yaml") pool_child_pubkeys = [ master_sk_to_pool_sk(sk).get_g1() for sk, _ in all_sks ] all_targets = [] stop_searching_for_farmer = "xch_target_address" not in config["farmer"] stop_searching_for_pool = "xch_target_address" not in config["pool"] for i in range(500): if stop_searching_for_farmer and stop_searching_for_pool and i > 0: break for sk, _ in all_sks: all_targets.append( encode_puzzle_hash( create_puzzlehash_for_pk( master_sk_to_wallet_sk(sk, uint32(i)).get_g1()))) if all_targets[-1] == config["farmer"].get("xch_target_address"): stop_searching_for_farmer = True if all_targets[-1] == config["pool"].get("xch_target_address"): stop_searching_for_pool = True # Set the destinations if "xch_target_address" not in config["farmer"]: print( f"Setting the xch destination address for coinbase fees reward to {all_targets[0]}" ) config["farmer"]["xch_target_address"] = all_targets[0] elif config["farmer"]["xch_target_address"] not in all_targets: print( f"WARNING: farmer using a puzzle hash which we don't have the private" f" keys for. Overriding " f"{config['farmer']['xch_target_address']} with {all_targets[0]}") config["farmer"]["xch_target_address"] = all_targets[0] if "pool" not in config: config["pool"] = {} if "xch_target_address" not in config["pool"]: print( f"Setting the xch destination address for coinbase reward to {all_targets[0]}" ) config["pool"]["xch_target_address"] = all_targets[0] elif config["pool"]["xch_target_address"] not in all_targets: print( f"WARNING: pool using a puzzle hash which we don't have the private" f" keys for. Overriding " f"{config['pool']['xch_target_address']} with {all_targets[0]}") config["pool"]["xch_target_address"] = all_targets[0] # Set the pool pks in the farmer pool_pubkeys_hex = set(bytes(pk).hex() for pk in pool_child_pubkeys) if "pool_public_keys" in config["farmer"]: for pk_hex in config["farmer"]["pool_public_keys"]: # Add original ones in config pool_pubkeys_hex.add(pk_hex) config["farmer"]["pool_public_keys"] = pool_pubkeys_hex save_config(new_root, "config.yaml", config)
async def test_create_rl_coin(self, three_wallet_nodes): num_blocks = 4 full_nodes, wallets = three_wallet_nodes full_node, server_1 = full_nodes[0] wallet_node, server_2 = wallets[0] wallet_node_1, wallet_server_1 = wallets[1] wallet_node_2, wallet_server_2 = wallets[2] wallet = wallet_node.wallet_state_manager.main_wallet ph = await wallet.get_new_puzzlehash() await server_2.start_client(PeerInfo("localhost", uint16(server_1._port)), None) await wallet_server_1.start_client( PeerInfo("localhost", uint16(server_1._port)), None ) await wallet_server_2.start_client( PeerInfo("localhost", uint16(server_1._port)), None ) await full_node.farm_new_block(FarmNewBlockProtocol(ph)) for i in range(0, num_blocks + 1): await full_node.farm_new_block(FarmNewBlockProtocol(32 * b"\0")) fund_owners_initial_balance = await wallet.get_confirmed_balance() api_user = WalletRpcApi(wallet_node_1) val = await api_user.create_new_wallet( {"wallet_type": "rl_wallet", "rl_type": "user", "host": "127.0.0.1:5000"} ) assert isinstance(val, dict) if "success" in val: assert val["success"] assert val["id"] assert val["type"] == WalletType.RATE_LIMITED.value user_wallet_id = val["id"] pubkey = val["pubkey"] api_admin = WalletRpcApi(wallet_node) val = await api_admin.create_new_wallet( { "wallet_type": "rl_wallet", "rl_type": "admin", "interval": 2, "limit": 10, "pubkey": pubkey, "amount": 100, "fee": 1, "host": "127.0.0.1:5000", } ) assert isinstance(val, dict) if "success" in val: assert val["success"] assert val["id"] assert val["type"] == WalletType.RATE_LIMITED.value assert val["origin"] assert val["pubkey"] admin_wallet_id = val["id"] admin_pubkey = val["pubkey"] origin: Coin = val["origin"] await api_user.rl_set_user_info( { "wallet_id": user_wallet_id, "interval": 2, "limit": 10, "origin": { "parent_coin_info": origin.parent_coin_info.hex(), "puzzle_hash": origin.puzzle_hash.hex(), "amount": origin.amount, }, "admin_pubkey": admin_pubkey, } ) assert (await api_user.get_wallet_balance({"wallet_id": user_wallet_id}))[ "wallet_balance" ]["confirmed_wallet_balance"] == 0 for i in range(0, 2 * num_blocks): await full_node.farm_new_block(FarmNewBlockProtocol(32 * b"\0")) assert await wallet.get_confirmed_balance() == fund_owners_initial_balance - 101 async def check_balance(api, wallet_id): balance_response = await api.get_wallet_balance({"wallet_id": wallet_id}) balance = balance_response["wallet_balance"]["confirmed_wallet_balance"] return balance await time_out_assert(15, check_balance, 100, api_user, user_wallet_id) receiving_wallet = wallet_node_2.wallet_state_manager.main_wallet address = encode_puzzle_hash(await receiving_wallet.get_new_puzzlehash()) assert await receiving_wallet.get_spendable_balance() == 0 val = await api_user.send_transaction( {"wallet_id": user_wallet_id, "amount": 3, "fee": 2, "address": address} ) assert "transaction_id" in val 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 await time_out_assert( 15, is_transaction_in_mempool, True, api_user, val["transaction_id"] ) for i in range(0, num_blocks): await full_node.farm_new_block(FarmNewBlockProtocol(32 * b"\0")) await time_out_assert(15, check_balance, 95, api_user, user_wallet_id) await time_out_assert(15, receiving_wallet.get_spendable_balance, 3) val = await api_admin.add_rate_limited_funds( {"wallet_id": admin_wallet_id, "amount": 100, "fee": 7} ) assert val["status"] == "SUCCESS" for i in range(0, 50): await full_node.farm_new_block(FarmNewBlockProtocol(32 * b"\0")) await time_out_assert(15, check_balance, 195, api_user, user_wallet_id) # test spending puzzle_hash = encode_puzzle_hash(await receiving_wallet.get_new_puzzlehash()) val = await api_user.send_transaction( { "wallet_id": user_wallet_id, "amount": 105, "fee": 0, "address": puzzle_hash, } ) await time_out_assert( 15, is_transaction_in_mempool, True, api_user, val["transaction_id"] ) for i in range(0, num_blocks): await full_node.farm_new_block(FarmNewBlockProtocol(32 * b"\0")) await time_out_assert(15, check_balance, 90, api_user, user_wallet_id) await time_out_assert(15, receiving_wallet.get_spendable_balance, 108) val = await api_admin.send_clawback_transaction( {"wallet_id": admin_wallet_id, "fee": 11} ) await time_out_assert( 15, is_transaction_in_mempool, True, api_admin, val["transaction_id"] ) for i in range(0, num_blocks): await full_node.farm_new_block(FarmNewBlockProtocol(32 * b"\0")) await time_out_assert(15, check_balance, 0, api_user, user_wallet_id) await time_out_assert(15, check_balance, 0, api_admin, user_wallet_id) final_balance = await wallet.get_confirmed_balance() assert final_balance == fund_owners_initial_balance - 129