From 4b010750e20e4ef708e0f0e155408eae73b65239 Mon Sep 17 00:00:00 2001 From: heyolaniran Date: Tue, 24 Feb 2026 19:32:00 +0100 Subject: [PATCH 1/5] feat: refactoring the python binding test --- bindings/python/src/ldk_node/test_ldk_node.py | 116 +++++++++--------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/bindings/python/src/ldk_node/test_ldk_node.py b/bindings/python/src/ldk_node/test_ldk_node.py index 0b73e6a47..dd98c7b80 100644 --- a/bindings/python/src/ldk_node/test_ldk_node.py +++ b/bindings/python/src/ldk_node/test_ldk_node.py @@ -12,6 +12,9 @@ DEFAULT_TEST_NETWORK = Network.REGTEST DEFAULT_BITCOIN_CLI_BIN = "bitcoin-cli" +DEFAULT_MAX_ATTEMPS=25 +SLEEP_TIME=0.5 + def bitcoin_cli(cmd): args = [] @@ -51,9 +54,9 @@ def mine_and_wait(esplora_endpoint, blocks): def wait_for_block(esplora_endpoint, block_hash): url = esplora_endpoint + "/block/" + block_hash + "/status" attempts = 0 - max_attempts = 30 - while attempts < max_attempts: + + while attempts < DEFAULT_MAX_ATTEMPS: try: res = requests.get(url, timeout=10) json = res.json() @@ -64,16 +67,16 @@ def wait_for_block(esplora_endpoint, block_hash): print(f"Error: {e}") attempts += 1 - time.sleep(0.5) + time.sleep(SLEEP_TIME) - raise Exception(f"Failed to confirm block {block_hash} after {max_attempts} attempts") + raise Exception(f"Failed to confirm block {block_hash} after {DEFAULT_MAX_ATTEMPS} attempts") def wait_for_tx(esplora_endpoint, txid): url = esplora_endpoint + "/tx/" + txid attempts = 0 - max_attempts = 30 + - while attempts < max_attempts: + while attempts < DEFAULT_MAX_ATTEMPS: try: res = requests.get(url, timeout=10) json = res.json() @@ -84,9 +87,9 @@ def wait_for_tx(esplora_endpoint, txid): print(f"Error: {e}") attempts += 1 - time.sleep(0.5) + time.sleep(SLEEP_TIME) - raise Exception(f"Failed to confirm transaction {txid} after {max_attempts} attempts") + raise Exception(f"Failed to confirm transaction {txid} after {DEFAULT_MAX_ATTEMPS} attempts") def send_to_address(address, amount_sats): amount_btc = amount_sats/100000000.0 @@ -112,6 +115,14 @@ def get_esplora_endpoint(): return str(os.environ['ESPLORA_ENDPOINT']) return DEFAULT_ESPLORA_SERVER_URL +# handling events + +def event_handling(node, expected_event_type): + event = node.wait_next_event() + assert isinstance(event, expected_event_type) + print("EVENT:", event) + node.event_handled() + class TestLdkNode(unittest.TestCase): def setUp(self): bitcoin_cli("createwallet ldk_node_test") @@ -123,26 +134,33 @@ def setUp(self): def test_channel_full_cycle(self): esplora_endpoint = get_esplora_endpoint() - ## Setup Node 1 + ## Setup NodeS 1 & 2 in paralel tmp_dir_1 = tempfile.TemporaryDirectory("_ldk_node_1") + tmp_dir_2 = tempfile.TemporaryDirectory("_ldk_node_2") print("TMP DIR 1:", tmp_dir_1.name) + print("TMP DIR 2:", tmp_dir_2.name) + # listening addresses listening_addresses_1 = ["127.0.0.1:2323"] - node_1 = setup_node(tmp_dir_1.name, esplora_endpoint, listening_addresses_1) - node_1.start() - node_id_1 = node_1.node_id() - print("Node ID 1:", node_id_1) + listening_addresses_2 = ["127.0.0.1:2324"] - # Setup Node 2 - tmp_dir_2 = tempfile.TemporaryDirectory("_ldk_node_2") - print("TMP DIR 2:", tmp_dir_2.name) + # Start both node - listening_addresses_2 = ["127.0.0.1:2324"] - node_2 = setup_node(tmp_dir_2.name, esplora_endpoint, listening_addresses_2) + node_1 = setup_node(tmp_dir=tmp_dir_1 , esplora_endpoint=esplora_endpoint, listening_addresses=listening_addresses_1) + node_2 = setup_node(tmp_dir=tmp_dir_2, esplora_endpoint=esplora_endpoint, listening_addresses=listening_addresses_2) + + node_1.start() node_2.start() + + # get Nodes IDs + node_id_1 = node_1.node_id() node_id_2 = node_2.node_id() + print("Node ID 1:", node_id_1) print("Node ID 2:", node_id_2) + + # Send funds to both addresses in parallel + address_1 = node_1.onchain_payment().new_address() txid_1 = send_to_address(address_1, 100000) address_2 = node_2.onchain_payment().new_address() @@ -153,37 +171,28 @@ def test_channel_full_cycle(self): mine_and_wait(esplora_endpoint, 6) + # Sync both nodes node_1.sync_wallets() node_2.sync_wallets() - spendable_balance_1 = node_1.list_balances().spendable_onchain_balance_sats - spendable_balance_2 = node_2.list_balances().spendable_onchain_balance_sats - total_balance_1 = node_1.list_balances().total_onchain_balance_sats - total_balance_2 = node_2.list_balances().total_onchain_balance_sats - - print("SPENDABLE 1:", spendable_balance_1) - self.assertEqual(spendable_balance_1, 100000) - - print("SPENDABLE 2:", spendable_balance_2) - self.assertEqual(spendable_balance_2, 100000) + # verify balances - print("TOTAL 1:", total_balance_1) - self.assertEqual(total_balance_1, 100000) - - print("TOTAL 2:", total_balance_2) - self.assertEqual(total_balance_2, 100000) + for node, name in [(node_1, '1'), (node_2,"2")] : + spendable_balance = node.list_balances().spendable_onchain_balance_sats + total_balance = node.list_balances().total_onchain_balance_sats + self.assertEqual(spendable_balance, 100000, f"Node {name} spendable balance should be 100000 sats, the test spotted {spendable_balance} sats") + self.assertEqual(total_balance, 100000, f"Node {name} total balance should be 100000 sats, the test spotted {total_balance} sats") + node_1.open_channel(node_id_2, listening_addresses_2[0], 50000, None, None) + # check if both nodes received the channel pending event channel_pending_event_1 = node_1.wait_next_event() assert isinstance(channel_pending_event_1, Event.CHANNEL_PENDING) print("EVENT:", channel_pending_event_1) node_1.event_handled() - channel_pending_event_2 = node_2.wait_next_event() - assert isinstance(channel_pending_event_2, Event.CHANNEL_PENDING) - print("EVENT:", channel_pending_event_2) - node_2.event_handled() + event_handling(node_2, Event.CHANNEL_PENDING) funding_txid = channel_pending_event_1.funding_txo.txid wait_for_tx(esplora_endpoint, funding_txid) @@ -198,37 +207,28 @@ def test_channel_full_cycle(self): print("funding_txo:", funding_txid) node_1.event_handled() - channel_ready_event_2 = node_2.wait_next_event() - assert isinstance(channel_ready_event_2, Event.CHANNEL_READY) - print("EVENT:", channel_ready_event_2) - node_2.event_handled() + # check if the channel is active + event_handling(node_2, Event.CHANNEL_READY) description = Bolt11InvoiceDescription.DIRECT("asdf") invoice = node_2.bolt11_payment().receive(2500000, description, 9217) node_1.bolt11_payment().send(invoice, None) - payment_successful_event_1 = node_1.wait_next_event() - assert isinstance(payment_successful_event_1, Event.PAYMENT_SUCCESSFUL) - print("EVENT:", payment_successful_event_1) - node_1.event_handled() - payment_received_event_2 = node_2.wait_next_event() - assert isinstance(payment_received_event_2, Event.PAYMENT_RECEIVED) - print("EVENT:", payment_received_event_2) - node_2.event_handled() + # check if the payment is done + event_handling(node_1, Event.PAYMENT_SUCCESSFUL) + # check if the node 2 received the payment + event_handling(node_2, Event.PAYMENT_RECEIVED) - node_2.close_channel(channel_ready_event_2.user_channel_id, node_id_1) - channel_closed_event_1 = node_1.wait_next_event() - assert isinstance(channel_closed_event_1, Event.CHANNEL_CLOSED) - print("EVENT:", channel_closed_event_1) - node_1.event_handled() + + + node_2.close_channel(channel_ready_event_2.user_channel_id, node_id_1) - channel_closed_event_2 = node_2.wait_next_event() - assert isinstance(channel_closed_event_2, Event.CHANNEL_CLOSED) - print("EVENT:", channel_closed_event_2) - node_2.event_handled() + for node in [node_1, node_2]: + event_handling(node, Event.CHANNEL_CLOSED) + # mine and wait for the close transaction to confirm mine_and_wait(esplora_endpoint, 1) node_1.sync_wallets() From 215d5b2099622cb22dcdf123723b48c583c933a8 Mon Sep 17 00:00:00 2001 From: heyolaniran Date: Tue, 24 Feb 2026 19:47:18 +0100 Subject: [PATCH 2/5] fix: temporary directory typeError --- bindings/python/src/ldk_node/test_ldk_node.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bindings/python/src/ldk_node/test_ldk_node.py b/bindings/python/src/ldk_node/test_ldk_node.py index dd98c7b80..0a300550d 100644 --- a/bindings/python/src/ldk_node/test_ldk_node.py +++ b/bindings/python/src/ldk_node/test_ldk_node.py @@ -146,8 +146,8 @@ def test_channel_full_cycle(self): # Start both node - node_1 = setup_node(tmp_dir=tmp_dir_1 , esplora_endpoint=esplora_endpoint, listening_addresses=listening_addresses_1) - node_2 = setup_node(tmp_dir=tmp_dir_2, esplora_endpoint=esplora_endpoint, listening_addresses=listening_addresses_2) + node_1 = setup_node(tmp_dir=tmp_dir_1.name , esplora_endpoint=esplora_endpoint, listening_addresses=listening_addresses_1) + node_2 = setup_node(tmp_dir=tmp_dir_2.name, esplora_endpoint=esplora_endpoint, listening_addresses=listening_addresses_2) node_1.start() node_2.start() From fa2c4314766b9105a6c23b0136eaee1c4f1c752a Mon Sep 17 00:00:00 2001 From: heyolaniran Date: Tue, 24 Feb 2026 20:04:55 +0100 Subject: [PATCH 3/5] fix: node_2 close event and clean up the temp dir even test fails --- bindings/python/src/ldk_node/test_ldk_node.py | 166 +++++++++--------- 1 file changed, 87 insertions(+), 79 deletions(-) diff --git a/bindings/python/src/ldk_node/test_ldk_node.py b/bindings/python/src/ldk_node/test_ldk_node.py index 0a300550d..1051d190f 100644 --- a/bindings/python/src/ldk_node/test_ldk_node.py +++ b/bindings/python/src/ldk_node/test_ldk_node.py @@ -137,117 +137,125 @@ def test_channel_full_cycle(self): ## Setup NodeS 1 & 2 in paralel tmp_dir_1 = tempfile.TemporaryDirectory("_ldk_node_1") tmp_dir_2 = tempfile.TemporaryDirectory("_ldk_node_2") - print("TMP DIR 1:", tmp_dir_1.name) - print("TMP DIR 2:", tmp_dir_2.name) + try: + print("TMP DIR 1:", tmp_dir_1.name) + print("TMP DIR 2:", tmp_dir_2.name) - # listening addresses - listening_addresses_1 = ["127.0.0.1:2323"] - listening_addresses_2 = ["127.0.0.1:2324"] + # listening addresses + listening_addresses_1 = ["127.0.0.1:2323"] + listening_addresses_2 = ["127.0.0.1:2324"] - # Start both node + # Start both node - node_1 = setup_node(tmp_dir=tmp_dir_1.name , esplora_endpoint=esplora_endpoint, listening_addresses=listening_addresses_1) - node_2 = setup_node(tmp_dir=tmp_dir_2.name, esplora_endpoint=esplora_endpoint, listening_addresses=listening_addresses_2) + node_1 = setup_node(tmp_dir=tmp_dir_1.name , esplora_endpoint=esplora_endpoint, listening_addresses=listening_addresses_1) + node_2 = setup_node(tmp_dir=tmp_dir_2.name, esplora_endpoint=esplora_endpoint, listening_addresses=listening_addresses_2) - node_1.start() - node_2.start() + node_1.start() + node_2.start() - # get Nodes IDs - node_id_1 = node_1.node_id() - node_id_2 = node_2.node_id() - print("Node ID 1:", node_id_1) - print("Node ID 2:", node_id_2) + # get Nodes IDs + node_id_1 = node_1.node_id() + node_id_2 = node_2.node_id() + print("Node ID 1:", node_id_1) + print("Node ID 2:", node_id_2) - # Send funds to both addresses in parallel + # Send funds to both addresses in parallel - address_1 = node_1.onchain_payment().new_address() - txid_1 = send_to_address(address_1, 100000) - address_2 = node_2.onchain_payment().new_address() - txid_2 = send_to_address(address_2, 100000) + address_1 = node_1.onchain_payment().new_address() + txid_1 = send_to_address(address_1, 100000) + address_2 = node_2.onchain_payment().new_address() + txid_2 = send_to_address(address_2, 100000) - wait_for_tx(esplora_endpoint, txid_1) - wait_for_tx(esplora_endpoint, txid_2) + wait_for_tx(esplora_endpoint, txid_1) + wait_for_tx(esplora_endpoint, txid_2) - mine_and_wait(esplora_endpoint, 6) + mine_and_wait(esplora_endpoint, 6) - # Sync both nodes - node_1.sync_wallets() - node_2.sync_wallets() + # Sync both nodes + node_1.sync_wallets() + node_2.sync_wallets() - # verify balances + # verify balances - for node, name in [(node_1, '1'), (node_2,"2")] : - spendable_balance = node.list_balances().spendable_onchain_balance_sats - total_balance = node.list_balances().total_onchain_balance_sats - self.assertEqual(spendable_balance, 100000, f"Node {name} spendable balance should be 100000 sats, the test spotted {spendable_balance} sats") - self.assertEqual(total_balance, 100000, f"Node {name} total balance should be 100000 sats, the test spotted {total_balance} sats") - + for node, name in [(node_1, '1'), (node_2,"2")] : + spendable_balance = node.list_balances().spendable_onchain_balance_sats + total_balance = node.list_balances().total_onchain_balance_sats + self.assertEqual(spendable_balance, 100000, f"Node {name} spendable balance should be 100000 sats, the test spotted {spendable_balance} sats") + self.assertEqual(total_balance, 100000, f"Node {name} total balance should be 100000 sats, the test spotted {total_balance} sats") + - node_1.open_channel(node_id_2, listening_addresses_2[0], 50000, None, None) + node_1.open_channel(node_id_2, listening_addresses_2[0], 50000, None, None) - # check if both nodes received the channel pending event - channel_pending_event_1 = node_1.wait_next_event() - assert isinstance(channel_pending_event_1, Event.CHANNEL_PENDING) - print("EVENT:", channel_pending_event_1) - node_1.event_handled() + # check if both nodes received the channel pending event + channel_pending_event_1 = node_1.wait_next_event() + assert isinstance(channel_pending_event_1, Event.CHANNEL_PENDING) + print("EVENT:", channel_pending_event_1) + node_1.event_handled() - event_handling(node_2, Event.CHANNEL_PENDING) + event_handling(node_2, Event.CHANNEL_PENDING) - funding_txid = channel_pending_event_1.funding_txo.txid - wait_for_tx(esplora_endpoint, funding_txid) - mine_and_wait(esplora_endpoint, 6) + funding_txid = channel_pending_event_1.funding_txo.txid + wait_for_tx(esplora_endpoint, funding_txid) + mine_and_wait(esplora_endpoint, 6) - node_1.sync_wallets() - node_2.sync_wallets() + node_1.sync_wallets() + node_2.sync_wallets() - channel_ready_event_1 = node_1.wait_next_event() - assert isinstance(channel_ready_event_1, Event.CHANNEL_READY) - print("EVENT:", channel_ready_event_1) - print("funding_txo:", funding_txid) - node_1.event_handled() + channel_ready_event_1 = node_1.wait_next_event() + assert isinstance(channel_ready_event_1, Event.CHANNEL_READY) + print("EVENT:", channel_ready_event_1) + print("funding_txo:", funding_txid) + node_1.event_handled() - # check if the channel is active - event_handling(node_2, Event.CHANNEL_READY) + # check if the channel is active + event_handling(node_2, Event.CHANNEL_READY) - description = Bolt11InvoiceDescription.DIRECT("asdf") - invoice = node_2.bolt11_payment().receive(2500000, description, 9217) - node_1.bolt11_payment().send(invoice, None) + description = Bolt11InvoiceDescription.DIRECT("asdf") + invoice = node_2.bolt11_payment().receive(2500000, description, 9217) + node_1.bolt11_payment().send(invoice, None) - # check if the payment is done - event_handling(node_1, Event.PAYMENT_SUCCESSFUL) - # check if the node 2 received the payment - event_handling(node_2, Event.PAYMENT_RECEIVED) + # check if the payment is done + event_handling(node_1, Event.PAYMENT_SUCCESSFUL) + # check if the node 2 received the payment + channel_ready_event_2 = node_2.wait_next_event() + assert isinstance(channel_ready_event_2, Event.PAYMENT_RECEIVED) + print("EVENT:", channel_ready_event_2) + node_2.event_handled() - + - node_2.close_channel(channel_ready_event_2.user_channel_id, node_id_1) + node_2.close_channel(channel_ready_event_2.user_channel_id, node_id_1) - for node in [node_1, node_2]: - event_handling(node, Event.CHANNEL_CLOSED) + for node in [node_1, node_2]: + event_handling(node, Event.CHANNEL_CLOSED) - # mine and wait for the close transaction to confirm - mine_and_wait(esplora_endpoint, 1) + # mine and wait for the close transaction to confirm + mine_and_wait(esplora_endpoint, 1) - node_1.sync_wallets() - node_2.sync_wallets() + node_1.sync_wallets() + node_2.sync_wallets() - spendable_balance_after_close_1 = node_1.list_balances().spendable_onchain_balance_sats - assert spendable_balance_after_close_1 > 95000 - assert spendable_balance_after_close_1 < 100000 - spendable_balance_after_close_2 = node_2.list_balances().spendable_onchain_balance_sats - self.assertEqual(spendable_balance_after_close_2, 102500) + spendable_balance_after_close_1 = node_1.list_balances().spendable_onchain_balance_sats + assert spendable_balance_after_close_1 > 95000 + assert spendable_balance_after_close_1 < 100000 + spendable_balance_after_close_2 = node_2.list_balances().spendable_onchain_balance_sats + self.assertEqual(spendable_balance_after_close_2, 102500) - # Stop nodes - node_1.stop() - node_2.stop() + # Stop nodes + node_1.stop() + node_2.stop() - # Cleanup - time.sleep(1) # Wait a sec so our logs can finish writing - tmp_dir_1.cleanup() - tmp_dir_2.cleanup() + # Cleanup + time.sleep(1) # Wait a sec so our logs can finish writing + tmp_dir_1.cleanup() + tmp_dir_2.cleanup() + finally: + # Cleanup even if the test fails + tmp_dir_1.cleanup() + tmp_dir_2.cleanup() if __name__ == '__main__': unittest.main() From b376446906b484d00957d72ee87e93ddc339c563 Mon Sep 17 00:00:00 2001 From: heyolaniran Date: Tue, 24 Feb 2026 20:15:30 +0100 Subject: [PATCH 4/5] fix: cleanup only at the end --- bindings/python/src/ldk_node/test_ldk_node.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/bindings/python/src/ldk_node/test_ldk_node.py b/bindings/python/src/ldk_node/test_ldk_node.py index 1051d190f..111ce89f8 100644 --- a/bindings/python/src/ldk_node/test_ldk_node.py +++ b/bindings/python/src/ldk_node/test_ldk_node.py @@ -248,11 +248,9 @@ def test_channel_full_cycle(self): node_1.stop() node_2.stop() + finally: # Cleanup time.sleep(1) # Wait a sec so our logs can finish writing - tmp_dir_1.cleanup() - tmp_dir_2.cleanup() - finally: # Cleanup even if the test fails tmp_dir_1.cleanup() tmp_dir_2.cleanup() From 58d16d5caca22a5edb702763eeba2c984a421daf Mon Sep 17 00:00:00 2001 From: heyolaniran Date: Wed, 25 Feb 2026 12:46:04 +0100 Subject: [PATCH 5/5] fix: focusing the refactoring on the expect_event method --- bindings/python/src/ldk_node/test_ldk_node.py | 179 +++++++++--------- 1 file changed, 90 insertions(+), 89 deletions(-) diff --git a/bindings/python/src/ldk_node/test_ldk_node.py b/bindings/python/src/ldk_node/test_ldk_node.py index 111ce89f8..e4c6214cd 100644 --- a/bindings/python/src/ldk_node/test_ldk_node.py +++ b/bindings/python/src/ldk_node/test_ldk_node.py @@ -115,13 +115,24 @@ def get_esplora_endpoint(): return str(os.environ['ESPLORA_ENDPOINT']) return DEFAULT_ESPLORA_SERVER_URL -# handling events +# handling expect events -def event_handling(node, expected_event_type): +def expect_event(node, expected_event_type): event = node.wait_next_event() assert isinstance(event, expected_event_type) print("EVENT:", event) node.event_handled() + #According to the event type, we may want to return some data from the event for further processing + match expected_event_type: + case Event.CHANNEL_PENDING: + return event.funding_txo.txid + case Event.PAYMENT_RECEIVED: + return event.payment_hash + case Event.CHANNEL_READY: + if node.name == "node_2": + return event.user.channel_id + case _: + return None class TestLdkNode(unittest.TestCase): def setUp(self): @@ -134,127 +145,117 @@ def setUp(self): def test_channel_full_cycle(self): esplora_endpoint = get_esplora_endpoint() - ## Setup NodeS 1 & 2 in paralel + ## Setup Node 1 tmp_dir_1 = tempfile.TemporaryDirectory("_ldk_node_1") - tmp_dir_2 = tempfile.TemporaryDirectory("_ldk_node_2") - try: - print("TMP DIR 1:", tmp_dir_1.name) - print("TMP DIR 2:", tmp_dir_2.name) + print("TMP DIR 1:", tmp_dir_1.name) - # listening addresses - listening_addresses_1 = ["127.0.0.1:2323"] - listening_addresses_2 = ["127.0.0.1:2324"] + listening_addresses_1 = ["127.0.0.1:2323"] + node_1 = setup_node(tmp_dir_1.name, esplora_endpoint, listening_addresses_1) + node_1.start() + node_id_1 = node_1.node_id() + print("Node ID 1:", node_id_1) - # Start both node + # Setup Node 2 + tmp_dir_2 = tempfile.TemporaryDirectory("_ldk_node_2") + print("TMP DIR 2:", tmp_dir_2.name) - node_1 = setup_node(tmp_dir=tmp_dir_1.name , esplora_endpoint=esplora_endpoint, listening_addresses=listening_addresses_1) - node_2 = setup_node(tmp_dir=tmp_dir_2.name, esplora_endpoint=esplora_endpoint, listening_addresses=listening_addresses_2) + listening_addresses_2 = ["127.0.0.1:2324"] + node_2 = setup_node(tmp_dir_2.name, esplora_endpoint, listening_addresses_2) + node_2.start() + node_id_2 = node_2.node_id() + print("Node ID 2:", node_id_2) - node_1.start() - node_2.start() + address_1 = node_1.onchain_payment().new_address() + txid_1 = send_to_address(address_1, 100000) + address_2 = node_2.onchain_payment().new_address() + txid_2 = send_to_address(address_2, 100000) - # get Nodes IDs - node_id_1 = node_1.node_id() - node_id_2 = node_2.node_id() - print("Node ID 1:", node_id_1) - print("Node ID 2:", node_id_2) + wait_for_tx(esplora_endpoint, txid_1) + wait_for_tx(esplora_endpoint, txid_2) + mine_and_wait(esplora_endpoint, 6) - # Send funds to both addresses in parallel + node_1.sync_wallets() + node_2.sync_wallets() - address_1 = node_1.onchain_payment().new_address() - txid_1 = send_to_address(address_1, 100000) - address_2 = node_2.onchain_payment().new_address() - txid_2 = send_to_address(address_2, 100000) + spendable_balance_1 = node_1.list_balances().spendable_onchain_balance_sats + spendable_balance_2 = node_2.list_balances().spendable_onchain_balance_sats + total_balance_1 = node_1.list_balances().total_onchain_balance_sats + total_balance_2 = node_2.list_balances().total_onchain_balance_sats - wait_for_tx(esplora_endpoint, txid_1) - wait_for_tx(esplora_endpoint, txid_2) + print("SPENDABLE 1:", spendable_balance_1) + self.assertEqual(spendable_balance_1, 100000) - mine_and_wait(esplora_endpoint, 6) + print("SPENDABLE 2:", spendable_balance_2) + self.assertEqual(spendable_balance_2, 100000) - # Sync both nodes - node_1.sync_wallets() - node_2.sync_wallets() + print("TOTAL 1:", total_balance_1) + self.assertEqual(total_balance_1, 100000) - # verify balances + print("TOTAL 2:", total_balance_2) + self.assertEqual(total_balance_2, 100000) - for node, name in [(node_1, '1'), (node_2,"2")] : - spendable_balance = node.list_balances().spendable_onchain_balance_sats - total_balance = node.list_balances().total_onchain_balance_sats - self.assertEqual(spendable_balance, 100000, f"Node {name} spendable balance should be 100000 sats, the test spotted {spendable_balance} sats") - self.assertEqual(total_balance, 100000, f"Node {name} total balance should be 100000 sats, the test spotted {total_balance} sats") - + node_1.open_channel(node_id_2, listening_addresses_2[0], 50000, None, None) - node_1.open_channel(node_id_2, listening_addresses_2[0], 50000, None, None) + # expect the channel pending event on the node 1 then get the funding txid from the event - # check if both nodes received the channel pending event - channel_pending_event_1 = node_1.wait_next_event() - assert isinstance(channel_pending_event_1, Event.CHANNEL_PENDING) - print("EVENT:", channel_pending_event_1) - node_1.event_handled() + funding_txid = expect_event(node_1, Event.CHANNEL_PENDING) - event_handling(node_2, Event.CHANNEL_PENDING) + # expect channel pending on node 2 + expect_event(node_2, Event.CHANNEL_PENDING) - funding_txid = channel_pending_event_1.funding_txo.txid - wait_for_tx(esplora_endpoint, funding_txid) - mine_and_wait(esplora_endpoint, 6) + wait_for_tx(esplora_endpoint, funding_txid) + mine_and_wait(esplora_endpoint, 6) - node_1.sync_wallets() - node_2.sync_wallets() + node_1.sync_wallets() + node_2.sync_wallets() - channel_ready_event_1 = node_1.wait_next_event() - assert isinstance(channel_ready_event_1, Event.CHANNEL_READY) - print("EVENT:", channel_ready_event_1) - print("funding_txo:", funding_txid) - node_1.event_handled() + expect_event(node_1, Event.CHANNEL_READY) + print(f"Node 1 channel ready with node 2, funding txid: {funding_txid}") - # check if the channel is active - event_handling(node_2, Event.CHANNEL_READY) + node_2_channel_id = expect_event(node_2, Event.CHANNEL_READY) - description = Bolt11InvoiceDescription.DIRECT("asdf") - invoice = node_2.bolt11_payment().receive(2500000, description, 9217) - node_1.bolt11_payment().send(invoice, None) + description = Bolt11InvoiceDescription.DIRECT("asdf") + invoice = node_2.bolt11_payment().receive(2500000, description, 9217) + node_1.bolt11_payment().send(invoice, None) + # expect payment successful on node 1 + expect_event(node_1, Event.PAYMENT_SUCCESSFUL) - # check if the payment is done - event_handling(node_1, Event.PAYMENT_SUCCESSFUL) - # check if the node 2 received the payment - channel_ready_event_2 = node_2.wait_next_event() - assert isinstance(channel_ready_event_2, Event.PAYMENT_RECEIVED) - print("EVENT:", channel_ready_event_2) - node_2.event_handled() + # expect payment received on node_2 + expect_event(node_2, Event.PAYMENT_RECEIVED) + + node_2.close_channel(node_2_channel_id, node_id_1) - + #Expecting node 1 channel closed + expect_event(node_1, Event.CHANNEL_CLOSED) - node_2.close_channel(channel_ready_event_2.user_channel_id, node_id_1) + #expecting channel close + expect_event(node_2, Event.CHANNEL_CLOSED) - for node in [node_1, node_2]: - event_handling(node, Event.CHANNEL_CLOSED) + mine_and_wait(esplora_endpoint, 1) - # mine and wait for the close transaction to confirm - mine_and_wait(esplora_endpoint, 1) + node_1.sync_wallets() + node_2.sync_wallets() - node_1.sync_wallets() - node_2.sync_wallets() + spendable_balance_after_close_1 = node_1.list_balances().spendable_onchain_balance_sats + assert spendable_balance_after_close_1 > 95000 + assert spendable_balance_after_close_1 < 100000 + spendable_balance_after_close_2 = node_2.list_balances().spendable_onchain_balance_sats + self.assertEqual(spendable_balance_after_close_2, 102500) - spendable_balance_after_close_1 = node_1.list_balances().spendable_onchain_balance_sats - assert spendable_balance_after_close_1 > 95000 - assert spendable_balance_after_close_1 < 100000 - spendable_balance_after_close_2 = node_2.list_balances().spendable_onchain_balance_sats - self.assertEqual(spendable_balance_after_close_2, 102500) + # Stop nodes + node_1.stop() + node_2.stop() - # Stop nodes - node_1.stop() - node_2.stop() + # Cleanup + time.sleep(1) # Wait a sec so our logs can finish writing + tmp_dir_1.cleanup() + tmp_dir_2.cleanup() - finally: - # Cleanup - time.sleep(1) # Wait a sec so our logs can finish writing - # Cleanup even if the test fails - tmp_dir_1.cleanup() - tmp_dir_2.cleanup() + if __name__ == '__main__': unittest.main()