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()
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_create_rl_coin(self, three_wallet_nodes): num_blocks = 4 full_nodes, wallets = three_wallet_nodes full_node_api = full_nodes[0] full_node_server = full_node_api.server 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(self_hostname, uint16(full_node_server._port)), None) await wallet_server_1.start_client(PeerInfo(self_hostname, uint16(full_node_server._port)), None) await wallet_server_2.start_client(PeerInfo(self_hostname, uint16(full_node_server._port)), None) await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) for i in range(0, num_blocks + 1): await full_node_api.farm_new_transaction_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": f"{self_hostname}: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": f"{self_hostname}: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_api.farm_new_transaction_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(), "xch") 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_api.farm_new_transaction_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_api.farm_new_transaction_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(), "xch") 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_api.farm_new_transaction_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_api.farm_new_transaction_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