diff --git a/chia/_tests/core/full_node/test_full_node.py b/chia/_tests/core/full_node/test_full_node.py index e6499a6416ad..a1372ee09f42 100644 --- a/chia/_tests/core/full_node/test_full_node.py +++ b/chia/_tests/core/full_node/test_full_node.py @@ -185,14 +185,14 @@ async def test_block_compression(self, setup_two_nodes_and_wallet, empty_blockch await full_node_1.wait_for_wallet_synced(wallet_node=wallet_node_1, timeout=30) # Send a transaction to mempool - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tr] = await wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.generate_signed_transaction( tx_size, ph, DEFAULT_TX_CONFIG, action_scope, ) - [tr] = await wallet.wallet_state_manager.add_pending_transactions([tr]) + [tr] = action_scope.side_effects.transactions await time_out_assert( 10, full_node_2.full_node.mempool_manager.get_spendbundle, @@ -219,14 +219,14 @@ async def check_transaction_confirmed(transaction) -> bool: assert len((await full_node_1.get_all_full_blocks())[-1].transactions_generator_ref_list) == 0 # Send another tx - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tr] = await wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.generate_signed_transaction( 20000, ph, DEFAULT_TX_CONFIG, action_scope, ) - [tr] = await wallet.wallet_state_manager.add_pending_transactions([tr]) + [tr] = action_scope.side_effects.transactions await time_out_assert( 10, full_node_2.full_node.mempool_manager.get_spendbundle, @@ -260,28 +260,28 @@ async def check_transaction_confirmed(transaction) -> bool: await full_node_1.wait_for_wallet_synced(wallet_node=wallet_node_1, timeout=30) # Send another 2 tx - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tr] = await wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.generate_signed_transaction( 30000, ph, DEFAULT_TX_CONFIG, action_scope, ) - [tr] = await wallet.wallet_state_manager.add_pending_transactions([tr]) + [tr] = action_scope.side_effects.transactions await time_out_assert( 10, full_node_2.full_node.mempool_manager.get_spendbundle, tr.spend_bundle, tr.name, ) - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tr] = await wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.generate_signed_transaction( 40000, ph, DEFAULT_TX_CONFIG, action_scope, ) - [tr] = await wallet.wallet_state_manager.add_pending_transactions([tr]) + [tr] = action_scope.side_effects.transactions await time_out_assert( 10, full_node_2.full_node.mempool_manager.get_spendbundle, @@ -289,14 +289,14 @@ async def check_transaction_confirmed(transaction) -> bool: tr.name, ) - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tr] = await wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.generate_signed_transaction( 50000, ph, DEFAULT_TX_CONFIG, action_scope, ) - [tr] = await wallet.wallet_state_manager.add_pending_transactions([tr]) + [tr] = action_scope.side_effects.transactions await time_out_assert( 10, full_node_2.full_node.mempool_manager.get_spendbundle, @@ -304,14 +304,14 @@ async def check_transaction_confirmed(transaction) -> bool: tr.name, ) - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tr] = await wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.generate_signed_transaction( 3000000000000, ph, DEFAULT_TX_CONFIG, action_scope, ) - [tr] = await wallet.wallet_state_manager.add_pending_transactions([tr]) + [tr] = action_scope.side_effects.transactions await time_out_assert( 10, full_node_2.full_node.mempool_manager.get_spendbundle, @@ -338,12 +338,13 @@ async def check_transaction_confirmed(transaction) -> bool: # Creates a standard_transaction and an anyone-can-spend tx async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tr] = await wallet.generate_signed_transaction( + await wallet.generate_signed_transaction( 30000, Program.to(1).get_tree_hash(), DEFAULT_TX_CONFIG, action_scope, ) + [tr] = action_scope.side_effects.transactions extra_spend = SpendBundle( [ make_spend( @@ -386,12 +387,13 @@ async def check_transaction_confirmed(transaction) -> bool: # Make a standard transaction and an anyone-can-spend transaction async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tr] = await wallet.generate_signed_transaction( + await wallet.generate_signed_transaction( 30000, Program.to(1).get_tree_hash(), DEFAULT_TX_CONFIG, action_scope, ) + [tr] = action_scope.side_effects.transactions extra_spend = SpendBundle( [ make_spend( diff --git a/chia/_tests/core/full_node/test_transactions.py b/chia/_tests/core/full_node/test_transactions.py index f9d1b196faf9..d6726552c04b 100644 --- a/chia/_tests/core/full_node/test_transactions.py +++ b/chia/_tests/core/full_node/test_transactions.py @@ -83,11 +83,11 @@ async def peak_height(fna: FullNodeAPI): await time_out_assert(20, peak_height, num_blocks, full_node_api_1) await time_out_assert(20, peak_height, num_blocks, full_node_api_2) - async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await wallet_0.wallet_state_manager.main_wallet.generate_signed_transaction( + async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet_0.wallet_state_manager.main_wallet.generate_signed_transaction( 10, ph1, DEFAULT_TX_CONFIG, action_scope, 0 ) - [tx] = await wallet_0.wallet_state_manager.add_pending_transactions([tx]) + [tx] = action_scope.side_effects.transactions await time_out_assert( 10, @@ -155,11 +155,11 @@ async def test_mempool_tx_sync(self, three_nodes_two_wallets, self_hostname, see ) await time_out_assert(20, wallet_0.wallet_state_manager.main_wallet.get_confirmed_balance, funds) - async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await wallet_0.wallet_state_manager.main_wallet.generate_signed_transaction( + async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet_0.wallet_state_manager.main_wallet.generate_signed_transaction( 10, bytes32.random(seeded_random), DEFAULT_TX_CONFIG, action_scope, 0 ) - [tx] = await wallet_0.wallet_state_manager.add_pending_transactions([tx]) + [tx] = action_scope.side_effects.transactions await time_out_assert( 10, diff --git a/chia/_tests/core/mempool/test_mempool_manager.py b/chia/_tests/core/mempool/test_mempool_manager.py index 52d4d4165c37..64972d39729f 100644 --- a/chia/_tests/core/mempool/test_mempool_manager.py +++ b/chia/_tests/core/mempool/test_mempool_manager.py @@ -1622,11 +1622,11 @@ async def make_setup_and_coins( for _ in range(2): await farm_a_block(full_node_api, wallet_node, ph) other_recipients = [Payment(puzzle_hash=p, amount=uint64(200), memos=[]) for p in phs[1:]] - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=False, sign=True) as action_scope: + await wallet.generate_signed_transaction( uint64(200), phs[0], DEFAULT_TX_CONFIG, action_scope, primaries=other_recipients ) - [tx], _ = await wallet.wallet_state_manager.sign_transactions([tx]) + [tx] = action_scope.side_effects.transactions assert tx.spend_bundle is not None await send_to_mempool(full_node_api, tx.spend_bundle) await farm_a_block(full_node_api, wallet_node, ph) @@ -1641,17 +1641,11 @@ async def make_setup_and_coins( wallet, coins, ph = await make_setup_and_coins(full_node_api, wallet_node) # Make sure spending AB then BC would generate a conflict for the latter - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx_a] = await wallet.generate_signed_transaction( - uint64(30), ph, DEFAULT_TX_CONFIG, action_scope, coins={coins[0].coin} - ) - [tx_b] = await wallet.generate_signed_transaction( - uint64(30), ph, DEFAULT_TX_CONFIG, action_scope, coins={coins[1].coin} - ) - [tx_c] = await wallet.generate_signed_transaction( - uint64(30), ph, DEFAULT_TX_CONFIG, action_scope, coins={coins[2].coin} - ) - [tx_a, tx_b, tx_c], _ = await wallet.wallet_state_manager.sign_transactions([tx_a, tx_b, tx_c]) + async with wallet.wallet_state_manager.new_action_scope(push=False, merge_spends=False, sign=True) as action_scope: + await wallet.generate_signed_transaction(uint64(30), ph, DEFAULT_TX_CONFIG, action_scope, coins={coins[0].coin}) + await wallet.generate_signed_transaction(uint64(30), ph, DEFAULT_TX_CONFIG, action_scope, coins={coins[1].coin}) + await wallet.generate_signed_transaction(uint64(30), ph, DEFAULT_TX_CONFIG, action_scope, coins={coins[2].coin}) + [tx_a, tx_b, tx_c] = action_scope.side_effects.transactions assert tx_a.spend_bundle is not None assert tx_b.spend_bundle is not None assert tx_c.spend_bundle is not None @@ -1665,11 +1659,11 @@ async def make_setup_and_coins( # Make sure DE and EF would aggregate on E when E is eligible for deduplication # Create a coin with the identity puzzle hash - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=False, merge_spends=False, sign=True) as action_scope: + await wallet.generate_signed_transaction( uint64(200), IDENTITY_PUZZLE_HASH, DEFAULT_TX_CONFIG, action_scope, coins={coins[3].coin} ) - [tx], _ = await wallet.wallet_state_manager.sign_transactions([tx]) + [tx] = action_scope.side_effects.transactions assert tx.spend_bundle is not None await send_to_mempool(full_node_api, tx.spend_bundle) await farm_a_block(full_node_api, wallet_node, ph) @@ -1691,8 +1685,8 @@ async def make_setup_and_coins( message = b"Identical spend aggregation test" e_announcement = AssertCoinAnnouncement(asserted_id=e_coin_id, asserted_msg=message) # Create transactions D and F that consume an announcement created by E - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx_d] = await wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=False, merge_spends=False, sign=True) as action_scope: + await wallet.generate_signed_transaction( uint64(100), ph, DEFAULT_TX_CONFIG, @@ -1701,7 +1695,7 @@ async def make_setup_and_coins( coins={coins[4].coin}, extra_conditions=(e_announcement,), ) - [tx_f] = await wallet.generate_signed_transaction( + await wallet.generate_signed_transaction( uint64(150), ph, DEFAULT_TX_CONFIG, @@ -1710,7 +1704,7 @@ async def make_setup_and_coins( coins={coins[5].coin}, extra_conditions=(e_announcement,), ) - [tx_d, tx_f], _ = await wallet.wallet_state_manager.sign_transactions([tx_d, tx_f]) + [tx_d, tx_f] = action_scope.side_effects.transactions assert tx_d.spend_bundle is not None assert tx_f.spend_bundle is not None # Create transaction E now that spends e_coin to create another eligible @@ -1736,11 +1730,11 @@ async def make_setup_and_coins( sb_e2 = spend_bundle_from_conditions(conditions, e_coin) g_coin = coins[6].coin g_coin_id = g_coin.name() - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx_g] = await wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=False, merge_spends=False, sign=True) as action_scope: + await wallet.generate_signed_transaction( uint64(13), ph, DEFAULT_TX_CONFIG, action_scope, coins={g_coin}, extra_conditions=(e_announcement,) ) - [tx_g], _ = await wallet.wallet_state_manager.sign_transactions([tx_g]) + [tx_g] = action_scope.side_effects.transactions assert tx_g.spend_bundle is not None sb_e2g = SpendBundle.aggregate([sb_e2, tx_g.spend_bundle]) sb_e2g_name = sb_e2g.name() diff --git a/chia/_tests/core/mempool/test_mempool_performance.py b/chia/_tests/core/mempool/test_mempool_performance.py index c446deebaabb..4531eae8b45d 100644 --- a/chia/_tests/core/mempool/test_mempool_performance.py +++ b/chia/_tests/core/mempool/test_mempool_performance.py @@ -46,11 +46,9 @@ async def test_mempool_update_performance( await time_out_assert(30, wallet_balance_at_least, True, wallet_node, send_amount + fee_amount) ph = await wallet.get_new_puzzlehash() - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [big_transaction] = await wallet.generate_signed_transaction( - send_amount, ph, DEFAULT_TX_CONFIG, action_scope, fee_amount - ) - [big_transaction], _ = await wallet.wallet_state_manager.sign_transactions([big_transaction]) + async with wallet.wallet_state_manager.new_action_scope(push=False, sign=True) as action_scope: + await wallet.generate_signed_transaction(send_amount, ph, DEFAULT_TX_CONFIG, action_scope, fee_amount) + [big_transaction] = action_scope.side_effects.transactions assert big_transaction.spend_bundle is not None status, err = await full_node.add_transaction( big_transaction.spend_bundle, big_transaction.spend_bundle.name(), test=True diff --git a/chia/_tests/pools/test_pool_rpc.py b/chia/_tests/pools/test_pool_rpc.py index 5d1499af931b..c5412f876315 100644 --- a/chia/_tests/pools/test_pool_rpc.py +++ b/chia/_tests/pools/test_pool_rpc.py @@ -533,8 +533,8 @@ async def test_absorb_self_multiple_coins( assert bal["confirmed_wallet_balance"] == pool_expected_confirmed_balance # Claim - absorb_tx: TransactionRecord = (await client.pw_absorb_rewards(2, uint64(fee), 1))["transaction"] - await full_node_api.process_transaction_records(records=[absorb_tx]) + absorb_txs: List[TransactionRecord] = (await client.pw_absorb_rewards(2, uint64(fee), 1))["transactions"] + await full_node_api.process_transaction_records(records=absorb_txs) main_expected_confirmed_balance -= fee main_expected_confirmed_balance += 1_750_000_000_000 pool_expected_confirmed_balance -= 1_750_000_000_000 @@ -602,13 +602,14 @@ async def farming_to_pool() -> bool: # Claim block_count * 1.75 ret = await client.pw_absorb_rewards(2, uint64(fee)) - absorb_tx: TransactionRecord = ret["transaction"] + absorb_txs: List[TransactionRecord] = ret["transactions"] if fee == 0: assert ret["fee_transaction"] is None else: assert ret["fee_transaction"].fee_amount == fee - assert absorb_tx.fee_amount == fee - await full_node_api.process_transaction_records(records=[absorb_tx]) + for tx in absorb_txs: + assert tx.fee_amount == fee + await full_node_api.process_transaction_records(records=absorb_txs) main_expected_confirmed_balance -= fee main_expected_confirmed_balance += block_count * 1_750_000_000_000 @@ -821,7 +822,7 @@ async def status_is_farming_to_pool() -> bool: leave_pool_tx: Dict[str, Any] = await client.pw_self_pool(wallet_id, uint64(fee)) assert leave_pool_tx["transaction"].wallet_id == wallet_id assert leave_pool_tx["transaction"].amount == 1 - await full_node_api.wait_transaction_records_entered_mempool(records=[leave_pool_tx["transaction"]]) + await full_node_api.wait_transaction_records_entered_mempool(records=leave_pool_tx["transactions"]) await full_node_api.farm_blocks_to_puzzlehash(count=1, farm_to=our_ph, guarantee_transaction_blocks=True) @@ -897,7 +898,6 @@ async def status_is_farming_to_pool() -> bool: assert pw_info.current.relative_lock_height == 5 await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node, timeout=20) - join_pool_tx: TransactionRecord = ( await client.pw_join_pool( wallet_id, @@ -964,7 +964,7 @@ async def status_is_farming_to_pool() -> bool: assert pw_info.current.pool_url == "https://pool-a.org" assert pw_info.current.relative_lock_height == 5 - join_pool_tx: TransactionRecord = ( + join_pool_txs: List[TransactionRecord] = ( await client.pw_join_pool( wallet_id, pool_b_ph, @@ -972,9 +972,8 @@ async def status_is_farming_to_pool() -> bool: uint32(10), uint64(fee), ) - )["transaction"] - assert join_pool_tx is not None - await full_node_api.wait_transaction_records_entered_mempool(records=[join_pool_tx]) + )["transactions"] + await full_node_api.wait_transaction_records_entered_mempool(records=join_pool_txs) await full_node_api.farm_blocks_to_puzzlehash(count=1, farm_to=our_ph, guarantee_transaction_blocks=True) async def status_is_leaving_no_blocks() -> bool: @@ -992,7 +991,7 @@ async def status_is_leaving_no_blocks() -> bool: force_overflow=True, guarantee_transaction_block=True, seed=32 * b"4", - transaction_data=join_pool_tx.spend_bundle, + transaction_data=next(tx.spend_bundle for tx in join_pool_txs if tx.spend_bundle is not None), ) for block in more_blocks[-3:]: diff --git a/chia/_tests/simulation/test_simulation.py b/chia/_tests/simulation/test_simulation.py index 161c7f9b0eff..acd3e4880639 100644 --- a/chia/_tests/simulation/test_simulation.py +++ b/chia/_tests/simulation/test_simulation.py @@ -212,15 +212,15 @@ async def test_simulator_auto_farm_and_get_coins( await time_out_assert(10, wallet.get_confirmed_balance, funds) await time_out_assert(5, wallet.get_unconfirmed_balance, funds) - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.generate_signed_transaction( uint64(10), await wallet_node_2.wallet_state_manager.main_wallet.get_new_puzzlehash(), DEFAULT_TX_CONFIG, action_scope, uint64(0), ) - [tx] = await wallet.wallet_state_manager.add_pending_transactions([tx]) + [tx] = await wallet.wallet_state_manager.add_pending_transactions(action_scope.side_effects.transactions) # wait till out of mempool await time_out_assert(10, full_node_api.full_node.mempool_manager.get_spendbundle, None, tx.name) # wait until the transaction is confirmed @@ -389,17 +389,17 @@ async def test_wait_transaction_records_entered_mempool( # repeating just to try to expose any flakiness for coin in coins: - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.generate_signed_transaction( amount=uint64(tx_amount), puzzle_hash=await wallet_node.wallet_state_manager.main_wallet.get_new_puzzlehash(), tx_config=DEFAULT_TX_CONFIG, action_scope=action_scope, coins={coin}, ) - [tx] = await wallet.wallet_state_manager.add_pending_transactions([tx]) - await full_node_api.wait_transaction_records_entered_mempool(records=[tx]) + [tx] = action_scope.side_effects.transactions + await full_node_api.wait_transaction_records_entered_mempool(records=action_scope.side_effects.transactions) assert tx.spend_bundle is not None assert full_node_api.full_node.mempool_manager.get_spendbundle(tx.spend_bundle.name()) is not None # TODO: this fails but it seems like it shouldn't when above passes @@ -436,23 +436,20 @@ async def test_process_transactions( # repeating just to try to expose any flakiness for repeat in range(repeats): coins = [next(coins_iter) for _ in range(tx_per_repeat)] - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - transactions = [ - ( - await wallet.generate_signed_transaction( - amount=uint64(tx_amount), - puzzle_hash=await wallet_node.wallet_state_manager.main_wallet.get_new_puzzlehash(), - tx_config=DEFAULT_TX_CONFIG, - action_scope=action_scope, - coins={coin}, - ) - )[0] - for coin in coins - ] - for tx in transactions: + async with wallet.wallet_state_manager.new_action_scope(push=True, merge_spends=False) as action_scope: + for coin in coins: + await wallet.generate_signed_transaction( + amount=uint64(tx_amount), + puzzle_hash=await wallet_node.wallet_state_manager.main_wallet.get_new_puzzlehash(), + tx_config=DEFAULT_TX_CONFIG, + action_scope=action_scope, + coins={coin}, + ) + + for tx in action_scope.side_effects.transactions: assert tx.spend_bundle is not None, "the above created transaction is missing the expected spend bundle" - transactions = await wallet.wallet_state_manager.add_pending_transactions(transactions) + transactions = action_scope.side_effects.transactions if records_or_bundles_or_coins == "records": await full_node_api.process_transaction_records(records=transactions) diff --git a/chia/_tests/simulation/test_simulator.py b/chia/_tests/simulation/test_simulator.py index f485f87f5e51..4a60ea7c96f6 100644 --- a/chia/_tests/simulation/test_simulator.py +++ b/chia/_tests/simulation/test_simulator.py @@ -127,17 +127,17 @@ async def test_wait_transaction_records_entered_mempool( # repeating just to try to expose any flakiness for coin in coins: - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.generate_signed_transaction( amount=uint64(tx_amount), puzzle_hash=await wallet_node.wallet_state_manager.main_wallet.get_new_puzzlehash(), tx_config=DEFAULT_TX_CONFIG, action_scope=action_scope, coins={coin}, ) - [tx] = await wallet.wallet_state_manager.add_pending_transactions([tx]) - await full_node_api.wait_transaction_records_entered_mempool(records=[tx]) + [tx] = action_scope.side_effects.transactions + await full_node_api.wait_transaction_records_entered_mempool(records=action_scope.side_effects.transactions) assert tx.spend_bundle is not None assert full_node_api.full_node.mempool_manager.get_spendbundle(tx.spend_bundle.name()) is not None @@ -164,17 +164,16 @@ async def test_process_transaction_records( # repeating just to try to expose any flakiness for coin in coins: - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.generate_signed_transaction( amount=uint64(tx_amount), puzzle_hash=await wallet_node.wallet_state_manager.main_wallet.get_new_puzzlehash(), tx_config=DEFAULT_TX_CONFIG, action_scope=action_scope, coins={coin}, ) - [tx] = await wallet.wallet_state_manager.add_pending_transactions([tx]) - await full_node_api.process_transaction_records(records=[tx]) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) assert full_node_api.full_node.coin_store.get_coin_record(coin.name()) is not None diff --git a/chia/_tests/wallet/cat_wallet/test_cat_wallet.py b/chia/_tests/wallet/cat_wallet/test_cat_wallet.py index 87010d283936..babc91214665 100644 --- a/chia/_tests/wallet/cat_wallet/test_cat_wallet.py +++ b/chia/_tests/wallet/cat_wallet/test_cat_wallet.py @@ -71,8 +71,8 @@ async def test_cat_creation(self_hostname: str, two_wallet_nodes: OldSimulatorsA await time_out_assert(20, wallet.get_confirmed_balance, funds) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node, timeout=20) - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_wallet, tx_records = await CATWallet.create_new_cat_wallet( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + cat_wallet = await CATWallet.create_new_cat_wallet( wallet_node.wallet_state_manager, wallet, {"identifier": "genesis_by_id"}, @@ -85,7 +85,7 @@ async def test_cat_creation(self_hostname: str, two_wallet_nodes: OldSimulatorsA cat_wallet = await CATWallet.create(wallet_node.wallet_state_manager, wallet, cat_wallet.wallet_info) await wallet_node.wallet_state_manager.add_new_wallet(cat_wallet) - await full_node_api.process_transaction_records(records=tx_records) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(20, cat_wallet.get_confirmed_balance, 100) await time_out_assert(20, cat_wallet.get_spendable_balance, 100) @@ -139,8 +139,8 @@ async def test_cat_creation_unique_lineage_store(self_hostname: str, two_wallet_ await time_out_assert(20, wallet.get_confirmed_balance, funds) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node, timeout=20) - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_wallet_1, _ = await CATWallet.create_new_cat_wallet( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + cat_wallet_1 = await CATWallet.create_new_cat_wallet( wallet_node.wallet_state_manager, wallet, {"identifier": "genesis_by_id"}, @@ -148,7 +148,8 @@ async def test_cat_creation_unique_lineage_store(self_hostname: str, two_wallet_ DEFAULT_TX_CONFIG, action_scope, ) - cat_wallet_2, _ = await CATWallet.create_new_cat_wallet( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + cat_wallet_2 = await CATWallet.create_new_cat_wallet( wallet_node.wallet_state_manager, wallet, {"identifier": "genesis_by_id"}, @@ -197,8 +198,8 @@ async def test_cat_spend(wallet_environments: WalletTestFramework) -> None: "cat": 2, } - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_wallet, tx_records = await CATWallet.create_new_cat_wallet( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + cat_wallet = await CATWallet.create_new_cat_wallet( wallet_node.wallet_state_manager, wallet, {"identifier": "genesis_by_id"}, @@ -261,16 +262,16 @@ async def test_cat_spend(wallet_environments: WalletTestFramework) -> None: assert cat_wallet.cat_info.limitations_program_hash == cat_wallet_2.cat_info.limitations_program_hash cat_2_hash = await cat_wallet_2.get_new_inner_hash() - async with cat_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - tx_records = await cat_wallet.generate_signed_transaction( + async with cat_wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await cat_wallet.generate_signed_transaction( [uint64(60)], [cat_2_hash], DEFAULT_TX_CONFIG, action_scope, fee=uint64(1) ) tx_id = None - tx_records = await wallet.wallet_state_manager.add_pending_transactions(tx_records) - for tx_record in tx_records: - if tx_record.wallet_id is cat_wallet.id(): - tx_id = tx_record.name.hex() + for tx_record in action_scope.side_effects.transactions: + if tx_record.wallet_id == cat_wallet.id(): assert tx_record.to_puzzle_hash == cat_2_hash + if tx_record.spend_bundle is not None: + tx_id = tx_record.name.hex() assert tx_id is not None memos = await api_0.get_transaction_memo({"transaction_id": tx_id}) assert len(memos[tx_id]) == 2 # One for tx, one for change @@ -353,11 +354,8 @@ async def test_cat_spend(wallet_environments: WalletTestFramework) -> None: assert len(memos[tx_id]) == 2 assert list(memos[tx_id].values())[0][0] == cat_2_hash.hex() cat_hash = await cat_wallet.get_new_inner_hash() - async with cat_wallet_2.wallet_state_manager.new_action_scope(push=False) as action_scope: - tx_records = await cat_wallet_2.generate_signed_transaction( - [uint64(15)], [cat_hash], DEFAULT_TX_CONFIG, action_scope - ) - tx_records = await wallet2.wallet_state_manager.add_pending_transactions(tx_records) + async with cat_wallet_2.wallet_state_manager.new_action_scope(push=True) as action_scope: + await cat_wallet_2.generate_signed_transaction([uint64(15)], [cat_hash], DEFAULT_TX_CONFIG, action_scope) await wallet_environments.process_pending_states( [ @@ -454,8 +452,8 @@ async def test_cat_reuse_address(self_hostname: str, two_wallet_nodes: OldSimula await time_out_assert(20, wallet.get_confirmed_balance, funds) - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_wallet, tx_records = await CATWallet.create_new_cat_wallet( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + cat_wallet = await CATWallet.create_new_cat_wallet( wallet_node.wallet_state_manager, wallet, {"identifier": "genesis_by_id"}, @@ -463,7 +461,7 @@ async def test_cat_reuse_address(self_hostname: str, two_wallet_nodes: OldSimula DEFAULT_TX_CONFIG, action_scope, ) - await full_node_api.process_transaction_records(records=tx_records) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(20, cat_wallet.get_confirmed_balance, 100) await time_out_assert(20, cat_wallet.get_unconfirmed_balance, 100) @@ -476,12 +474,12 @@ async def test_cat_reuse_address(self_hostname: str, two_wallet_nodes: OldSimula assert cat_wallet.cat_info.limitations_program_hash == cat_wallet_2.cat_info.limitations_program_hash cat_2_hash = await cat_wallet_2.get_new_inner_hash() - async with cat_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - tx_records = await cat_wallet.generate_signed_transaction( + async with cat_wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await cat_wallet.generate_signed_transaction( [uint64(60)], [cat_2_hash], DEFAULT_TX_CONFIG.override(reuse_puzhash=True), action_scope, fee=uint64(1) ) - tx_records = await wallet.wallet_state_manager.add_pending_transactions(tx_records) - for tx_record in tx_records: + + for tx_record in action_scope.side_effects.transactions: if tx_record.wallet_id is cat_wallet.id(): assert tx_record.to_puzzle_hash == cat_2_hash assert tx_record.spend_bundle is not None @@ -494,7 +492,7 @@ async def test_cat_reuse_address(self_hostname: str, two_wallet_nodes: OldSimula new_puzhash = [c.puzzle_hash.hex() for c in tx_record.additions] assert old_puzhash in new_puzhash - await time_out_assert(15, full_node_api.txs_in_mempool, True, tx_records) + await time_out_assert(15, full_node_api.txs_in_mempool, True, action_scope.side_effects.transactions) await time_out_assert(20, cat_wallet.get_pending_change_balance, 40) @@ -510,13 +508,10 @@ async def test_cat_reuse_address(self_hostname: str, two_wallet_nodes: OldSimula await time_out_assert(30, cat_wallet_2.get_unconfirmed_balance, 60) cat_hash = await cat_wallet.get_new_inner_hash() - async with cat_wallet_2.wallet_state_manager.new_action_scope(push=False) as action_scope: - tx_records = await cat_wallet_2.generate_signed_transaction( - [uint64(15)], [cat_hash], DEFAULT_TX_CONFIG, action_scope - ) - tx_records = await cat_wallet_2.wallet_state_manager.add_pending_transactions(tx_records) + async with cat_wallet_2.wallet_state_manager.new_action_scope(push=True) as action_scope: + await cat_wallet_2.generate_signed_transaction([uint64(15)], [cat_hash], DEFAULT_TX_CONFIG, action_scope) - await time_out_assert(15, full_node_api.txs_in_mempool, True, tx_records) + await time_out_assert(15, full_node_api.txs_in_mempool, True, action_scope.side_effects.transactions) await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) @@ -560,8 +555,8 @@ async def test_get_wallet_for_asset_id( await time_out_assert(20, wallet.get_confirmed_balance, funds) - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_wallet, _ = await CATWallet.create_new_cat_wallet( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + cat_wallet = await CATWallet.create_new_cat_wallet( wallet_node.wallet_state_manager, wallet, {"identifier": "genesis_by_id"}, @@ -619,8 +614,8 @@ async def test_cat_doesnt_see_eve(self_hostname: str, two_wallet_nodes: OldSimul await time_out_assert(20, wallet.get_confirmed_balance, funds) - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_wallet, tx_records = await CATWallet.create_new_cat_wallet( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + cat_wallet = await CATWallet.create_new_cat_wallet( wallet_node.wallet_state_manager, wallet, {"identifier": "genesis_by_id"}, @@ -628,7 +623,7 @@ async def test_cat_doesnt_see_eve(self_hostname: str, two_wallet_nodes: OldSimul DEFAULT_TX_CONFIG, action_scope, ) - await full_node_api.process_transaction_records(records=tx_records) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(20, cat_wallet.get_confirmed_balance, 100) await time_out_assert(20, cat_wallet.get_unconfirmed_balance, 100) @@ -641,12 +636,11 @@ async def test_cat_doesnt_see_eve(self_hostname: str, two_wallet_nodes: OldSimul assert cat_wallet.cat_info.limitations_program_hash == cat_wallet_2.cat_info.limitations_program_hash cat_2_hash = await cat_wallet_2.get_new_inner_hash() - async with cat_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - tx_records = await cat_wallet.generate_signed_transaction( + async with cat_wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await cat_wallet.generate_signed_transaction( [uint64(60)], [cat_2_hash], DEFAULT_TX_CONFIG, action_scope, fee=uint64(1) ) - tx_records = await wallet.wallet_state_manager.add_pending_transactions(tx_records) - await full_node_api.process_transaction_records(records=tx_records) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(30, wallet.get_confirmed_balance, funds - 101) await time_out_assert(30, wallet.get_unconfirmed_balance, funds - 101) @@ -658,12 +652,11 @@ async def test_cat_doesnt_see_eve(self_hostname: str, two_wallet_nodes: OldSimul await time_out_assert(20, cat_wallet_2.get_unconfirmed_balance, 60) cc2_ph = await cat_wallet_2.get_new_cat_puzzle_hash() - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx_record] = await wallet.wallet_state_manager.main_wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.wallet_state_manager.main_wallet.generate_signed_transaction( uint64(10), cc2_ph, DEFAULT_TX_CONFIG, action_scope ) - [tx_record] = await wallet.wallet_state_manager.add_pending_transactions([tx_record]) - await full_node_api.process_transaction_records(records=[tx_record]) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) id = cat_wallet_2.id() wsm = cat_wallet_2.wallet_state_manager @@ -716,8 +709,8 @@ async def test_cat_spend_multiple( await time_out_assert(20, wallet_0.get_confirmed_balance, funds) - async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_wallet_0, tx_records = await CATWallet.create_new_cat_wallet( + async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + cat_wallet_0 = await CATWallet.create_new_cat_wallet( wallet_node_0.wallet_state_manager, wallet_0, {"identifier": "genesis_by_id"}, @@ -725,7 +718,7 @@ async def test_cat_spend_multiple( DEFAULT_TX_CONFIG, action_scope, ) - await full_node_api.process_transaction_records(records=tx_records) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(20, cat_wallet_0.get_confirmed_balance, 100) await time_out_assert(20, cat_wallet_0.get_unconfirmed_balance, 100) @@ -743,12 +736,11 @@ async def test_cat_spend_multiple( cat_1_hash = await cat_wallet_1.get_new_inner_hash() cat_2_hash = await cat_wallet_2.get_new_inner_hash() - async with cat_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - tx_records = await cat_wallet_0.generate_signed_transaction( + async with cat_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await cat_wallet_0.generate_signed_transaction( [uint64(60), uint64(20)], [cat_1_hash, cat_2_hash], DEFAULT_TX_CONFIG, action_scope ) - tx_records = await wallet_0.wallet_state_manager.add_pending_transactions(tx_records) - await full_node_api.process_transaction_records(records=tx_records) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(20, cat_wallet_0.get_confirmed_balance, 20) await time_out_assert(20, cat_wallet_0.get_unconfirmed_balance, 20) @@ -761,19 +753,15 @@ async def test_cat_spend_multiple( cat_hash = await cat_wallet_0.get_new_inner_hash() - async with cat_wallet_1.wallet_state_manager.new_action_scope(push=False) as action_scope: - tx_records = await cat_wallet_1.generate_signed_transaction( - [uint64(15)], [cat_hash], DEFAULT_TX_CONFIG, action_scope - ) - tx_records = await wallet_1.wallet_state_manager.add_pending_transactions(tx_records) + async with cat_wallet_1.wallet_state_manager.new_action_scope(push=True) as action_scope: + await cat_wallet_1.generate_signed_transaction([uint64(15)], [cat_hash], DEFAULT_TX_CONFIG, action_scope) - async with cat_wallet_2.wallet_state_manager.new_action_scope(push=False) as action_scope: - tx_records_2 = await cat_wallet_2.generate_signed_transaction( - [uint64(20)], [cat_hash], DEFAULT_TX_CONFIG, action_scope - ) - tx_records_2 = await wallet_2.wallet_state_manager.add_pending_transactions(tx_records_2) + async with cat_wallet_2.wallet_state_manager.new_action_scope(push=True) as action_scope_2: + await cat_wallet_2.generate_signed_transaction([uint64(20)], [cat_hash], DEFAULT_TX_CONFIG, action_scope_2) - await full_node_api.process_transaction_records(records=[*tx_records, *tx_records_2]) + await full_node_api.process_transaction_records( + records=[*action_scope.side_effects.transactions, *action_scope_2.side_effects.transactions] + ) await time_out_assert(20, cat_wallet_0.get_confirmed_balance, 55) await time_out_assert(20, cat_wallet_0.get_unconfirmed_balance, 55) @@ -786,18 +774,21 @@ async def test_cat_spend_multiple( txs = await wallet_1.wallet_state_manager.tx_store.get_transactions_between(cat_wallet_1.id(), 0, 100000) # Test with Memo - async with cat_wallet_1.wallet_state_manager.new_action_scope(push=False) as action_scope: - tx_records_3 = await cat_wallet_1.generate_signed_transaction( + async with cat_wallet_1.wallet_state_manager.new_action_scope(push=True) as action_scope: + await cat_wallet_1.generate_signed_transaction( [uint64(30)], [cat_hash], DEFAULT_TX_CONFIG, action_scope, memos=[[b"Markus Walburg"]] ) with pytest.raises(ValueError): - async with cat_wallet_1.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with cat_wallet_1.wallet_state_manager.new_action_scope(push=False) as failed_action_scope: await cat_wallet_1.generate_signed_transaction( - [uint64(30)], [cat_hash], DEFAULT_TX_CONFIG, action_scope, memos=[[b"too"], [b"many"], [b"memos"]] + [uint64(30)], + [cat_hash], + DEFAULT_TX_CONFIG, + failed_action_scope, + memos=[[b"too"], [b"many"], [b"memos"]], ) - tx_records_3 = await wallet_1.wallet_state_manager.add_pending_transactions(tx_records_3) - await time_out_assert(15, full_node_api.txs_in_mempool, True, tx_records_3) + await time_out_assert(15, full_node_api.txs_in_mempool, True, action_scope.side_effects.transactions) txs = await wallet_1.wallet_state_manager.tx_store.get_transactions_between(cat_wallet_1.id(), 0, 100000) for tx in txs: if tx.amount == 30: @@ -841,8 +832,8 @@ async def test_cat_max_amount_send( await time_out_assert(20, wallet.get_confirmed_balance, funds) - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_wallet, tx_records = await CATWallet.create_new_cat_wallet( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + cat_wallet = await CATWallet.create_new_cat_wallet( wallet_node.wallet_state_manager, wallet, {"identifier": "genesis_by_id"}, @@ -850,7 +841,7 @@ async def test_cat_max_amount_send( DEFAULT_TX_CONFIG, action_scope, ) - await full_node_api.process_transaction_records(records=tx_records) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(20, cat_wallet.get_confirmed_balance, 100000) await time_out_assert(20, cat_wallet.get_unconfirmed_balance, 100000) @@ -865,12 +856,11 @@ async def test_cat_max_amount_send( amounts.append(uint64(i)) puzzle_hashes.append(cat_2_hash) spent_coint = (await cat_wallet.get_cat_spendable_coins())[0].coin - async with cat_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - tx_records = await cat_wallet.generate_signed_transaction( + async with cat_wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await cat_wallet.generate_signed_transaction( amounts, puzzle_hashes, DEFAULT_TX_CONFIG, action_scope, coins={spent_coint} ) - tx_records = await wallet.wallet_state_manager.add_pending_transactions(tx_records) - await full_node_api.process_transaction_records(records=tx_records) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await asyncio.sleep(2) @@ -892,17 +882,15 @@ async def check_all_there() -> bool: # 1) Generate transaction that is under the limit async with cat_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [transaction_record] = await cat_wallet.generate_signed_transaction( + await cat_wallet.generate_signed_transaction( [uint64(max_sent_amount - 1)], [ph], DEFAULT_TX_CONFIG, action_scope ) - assert transaction_record.amount == uint64(max_sent_amount - 1) + assert action_scope.side_effects.transactions[0].amount == uint64(max_sent_amount - 1) # 2) Generate transaction that is equal to limit async with cat_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [transaction_record] = await cat_wallet.generate_signed_transaction( - [uint64(max_sent_amount)], [ph], DEFAULT_TX_CONFIG, action_scope - ) - assert transaction_record.amount == uint64(max_sent_amount) + await cat_wallet.generate_signed_transaction([uint64(max_sent_amount)], [ph], DEFAULT_TX_CONFIG, action_scope) + assert action_scope.side_effects.transactions[0].amount == uint64(max_sent_amount) # 3) Generate transaction that is greater than limit with pytest.raises(ValueError): @@ -949,8 +937,8 @@ async def test_cat_hint( await time_out_assert(20, wallet.get_confirmed_balance, funds) - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_wallet, tx_records = await CATWallet.create_new_cat_wallet( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + cat_wallet = await CATWallet.create_new_cat_wallet( wallet_node.wallet_state_manager, wallet, {"identifier": "genesis_by_id"}, @@ -958,21 +946,19 @@ async def test_cat_hint( DEFAULT_TX_CONFIG, action_scope, ) - await full_node_api.process_transaction_records(records=tx_records) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(20, cat_wallet.get_confirmed_balance, 100) await time_out_assert(20, cat_wallet.get_unconfirmed_balance, 100) assert cat_wallet.cat_info.limitations_program_hash is not None cat_2_hash = await wallet2.get_new_puzzlehash() - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - tx_records = await cat_wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await cat_wallet.generate_signed_transaction( [uint64(60)], [cat_2_hash], DEFAULT_TX_CONFIG, action_scope, memos=[[cat_2_hash]] ) - tx_records = await wallet.wallet_state_manager.add_pending_transactions(tx_records) - - await full_node_api.process_transaction_records(records=tx_records) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(20, cat_wallet.get_confirmed_balance, 40) await time_out_assert(20, cat_wallet.get_unconfirmed_balance, 40) @@ -994,14 +980,12 @@ async def test_cat_hint( } # Then we send another transaction - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - tx_records = await cat_wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await cat_wallet.generate_signed_transaction( [uint64(10)], [cat_2_hash], DEFAULT_TX_CONFIG, action_scope, memos=[[cat_2_hash]] ) - tx_records = await wallet.wallet_state_manager.add_pending_transactions(tx_records) - - await full_node_api.process_transaction_records(records=tx_records) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(20, cat_wallet.get_confirmed_balance, 30) await time_out_assert(20, cat_wallet.get_unconfirmed_balance, 30) @@ -1016,13 +1000,10 @@ async def test_cat_hint( await time_out_assert(30, cat_wallet_2.get_unconfirmed_balance, 70) cat_hash = await cat_wallet.get_new_inner_hash() - async with cat_wallet_2.wallet_state_manager.new_action_scope(push=False) as action_scope: - tx_records = await cat_wallet_2.generate_signed_transaction( - [uint64(5)], [cat_hash], DEFAULT_TX_CONFIG, action_scope - ) - tx_records = await cat_wallet_2.wallet_state_manager.add_pending_transactions(tx_records) + async with cat_wallet_2.wallet_state_manager.new_action_scope(push=True) as action_scope: + await cat_wallet_2.generate_signed_transaction([uint64(5)], [cat_hash], DEFAULT_TX_CONFIG, action_scope) - await full_node_api.process_transaction_records(records=tx_records) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(20, cat_wallet.get_confirmed_balance, 35) await time_out_assert(20, cat_wallet.get_unconfirmed_balance, 35) diff --git a/chia/_tests/wallet/cat_wallet/test_trades.py b/chia/_tests/wallet/cat_wallet/test_trades.py index ebeec0036e35..dbb65e92b913 100644 --- a/chia/_tests/wallet/cat_wallet/test_trades.py +++ b/chia/_tests/wallet/cat_wallet/test_trades.py @@ -140,7 +140,7 @@ async def test_cat_trades( } # Mint some DIDs - async with wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet_maker: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_maker.wallet_state_manager, wallet_maker, @@ -148,7 +148,7 @@ async def test_cat_trades( wallet_environments.tx_config, action_scope, ) - async with wallet_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_taker.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet_taker: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_taker.wallet_state_manager, wallet_taker, @@ -323,8 +323,8 @@ async def test_cat_trades( } # Mint some standard CATs - async with wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_wallet_maker, _ = await CATWallet.create_new_cat_wallet( + async with wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + cat_wallet_maker = await CATWallet.create_new_cat_wallet( wallet_node_maker.wallet_state_manager, wallet_maker, {"identifier": "genesis_by_id"}, @@ -333,8 +333,8 @@ async def test_cat_trades( action_scope, ) - async with wallet_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - new_cat_wallet_taker, _ = await CATWallet.create_new_cat_wallet( + async with wallet_taker.wallet_state_manager.new_action_scope(push=True) as action_scope: + new_cat_wallet_taker = await CATWallet.create_new_cat_wallet( wallet_node_taker.wallet_state_manager, wallet_taker, {"identifier": "genesis_by_id"}, @@ -475,7 +475,7 @@ async def test_cat_trades( # Execute all of the trades # chia_for_cat async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make, error = await trade_manager_maker.create_offer_for_ids( chia_for_cat, wallet_environments.tx_config, action_scope, fee=uint64(1) ) assert error is None @@ -486,19 +486,16 @@ async def test_cat_trades( [maker_offer], signing_response = await wallet_node_maker.wallet_state_manager.sign_offers( [Offer.from_bytes(trade_make.offer)] ) - async with trade_manager_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - trade_take, tx_records = await trade_manager_taker.respond_to_offer( - Offer.from_bytes(trade_make.offer), + async with trade_manager_taker.wallet_state_manager.new_action_scope( + push=True, additional_signing_responses=signing_response + ) as action_scope: + trade_take = await trade_manager_taker.respond_to_offer( + maker_offer, peer, wallet_environments.tx_config, action_scope, fee=uint64(1), ) - tx_records = await wallet_taker.wallet_state_manager.add_pending_transactions( - tx_records, additional_signing_responses=signing_response - ) - assert trade_take is not None - assert tx_records is not None if test_aggregation: first_offer = Offer.from_bytes(trade_take.offer) @@ -698,7 +695,7 @@ async def assert_trade_tx_number(wallet_node: WalletNode, trade_id: bytes32, num # cat_for_chia async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make, error = await trade_manager_maker.create_offer_for_ids( cat_for_chia, wallet_environments.tx_config, action_scope ) assert error is None @@ -708,22 +705,19 @@ async def assert_trade_tx_number(wallet_node: WalletNode, trade_id: bytes32, num [maker_offer], signing_response = await wallet_node_maker.wallet_state_manager.sign_offers( [Offer.from_bytes(trade_make.offer)] ) - async with trade_manager_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - trade_take, tx_records = await trade_manager_taker.respond_to_offer( + async with trade_manager_taker.wallet_state_manager.new_action_scope( + push=True, additional_signing_responses=signing_response + ) as action_scope: + trade_take = await trade_manager_taker.respond_to_offer( Offer.from_bytes(trade_make.offer), peer, wallet_environments.tx_config, action_scope, fee=uint64(1), ) - tx_records = await wallet_taker.wallet_state_manager.add_pending_transactions( - tx_records, additional_signing_responses=signing_response - ) - assert trade_take is not None - assert tx_records is not None # Testing a precious display bug real quick - xch_tx: TransactionRecord = next(tx for tx in tx_records if tx.wallet_id == 1) + xch_tx: TransactionRecord = next(tx for tx in action_scope.side_effects.transactions if tx.wallet_id == 1) assert xch_tx.amount == 3 assert xch_tx.fee_amount == 1 @@ -832,7 +826,7 @@ async def assert_trade_tx_number(wallet_node: WalletNode, trade_id: bytes32, num assert taker_unused_dr is not None taker_unused_index = taker_unused_dr.index async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make, error = await trade_manager_maker.create_offer_for_ids( cat_for_cat, wallet_environments.tx_config, action_scope ) assert error is None @@ -841,19 +835,15 @@ async def assert_trade_tx_number(wallet_node: WalletNode, trade_id: bytes32, num [maker_offer], signing_response = await wallet_node_maker.wallet_state_manager.sign_offers( [Offer.from_bytes(trade_make.offer)] ) - async with trade_manager_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - trade_take, tx_records = await trade_manager_taker.respond_to_offer( + async with trade_manager_taker.wallet_state_manager.new_action_scope( + push=True, additional_signing_responses=signing_response + ) as action_scope: + trade_take = await trade_manager_taker.respond_to_offer( Offer.from_bytes(trade_make.offer), peer, wallet_environments.tx_config, action_scope, ) - tx_records = await wallet_taker.wallet_state_manager.add_pending_transactions( - tx_records, additional_signing_responses=signing_response - ) - await time_out_assert(15, full_node.txs_in_mempool, True, tx_records) - assert trade_take is not None - assert tx_records is not None if test_aggregation: second_offer = Offer.from_bytes(trade_take.offer) @@ -914,8 +904,8 @@ async def assert_trade_tx_number(wallet_node: WalletNode, trade_id: bytes32, num }, "new cat": { "unconfirmed_wallet_balance": -6, - "<=#spendable_balance": -6, "pending_change": 92, + "<=#spendable_balance": -6, "<=#max_send_amount": -6, "pending_coin_removal_count": 1, }, @@ -1034,7 +1024,7 @@ async def assert_trade_tx_number(wallet_node: WalletNode, trade_id: bytes32, num # chia_for_multiple_cat async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make, error = await trade_manager_maker.create_offer_for_ids( chia_for_multiple_cat, wallet_environments.tx_config, action_scope, @@ -1047,19 +1037,15 @@ async def assert_trade_tx_number(wallet_node: WalletNode, trade_id: bytes32, num [maker_offer], signing_response = await wallet_node_maker.wallet_state_manager.sign_offers( [Offer.from_bytes(trade_make.offer)] ) - async with trade_manager_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - trade_take, tx_records = await trade_manager_taker.respond_to_offer( + async with trade_manager_taker.wallet_state_manager.new_action_scope( + push=True, additional_signing_responses=signing_response + ) as action_scope: + trade_take = await trade_manager_taker.respond_to_offer( Offer.from_bytes(trade_make.offer), peer, wallet_environments.tx_config, action_scope, ) - tx_records = await wallet_taker.wallet_state_manager.add_pending_transactions( - tx_records, additional_signing_responses=signing_response - ) - await time_out_assert(15, full_node.txs_in_mempool, True, tx_records) - assert trade_take is not None - assert tx_records is not None if test_aggregation: third_offer = Offer.from_bytes(trade_take.offer) @@ -1141,16 +1127,16 @@ async def assert_trade_tx_number(wallet_node: WalletNode, trade_id: bytes32, num }, "cat": { "unconfirmed_wallet_balance": -8, + "pending_change": 1, "<=#spendable_balance": -8, "<=#max_send_amount": -8, - "pending_change": 1, "pending_coin_removal_count": 2, # For the first time, we're using two coins in an offer }, "new cat": { "unconfirmed_wallet_balance": -9, + "pending_change": 83, "<=#spendable_balance": -9, "<=#max_send_amount": -9, - "pending_change": 83, "pending_coin_removal_count": 1, }, **( @@ -1172,17 +1158,17 @@ async def assert_trade_tx_number(wallet_node: WalletNode, trade_id: bytes32, num }, "cat": { "confirmed_wallet_balance": -8, + "pending_change": -1, ">#spendable_balance": 0, ">#max_send_amount": 0, - "pending_change": -1, "pending_coin_removal_count": -2, "unspent_coin_count": -1, }, "new cat": { "confirmed_wallet_balance": -9, + "pending_change": -83, ">#spendable_balance": 0, ">#max_send_amount": 0, - "pending_change": -83, "pending_coin_removal_count": -1, }, **( @@ -1299,7 +1285,7 @@ async def assert_trade_tx_number(wallet_node: WalletNode, trade_id: bytes32, num # multiple_cat_for_chia async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make, error = await trade_manager_maker.create_offer_for_ids( multiple_cat_for_chia, wallet_environments.tx_config, action_scope, @@ -1310,19 +1296,15 @@ async def assert_trade_tx_number(wallet_node: WalletNode, trade_id: bytes32, num [maker_offer], signing_response = await wallet_node_maker.wallet_state_manager.sign_offers( [Offer.from_bytes(trade_make.offer)] ) - async with trade_manager_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - trade_take, tx_records = await trade_manager_taker.respond_to_offer( + async with trade_manager_taker.wallet_state_manager.new_action_scope( + push=True, additional_signing_responses=signing_response + ) as action_scope: + trade_take = await trade_manager_taker.respond_to_offer( Offer.from_bytes(trade_make.offer), peer, wallet_environments.tx_config, action_scope, ) - tx_records = await wallet_taker.wallet_state_manager.add_pending_transactions( - tx_records, additional_signing_responses=signing_response - ) - await time_out_assert(15, full_node.txs_in_mempool, True, tx_records) - assert trade_take is not None - assert tx_records is not None if test_aggregation: fourth_offer = Offer.from_bytes(trade_take.offer) @@ -1435,7 +1417,7 @@ async def assert_trade_tx_number(wallet_node: WalletNode, trade_id: bytes32, num # chia_and_cat_for_cat async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make, error = await trade_manager_maker.create_offer_for_ids( chia_and_cat_for_cat, wallet_environments.tx_config, action_scope, @@ -1447,19 +1429,15 @@ async def assert_trade_tx_number(wallet_node: WalletNode, trade_id: bytes32, num [maker_offer], signing_response = await wallet_node_maker.wallet_state_manager.sign_offers( [Offer.from_bytes(trade_make.offer)] ) - async with trade_manager_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - trade_take, tx_records = await trade_manager_taker.respond_to_offer( + async with trade_manager_taker.wallet_state_manager.new_action_scope( + push=True, additional_signing_responses=signing_response + ) as action_scope: + trade_take = await trade_manager_taker.respond_to_offer( Offer.from_bytes(trade_make.offer), peer, wallet_environments.tx_config, action_scope, ) - tx_records = await wallet_taker.wallet_state_manager.add_pending_transactions( - tx_records, additional_signing_responses=signing_response - ) - await time_out_assert(15, full_node.txs_in_mempool, True, tx_records) - assert trade_take is not None - assert tx_records is not None if test_aggregation: fifth_offer = Offer.from_bytes(trade_take.offer) @@ -1528,9 +1506,9 @@ async def assert_trade_tx_number(wallet_node: WalletNode, trade_id: bytes32, num }, "new cat": { "unconfirmed_wallet_balance": -15, + "pending_change": 68, "<=#spendable_balance": -15, "<=#max_send_amount": -15, - "pending_change": 68, "pending_coin_removal_count": 1, }, **( @@ -1558,9 +1536,9 @@ async def assert_trade_tx_number(wallet_node: WalletNode, trade_id: bytes32, num }, "new cat": { "confirmed_wallet_balance": -15, + "pending_change": -68, ">#spendable_balance": 0, ">#max_send_amount": 0, - "pending_change": -68, "pending_coin_removal_count": -1, }, **( @@ -1650,8 +1628,8 @@ async def test_trade_cancellation( xch_to_cat_amount = uint64(100) - async with wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_wallet_maker, tx_records = await CATWallet.create_new_cat_wallet( + async with wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + cat_wallet_maker = await CATWallet.create_new_cat_wallet( wallet_node_maker.wallet_state_manager, wallet_maker, {"identifier": "genesis_by_id"}, @@ -1660,7 +1638,7 @@ async def test_trade_cancellation( action_scope, ) - await full_node.process_transaction_records(records=tx_records) + await full_node.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(15, cat_wallet_maker.get_confirmed_balance, xch_to_cat_amount) await time_out_assert(15, cat_wallet_maker.get_unconfirmed_balance, xch_to_cat_amount) @@ -1681,7 +1659,7 @@ async def test_trade_cancellation( trade_manager_taker = wallet_node_taker.wallet_state_manager.trade_manager async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make, error = await trade_manager_maker.create_offer_for_ids( cat_for_chia, DEFAULT_TX_CONFIG, action_scope ) assert error is None @@ -1701,11 +1679,11 @@ async def test_trade_cancellation( # [maker_offer], signing_response = await wallet_node_maker.wallet_state_manager.sign_offers( # [Offer.from_bytes(trade_make.offer)] # ) - # trade_take, tx_records = await trade_manager_taker.respond_to_offer( + # trade_take = await trade_manager_taker.respond_to_offer( # maker_offer, # ) # tx_records = await wallet_taker.wallet_state_manager.add_pending_transactions( - # tx_records, + # action_scope.side_effects.transactions, # additional_signing_responses=signing_response, # ) # await time_out_assert(15, full_node.txs_in_mempool, True, tx_records) @@ -1721,18 +1699,16 @@ async def test_trade_cancellation( fee = uint64(2_000_000_000_000) - async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await trade_manager_maker.cancel_pending_offers( + async with trade_manager_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await trade_manager_maker.cancel_pending_offers( [trade_make.trade_id], DEFAULT_TX_CONFIG, action_scope, fee=fee, secure=True ) - txs = await trade_manager_maker.wallet_state_manager.add_pending_transactions(txs) await time_out_assert(15, get_trade_and_status, TradeStatus.PENDING_CANCEL, trade_manager_maker, trade_make) - assert txs is not None - await full_node.process_transaction_records(records=txs) + await full_node.process_transaction_records(records=action_scope.side_effects.transactions) sum_of_outgoing = uint64(0) sum_of_incoming = uint64(0) - for tx in txs: + for tx in action_scope.side_effects.transactions: if tx.type == TransactionType.OUTGOING_TX.value: sum_of_outgoing = uint64(sum_of_outgoing + tx.amount) elif tx.type == TransactionType.INCOMING_TX.value: @@ -1756,7 +1732,7 @@ async def test_trade_cancellation( # Now we're going to create the other way around for test coverage sake async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make, error = await trade_manager_maker.create_offer_for_ids( chia_for_cat, DEFAULT_TX_CONFIG, action_scope ) assert error is None @@ -1773,14 +1749,12 @@ async def test_trade_cancellation( Offer.from_bytes(trade_make.offer), peer, DEFAULT_TX_CONFIG, action_scope ) - async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await trade_manager_maker.cancel_pending_offers( + async with trade_manager_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await trade_manager_maker.cancel_pending_offers( [trade_make.trade_id], DEFAULT_TX_CONFIG, action_scope, fee=uint64(0), secure=True ) - txs = await trade_manager_maker.wallet_state_manager.add_pending_transactions(txs) await time_out_assert(15, get_trade_and_status, TradeStatus.PENDING_CANCEL, trade_manager_maker, trade_make) - assert txs is not None - await full_node.process_transaction_records(records=txs) + await full_node.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(15, get_trade_and_status, TradeStatus.CANCELLED, trade_manager_maker, trade_make) @@ -1793,7 +1767,7 @@ async def test_trade_cancellation( # Now we're going to create the other way around for test coverage sake async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make, error = await trade_manager_maker.create_offer_for_ids( chia_and_cat_for_something, DEFAULT_TX_CONFIG, action_scope, @@ -1803,13 +1777,15 @@ async def test_trade_cancellation( assert success is True assert trade_make is not None - async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await trade_manager_maker.cancel_pending_offers( + async with trade_manager_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await trade_manager_maker.cancel_pending_offers( [trade_make.trade_id], DEFAULT_TX_CONFIG, action_scope, fee=uint64(0), secure=True ) # Check an announcement ring has been created - total_spend = SpendBundle.aggregate([tx.spend_bundle for tx in txs if tx.spend_bundle is not None]) + total_spend = SpendBundle.aggregate( + [tx.spend_bundle for tx in action_scope.side_effects.transactions if tx.spend_bundle is not None] + ) all_conditions: List[Program] = [] creations: List[CreateCoinAnnouncement] = [] announcement_nonce = std_hash(trade_make.trade_id) @@ -1826,9 +1802,8 @@ async def test_trade_cancellation( for creation in creations: assert creation.corresponding_assertion().to_program() in all_conditions - txs = await wallet_maker.wallet_state_manager.add_pending_transactions(txs) await time_out_assert(15, get_trade_and_status, TradeStatus.PENDING_CANCEL, trade_manager_maker, trade_make) - await full_node.process_transaction_records(records=txs) + await full_node.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(15, get_trade_and_status, TradeStatus.CANCELLED, trade_manager_maker, trade_make) @@ -1843,8 +1818,8 @@ async def test_trade_cancellation_balance_check( xch_to_cat_amount = uint64(100) - async with wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_wallet_maker, tx_records = await CATWallet.create_new_cat_wallet( + async with wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + cat_wallet_maker = await CATWallet.create_new_cat_wallet( wallet_node_maker.wallet_state_manager, wallet_maker, {"identifier": "genesis_by_id"}, @@ -1853,7 +1828,7 @@ async def test_trade_cancellation_balance_check( action_scope, ) - await full_node.process_transaction_records(records=tx_records) + await full_node.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(15, cat_wallet_maker.get_confirmed_balance, xch_to_cat_amount) await time_out_assert(15, cat_wallet_maker.get_unconfirmed_balance, xch_to_cat_amount) @@ -1868,21 +1843,19 @@ async def test_trade_cancellation_balance_check( trade_manager_maker = wallet_node_maker.wallet_state_manager.trade_manager async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make, error = await trade_manager_maker.create_offer_for_ids( chia_for_cat, DEFAULT_TX_CONFIG, action_scope ) await time_out_assert(10, get_trade_and_status, TradeStatus.PENDING_ACCEPT, trade_manager_maker, trade_make) assert error is None assert success is True assert trade_make is not None - async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await trade_manager_maker.cancel_pending_offers( + async with trade_manager_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await trade_manager_maker.cancel_pending_offers( [trade_make.trade_id], DEFAULT_TX_CONFIG, action_scope, fee=uint64(0), secure=True ) - txs = await trade_manager_maker.wallet_state_manager.add_pending_transactions(txs) await time_out_assert(15, get_trade_and_status, TradeStatus.PENDING_CANCEL, trade_manager_maker, trade_make) - assert txs is not None - await full_node.process_transaction_records(records=txs) + await full_node.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(15, get_trade_and_status, TradeStatus.CANCELLED, trade_manager_maker, trade_make) @@ -1900,8 +1873,8 @@ async def test_trade_conflict( wallet_maker = wallet_node_maker.wallet_state_manager.main_wallet xch_to_cat_amount = uint64(100) - async with wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_wallet_maker, tx_records = await CATWallet.create_new_cat_wallet( + async with wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + cat_wallet_maker = await CATWallet.create_new_cat_wallet( wallet_node_maker.wallet_state_manager, wallet_maker, {"identifier": "genesis_by_id"}, @@ -1910,7 +1883,7 @@ async def test_trade_conflict( action_scope, ) - await full_node.process_transaction_records(records=tx_records) + await full_node.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(15, cat_wallet_maker.get_confirmed_balance, xch_to_cat_amount) await time_out_assert(15, cat_wallet_maker.get_unconfirmed_balance, xch_to_cat_amount) @@ -1927,7 +1900,7 @@ async def test_trade_conflict( trade_manager_trader = wallet_node_trader.wallet_state_manager.trade_manager async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make, error = await trade_manager_maker.create_offer_for_ids( chia_for_cat, DEFAULT_TX_CONFIG, action_scope ) await time_out_assert(10, get_trade_and_status, TradeStatus.PENDING_ACCEPT, trade_manager_maker, trade_make) @@ -1937,14 +1910,11 @@ async def test_trade_conflict( peer = wallet_node_taker.get_full_node_peer() offer = Offer.from_bytes(trade_make.offer) [offer], signing_response = await wallet_node_maker.wallet_state_manager.sign_offers([offer]) - async with trade_manager_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - tr1, txs1 = await trade_manager_taker.respond_to_offer( - offer, peer, DEFAULT_TX_CONFIG, action_scope, fee=uint64(10) - ) - txs1 = await trade_manager_taker.wallet_state_manager.add_pending_transactions( - txs1, additional_signing_responses=signing_response - ) - await full_node.wait_transaction_records_entered_mempool(records=txs1) + async with trade_manager_taker.wallet_state_manager.new_action_scope( + push=True, additional_signing_responses=signing_response + ) as action_scope: + tr1 = await trade_manager_taker.respond_to_offer(offer, peer, DEFAULT_TX_CONFIG, action_scope, fee=uint64(10)) + await full_node.wait_transaction_records_entered_mempool(records=action_scope.side_effects.transactions) # we shouldn't be able to respond to a duplicate offer with pytest.raises(ValueError): async with trade_manager_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: @@ -1952,13 +1922,10 @@ async def test_trade_conflict( await time_out_assert(15, get_trade_and_status, TradeStatus.PENDING_CONFIRM, trade_manager_taker, tr1) # pushing into mempool while already in it should fail [offer], signing_response = await wallet_node_maker.wallet_state_manager.sign_offers([offer]) - async with trade_manager_trader.wallet_state_manager.new_action_scope(push=False) as action_scope: - tr2, txs2 = await trade_manager_trader.respond_to_offer( - offer, peer, DEFAULT_TX_CONFIG, action_scope, fee=uint64(10) - ) - txs2 = await trade_manager_trader.wallet_state_manager.add_pending_transactions( - txs2, additional_signing_responses=signing_response - ) + async with trade_manager_trader.wallet_state_manager.new_action_scope( + push=True, additional_signing_responses=signing_response + ) as action_scope: + tr2 = await trade_manager_trader.respond_to_offer(offer, peer, DEFAULT_TX_CONFIG, action_scope, fee=uint64(10)) assert await trade_manager_trader.get_coins_of_interest() offer_tx_records: List[TransactionRecord] = await wallet_node_maker.wallet_state_manager.tx_store.get_not_sent() await full_node.process_transaction_records(records=offer_tx_records) @@ -1975,8 +1942,8 @@ async def test_trade_bad_spend( wallet_maker = wallet_node_maker.wallet_state_manager.main_wallet xch_to_cat_amount = uint64(100) - async with wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_wallet_maker, tx_records = await CATWallet.create_new_cat_wallet( + async with wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + cat_wallet_maker = await CATWallet.create_new_cat_wallet( wallet_node_maker.wallet_state_manager, wallet_maker, {"identifier": "genesis_by_id"}, @@ -1985,7 +1952,7 @@ async def test_trade_bad_spend( action_scope, ) - await full_node.process_transaction_records(records=tx_records) + await full_node.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(15, cat_wallet_maker.get_confirmed_balance, xch_to_cat_amount) await time_out_assert(15, cat_wallet_maker.get_unconfirmed_balance, xch_to_cat_amount) @@ -2001,7 +1968,7 @@ async def test_trade_bad_spend( trade_manager_taker = wallet_node_taker.wallet_state_manager.trade_manager async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make, error = await trade_manager_maker.create_offer_for_ids( chia_for_cat, DEFAULT_TX_CONFIG, action_scope ) await time_out_assert(30, get_trade_and_status, TradeStatus.PENDING_ACCEPT, trade_manager_maker, trade_make) @@ -2012,11 +1979,8 @@ async def test_trade_bad_spend( offer = Offer.from_bytes(trade_make.offer) bundle = offer._bundle.replace(aggregated_signature=G2Element()) offer = dataclasses.replace(offer, _bundle=bundle) - async with trade_manager_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - tr1, txs1 = await trade_manager_taker.respond_to_offer( - offer, peer, DEFAULT_TX_CONFIG, action_scope, fee=uint64(10) - ) - txs1 = await trade_manager_taker.wallet_state_manager.add_pending_transactions(txs1, sign=False) + async with trade_manager_taker.wallet_state_manager.new_action_scope(push=True, sign=False) as action_scope: + tr1 = await trade_manager_taker.respond_to_offer(offer, peer, DEFAULT_TX_CONFIG, action_scope, fee=uint64(10)) wallet_node_taker.wallet_tx_resend_timeout_secs = 0 # don't wait for resend def check_wallet_cache_empty() -> bool: @@ -2039,8 +2003,8 @@ async def test_trade_high_fee( wallet_maker = wallet_node_maker.wallet_state_manager.main_wallet xch_to_cat_amount = uint64(100) - async with wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_wallet_maker, tx_records = await CATWallet.create_new_cat_wallet( + async with wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + cat_wallet_maker = await CATWallet.create_new_cat_wallet( wallet_node_maker.wallet_state_manager, wallet_maker, {"identifier": "genesis_by_id"}, @@ -2049,7 +2013,7 @@ async def test_trade_high_fee( action_scope, ) - await full_node.process_transaction_records(records=tx_records) + await full_node.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(15, cat_wallet_maker.get_confirmed_balance, xch_to_cat_amount) await time_out_assert(15, cat_wallet_maker.get_unconfirmed_balance, xch_to_cat_amount) @@ -2065,7 +2029,7 @@ async def test_trade_high_fee( trade_manager_taker = wallet_node_taker.wallet_state_manager.trade_manager async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make, error = await trade_manager_maker.create_offer_for_ids( chia_for_cat, DEFAULT_TX_CONFIG, action_scope ) await time_out_assert(10, get_trade_and_status, TradeStatus.PENDING_ACCEPT, trade_manager_maker, trade_make) @@ -2076,14 +2040,13 @@ async def test_trade_high_fee( [offer], signing_response = await wallet_node_maker.wallet_state_manager.sign_offers( [Offer.from_bytes(trade_make.offer)] ) - async with trade_manager_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - tr1, txs1 = await trade_manager_taker.respond_to_offer( + async with trade_manager_taker.wallet_state_manager.new_action_scope( + push=True, additional_signing_responses=signing_response + ) as action_scope: + tr1 = await trade_manager_taker.respond_to_offer( offer, peer, DEFAULT_TX_CONFIG, action_scope, fee=uint64(1000000000000) ) - txs1 = await trade_manager_taker.wallet_state_manager.add_pending_transactions( - txs1, additional_signing_responses=signing_response - ) - await full_node.process_transaction_records(records=txs1) + await full_node.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(15, get_trade_and_status, TradeStatus.CONFIRMED, trade_manager_taker, tr1) @@ -2096,8 +2059,8 @@ async def test_aggregated_trade_state( wallet_maker = wallet_node_maker.wallet_state_manager.main_wallet xch_to_cat_amount = uint64(100) - async with wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_wallet_maker, tx_records = await CATWallet.create_new_cat_wallet( + async with wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + cat_wallet_maker = await CATWallet.create_new_cat_wallet( wallet_node_maker.wallet_state_manager, wallet_maker, {"identifier": "genesis_by_id"}, @@ -2106,7 +2069,7 @@ async def test_aggregated_trade_state( action_scope, ) - await full_node.process_transaction_records(records=tx_records) + await full_node.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(15, cat_wallet_maker.get_confirmed_balance, xch_to_cat_amount) await time_out_assert(15, cat_wallet_maker.get_unconfirmed_balance, xch_to_cat_amount) @@ -2126,7 +2089,7 @@ async def test_aggregated_trade_state( trade_manager_taker = wallet_node_taker.wallet_state_manager.trade_manager async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make_1, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make_1, error = await trade_manager_maker.create_offer_for_ids( chia_for_cat, DEFAULT_TX_CONFIG, action_scope ) await time_out_assert(10, get_trade_and_status, TradeStatus.PENDING_ACCEPT, trade_manager_maker, trade_make_1) @@ -2134,7 +2097,7 @@ async def test_aggregated_trade_state( assert success is True assert trade_make_1 is not None async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make_2, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make_2, error = await trade_manager_maker.create_offer_for_ids( cat_for_chia, DEFAULT_TX_CONFIG, action_scope ) await time_out_assert(10, get_trade_and_status, TradeStatus.PENDING_ACCEPT, trade_manager_maker, trade_make_2) @@ -2151,21 +2114,17 @@ async def test_aggregated_trade_state( agg_offer = Offer.aggregate([offer_1, offer_2]) peer = wallet_node_taker.get_full_node_peer() - async with trade_manager_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - trade_take, tx_records = await trade_manager_taker.respond_to_offer( + async with trade_manager_taker.wallet_state_manager.new_action_scope( + push=True, additional_signing_responses=[*signing_response_1, *signing_response_2] + ) as action_scope: + await trade_manager_taker.respond_to_offer( agg_offer, peer, DEFAULT_TX_CONFIG, action_scope, ) - assert trade_take is not None - assert tx_records is not None - tx_records = await trade_manager_taker.wallet_state_manager.add_pending_transactions( - tx_records, - additional_signing_responses=[*signing_response_1, *signing_response_2], - ) - await full_node.process_transaction_records(records=tx_records) + await full_node.process_transaction_records(records=action_scope.side_effects.transactions) await full_node.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker, wallet_node_taker], timeout=60) await time_out_assert(15, wallet_maker.get_confirmed_balance, maker_funds + 1) diff --git a/chia/_tests/wallet/dao_wallet/test_dao_wallets.py b/chia/_tests/wallet/dao_wallet/test_dao_wallets.py index 32d4c460e7f2..100494d60cdd 100644 --- a/chia/_tests/wallet/dao_wallet/test_dao_wallets.py +++ b/chia/_tests/wallet/dao_wallet/test_dao_wallets.py @@ -143,8 +143,8 @@ async def test_dao_creation(self_hostname: str, two_wallet_nodes: OldSimulatorsA ) assert e_info.value.args[0] == f"Your balance of {funds} mojos is not enough to create {funds + 1} CATs" - async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - dao_wallet_0, tx_queue = await DAOWallet.create_new_dao_and_wallet( + async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + dao_wallet_0 = await DAOWallet.create_new_dao_and_wallet( wallet_node_0.wallet_state_manager, wallet_0, uint64(cat_amt * 2), @@ -155,8 +155,9 @@ async def test_dao_creation(self_hostname: str, two_wallet_nodes: OldSimulatorsA fee_for_cat=fee_for_cat, ) - tx_queue = await wallet_node_0.wallet_state_manager.add_pending_transactions(tx_queue) - await full_node_api.wait_transaction_records_entered_mempool(records=tx_queue, timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30) @@ -201,11 +202,12 @@ async def test_dao_creation(self_hostname: str, two_wallet_nodes: OldSimulatorsA # Send some cats to the dao_cat lockup dao_cat_amt = uint64(100) - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await dao_wallet_0.enter_dao_cat_voting_mode(dao_cat_amt, DEFAULT_TX_CONFIG, action_scope) - txs = await dao_wallet_0.wallet_state_manager.add_pending_transactions(txs) + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.enter_dao_cat_voting_mode(dao_cat_amt, DEFAULT_TX_CONFIG, action_scope) - await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30) @@ -222,11 +224,12 @@ async def test_dao_creation(self_hostname: str, two_wallet_nodes: OldSimulatorsA assert list(coins)[0].coin.amount == dao_cat_amt # send some cats from wallet_0 to wallet_1 so we can test voting - async with cat_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_txs = await cat_wallet_0.generate_signed_transaction([cat_amt], [ph_1], DEFAULT_TX_CONFIG, action_scope) - cat_txs = await cat_wallet_0.wallet_state_manager.add_pending_transactions(cat_txs) + async with cat_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await cat_wallet_0.generate_signed_transaction([cat_amt], [ph_1], DEFAULT_TX_CONFIG, action_scope) - await full_node_api.wait_transaction_records_entered_mempool(records=cat_txs, timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30) @@ -313,16 +316,17 @@ async def test_dao_funding(self_hostname: str, three_wallet_nodes: OldSimulators proposal_minimum_amount=uint64(1), ) - async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - dao_wallet_0, tx_queue = await DAOWallet.create_new_dao_and_wallet( + async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + dao_wallet_0 = await DAOWallet.create_new_dao_and_wallet( wallet_node_0.wallet_state_manager, wallet_0, uint64(cat_amt), dao_rules, DEFAULT_TX_CONFIG, action_scope ) treasury_id = dao_wallet_0.dao_info.treasury_id # Get the full node sim to process the wallet creation spend - tx_queue = await wallet_node_0.wallet_state_manager.add_pending_transactions(tx_queue) - await full_node_api.wait_transaction_records_entered_mempool(records=tx_queue, timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30) @@ -333,22 +337,24 @@ async def test_dao_funding(self_hostname: str, three_wallet_nodes: OldSimulators # Create funding spends for xch and cat xch_funds = uint64(500000) cat_funds = uint64(100000) - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - funding_tx = await dao_wallet_0.create_add_funds_to_treasury_spend(xch_funds, DEFAULT_TX_CONFIG, action_scope) - [funding_tx] = await dao_wallet_0.wallet_state_manager.add_pending_transactions([funding_tx]) - await full_node_api.wait_transaction_records_entered_mempool(records=[funding_tx], timeout=60) + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.create_add_funds_to_treasury_spend(xch_funds, DEFAULT_TX_CONFIG, action_scope) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30) # Check that the funding spend is found await time_out_assert(20, dao_wallet_0.get_balance_by_asset_type, xch_funds) - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_funding_tx = await dao_wallet_0.create_add_funds_to_treasury_spend( + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.create_add_funds_to_treasury_spend( cat_funds, DEFAULT_TX_CONFIG, action_scope, funding_wallet_id=cat_wallet_0.id() ) - [cat_funding_tx] = await dao_wallet_0.wallet_state_manager.add_pending_transactions([cat_funding_tx]) - await full_node_api.wait_transaction_records_entered_mempool(records=[cat_funding_tx], timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30) @@ -362,10 +368,11 @@ async def test_dao_funding(self_hostname: str, three_wallet_nodes: OldSimulators cat_wallet_0 = dao_wallet_0.wallet_state_manager.wallets[dao_wallet_0.dao_info.cat_wallet_id] dao_cat_wallet_0 = dao_wallet_0.wallet_state_manager.wallets[dao_wallet_0.dao_info.dao_cat_wallet_id] dao_cat_0_bal = await dao_cat_wallet_0.get_votable_balance() - async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await dao_cat_wallet_0.enter_dao_cat_voting_mode(dao_cat_0_bal, DEFAULT_TX_CONFIG, action_scope) - txs = await dao_cat_wallet_0.wallet_state_manager.add_pending_transactions(txs) - await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60) + async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_cat_wallet_0.enter_dao_cat_voting_mode(dao_cat_0_bal, DEFAULT_TX_CONFIG, action_scope) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30) @@ -377,12 +384,11 @@ async def test_dao_funding(self_hostname: str, three_wallet_nodes: OldSimulators [proposal_amount_1], [None], ) - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - [proposal_tx] = await dao_wallet_0.generate_new_proposal( - xch_proposal_inner, DEFAULT_TX_CONFIG, action_scope, dao_cat_0_bal - ) - [proposal_tx] = await dao_wallet_0.wallet_state_manager.add_pending_transactions([proposal_tx]) - await full_node_api.wait_transaction_records_entered_mempool(records=[proposal_tx], timeout=60) + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.generate_new_proposal(xch_proposal_inner, DEFAULT_TX_CONFIG, action_scope, dao_cat_0_bal) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30) @@ -391,10 +397,11 @@ async def test_dao_funding(self_hostname: str, three_wallet_nodes: OldSimulators await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0)) prop_0 = dao_wallet_0.dao_info.proposals_list[0] - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - close_tx_0 = await dao_wallet_0.create_proposal_close_spend(prop_0.proposal_id, DEFAULT_TX_CONFIG, action_scope) - [close_tx_0] = await dao_wallet_0.wallet_state_manager.add_pending_transactions([close_tx_0]) - await full_node_api.wait_transaction_records_entered_mempool(records=[close_tx_0], timeout=60) + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.create_proposal_close_spend(prop_0.proposal_id, DEFAULT_TX_CONFIG, action_scope) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30) @@ -499,8 +506,8 @@ async def test_dao_proposals(self_hostname: str, three_wallet_nodes: OldSimulato # Create the DAO. # This takes two steps: create the treasury singleton, wait for oracle_spend_delay and # then complete the eve spend - async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - dao_wallet_0, tx_queue = await DAOWallet.create_new_dao_and_wallet( + async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + dao_wallet_0 = await DAOWallet.create_new_dao_and_wallet( wallet_node_0.wallet_state_manager, wallet_0, uint64(cat_issuance), @@ -509,8 +516,9 @@ async def test_dao_proposals(self_hostname: str, three_wallet_nodes: OldSimulato action_scope, ) - tx_queue = await wallet_node_0.wallet_state_manager.add_pending_transactions(tx_queue) - await full_node_api.wait_transaction_records_entered_mempool(records=tx_queue, timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30) @@ -543,39 +551,41 @@ async def test_dao_proposals(self_hostname: str, three_wallet_nodes: OldSimulato # Send 100k cats to wallet_1 and wallet_2 cat_amt = uint64(100000) - async with cat_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_tx = await cat_wallet_0.generate_signed_transaction( + async with cat_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await cat_wallet_0.generate_signed_transaction( [cat_amt, cat_amt], [ph_1, ph_2], DEFAULT_TX_CONFIG, action_scope, fee=base_fee ) - cat_tx = await wallet_0.wallet_state_manager.add_pending_transactions(cat_tx) - await full_node_api.wait_transaction_records_entered_mempool(records=cat_tx, timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30) # Lockup voting cats for all wallets dao_cat_0_bal = await dao_cat_wallet_0.get_votable_balance() - async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs_0 = await dao_cat_wallet_0.enter_dao_cat_voting_mode( - dao_cat_0_bal, DEFAULT_TX_CONFIG, action_scope, fee=base_fee - ) - txs_0 = await wallet_0.wallet_state_manager.add_pending_transactions(txs_0) - await full_node_api.wait_transaction_records_entered_mempool(records=txs_0, timeout=60) + async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_cat_wallet_0.enter_dao_cat_voting_mode(dao_cat_0_bal, DEFAULT_TX_CONFIG, action_scope, fee=base_fee) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30) dao_cat_1_bal = await dao_cat_wallet_1.get_votable_balance() - async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs_1 = await dao_cat_wallet_1.enter_dao_cat_voting_mode(dao_cat_1_bal, DEFAULT_TX_CONFIG, action_scope) - txs_1 = await wallet_1.wallet_state_manager.add_pending_transactions(txs_1) - await full_node_api.wait_transaction_records_entered_mempool(records=txs_1, timeout=60) + async with dao_cat_wallet_1.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_cat_wallet_1.enter_dao_cat_voting_mode(dao_cat_1_bal, DEFAULT_TX_CONFIG, action_scope) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_1, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30) dao_cat_2_bal = await dao_cat_wallet_2.get_votable_balance() - async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs_2 = await dao_cat_wallet_2.enter_dao_cat_voting_mode(dao_cat_2_bal, DEFAULT_TX_CONFIG, action_scope) - txs_2 = await wallet_2.wallet_state_manager.add_pending_transactions(txs_2) - await full_node_api.wait_transaction_records_entered_mempool(records=txs_2, timeout=60) + async with dao_cat_wallet_2.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_cat_wallet_2.enter_dao_cat_voting_mode(dao_cat_2_bal, DEFAULT_TX_CONFIG, action_scope) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_2, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30) @@ -585,10 +595,11 @@ async def test_dao_proposals(self_hostname: str, three_wallet_nodes: OldSimulato # Create funding spend so the treasury holds some XCH xch_funds = uint64(500000) - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - funding_tx = await dao_wallet_0.create_add_funds_to_treasury_spend(xch_funds, DEFAULT_TX_CONFIG, action_scope) - [funding_tx] = await wallet_0.wallet_state_manager.add_pending_transactions([funding_tx]) - await full_node_api.wait_transaction_records_entered_mempool(records=[funding_tx], timeout=60) + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.create_add_funds_to_treasury_spend(xch_funds, DEFAULT_TX_CONFIG, action_scope) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_1, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30) @@ -608,12 +619,13 @@ async def test_dao_proposals(self_hostname: str, three_wallet_nodes: OldSimulato [proposal_amount_1], [None], ) - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - [proposal_tx] = await dao_wallet_0.generate_new_proposal( + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.generate_new_proposal( xch_proposal_inner, DEFAULT_TX_CONFIG, action_scope, dao_cat_0_bal, fee=base_fee ) - [proposal_tx] = await wallet_0.wallet_state_manager.add_pending_transactions([proposal_tx]) - await full_node_api.wait_transaction_records_entered_mempool(records=[proposal_tx], timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30) @@ -631,12 +643,13 @@ async def test_dao_proposals(self_hostname: str, three_wallet_nodes: OldSimulato recipient_puzzle_hash, ) - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - [proposal_tx] = await dao_wallet_0.generate_new_proposal( + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.generate_new_proposal( mint_proposal_inner, DEFAULT_TX_CONFIG, action_scope, vote_amount=dao_cat_0_bal, fee=base_fee ) - [proposal_tx] = await wallet_0.wallet_state_manager.add_pending_transactions([proposal_tx]) - await full_node_api.wait_transaction_records_entered_mempool(records=[proposal_tx], timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30) @@ -656,12 +669,13 @@ async def test_dao_proposals(self_hostname: str, three_wallet_nodes: OldSimulato current_innerpuz = dao_wallet_0.dao_info.current_treasury_innerpuz assert current_innerpuz is not None update_inner = await generate_update_proposal_innerpuz(current_innerpuz, new_dao_rules) - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - [proposal_tx] = await dao_wallet_0.generate_new_proposal( + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.generate_new_proposal( update_inner, DEFAULT_TX_CONFIG, action_scope, dao_cat_0_bal, fee=base_fee ) - [proposal_tx] = await wallet_0.wallet_state_manager.add_pending_transactions([proposal_tx]) - await full_node_api.wait_transaction_records_entered_mempool(records=[proposal_tx], timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30) @@ -673,12 +687,13 @@ async def test_dao_proposals(self_hostname: str, three_wallet_nodes: OldSimulato xch_proposal_inner = generate_simple_proposal_innerpuz( treasury_id, [recipient_puzzle_hash], [proposal_amount_2], [None] ) - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - [proposal_tx] = await dao_wallet_0.generate_new_proposal( + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.generate_new_proposal( xch_proposal_inner, DEFAULT_TX_CONFIG, action_scope, dao_cat_0_bal, fee=base_fee ) - [proposal_tx] = await wallet_0.wallet_state_manager.add_pending_transactions([proposal_tx]) - await full_node_api.wait_transaction_records_entered_mempool(records=[proposal_tx], timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30) @@ -687,12 +702,13 @@ async def test_dao_proposals(self_hostname: str, three_wallet_nodes: OldSimulato # Proposal 4: Create a 'bad' proposal (can't be executed, must be force-closed) xch_proposal_inner = Program.to(["x"]) - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - [proposal_tx] = await dao_wallet_0.generate_new_proposal( + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.generate_new_proposal( xch_proposal_inner, DEFAULT_TX_CONFIG, action_scope, dao_cat_0_bal, fee=base_fee ) - [proposal_tx] = await wallet_0.wallet_state_manager.add_pending_transactions([proposal_tx]) - await full_node_api.wait_transaction_records_entered_mempool(records=[proposal_tx], timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30) @@ -702,21 +718,23 @@ async def test_dao_proposals(self_hostname: str, three_wallet_nodes: OldSimulato prop_4 = dao_wallet_0.dao_info.proposals_list[4] # Proposal 0 Voting: wallet 1 votes yes, wallet 2 votes no. Proposal Passes - async with dao_wallet_1.wallet_state_manager.new_action_scope(push=False) as action_scope: - [vote_tx_1] = await dao_wallet_1.generate_proposal_vote_spend( + async with dao_wallet_1.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_1.generate_proposal_vote_spend( prop_0.proposal_id, dao_cat_1_bal, True, DEFAULT_TX_CONFIG, action_scope ) - [vote_tx_1] = await wallet_1.wallet_state_manager.add_pending_transactions([vote_tx_1]) - await full_node_api.wait_transaction_records_entered_mempool(records=[vote_tx_1], timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_1, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30) - async with dao_wallet_2.wallet_state_manager.new_action_scope(push=False) as action_scope: - [vote_tx_2] = await dao_wallet_2.generate_proposal_vote_spend( + async with dao_wallet_2.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_2.generate_proposal_vote_spend( prop_0.proposal_id, dao_cat_2_bal, False, DEFAULT_TX_CONFIG, action_scope ) - [vote_tx_2] = await wallet_2.wallet_state_manager.add_pending_transactions([vote_tx_2]) - await full_node_api.wait_transaction_records_entered_mempool(records=[vote_tx_2], timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_1, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30) @@ -733,28 +751,24 @@ async def test_dao_proposals(self_hostname: str, three_wallet_nodes: OldSimulato assert prop_0_state["closable"] # Proposal 0 is closable, but soft_close_length has not passed. - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - close_tx_0_fail = await dao_wallet_0.create_proposal_close_spend( - prop_0.proposal_id, DEFAULT_TX_CONFIG, action_scope - ) - close_sb_0_fail = close_tx_0_fail.spend_bundle - assert close_sb_0_fail is not None - with pytest.raises(AssertionError) as e: - await wallet_0.wallet_state_manager.add_pending_transactions([close_tx_0_fail]) + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.create_proposal_close_spend(prop_0.proposal_id, DEFAULT_TX_CONFIG, action_scope) + with pytest.raises(AssertionError, match="Timed assertion timed out"): + assert action_scope.side_effects.transactions[0].spend_bundle is not None await time_out_assert_not_none( - 5, full_node_api.full_node.mempool_manager.get_spendbundle, close_sb_0_fail.name() + 5, + full_node_api.full_node.mempool_manager.get_spendbundle, + action_scope.side_effects.transactions[0].spend_bundle.name(), ) - assert e.value.args[0] == "Timed assertion timed out" for _ in range(5): await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0)) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30) # Proposal 0: Close - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - close_tx_0 = await dao_wallet_0.create_proposal_close_spend(prop_0.proposal_id, DEFAULT_TX_CONFIG, action_scope) - [close_tx_0] = await wallet_0.wallet_state_manager.add_pending_transactions([close_tx_0]) - close_sb_0 = close_tx_0.spend_bundle + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.create_proposal_close_spend(prop_0.proposal_id, DEFAULT_TX_CONFIG, action_scope) + close_sb_0 = action_scope.side_effects.transactions[0].spend_bundle assert close_sb_0 is not None await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, close_sb_0.name()) await full_node_api.process_spend_bundles(bundles=[close_sb_0]) @@ -770,12 +784,13 @@ async def test_dao_proposals(self_hostname: str, three_wallet_nodes: OldSimulato await time_out_assert(20, get_proposal_state, (True, True), *[dao_wallet_2, 0]) # Proposal 1 vote and close - async with dao_wallet_1.wallet_state_manager.new_action_scope(push=False) as action_scope: - [vote_tx_1] = await dao_wallet_1.generate_proposal_vote_spend( + async with dao_wallet_1.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_1.generate_proposal_vote_spend( prop_1.proposal_id, dao_cat_1_bal, True, DEFAULT_TX_CONFIG, action_scope ) - [vote_tx_1] = await wallet_1.wallet_state_manager.add_pending_transactions([vote_tx_1]) - await full_node_api.wait_transaction_records_entered_mempool(records=[vote_tx_1], timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_1, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30) @@ -787,22 +802,24 @@ async def test_dao_proposals(self_hostname: str, three_wallet_nodes: OldSimulato assert prop_1_state["passed"] assert prop_1_state["closable"] - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - close_tx_1 = await dao_wallet_0.create_proposal_close_spend(prop_1.proposal_id, DEFAULT_TX_CONFIG, action_scope) - [close_tx_1] = await wallet_0.wallet_state_manager.add_pending_transactions([close_tx_1]) - await full_node_api.wait_transaction_records_entered_mempool(records=[close_tx_1], timeout=60) + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.create_proposal_close_spend(prop_1.proposal_id, DEFAULT_TX_CONFIG, action_scope) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30) await time_out_assert(20, cat_wallet_2.get_confirmed_balance, new_mint_amount) # Proposal 2 vote and close - async with dao_wallet_1.wallet_state_manager.new_action_scope(push=False) as action_scope: - [vote_tx_2] = await dao_wallet_1.generate_proposal_vote_spend( + async with dao_wallet_1.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_1.generate_proposal_vote_spend( prop_2.proposal_id, dao_cat_1_bal, True, DEFAULT_TX_CONFIG, action_scope ) - [vote_tx_2] = await wallet_1.wallet_state_manager.add_pending_transactions([vote_tx_2]) - await full_node_api.wait_transaction_records_entered_mempool(records=[vote_tx_2], timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_1, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30) @@ -814,10 +831,11 @@ async def test_dao_proposals(self_hostname: str, three_wallet_nodes: OldSimulato assert prop_2_state["passed"] assert prop_2_state["closable"] - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - close_tx_2 = await dao_wallet_0.create_proposal_close_spend(prop_2.proposal_id, DEFAULT_TX_CONFIG, action_scope) - [close_tx_2] = await wallet_0.wallet_state_manager.add_pending_transactions([close_tx_2]) - await full_node_api.wait_transaction_records_entered_mempool(records=[close_tx_2], timeout=60) + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.create_proposal_close_spend(prop_2.proposal_id, DEFAULT_TX_CONFIG, action_scope) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30) @@ -826,12 +844,13 @@ async def test_dao_proposals(self_hostname: str, three_wallet_nodes: OldSimulato assert dao_wallet_2.dao_rules == new_dao_rules # Proposal 3 - Close as FAILED - async with dao_wallet_1.wallet_state_manager.new_action_scope(push=False) as action_scope: - [vote_tx_3] = await dao_wallet_1.generate_proposal_vote_spend( + async with dao_wallet_1.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_1.generate_proposal_vote_spend( prop_3.proposal_id, dao_cat_1_bal, False, DEFAULT_TX_CONFIG, action_scope ) - [vote_tx_3] = await wallet_1.wallet_state_manager.add_pending_transactions([vote_tx_3]) - await full_node_api.wait_transaction_records_entered_mempool(records=[vote_tx_3], timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_1, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30) @@ -843,10 +862,11 @@ async def test_dao_proposals(self_hostname: str, three_wallet_nodes: OldSimulato assert not prop_3_state["passed"] assert prop_3_state["closable"] - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - close_tx_3 = await dao_wallet_0.create_proposal_close_spend(prop_3.proposal_id, DEFAULT_TX_CONFIG, action_scope) - [close_tx_3] = await wallet_0.wallet_state_manager.add_pending_transactions([close_tx_3]) - await full_node_api.wait_transaction_records_entered_mempool(records=[close_tx_3], timeout=60) + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.create_proposal_close_spend(prop_3.proposal_id, DEFAULT_TX_CONFIG, action_scope) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30) @@ -859,12 +879,13 @@ async def test_dao_proposals(self_hostname: str, three_wallet_nodes: OldSimulato await time_out_assert(20, get_proposal_state, (False, True), *[dao_wallet_2, 3]) # Proposal 4 - Self Destruct a broken proposal - async with dao_wallet_1.wallet_state_manager.new_action_scope(push=False) as action_scope: - [vote_tx_4] = await dao_wallet_1.generate_proposal_vote_spend( + async with dao_wallet_1.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_1.generate_proposal_vote_spend( prop_4.proposal_id, dao_cat_1_bal, True, DEFAULT_TX_CONFIG, action_scope ) - [vote_tx_4] = await wallet_1.wallet_state_manager.add_pending_transactions([vote_tx_4]) - await full_node_api.wait_transaction_records_entered_mempool(records=[vote_tx_4], timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_1, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30) @@ -876,19 +897,17 @@ async def test_dao_proposals(self_hostname: str, three_wallet_nodes: OldSimulato assert prop_4_state["passed"] assert prop_4_state["closable"] - with pytest.raises(Exception) as e_info: - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - close_tx_4 = await dao_wallet_0.create_proposal_close_spend( - prop_4.proposal_id, DEFAULT_TX_CONFIG, action_scope - ) - assert e_info.value.args[0] == "Unrecognised proposal type" + with pytest.raises(Exception, match="Unrecognised proposal type"): + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.create_proposal_close_spend(prop_4.proposal_id, DEFAULT_TX_CONFIG, action_scope) - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - close_tx_4 = await dao_wallet_0.create_proposal_close_spend( + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.create_proposal_close_spend( prop_4.proposal_id, DEFAULT_TX_CONFIG, action_scope, self_destruct=True ) - [close_tx_4] = await wallet_0.wallet_state_manager.add_pending_transactions([close_tx_4]) - await full_node_api.wait_transaction_records_entered_mempool(records=[close_tx_4], timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30) @@ -901,12 +920,11 @@ async def test_dao_proposals(self_hostname: str, three_wallet_nodes: OldSimulato # Remove Proposals from Memory and Free up locked coins await time_out_assert(20, len, 5, dao_wallet_0.dao_info.proposals_list) await dao_wallet_0.clear_finished_proposals_from_memory() - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - free_tx = await dao_wallet_0.free_coins_from_finished_proposals( - DEFAULT_TX_CONFIG, action_scope, fee=uint64(100) - ) - [free_tx] = await wallet_0.wallet_state_manager.add_pending_transactions([free_tx]) - await full_node_api.wait_transaction_records_entered_mempool(records=[free_tx], timeout=60) + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.free_coins_from_finished_proposals(DEFAULT_TX_CONFIG, action_scope, fee=uint64(100)) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30) @@ -967,14 +985,15 @@ async def test_dao_proposal_partial_vote( proposal_minimum_amount=uint64(1), ) - async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - dao_wallet_0, tx_queue = await DAOWallet.create_new_dao_and_wallet( + async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + dao_wallet_0 = await DAOWallet.create_new_dao_and_wallet( wallet_node_0.wallet_state_manager, wallet_0, uint64(cat_amt), dao_rules, DEFAULT_TX_CONFIG, action_scope ) # Get the full node sim to process the wallet creation spend - tx_queue = await wallet_node_0.wallet_state_manager.add_pending_transactions(tx_queue) - await full_node_api.wait_transaction_records_entered_mempool(records=tx_queue, timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30) @@ -1002,18 +1021,13 @@ async def test_dao_proposal_partial_vote( # Create funding spends for xch xch_funds = uint64(500000) - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - funding_tx = await dao_wallet_0.create_add_funds_to_treasury_spend( + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.create_add_funds_to_treasury_spend( xch_funds, DEFAULT_TX_CONFIG, action_scope, ) - [funding_tx] = await dao_wallet_0.wallet_state_manager.add_pending_transactions([funding_tx]) - assert isinstance(funding_tx, TransactionRecord) - funding_sb = funding_tx.spend_bundle - assert funding_sb is not None - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, funding_sb.name()) - await full_node_api.process_transaction_records(records=[funding_tx]) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0)) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30) @@ -1027,25 +1041,18 @@ async def test_dao_proposal_partial_vote( assert cat_wallet_1 assert dao_cat_wallet_1 - async with cat_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_tx = await cat_wallet_0.generate_signed_transaction([100000], [ph_1], DEFAULT_TX_CONFIG, action_scope) - cat_tx = await cat_wallet_0.wallet_state_manager.add_pending_transactions(cat_tx) - cat_sb = cat_tx[0].spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, cat_sb.name()) - await full_node_api.process_transaction_records(records=cat_tx) + async with cat_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await cat_wallet_0.generate_signed_transaction([100000], [ph_1], DEFAULT_TX_CONFIG, action_scope) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0)) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30) await time_out_assert(10, cat_wallet_1.get_spendable_balance, 100000) # Create dao cats for voting dao_cat_0_bal = await dao_cat_wallet_0.get_votable_balance() - async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await dao_cat_wallet_0.enter_dao_cat_voting_mode(dao_cat_0_bal, DEFAULT_TX_CONFIG, action_scope) - txs = await dao_cat_wallet_0.wallet_state_manager.add_pending_transactions(txs) - dao_cat_sb = txs[0].spend_bundle - assert dao_cat_sb is not None - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, dao_cat_sb.name()) - await full_node_api.process_transaction_records(records=txs) + async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_cat_wallet_0.enter_dao_cat_voting_mode(dao_cat_0_bal, DEFAULT_TX_CONFIG, action_scope) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0)) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30) @@ -1060,16 +1067,11 @@ async def test_dao_proposal_partial_vote( ) vote_amount = dao_cat_0_bal - 10 - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - [proposal_tx] = await dao_wallet_0.generate_new_proposal( + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.generate_new_proposal( mint_proposal_inner, DEFAULT_TX_CONFIG, action_scope, vote_amount=vote_amount, fee=uint64(1000) ) - [proposal_tx] = await dao_wallet_0.wallet_state_manager.add_pending_transactions([proposal_tx]) - assert isinstance(proposal_tx, TransactionRecord) - proposal_sb = proposal_tx.spend_bundle - assert proposal_sb is not None - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, proposal_sb.name()) - await full_node_api.process_spend_bundles(bundles=[proposal_sb]) + await full_node_api.wait_transaction_records_entered_mempool(records=action_scope.side_effects.transactions) await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0)) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30) @@ -1084,21 +1086,17 @@ async def test_dao_proposal_partial_vote( # Create votable dao cats and add a new vote dao_cat_1_bal = await dao_cat_wallet_1.get_votable_balance() - async with dao_cat_wallet_1.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await dao_cat_wallet_1.enter_dao_cat_voting_mode(dao_cat_1_bal, DEFAULT_TX_CONFIG, action_scope) - txs = await wallet_1.wallet_state_manager.add_pending_transactions(txs) - dao_cat_sb = txs[0].spend_bundle - assert dao_cat_sb is not None - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, dao_cat_sb.name()) - await full_node_api.process_transaction_records(records=txs) + async with dao_cat_wallet_1.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_cat_wallet_1.enter_dao_cat_voting_mode(dao_cat_1_bal, DEFAULT_TX_CONFIG, action_scope) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0)) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30) - async with dao_wallet_1.wallet_state_manager.new_action_scope(push=False) as action_scope: - [vote_tx] = await dao_wallet_1.generate_proposal_vote_spend( + async with dao_wallet_1.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_1.generate_proposal_vote_spend( prop.proposal_id, dao_cat_1_bal // 2, True, DEFAULT_TX_CONFIG, action_scope ) - [vote_tx] = await wallet_1.wallet_state_manager.add_pending_transactions([vote_tx]) + [vote_tx] = action_scope.side_effects.transactions vote_sb = vote_tx.spend_bundle assert vote_sb is not None await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, vote_sb.name()) @@ -1116,20 +1114,16 @@ async def test_dao_proposal_partial_vote( assert dao_wallet_1.dao_info.proposals_list[0].yes_votes == total_votes try: - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - close_tx = await dao_wallet_0.create_proposal_close_spend( + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.create_proposal_close_spend( prop.proposal_id, DEFAULT_TX_CONFIG, action_scope, fee=uint64(100) ) - [close_tx] = await dao_wallet_0.wallet_state_manager.add_pending_transactions([close_tx]) - close_sb = close_tx.spend_bundle except Exception as e: # pragma: no cover print(e) - assert close_sb is not None - await full_node_api.process_spend_bundles(bundles=[close_sb]) + await full_node_api.process_transaction_records(action_scope.side_effects.transactions) balance = await cat_wallet_1.get_spendable_balance() - assert close_sb is not None await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0)) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30) @@ -1140,21 +1134,18 @@ async def test_dao_proposal_partial_vote( # Can we spend the newly minted CATs? old_balance = await cat_wallet_0.get_spendable_balance() ph_0 = await cat_wallet_0.get_new_inner_hash() - async with cat_wallet_1.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_tx = await cat_wallet_1.generate_signed_transaction( + async with cat_wallet_1.wallet_state_manager.new_action_scope(push=True) as action_scope: + await cat_wallet_1.generate_signed_transaction( [balance + new_mint_amount], [ph_0], DEFAULT_TX_CONFIG, action_scope ) - cat_tx = await wallet_1.wallet_state_manager.add_pending_transactions(cat_tx) - cat_sb = cat_tx[0].spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, cat_sb.name()) - await full_node_api.process_transaction_records(records=cat_tx) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0)) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30) await time_out_assert(20, cat_wallet_1.get_spendable_balance, 0) await time_out_assert(20, cat_wallet_0.get_spendable_balance, old_balance + balance + new_mint_amount) # release coins - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: await dao_wallet_0.free_coins_from_finished_proposals(DEFAULT_TX_CONFIG, action_scope) @@ -2488,14 +2479,15 @@ async def test_dao_concurrency(self_hostname: str, three_wallet_nodes: OldSimula proposal_minimum_amount=uint64(101), ) - async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - dao_wallet_0, tx_queue = await DAOWallet.create_new_dao_and_wallet( + async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + dao_wallet_0 = await DAOWallet.create_new_dao_and_wallet( wallet_node_0.wallet_state_manager, wallet_0, uint64(cat_amt), dao_rules, DEFAULT_TX_CONFIG, action_scope ) # Get the full node sim to process the wallet creation spend - tx_queue = await wallet_node_0.wallet_state_manager.add_pending_transactions(tx_queue) - await full_node_api.wait_transaction_records_entered_mempool(records=tx_queue, timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30) @@ -2516,10 +2508,11 @@ async def test_dao_concurrency(self_hostname: str, three_wallet_nodes: OldSimula # Create funding spends for xch xch_funds = uint64(500000) - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - funding_tx = await dao_wallet_0.create_add_funds_to_treasury_spend(xch_funds, DEFAULT_TX_CONFIG, action_scope) - [funding_tx] = await dao_wallet_0.wallet_state_manager.add_pending_transactions([funding_tx]) - await full_node_api.wait_transaction_records_entered_mempool(records=[funding_tx], timeout=60) + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.create_add_funds_to_treasury_spend(xch_funds, DEFAULT_TX_CONFIG, action_scope) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30) @@ -2542,12 +2535,11 @@ async def test_dao_concurrency(self_hostname: str, three_wallet_nodes: OldSimula dao_cat_wallet_2 = dao_wallet_2.wallet_state_manager.wallets[dao_wallet_2.dao_info.dao_cat_wallet_id] assert dao_cat_wallet_2 - async with cat_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_tx = await cat_wallet_0.generate_signed_transaction( - [100000, 100000], [ph_1, ph_2], DEFAULT_TX_CONFIG, action_scope - ) - cat_tx = await cat_wallet_0.wallet_state_manager.add_pending_transactions(cat_tx) - await full_node_api.wait_transaction_records_entered_mempool(records=cat_tx, timeout=60) + async with cat_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await cat_wallet_0.generate_signed_transaction([100000, 100000], [ph_1, ph_2], DEFAULT_TX_CONFIG, action_scope) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30) @@ -2560,10 +2552,11 @@ async def test_dao_concurrency(self_hostname: str, three_wallet_nodes: OldSimula # Create dao cats for voting dao_cat_0_bal = await dao_cat_wallet_0.get_votable_balance() assert dao_cat_0_bal == 100000 - async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await dao_cat_wallet_0.enter_dao_cat_voting_mode(dao_cat_0_bal, DEFAULT_TX_CONFIG, action_scope) - txs = await wallet_0.wallet_state_manager.add_pending_transactions(txs) - await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60) + async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_cat_wallet_0.enter_dao_cat_voting_mode(dao_cat_0_bal, DEFAULT_TX_CONFIG, action_scope) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30) @@ -2576,12 +2569,13 @@ async def test_dao_concurrency(self_hostname: str, three_wallet_nodes: OldSimula [proposal_amount], [None], ) - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - [proposal_tx] = await dao_wallet_0.generate_new_proposal( + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.generate_new_proposal( xch_proposal_inner, DEFAULT_TX_CONFIG, action_scope, dao_cat_0_bal, uint64(1000) ) - [proposal_tx] = await wallet_0.wallet_state_manager.add_pending_transactions([proposal_tx]) - await full_node_api.wait_transaction_records_entered_mempool(records=[proposal_tx], timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30) @@ -2603,32 +2597,34 @@ async def test_dao_concurrency(self_hostname: str, three_wallet_nodes: OldSimula # Create votable dao cats and add a new vote dao_cat_1_bal = await dao_cat_wallet_1.get_votable_balance() - async with dao_cat_wallet_1.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await dao_cat_wallet_1.enter_dao_cat_voting_mode(dao_cat_1_bal, DEFAULT_TX_CONFIG, action_scope) - txs = await wallet_1.wallet_state_manager.add_pending_transactions(txs) - await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60) + async with dao_cat_wallet_1.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_cat_wallet_1.enter_dao_cat_voting_mode(dao_cat_1_bal, DEFAULT_TX_CONFIG, action_scope) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_1, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30) - async with dao_cat_wallet_2.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await dao_cat_wallet_2.enter_dao_cat_voting_mode(dao_cat_1_bal, DEFAULT_TX_CONFIG, action_scope) - txs = await wallet_2.wallet_state_manager.add_pending_transactions(txs) - await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60) + async with dao_cat_wallet_2.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_cat_wallet_2.enter_dao_cat_voting_mode(dao_cat_1_bal, DEFAULT_TX_CONFIG, action_scope) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_2, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30) - async with dao_wallet_1.wallet_state_manager.new_action_scope(push=False) as action_scope: - [vote_tx] = await dao_wallet_1.generate_proposal_vote_spend( + async with dao_wallet_1.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_1.generate_proposal_vote_spend( prop.proposal_id, dao_cat_1_bal, True, DEFAULT_TX_CONFIG, action_scope ) - [vote_tx] = await wallet_1.wallet_state_manager.add_pending_transactions([vote_tx]) + [vote_tx] = action_scope.side_effects.transactions vote_sb = vote_tx.spend_bundle assert vote_sb is not None - async with dao_wallet_2.wallet_state_manager.new_action_scope(push=False) as action_scope: - [vote_tx_2] = await dao_wallet_2.generate_proposal_vote_spend( + async with dao_wallet_2.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_2.generate_proposal_vote_spend( prop.proposal_id, dao_cat_1_bal, True, DEFAULT_TX_CONFIG, action_scope ) - [vote_tx_2] = await wallet_2.wallet_state_manager.add_pending_transactions([vote_tx_2]) + [vote_tx_2] = action_scope.side_effects.transactions vote_2 = vote_tx_2.spend_bundle assert vote_2 is not None await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, vote_sb.name()) @@ -2655,6 +2651,7 @@ async def test_dao_concurrency(self_hostname: str, three_wallet_nodes: OldSimula [True, False], ) @pytest.mark.anyio +@pytest.mark.standard_block_tools async def test_dao_cat_exits( two_wallet_nodes_services: SimulatorsAndWalletsServices, trusted: bool, self_hostname: str ) -> None: @@ -2735,8 +2732,7 @@ async def test_dao_cat_exits( cat_wallet_0 = wallet_node_0.wallet_state_manager.wallets[dao_wallet_res_0.cat_wallet_id] dao_cat_wallet_0 = wallet_node_0.wallet_state_manager.wallets[dao_wallet_res_0.dao_cat_wallet_id] txs = await wallet_0.wallet_state_manager.tx_store.get_all_unconfirmed() - for tx in txs: - await full_node_api.wait_transaction_records_entered_mempool(records=[tx], timeout=60) + await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60) await full_node_api.process_transaction_records(records=txs, timeout=60) await full_node_api.process_all_wallet_transactions(wallet_0, 60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30) @@ -2886,14 +2882,15 @@ async def test_dao_reorgs(self_hostname: str, two_wallet_nodes: OldSimulatorsAnd proposal_minimum_amount=uint64(101), ) - async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - dao_wallet_0, tx_queue = await DAOWallet.create_new_dao_and_wallet( + async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + dao_wallet_0 = await DAOWallet.create_new_dao_and_wallet( wallet_node_0.wallet_state_manager, wallet_0, uint64(cat_amt), dao_rules, DEFAULT_TX_CONFIG, action_scope ) # Get the full node sim to process the wallet creation spend - tx_queue = await wallet_node_0.wallet_state_manager.add_pending_transactions(tx_queue) - await full_node_api.wait_transaction_records_entered_mempool(records=tx_queue, timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30) @@ -2926,14 +2923,15 @@ async def test_dao_reorgs(self_hostname: str, two_wallet_nodes: OldSimulatorsAnd # Create funding spends for xch xch_funds = uint64(500000) - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - funding_tx = await dao_wallet_0.create_add_funds_to_treasury_spend( + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.create_add_funds_to_treasury_spend( xch_funds, DEFAULT_TX_CONFIG, action_scope, ) - [funding_tx] = await dao_wallet_0.wallet_state_manager.add_pending_transactions([funding_tx]) - await full_node_api.wait_transaction_records_entered_mempool(records=[funding_tx], timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30) @@ -2957,15 +2955,16 @@ async def test_dao_reorgs(self_hostname: str, two_wallet_nodes: OldSimulatorsAnd assert cat_wallet_1 assert dao_cat_wallet_1 - async with cat_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_tx = await cat_wallet_0.generate_signed_transaction( + async with cat_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await cat_wallet_0.generate_signed_transaction( [100000], [ph_1], DEFAULT_TX_CONFIG, action_scope, ) - cat_tx = await cat_wallet_0.wallet_state_manager.add_pending_transactions(cat_tx) - await full_node_api.wait_transaction_records_entered_mempool(records=cat_tx, timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30) @@ -2975,10 +2974,11 @@ async def test_dao_reorgs(self_hostname: str, two_wallet_nodes: OldSimulatorsAnd # Create dao cats for voting dao_cat_0_bal = await dao_cat_wallet_0.get_votable_balance() assert dao_cat_0_bal == 200000 - async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await dao_cat_wallet_0.enter_dao_cat_voting_mode(dao_cat_0_bal, DEFAULT_TX_CONFIG, action_scope) - txs = await wallet_0.wallet_state_manager.add_pending_transactions(txs) - await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60) + async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_cat_wallet_0.enter_dao_cat_voting_mode(dao_cat_0_bal, DEFAULT_TX_CONFIG, action_scope) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30) @@ -2991,12 +2991,13 @@ async def test_dao_reorgs(self_hostname: str, two_wallet_nodes: OldSimulatorsAnd [proposal_amount], [None], ) - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - [proposal_tx] = await dao_wallet_0.generate_new_proposal( + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.generate_new_proposal( xch_proposal_inner, DEFAULT_TX_CONFIG, action_scope, dao_cat_0_bal, uint64(1000) ) - [proposal_tx] = await wallet_0.wallet_state_manager.add_pending_transactions([proposal_tx]) - await full_node_api.wait_transaction_records_entered_mempool(records=[proposal_tx], timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30) @@ -3028,19 +3029,21 @@ async def test_dao_reorgs(self_hostname: str, two_wallet_nodes: OldSimulatorsAnd # Create votable dao cats and add a new vote dao_cat_1_bal = await dao_cat_wallet_1.get_votable_balance() - async with dao_cat_wallet_1.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await dao_cat_wallet_1.enter_dao_cat_voting_mode(dao_cat_1_bal, DEFAULT_TX_CONFIG, action_scope) - txs = await wallet_1.wallet_state_manager.add_pending_transactions(txs) - await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60) + async with dao_cat_wallet_1.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_cat_wallet_1.enter_dao_cat_voting_mode(dao_cat_1_bal, DEFAULT_TX_CONFIG, action_scope) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_1, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30) - async with dao_cat_wallet_1.wallet_state_manager.new_action_scope(push=False) as action_scope: - [vote_tx] = await dao_wallet_1.generate_proposal_vote_spend( + async with dao_cat_wallet_1.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_1.generate_proposal_vote_spend( prop.proposal_id, dao_cat_1_bal, True, DEFAULT_TX_CONFIG, action_scope ) - [vote_tx] = await wallet_1.wallet_state_manager.add_pending_transactions([vote_tx]) - await full_node_api.wait_transaction_records_entered_mempool(records=[vote_tx], timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_1, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30) @@ -3065,12 +3068,13 @@ async def test_dao_reorgs(self_hostname: str, two_wallet_nodes: OldSimulatorsAnd await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0)) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30) - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - close_tx = await dao_wallet_0.create_proposal_close_spend( + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.create_proposal_close_spend( prop.proposal_id, DEFAULT_TX_CONFIG, action_scope, fee=uint64(100) ) - [close_tx] = await dao_wallet_0.wallet_state_manager.add_pending_transactions([close_tx]) - await full_node_api.wait_transaction_records_entered_mempool(records=[close_tx], timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30) @@ -3153,8 +3157,8 @@ async def test_dao_votes(self_hostname: str, three_wallet_nodes: OldSimulatorsAn proposal_minimum_amount=proposal_min_amt, ) - async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - dao_wallet_0, tx_queue = await DAOWallet.create_new_dao_and_wallet( + async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + dao_wallet_0 = await DAOWallet.create_new_dao_and_wallet( wallet_node_0.wallet_state_manager, wallet_0, uint64(cat_issuance), @@ -3163,8 +3167,9 @@ async def test_dao_votes(self_hostname: str, three_wallet_nodes: OldSimulatorsAn action_scope, ) - tx_queue = await wallet_node_0.wallet_state_manager.add_pending_transactions(tx_queue) - await full_node_api.wait_transaction_records_entered_mempool(records=tx_queue, timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30) @@ -3182,38 +3187,43 @@ async def test_dao_votes(self_hostname: str, three_wallet_nodes: OldSimulatorsAn dc_5 = uint64(10000) # Lockup voting cats for all wallets - async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await dao_cat_wallet_0.enter_dao_cat_voting_mode(dc_1, DEFAULT_TX_CONFIG, action_scope, fee=base_fee) - txs = await wallet_0.wallet_state_manager.add_pending_transactions(txs) - await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60) + async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_cat_wallet_0.enter_dao_cat_voting_mode(dc_1, DEFAULT_TX_CONFIG, action_scope, fee=base_fee) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30) - async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await dao_cat_wallet_0.enter_dao_cat_voting_mode(dc_2, DEFAULT_TX_CONFIG, action_scope, fee=base_fee) - txs = await wallet_0.wallet_state_manager.add_pending_transactions(txs) - await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60) + async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_cat_wallet_0.enter_dao_cat_voting_mode(dc_2, DEFAULT_TX_CONFIG, action_scope, fee=base_fee) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30) - async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await dao_cat_wallet_0.enter_dao_cat_voting_mode(dc_3, DEFAULT_TX_CONFIG, action_scope, fee=base_fee) - txs = await wallet_0.wallet_state_manager.add_pending_transactions(txs) - await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60) + async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_cat_wallet_0.enter_dao_cat_voting_mode(dc_3, DEFAULT_TX_CONFIG, action_scope, fee=base_fee) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30) - async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await dao_cat_wallet_0.enter_dao_cat_voting_mode(dc_4, DEFAULT_TX_CONFIG, action_scope, fee=base_fee) - txs = await wallet_0.wallet_state_manager.add_pending_transactions(txs) - await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60) + async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_cat_wallet_0.enter_dao_cat_voting_mode(dc_4, DEFAULT_TX_CONFIG, action_scope, fee=base_fee) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30) - async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await dao_cat_wallet_0.enter_dao_cat_voting_mode(dc_5, DEFAULT_TX_CONFIG, action_scope, fee=base_fee) - txs = await wallet_0.wallet_state_manager.add_pending_transactions(txs) - await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60) + async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_cat_wallet_0.enter_dao_cat_voting_mode(dc_5, DEFAULT_TX_CONFIG, action_scope, fee=base_fee) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30) @@ -3221,10 +3231,11 @@ async def test_dao_votes(self_hostname: str, three_wallet_nodes: OldSimulatorsAn # Create funding spend so the treasury holds some XCH xch_funds = uint64(500000) - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - funding_tx = await dao_wallet_0.create_add_funds_to_treasury_spend(xch_funds, DEFAULT_TX_CONFIG, action_scope) - [funding_tx] = await dao_wallet_0.wallet_state_manager.add_pending_transactions([funding_tx]) - await full_node_api.wait_transaction_records_entered_mempool(records=[funding_tx], timeout=60) + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.create_add_funds_to_treasury_spend(xch_funds, DEFAULT_TX_CONFIG, action_scope) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30) @@ -3244,12 +3255,13 @@ async def test_dao_votes(self_hostname: str, three_wallet_nodes: OldSimulatorsAn vote_1 = uint64(120000) vote_2 = uint64(150000) - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - [proposal_tx] = await dao_wallet_0.generate_new_proposal( + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.generate_new_proposal( xch_proposal_inner, DEFAULT_TX_CONFIG, action_scope, vote_1, fee=base_fee ) - [proposal_tx] = await wallet_0.wallet_state_manager.add_pending_transactions([proposal_tx]) - await full_node_api.wait_transaction_records_entered_mempool(records=[proposal_tx], timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30) @@ -3258,12 +3270,13 @@ async def test_dao_votes(self_hostname: str, three_wallet_nodes: OldSimulatorsAn assert dao_wallet_0.dao_info.proposals_list[0].timer_coin is not None prop_0 = dao_wallet_0.dao_info.proposals_list[0] - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - [proposal_tx] = await dao_wallet_0.generate_new_proposal( + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.generate_new_proposal( xch_proposal_inner, DEFAULT_TX_CONFIG, action_scope, vote_2, fee=base_fee ) - [proposal_tx] = await wallet_0.wallet_state_manager.add_pending_transactions([proposal_tx]) - await full_node_api.wait_transaction_records_entered_mempool(records=[proposal_tx], timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30) @@ -3271,36 +3284,39 @@ async def test_dao_votes(self_hostname: str, three_wallet_nodes: OldSimulatorsAn assert dao_wallet_0.dao_info.proposals_list[1].amount_voted == vote_2 vote_3 = uint64(30000) - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - [vote_tx] = await dao_wallet_0.generate_proposal_vote_spend( + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.generate_proposal_vote_spend( prop_0.proposal_id, vote_3, True, DEFAULT_TX_CONFIG, action_scope ) - [vote_tx] = await wallet_0.wallet_state_manager.add_pending_transactions([vote_tx]) - await full_node_api.wait_transaction_records_entered_mempool(records=[vote_tx], timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30) assert dao_wallet_0.dao_info.proposals_list[0].amount_voted == vote_1 + vote_3 vote_4 = uint64(60000) - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - [vote_tx] = await dao_wallet_0.generate_proposal_vote_spend( + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.generate_proposal_vote_spend( prop_0.proposal_id, vote_4, True, DEFAULT_TX_CONFIG, action_scope ) - [vote_tx] = await wallet_0.wallet_state_manager.add_pending_transactions([vote_tx]) - await full_node_api.wait_transaction_records_entered_mempool(records=[vote_tx], timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30) assert dao_wallet_0.dao_info.proposals_list[0].amount_voted == vote_1 + vote_3 + vote_4 vote_5 = uint64(1) - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - [proposal_tx] = await dao_wallet_0.generate_new_proposal( + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.generate_new_proposal( xch_proposal_inner, DEFAULT_TX_CONFIG, action_scope, vote_5, fee=base_fee ) - [proposal_tx] = await wallet_0.wallet_state_manager.add_pending_transactions([proposal_tx]) - await full_node_api.wait_transaction_records_entered_mempool(records=[proposal_tx], timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30) @@ -3310,30 +3326,31 @@ async def test_dao_votes(self_hostname: str, three_wallet_nodes: OldSimulatorsAn vote_6 = uint64(20000) for i in range(10): - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - [vote_tx] = await dao_wallet_0.generate_proposal_vote_spend( + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.generate_proposal_vote_spend( prop_2.proposal_id, vote_6, True, DEFAULT_TX_CONFIG, action_scope ) - [vote_tx] = await wallet_0.wallet_state_manager.add_pending_transactions([vote_tx]) - await full_node_api.wait_transaction_records_entered_mempool(records=[vote_tx], timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30) assert dao_wallet_0.dao_info.proposals_list[2].amount_voted == 200001 - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - close_tx = await dao_wallet_0.create_proposal_close_spend(prop_0.proposal_id, DEFAULT_TX_CONFIG, action_scope) - [close_tx] = await wallet_0.wallet_state_manager.add_pending_transactions([close_tx]) - await full_node_api.wait_transaction_records_entered_mempool(records=[close_tx], timeout=60) + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.create_proposal_close_spend(prop_0.proposal_id, DEFAULT_TX_CONFIG, action_scope) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30) - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - [proposal_tx] = await dao_wallet_0.generate_new_proposal( - xch_proposal_inner, DEFAULT_TX_CONFIG, action_scope, fee=base_fee - ) - [proposal_tx] = await wallet_0.wallet_state_manager.add_pending_transactions([proposal_tx]) - await full_node_api.wait_transaction_records_entered_mempool(records=[proposal_tx], timeout=60) + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.generate_new_proposal(xch_proposal_inner, DEFAULT_TX_CONFIG, action_scope, fee=base_fee) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30) @@ -3394,8 +3411,8 @@ async def test_dao_resync(self_hostname: str, two_wallet_nodes: OldSimulatorsAnd fee = uint64(10) fee_for_cat = uint64(20) - async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - dao_wallet_0, tx_queue = await DAOWallet.create_new_dao_and_wallet( + async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + dao_wallet_0 = await DAOWallet.create_new_dao_and_wallet( wallet_node_0.wallet_state_manager, wallet_0, uint64(cat_amt * 2), @@ -3406,8 +3423,9 @@ async def test_dao_resync(self_hostname: str, two_wallet_nodes: OldSimulatorsAnd fee_for_cat=fee_for_cat, ) - tx_queue = await dao_wallet_0.wallet_state_manager.add_pending_transactions(tx_queue) - await full_node_api.wait_transaction_records_entered_mempool(records=tx_queue, timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30) @@ -3428,20 +3446,22 @@ async def test_dao_resync(self_hostname: str, two_wallet_nodes: OldSimulatorsAnd # Send some cats to the dao_cat lockup dao_cat_amt = uint64(100) - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await dao_wallet_0.enter_dao_cat_voting_mode(dao_cat_amt, DEFAULT_TX_CONFIG, action_scope) - txs = await wallet_0.wallet_state_manager.add_pending_transactions(txs) + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.enter_dao_cat_voting_mode(dao_cat_amt, DEFAULT_TX_CONFIG, action_scope) - await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30) # send some cats from wallet_0 to wallet_1 so we can test voting - async with cat_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_txs = await cat_wallet_0.generate_signed_transaction([cat_amt], [ph_1], DEFAULT_TX_CONFIG, action_scope) - cat_txs = await wallet_0.wallet_state_manager.add_pending_transactions(cat_txs) + async with cat_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await cat_wallet_0.generate_signed_transaction([cat_amt], [ph_1], DEFAULT_TX_CONFIG, action_scope) - await full_node_api.wait_transaction_records_entered_mempool(records=cat_txs, timeout=60) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30) @@ -3455,12 +3475,11 @@ async def test_dao_resync(self_hostname: str, two_wallet_nodes: OldSimulatorsAnd [proposal_amount_1], [None], ) - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - [proposal_tx] = await dao_wallet_0.generate_new_proposal( - xch_proposal_inner, DEFAULT_TX_CONFIG, action_scope, uint64(10) - ) - [proposal_tx] = await wallet_0.wallet_state_manager.add_pending_transactions([proposal_tx]) - await full_node_api.wait_transaction_records_entered_mempool(records=[proposal_tx], timeout=60) + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.generate_new_proposal(xch_proposal_inner, DEFAULT_TX_CONFIG, action_scope, uint64(10)) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30) @@ -3471,10 +3490,11 @@ async def test_dao_resync(self_hostname: str, two_wallet_nodes: OldSimulatorsAnd [proposal_amount_1], [None], ) - async with dao_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - [proposal_tx] = await dao_wallet_0.generate_new_proposal(xch_proposal_inner, DEFAULT_TX_CONFIG, action_scope) - [proposal_tx] = await wallet_0.wallet_state_manager.add_pending_transactions([proposal_tx]) - await full_node_api.wait_transaction_records_entered_mempool(records=[proposal_tx], timeout=60) + async with dao_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dao_wallet_0.generate_new_proposal(xch_proposal_inner, DEFAULT_TX_CONFIG, action_scope) + await full_node_api.wait_transaction_records_entered_mempool( + records=action_scope.side_effects.transactions, timeout=60 + ) await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30) diff --git a/chia/_tests/wallet/db_wallet/test_dl_offers.py b/chia/_tests/wallet/db_wallet/test_dl_offers.py index 2e003bf8c896..9e9b6723614b 100644 --- a/chia/_tests/wallet/db_wallet/test_dl_offers.py +++ b/chia/_tests/wallet/db_wallet/test_dl_offers.py @@ -62,24 +62,22 @@ async def test_dl_offers(wallets_prefarm: Any, trusted: bool) -> None: fee = uint64(1_999_999_999_999) - async with dl_wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - std_record, launcher_id_maker = await dl_wallet_maker.generate_new_reporter( + async with dl_wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + launcher_id_maker = await dl_wallet_maker.generate_new_reporter( maker_root, DEFAULT_TX_CONFIG, action_scope, fee=fee ) assert await dl_wallet_maker.get_latest_singleton(launcher_id_maker) is not None - [std_record] = await wsm_maker.add_pending_transactions([std_record]) - await full_node_api.process_transaction_records(records=[std_record]) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) maker_funds -= fee maker_funds -= 1 await time_out_assert(15, is_singleton_confirmed_and_root, True, dl_wallet_maker, launcher_id_maker, maker_root) - async with dl_wallet_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - std_record, launcher_id_taker = await dl_wallet_taker.generate_new_reporter( + async with dl_wallet_taker.wallet_state_manager.new_action_scope(push=True) as action_scope: + launcher_id_taker = await dl_wallet_taker.generate_new_reporter( taker_root, DEFAULT_TX_CONFIG, action_scope, fee=fee ) assert await dl_wallet_taker.get_latest_singleton(launcher_id_taker) is not None - [std_record] = await wsm_taker.add_pending_transactions([std_record]) - await full_node_api.process_transaction_records(records=[std_record]) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) taker_funds -= fee taker_funds -= 1 await time_out_assert(15, is_singleton_confirmed_and_root, True, dl_wallet_taker, launcher_id_taker, taker_root) @@ -105,7 +103,7 @@ async def test_dl_offers(wallets_prefarm: Any, trusted: bool) -> None: fee = uint64(2_000_000_000_000) async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, offer_maker, _, error = await trade_manager_maker.create_offer_for_ids( + success, offer_maker, error = await trade_manager_maker.create_offer_for_ids( {launcher_id_maker: -1, launcher_id_taker: 1}, DEFAULT_TX_CONFIG, action_scope, @@ -146,8 +144,10 @@ async def test_dl_offers(wallets_prefarm: Any, trusted: bool) -> None: [maker_offer], signing_response = await wallet_node_maker.wallet_state_manager.sign_offers( [Offer.from_bytes(offer_maker.offer)] ) - async with trade_manager_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - offer_taker, tx_records = await trade_manager_taker.respond_to_offer( + async with trade_manager_taker.wallet_state_manager.new_action_scope( + push=True, additional_signing_responses=signing_response + ) as action_scope: + offer_taker = await trade_manager_taker.respond_to_offer( Offer.from_bytes(offer_maker.offer), peer, DEFAULT_TX_CONFIG, @@ -179,11 +179,7 @@ async def test_dl_offers(wallets_prefarm: Any, trusted: bool) -> None: ), fee=fee, ) - tx_records = await trade_manager_taker.wallet_state_manager.add_pending_transactions( - tx_records, additional_signing_responses=signing_response - ) assert offer_taker is not None - assert tx_records is not None assert await trade_manager_maker.get_offer_summary(Offer.from_bytes(offer_taker.offer)) == { "offered": [ @@ -216,7 +212,7 @@ async def test_dl_offers(wallets_prefarm: Any, trusted: bool) -> None: await time_out_assert(15, wallet_maker.get_unconfirmed_balance, maker_funds) await time_out_assert(15, wallet_taker.get_unconfirmed_balance, taker_funds - fee) - await full_node_api.process_transaction_records(records=tx_records) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) maker_funds -= fee taker_funds -= fee @@ -239,12 +235,11 @@ async def is_singleton_generation(wallet: DataLayerWallet, launcher_id: bytes32, await time_out_assert(15, is_singleton_generation, True, dl_wallet_taker, launcher_id_taker, 2) - async with dl_wallet_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await dl_wallet_taker.create_update_state_spend( + async with dl_wallet_taker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dl_wallet_taker.create_update_state_spend( launcher_id_taker, bytes32([2] * 32), DEFAULT_TX_CONFIG, action_scope ) - txs = await wallet_node_taker.wallet_state_manager.add_pending_transactions(txs) - await full_node_api.process_transaction_records(records=txs) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) @pytest.mark.parametrize( @@ -263,16 +258,14 @@ async def test_dl_offer_cancellation(wallets_prefarm: Any, trusted: bool) -> Non ROWS = [bytes32([i] * 32) for i in range(0, 10)] root, _ = build_merkle_tree(ROWS) - async with dl_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - std_record, launcher_id = await dl_wallet.generate_new_reporter(root, DEFAULT_TX_CONFIG, action_scope) + async with dl_wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + launcher_id = await dl_wallet.generate_new_reporter(root, DEFAULT_TX_CONFIG, action_scope) assert await dl_wallet.get_latest_singleton(launcher_id) is not None - [std_record] = await wsm.add_pending_transactions([std_record]) - await full_node_api.process_transaction_records(records=[std_record]) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(15, is_singleton_confirmed_and_root, True, dl_wallet, launcher_id, root) - async with dl_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - std_record_2, launcher_id_2 = await dl_wallet.generate_new_reporter(root, DEFAULT_TX_CONFIG, action_scope) - [std_record_2] = await wsm.add_pending_transactions([std_record_2]) - await full_node_api.process_transaction_records(records=[std_record_2]) + async with dl_wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + launcher_id_2 = await dl_wallet.generate_new_reporter(root, DEFAULT_TX_CONFIG, action_scope) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) trade_manager = wsm.trade_manager @@ -281,7 +274,7 @@ async def test_dl_offer_cancellation(wallets_prefarm: Any, trusted: bool) -> Non root, proofs = build_merkle_tree(ROWS) async with trade_manager.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, offer, _, error = await trade_manager.create_offer_for_ids( + success, offer, error = await trade_manager.create_offer_for_ids( {launcher_id: -1, launcher_id_2: 1}, DEFAULT_TX_CONFIG, action_scope, @@ -304,14 +297,14 @@ async def test_dl_offer_cancellation(wallets_prefarm: Any, trusted: bool) -> Non assert success is True assert offer is not None - async with trade_manager.wallet_state_manager.new_action_scope(push=False) as action_scope: - cancellation_txs = await trade_manager.cancel_pending_offers( + async with trade_manager.wallet_state_manager.new_action_scope(push=True) as action_scope: + await trade_manager.cancel_pending_offers( [offer.trade_id], DEFAULT_TX_CONFIG, action_scope, fee=uint64(2_000_000_000_000), secure=True ) - cancellation_txs = await trade_manager.wallet_state_manager.add_pending_transactions(cancellation_txs) - assert len(cancellation_txs) == 2 + # One outgoing for cancel, one outgoing for fee, one incoming from cancel + assert len(action_scope.side_effects.transactions) == 3 await time_out_assert(15, get_trade_and_status, TradeStatus.PENDING_CANCEL, trade_manager, offer) - await full_node_api.process_transaction_records(records=cancellation_txs) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(15, get_trade_and_status, TradeStatus.CANCELLED, trade_manager, offer) @@ -340,44 +333,40 @@ async def test_multiple_dl_offers(wallets_prefarm: Any, trusted: bool) -> None: fee = uint64(1_999_999_999_999) - async with dl_wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - std_record, launcher_id_maker_1 = await dl_wallet_maker.generate_new_reporter( + async with dl_wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + launcher_id_maker_1 = await dl_wallet_maker.generate_new_reporter( maker_root, DEFAULT_TX_CONFIG, action_scope, fee=fee ) assert await dl_wallet_maker.get_latest_singleton(launcher_id_maker_1) is not None - [std_record] = await wsm_maker.add_pending_transactions([std_record]) - await full_node_api.process_transaction_records(records=[std_record]) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) maker_funds -= fee maker_funds -= 1 await time_out_assert(15, is_singleton_confirmed_and_root, True, dl_wallet_maker, launcher_id_maker_1, maker_root) - async with dl_wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - std_record, launcher_id_maker_2 = await dl_wallet_maker.generate_new_reporter( + async with dl_wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + launcher_id_maker_2 = await dl_wallet_maker.generate_new_reporter( maker_root, DEFAULT_TX_CONFIG, action_scope, fee=fee ) assert await dl_wallet_maker.get_latest_singleton(launcher_id_maker_2) is not None - [std_record] = await wsm_maker.add_pending_transactions([std_record]) - await full_node_api.process_transaction_records(records=[std_record]) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) maker_funds -= fee maker_funds -= 1 await time_out_assert(15, is_singleton_confirmed_and_root, True, dl_wallet_maker, launcher_id_maker_2, maker_root) - async with dl_wallet_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - std_record, launcher_id_taker_1 = await dl_wallet_taker.generate_new_reporter( + async with dl_wallet_taker.wallet_state_manager.new_action_scope(push=True) as action_scope: + launcher_id_taker_1 = await dl_wallet_taker.generate_new_reporter( taker_root, DEFAULT_TX_CONFIG, action_scope, fee=fee ) assert await dl_wallet_taker.get_latest_singleton(launcher_id_taker_1) is not None - [std_record] = await wsm_taker.add_pending_transactions([std_record]) - await full_node_api.process_transaction_records(records=[std_record]) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) taker_funds -= fee taker_funds -= 1 await time_out_assert(15, is_singleton_confirmed_and_root, True, dl_wallet_taker, launcher_id_taker_1, taker_root) - async with dl_wallet_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - std_record, launcher_id_taker_2 = await dl_wallet_taker.generate_new_reporter( + async with dl_wallet_taker.wallet_state_manager.new_action_scope(push=True) as action_scope: + launcher_id_taker_2 = await dl_wallet_taker.generate_new_reporter( taker_root, DEFAULT_TX_CONFIG, action_scope, fee=fee ) assert await dl_wallet_taker.get_latest_singleton(launcher_id_taker_2) is not None - [std_record] = await wsm_taker.add_pending_transactions([std_record]) - await full_node_api.process_transaction_records(records=[std_record]) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) taker_funds -= fee taker_funds -= 1 await time_out_assert(15, is_singleton_confirmed_and_root, True, dl_wallet_taker, launcher_id_taker_2, taker_root) @@ -407,7 +396,7 @@ async def test_multiple_dl_offers(wallets_prefarm: Any, trusted: bool) -> None: fee = uint64(2_000_000_000_000) async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, offer_maker, _, error = await trade_manager_maker.create_offer_for_ids( + success, offer_maker, error = await trade_manager_maker.create_offer_for_ids( {launcher_id_maker_1: -1, launcher_id_taker_1: 1, launcher_id_maker_2: -1, launcher_id_taker_2: 1}, DEFAULT_TX_CONFIG, action_scope, @@ -446,8 +435,10 @@ async def test_multiple_dl_offers(wallets_prefarm: Any, trusted: bool) -> None: [maker_offer], signing_response = await wallet_node_maker.wallet_state_manager.sign_offers( [Offer.from_bytes(offer_maker.offer)] ) - async with trade_manager_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - offer_taker, tx_records = await trade_manager_taker.respond_to_offer( + async with trade_manager_taker.wallet_state_manager.new_action_scope( + push=True, additional_signing_responses=signing_response + ) as action_scope: + offer_taker = await trade_manager_taker.respond_to_offer( Offer.from_bytes(offer_maker.offer), peer, DEFAULT_TX_CONFIG, @@ -492,11 +483,7 @@ async def test_multiple_dl_offers(wallets_prefarm: Any, trusted: bool) -> None: ), fee=fee, ) - tx_records = await trade_manager_taker.wallet_state_manager.add_pending_transactions( - tx_records, additional_signing_responses=signing_response - ) assert offer_taker is not None - assert tx_records is not None wallet_maker = wsm_maker.main_wallet wallet_taker = wsm_taker.main_wallet @@ -504,7 +491,7 @@ async def test_multiple_dl_offers(wallets_prefarm: Any, trusted: bool) -> None: await time_out_assert(15, wallet_maker.get_unconfirmed_balance, maker_funds) await time_out_assert(15, wallet_taker.get_unconfirmed_balance, taker_funds - fee) - await full_node_api.process_transaction_records(records=tx_records) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) maker_funds -= fee taker_funds -= fee diff --git a/chia/_tests/wallet/db_wallet/test_dl_wallet.py b/chia/_tests/wallet/db_wallet/test_dl_wallet.py index f0e79ebdd098..2d825f0e3541 100644 --- a/chia/_tests/wallet/db_wallet/test_dl_wallet.py +++ b/chia/_tests/wallet/db_wallet/test_dl_wallet.py @@ -75,8 +75,8 @@ async def test_initial_creation( current_root = current_tree.calculate_root() for i in range(0, 2): - async with dl_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - std_record, launcher_id = await dl_wallet.generate_new_reporter( + async with dl_wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + launcher_id = await dl_wallet.generate_new_reporter( current_root, DEFAULT_TX_CONFIG.override(reuse_puzhash=reuse_puzhash), action_scope, @@ -84,12 +84,9 @@ async def test_initial_creation( ) assert await dl_wallet.get_latest_singleton(launcher_id) is not None - - [std_record] = await wallet_node_0.wallet_state_manager.add_pending_transactions([std_record]) - await full_node_api.process_transaction_records(records=[std_record]) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(15, is_singleton_confirmed, True, dl_wallet, launcher_id) - await asyncio.sleep(0.5) await time_out_assert(10, wallet_0.get_unconfirmed_balance, 0) await time_out_assert(10, wallet_0.get_confirmed_balance, 0) @@ -133,19 +130,17 @@ async def test_get_owned_singletons( expected_launcher_ids = set() for i in range(0, 2): - async with dl_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - std_record, launcher_id = await dl_wallet.generate_new_reporter( + async with dl_wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + launcher_id = await dl_wallet.generate_new_reporter( current_root, DEFAULT_TX_CONFIG, action_scope, fee=uint64(1999999999999) ) expected_launcher_ids.add(launcher_id) assert await dl_wallet.get_latest_singleton(launcher_id) is not None - [std_record] = await wallet_node_0.wallet_state_manager.add_pending_transactions([std_record]) - await full_node_api.process_transaction_records(records=[std_record]) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(15, is_singleton_confirmed, True, dl_wallet, launcher_id) - await asyncio.sleep(0.5) owned_singletons = await dl_wallet.get_owned_singletons() owned_launcher_ids = sorted(singleton.launcher_id for singleton in owned_singletons) @@ -194,15 +189,11 @@ async def test_tracking_non_owned( current_tree = MerkleTree(nodes) current_root = current_tree.calculate_root() - async with dl_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - std_record, launcher_id = await dl_wallet_0.generate_new_reporter( - current_root, DEFAULT_TX_CONFIG, action_scope - ) + async with dl_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + launcher_id = await dl_wallet_0.generate_new_reporter(current_root, DEFAULT_TX_CONFIG, action_scope) assert await dl_wallet_0.get_latest_singleton(launcher_id) is not None - - [std_record] = await wallet_node_0.wallet_state_manager.add_pending_transactions([std_record]) - await full_node_api.process_transaction_records(records=[std_record]) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(15, is_singleton_confirmed, True, dl_wallet_0, launcher_id) await asyncio.sleep(0.5) @@ -213,16 +204,12 @@ async def test_tracking_non_owned( for i in range(0, 5): new_root = MerkleTree([Program.to("root").get_tree_hash()]).calculate_root() - async with dl_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await dl_wallet_0.create_update_state_spend( - launcher_id, new_root, DEFAULT_TX_CONFIG, action_scope - ) + async with dl_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dl_wallet_0.create_update_state_spend(launcher_id, new_root, DEFAULT_TX_CONFIG, action_scope) - txs = await wallet_node_0.wallet_state_manager.add_pending_transactions(txs) - await full_node_api.process_transaction_records(records=txs) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(15, is_singleton_confirmed, True, dl_wallet_0, launcher_id) - await asyncio.sleep(0.5) async def do_tips_match() -> bool: latest_singleton_0 = await dl_wallet_0.get_latest_singleton(launcher_id) @@ -271,17 +258,16 @@ async def test_lifecycle( current_root = current_tree.calculate_root() async with dl_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - std_record, launcher_id = await dl_wallet.generate_new_reporter( - current_root, DEFAULT_TX_CONFIG, action_scope - ) + launcher_id = await dl_wallet.generate_new_reporter(current_root, DEFAULT_TX_CONFIG, action_scope) assert await dl_wallet.get_latest_singleton(launcher_id) is not None - [std_record] = await wallet_node_0.wallet_state_manager.add_pending_transactions([std_record]) + [std_record] = await wallet_node_0.wallet_state_manager.add_pending_transactions( + action_scope.side_effects.transactions + ) await full_node_api.process_transaction_records(records=[std_record]) await time_out_assert(15, is_singleton_confirmed, True, dl_wallet, launcher_id) - await asyncio.sleep(0.5) previous_record = await dl_wallet.get_latest_singleton(launcher_id) assert previous_record is not None @@ -290,7 +276,7 @@ async def test_lifecycle( new_root = MerkleTree([Program.to("root").get_tree_hash()]).calculate_root() async with dl_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await dl_wallet.generate_signed_transaction( + await dl_wallet.generate_signed_transaction( [previous_record.lineage_proof.amount], [previous_record.inner_puzzle_hash], DEFAULT_TX_CONFIG, @@ -299,15 +285,21 @@ async def test_lifecycle( new_root_hash=new_root, fee=uint64(1999999999999), ) - assert txs[0].spend_bundle is not None + assert action_scope.side_effects.transactions[0].spend_bundle is not None with pytest.raises(ValueError, match="is currently pending"): - async with dl_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with dl_wallet.wallet_state_manager.new_action_scope(push=False) as failed_action_scope: await dl_wallet.generate_signed_transaction( [previous_record.lineage_proof.amount], [previous_record.inner_puzzle_hash], DEFAULT_TX_CONFIG, - action_scope, - coins={txs[0].spend_bundle.removals()[0]}, + failed_action_scope, + coins={ + next( + rem + for rem in action_scope.side_effects.transactions[0].spend_bundle.removals() + if rem.amount == 1 + ) + }, fee=uint64(1999999999999), ) @@ -316,7 +308,7 @@ async def test_lifecycle( assert new_record != previous_record assert not new_record.confirmed - txs = await wallet_node_0.wallet_state_manager.add_pending_transactions(txs) + txs = await wallet_node_0.wallet_state_manager.add_pending_transactions(action_scope.side_effects.transactions) await full_node_api.process_transaction_records(records=txs) await time_out_assert(15, is_singleton_confirmed, True, dl_wallet, launcher_id) @@ -332,13 +324,13 @@ async def test_lifecycle( new_root = MerkleTree([Program.to("new root").get_tree_hash()]).calculate_root() async with dl_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await dl_wallet.create_update_state_spend(launcher_id, new_root, DEFAULT_TX_CONFIG, action_scope) + await dl_wallet.create_update_state_spend(launcher_id, new_root, DEFAULT_TX_CONFIG, action_scope) new_record = await dl_wallet.get_latest_singleton(launcher_id) assert new_record is not None assert new_record != previous_record assert not new_record.confirmed - txs = await wallet_node_0.wallet_state_manager.add_pending_transactions(txs) + txs = await wallet_node_0.wallet_state_manager.add_pending_transactions(action_scope.side_effects.transactions) await full_node_api.process_transaction_records(records=txs) await time_out_assert(15, is_singleton_confirmed, True, dl_wallet, launcher_id) @@ -399,14 +391,14 @@ async def is_singleton_confirmed(wallet: DataLayerWallet, lid: bytes32) -> bool: return latest_singleton.confirmed async with dl_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - std_record, launcher_id = await dl_wallet_0.generate_new_reporter( - current_root, DEFAULT_TX_CONFIG, action_scope - ) + launcher_id = await dl_wallet_0.generate_new_reporter(current_root, DEFAULT_TX_CONFIG, action_scope) initial_record = await dl_wallet_0.get_latest_singleton(launcher_id) assert initial_record is not None - [std_record] = await wallet_node_0.wallet_state_manager.add_pending_transactions([std_record]) + [std_record] = await wallet_node_0.wallet_state_manager.add_pending_transactions( + action_scope.side_effects.transactions + ) await asyncio.wait_for( full_node_api.process_transaction_records(records=[std_record]), timeout=adjusted_timeout(timeout=15), @@ -423,17 +415,19 @@ async def is_singleton_confirmed(wallet: DataLayerWallet, lid: bytes32) -> bool: await asyncio.sleep(0.5) # Because these have the same fee, the one that gets pushed first will win - async with dl_wallet_1.wallet_state_manager.new_action_scope(push=False) as action_scope: - report_txs = await dl_wallet_1.create_update_state_spend( + async with dl_wallet_1.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dl_wallet_1.create_update_state_spend( launcher_id, current_record.root, DEFAULT_TX_CONFIG, action_scope, fee=uint64(2000000000000) ) + report_txs = action_scope.side_effects.transactions record_1 = await dl_wallet_1.get_latest_singleton(launcher_id) assert record_1 is not None assert current_record != record_1 - async with dl_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - update_txs = await dl_wallet_0.create_update_state_spend( + async with dl_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dl_wallet_0.create_update_state_spend( launcher_id, bytes32([0] * 32), DEFAULT_TX_CONFIG, action_scope, fee=uint64(2000000000000) ) + update_txs = action_scope.side_effects.transactions record_0 = await dl_wallet_0.get_latest_singleton(launcher_id) assert record_0 is not None assert initial_record != record_0 @@ -487,12 +481,14 @@ async def is_singleton_generation(wallet: DataLayerWallet, launcher_id: bytes32, assert await dl_wallet_0.get_singleton_record(record_0.coin_id) is None async with dl_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - update_txs_1 = await dl_wallet_0.create_update_state_spend( + await dl_wallet_0.create_update_state_spend( launcher_id, bytes32([1] * 32), DEFAULT_TX_CONFIG, action_scope, fee=uint64(2000000000000) ) record_1 = await dl_wallet_0.get_latest_singleton(launcher_id) assert record_1 is not None - update_txs_1 = await wallet_node_0.wallet_state_manager.add_pending_transactions(update_txs_1) + update_txs_1 = await wallet_node_0.wallet_state_manager.add_pending_transactions( + action_scope.side_effects.transactions + ) await full_node_api.wait_transaction_records_entered_mempool(update_txs_1) # Delete any trace of that update @@ -501,14 +497,14 @@ async def is_singleton_generation(wallet: DataLayerWallet, launcher_id: bytes32, await wallet_node_0.wallet_state_manager.tx_store.delete_transaction_record(tx.name) async with dl_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - update_txs_0 = await dl_wallet_0.create_update_state_spend( - launcher_id, bytes32([2] * 32), DEFAULT_TX_CONFIG, action_scope - ) + await dl_wallet_0.create_update_state_spend(launcher_id, bytes32([2] * 32), DEFAULT_TX_CONFIG, action_scope) record_0 = await dl_wallet_0.get_latest_singleton(launcher_id) assert record_0 is not None assert record_0 != record_1 - update_txs_0 = await wallet_node_0.wallet_state_manager.add_pending_transactions(update_txs_0) + update_txs_0 = await wallet_node_0.wallet_state_manager.add_pending_transactions( + action_scope.side_effects.transactions + ) await asyncio.wait_for( full_node_api.process_transaction_records(records=update_txs_1), timeout=adjusted_timeout(timeout=15) @@ -571,22 +567,16 @@ async def test_mirrors(wallets_prefarm: Any, trusted: bool) -> None: async with wsm_2.lock: dl_wallet_2 = await DataLayerWallet.create_new_dl_wallet(wsm_2) - async with dl_wallet_1.wallet_state_manager.new_action_scope(push=False) as action_scope: - std_record, launcher_id_1 = await dl_wallet_1.generate_new_reporter( - bytes32([0] * 32), DEFAULT_TX_CONFIG, action_scope - ) + async with dl_wallet_1.wallet_state_manager.new_action_scope(push=True) as action_scope: + launcher_id_1 = await dl_wallet_1.generate_new_reporter(bytes32([0] * 32), DEFAULT_TX_CONFIG, action_scope) assert await dl_wallet_1.get_latest_singleton(launcher_id_1) is not None - [std_record] = await wsm_1.add_pending_transactions([std_record]) - await full_node_api.process_transaction_records(records=[std_record]) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(15, is_singleton_confirmed_and_root, True, dl_wallet_1, launcher_id_1, bytes32([0] * 32)) - async with dl_wallet_2.wallet_state_manager.new_action_scope(push=False) as action_scope: - std_record, launcher_id_2 = await dl_wallet_2.generate_new_reporter( - bytes32([0] * 32), DEFAULT_TX_CONFIG, action_scope - ) + async with dl_wallet_2.wallet_state_manager.new_action_scope(push=True) as action_scope: + launcher_id_2 = await dl_wallet_2.generate_new_reporter(bytes32([0] * 32), DEFAULT_TX_CONFIG, action_scope) assert await dl_wallet_2.get_latest_singleton(launcher_id_2) is not None - [std_record] = await wsm_2.add_pending_transactions([std_record]) - await full_node_api.process_transaction_records(records=[std_record]) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(15, is_singleton_confirmed_and_root, True, dl_wallet_2, launcher_id_2, bytes32([0] * 32)) peer_1 = wallet_node_1.get_full_node_peer() @@ -596,16 +586,15 @@ async def test_mirrors(wallets_prefarm: Any, trusted: bool) -> None: await time_out_assert(15, is_singleton_confirmed_and_root, True, dl_wallet_1, launcher_id_2, bytes32([0] * 32)) await time_out_assert(15, is_singleton_confirmed_and_root, True, dl_wallet_2, launcher_id_1, bytes32([0] * 32)) - async with dl_wallet_1.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await dl_wallet_1.create_new_mirror( + async with dl_wallet_1.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dl_wallet_1.create_new_mirror( launcher_id_2, uint64(3), [b"foo", b"bar"], DEFAULT_TX_CONFIG, action_scope, fee=uint64(1_999_999_999_999) ) additions: List[Coin] = [] - txs = await wsm_1.add_pending_transactions(txs) - for tx in txs: + for tx in action_scope.side_effects.transactions: if tx.spend_bundle is not None: additions.extend(tx.spend_bundle.additions()) - await full_node_api.process_transaction_records(records=txs) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) mirror_coin: Coin = [c for c in additions if c.puzzle_hash == create_mirror_puzzle().get_tree_hash()][0] mirror = Mirror( @@ -621,12 +610,11 @@ async def test_mirrors(wallets_prefarm: Any, trusted: bool) -> None: 15, dl_wallet_2.get_mirrors_for_launcher, [dataclasses.replace(mirror, ours=False)], launcher_id_2 ) - async with dl_wallet_1.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await dl_wallet_1.delete_mirror( + async with dl_wallet_1.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dl_wallet_1.delete_mirror( mirror.coin_id, peer_1, DEFAULT_TX_CONFIG, action_scope, fee=uint64(2_000_000_000_000) ) - txs = await wsm_1.add_pending_transactions(txs) - await full_node_api.process_transaction_records(records=txs) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(15, dl_wallet_1.get_mirrors_for_launcher, [], launcher_id_2) await time_out_assert(15, dl_wallet_2.get_mirrors_for_launcher, [], launcher_id_2) @@ -660,11 +648,8 @@ async def test_datalayer_reorgs(wallet_environments: WalletTestFramework) -> Non async with env.wallet_state_manager.lock: dl_wallet = await DataLayerWallet.create_new_dl_wallet(env.wallet_state_manager) - async with dl_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - std_record, launcher_id = await dl_wallet.generate_new_reporter( - bytes32([0] * 32), DEFAULT_TX_CONFIG, action_scope - ) - await env.wallet_state_manager.add_pending_transactions([std_record]) + async with dl_wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + launcher_id = await dl_wallet.generate_new_reporter(bytes32([0] * 32), DEFAULT_TX_CONFIG, action_scope) await wallet_environments.process_pending_states( [ @@ -731,11 +716,8 @@ async def test_datalayer_reorgs(wallet_environments: WalletTestFramework) -> Non ) await time_out_assert(15, is_singleton_confirmed_and_root, True, dl_wallet, launcher_id, bytes32([0] * 32)) - async with dl_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - update_txs = await dl_wallet.create_update_state_spend( - launcher_id, bytes32([2] * 32), DEFAULT_TX_CONFIG, action_scope - ) - await env.wallet_state_manager.add_pending_transactions(update_txs) + async with dl_wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dl_wallet.create_update_state_spend(launcher_id, bytes32([2] * 32), DEFAULT_TX_CONFIG, action_scope) await wallet_environments.process_pending_states( [ @@ -778,11 +760,8 @@ async def test_datalayer_reorgs(wallet_environments: WalletTestFramework) -> Non ) await time_out_assert(15, is_singleton_confirmed_and_root, True, dl_wallet, launcher_id, bytes32([2] * 32)) - async with dl_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await dl_wallet.create_new_mirror( - launcher_id, uint64(0), [b"foo", b"bar"], DEFAULT_TX_CONFIG, action_scope - ) - await env.wallet_state_manager.add_pending_transactions(txs) + async with dl_wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dl_wallet.create_new_mirror(launcher_id, uint64(0), [b"foo", b"bar"], DEFAULT_TX_CONFIG, action_scope) await wallet_environments.process_pending_states( [ WalletStateTransition( diff --git a/chia/_tests/wallet/did_wallet/test_did.py b/chia/_tests/wallet/did_wallet/test_did.py index f8f8b4d01a6c..dcc73dc66e9b 100644 --- a/chia/_tests/wallet/did_wallet/test_did.py +++ b/chia/_tests/wallet/did_wallet/test_did.py @@ -9,7 +9,7 @@ from chia._tests.environments.wallet import WalletStateTransition, WalletTestFramework from chia._tests.util.setup_nodes import OldSimulatorsAndWallets -from chia._tests.util.time_out_assert import time_out_assert, time_out_assert_not_none +from chia._tests.util.time_out_assert import time_out_assert from chia.rpc.wallet_rpc_api import WalletRpcApi from chia.simulator.simulator_protocol import FarmNewBlockProtocol from chia.types.blockchain_format.program import Program @@ -83,7 +83,7 @@ async def test_creation_from_coin_spend( await full_node_api.farm_blocks_to_wallet(1, wallet_1) # Wallet1 sets up DIDWallet1 without any backup set - async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet_0: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_0.wallet_state_manager, wallet_0, uint64(101), DEFAULT_TX_CONFIG, action_scope ) @@ -92,15 +92,8 @@ async def test_creation_from_coin_spend( assert await did_wallet_0.get_coin() == set() assert await did_wallet_0.get_info_for_recovery() is None - spend_bundle_list = await wallet_node_0.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_0.id() - ) - - spend_bundle = spend_bundle_list[0].spend_bundle - assert spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - await full_node_api.farm_blocks_to_wallet(1, wallet_0) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) + await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1]) await time_out_assert(15, did_wallet_0.get_confirmed_balance, 101) await time_out_assert(15, did_wallet_0.get_unconfirmed_balance, 101) @@ -155,19 +148,13 @@ async def test_creation_from_backup_file(self, self_hostname, three_wallet_nodes await full_node_api.farm_blocks_to_wallet(1, wallet_2) # Wallet1 sets up DIDWallet1 without any backup set - async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet_0: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_0.wallet_state_manager, wallet_0, uint64(101), DEFAULT_TX_CONFIG, action_scope ) - spend_bundle_list = await wallet_node_0.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_0.id() - ) - - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - await full_node_api.farm_blocks_to_wallet(1, wallet_0) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) + await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2]) await time_out_assert(15, did_wallet_0.get_confirmed_balance, 101) await time_out_assert(15, did_wallet_0.get_unconfirmed_balance, 101) @@ -175,19 +162,13 @@ async def test_creation_from_backup_file(self, self_hostname, three_wallet_nodes # Wallet1 sets up DIDWallet_1 with DIDWallet_0 as backup backup_ids = [bytes.fromhex(did_wallet_0.get_my_DID())] - async with wallet_1.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_1.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet_1: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_1.wallet_state_manager, wallet_1, uint64(201), DEFAULT_TX_CONFIG, action_scope, backup_ids ) - spend_bundle_list = await wallet_node_1.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_1.id() - ) - - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - await full_node_api.farm_blocks_to_wallet(1, wallet_0) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) + await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2]) await time_out_assert(15, did_wallet_1.get_confirmed_balance, 201) await time_out_assert(15, did_wallet_1.get_unconfirmed_balance, 201) @@ -206,20 +187,12 @@ async def test_creation_from_backup_file(self, self_hostname, three_wallet_nodes pubkey = bytes( (await did_wallet_2.wallet_state_manager.get_unused_derivation_record(did_wallet_2.wallet_info.id)).pubkey ) - async with did_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - message_tx, message_spend_bundle, attest_data = await did_wallet_0.create_attestment( + async with did_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + message_spend_bundle, attest_data = await did_wallet_0.create_attestment( did_wallet_2.did_info.temp_coin.name(), newpuzhash, pubkey, DEFAULT_TX_CONFIG, action_scope ) - [message_tx] = await did_wallet_0.wallet_state_manager.add_pending_transactions([message_tx]) - assert message_spend_bundle is not None - spend_bundle_list = await wallet_node_0.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_0.id() - ) - - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - await full_node_api.farm_blocks_to_wallet(1, wallet_0) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) + await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2]) ( test_info_list, @@ -227,21 +200,18 @@ async def test_creation_from_backup_file(self, self_hostname, three_wallet_nodes ) = await did_wallet_2.load_attest_files_for_recovery_spend([attest_data]) assert message_spend_bundle == test_message_spend_bundle - txs = await did_wallet_2.recovery_spend( - did_wallet_2.did_info.temp_coin, - newpuzhash, - test_info_list, - pubkey, - test_message_spend_bundle, - ) - assert txs[0].spend_bundle is not None - txs = await did_wallet_2.wallet_state_manager.add_pending_transactions(txs) - - await time_out_assert_not_none( - 5, full_node_api.full_node.mempool_manager.get_spendbundle, txs[0].spend_bundle.name() - ) + async with did_wallet_2.wallet_state_manager.new_action_scope(push=True) as action_scope: + await did_wallet_2.recovery_spend( + did_wallet_2.did_info.temp_coin, + newpuzhash, + test_info_list, + pubkey, + test_message_spend_bundle, + action_scope, + ) - await full_node_api.farm_blocks_to_wallet(1, wallet_0) + await full_node_api.process_transaction_records(action_scope.side_effects.transactions) + await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2]) await time_out_assert(45, did_wallet_2.get_confirmed_balance, 201) await time_out_assert(45, did_wallet_2.get_unconfirmed_balance, 201) @@ -250,18 +220,10 @@ async def test_creation_from_backup_file(self, self_hostname, three_wallet_nodes assert wallet.wallet_state_manager.wallets[wallet.id()] == wallet some_ph = 32 * b"\2" - async with did_wallet_2.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await did_wallet_2.create_exit_spend(some_ph, DEFAULT_TX_CONFIG, action_scope) - txs = await did_wallet_2.wallet_state_manager.add_pending_transactions(txs) - - spend_bundle_list = await wallet_node_2.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_2.id() - ) - - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - await full_node_api.farm_blocks_to_wallet(1, wallet_0) + async with did_wallet_2.wallet_state_manager.new_action_scope(push=True) as action_scope: + await did_wallet_2.create_exit_spend(some_ph, DEFAULT_TX_CONFIG, action_scope) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) + await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2]) async def get_coins_with_ph() -> bool: coins = await full_node_api.full_node.coin_store.get_coin_records_by_puzzle_hash(True, some_ph) @@ -302,37 +264,28 @@ async def test_did_recovery_with_multiple_backup_dids(self, self_hostname, two_w await server_3.start_client(PeerInfo(self_hostname, server_1.get_port()), None) await full_node_api.farm_blocks_to_wallet(1, wallet) + await full_node_api.farm_blocks_to_wallet(1, wallet2) - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node.wallet_state_manager, wallet, uint64(101), DEFAULT_TX_CONFIG, action_scope ) assert did_wallet.get_name() == "Profile 1" - spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(did_wallet.id()) - - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - await full_node_api.farm_blocks_to_wallet(1, wallet2) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) + await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2]) await time_out_assert(15, did_wallet.get_confirmed_balance, 101) await time_out_assert(15, did_wallet.get_unconfirmed_balance, 101) recovery_list = [bytes.fromhex(did_wallet.get_my_DID())] - async with wallet2.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet2.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet_2: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_2.wallet_state_manager, wallet2, uint64(101), DEFAULT_TX_CONFIG, action_scope, recovery_list ) - spend_bundle_list = await wallet_node_2.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_2.id() - ) - - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - await full_node_api.farm_blocks_to_wallet(1, wallet2) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) + await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2]) await time_out_assert(15, did_wallet_2.get_confirmed_balance, 101) await time_out_assert(15, did_wallet_2.get_unconfirmed_balance, 101) @@ -341,19 +294,13 @@ async def test_did_recovery_with_multiple_backup_dids(self, self_hostname, two_w recovery_list.append(bytes.fromhex(did_wallet_2.get_my_DID())) - async with wallet2.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet2.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet_3: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_2.wallet_state_manager, wallet2, uint64(201), DEFAULT_TX_CONFIG, action_scope, recovery_list ) - spend_bundle_list = await wallet_node_2.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_3.id() - ) - - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - await full_node_api.farm_blocks_to_wallet(1, wallet) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) + await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2]) assert did_wallet_3.did_info.backup_ids == recovery_list await time_out_assert(15, did_wallet_3.get_confirmed_balance, 201) @@ -374,28 +321,16 @@ async def test_did_recovery_with_multiple_backup_dids(self, self_hostname, two_w await did_wallet_4.wallet_state_manager.get_unused_derivation_record(did_wallet_2.wallet_info.id) ).pubkey new_ph = did_wallet_4.did_info.temp_puzhash - async with did_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - message_tx, message_spend_bundle, attest1 = await did_wallet.create_attestment( + async with did_wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + message_spend_bundle, attest1 = await did_wallet.create_attestment( coin.name(), new_ph, pubkey, DEFAULT_TX_CONFIG, action_scope ) - [message_tx] = await did_wallet.wallet_state_manager.add_pending_transactions([message_tx]) - assert message_spend_bundle is not None - spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(did_wallet.id()) - - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - async with did_wallet_2.wallet_state_manager.new_action_scope(push=False) as action_scope: - message_tx2, message_spend_bundle2, attest2 = await did_wallet_2.create_attestment( - coin.name(), new_ph, pubkey, DEFAULT_TX_CONFIG, action_scope + + async with did_wallet_2.wallet_state_manager.new_action_scope(push=True) as action_scope_2: + message_spend_bundle2, attest2 = await did_wallet_2.create_attestment( + coin.name(), new_ph, pubkey, DEFAULT_TX_CONFIG, action_scope_2 ) - [message_tx2] = await did_wallet_2.wallet_state_manager.add_pending_transactions([message_tx2]) - assert message_spend_bundle2 is not None - spend_bundle_list = await wallet_node_2.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_2.id() - ) - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) message_spend_bundle = message_spend_bundle.aggregate([message_spend_bundle, message_spend_bundle2]) ( @@ -404,19 +339,16 @@ async def test_did_recovery_with_multiple_backup_dids(self, self_hostname, two_w ) = await did_wallet_4.load_attest_files_for_recovery_spend([attest1, attest2]) assert message_spend_bundle == test_message_spend_bundle - await full_node_api.farm_blocks_to_wallet(1, wallet) + await full_node_api.process_transaction_records( + records=[*action_scope.side_effects.transactions, *action_scope_2.side_effects.transactions] + ) + await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2]) await time_out_assert(15, did_wallet_4.get_confirmed_balance, 0) await time_out_assert(15, did_wallet_4.get_unconfirmed_balance, 0) - txs = await did_wallet_4.recovery_spend(coin, new_ph, test_info_list, pubkey, message_spend_bundle) - txs = await did_wallet_4.wallet_state_manager.add_pending_transactions(txs) - spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_4.id() - ) - - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - await full_node_api.farm_blocks_to_wallet(1, wallet) + async with did_wallet_4.wallet_state_manager.new_action_scope(push=True) as action_scope: + await did_wallet_4.recovery_spend(coin, new_ph, test_info_list, pubkey, message_spend_bundle, action_scope) + await full_node_api.process_transaction_records(action_scope.side_effects.transactions) + await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2]) await time_out_assert(15, did_wallet_4.get_confirmed_balance, 201) await time_out_assert(15, did_wallet_4.get_unconfirmed_balance, 201) @@ -455,17 +387,13 @@ async def test_did_recovery_with_empty_set(self, self_hostname, two_wallet_nodes await full_node_api.farm_blocks_to_wallet(1, wallet) - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node.wallet_state_manager, wallet, uint64(101), DEFAULT_TX_CONFIG, action_scope ) - spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(did_wallet.id()) - - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - await full_node_api.farm_blocks_to_wallet(1, wallet) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) + await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2]) await time_out_assert(15, did_wallet.get_confirmed_balance, 101) await time_out_assert(15, did_wallet.get_unconfirmed_balance, 101) @@ -473,7 +401,10 @@ async def test_did_recovery_with_empty_set(self, self_hostname, two_wallet_nodes info = Program.to([]) pubkey = (await did_wallet.wallet_state_manager.get_unused_derivation_record(did_wallet.wallet_info.id)).pubkey with pytest.raises(Exception): # We expect a CLVM 80 error for this test - await did_wallet.recovery_spend(coin, ph, info, pubkey, SpendBundle([], AugSchemeMPL.aggregate([]))) + async with did_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: + await did_wallet.recovery_spend( + coin, ph, info, pubkey, SpendBundle([], AugSchemeMPL.aggregate([])), action_scope + ) @pytest.mark.parametrize( "trusted", @@ -487,7 +418,6 @@ async def test_did_find_lost_did(self, self_hostname, two_wallet_nodes, trusted) wallet_node, server_2 = wallets[0] wallet_node_2, server_3 = wallets[1] wallet = wallet_node.wallet_state_manager.main_wallet - wallet2 = wallet_node_2.wallet_state_manager.main_wallet api_0 = WalletRpcApi(wallet_node) if trusted: wallet_node.config["trusted_peers"] = { @@ -503,15 +433,12 @@ async def test_did_find_lost_did(self, self_hostname, two_wallet_nodes, trusted) await server_3.start_client(PeerInfo(self_hostname, server_1.get_port()), None) await full_node_api.farm_blocks_to_wallet(1, wallet) - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node.wallet_state_manager, wallet, uint64(101), DEFAULT_TX_CONFIG, action_scope ) - spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(did_wallet.id()) - - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(15, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - await full_node_api.farm_blocks_to_wallet(1, wallet2) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) + await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2]) await time_out_assert(15, did_wallet.get_confirmed_balance, 101) await time_out_assert(15, did_wallet.get_unconfirmed_balance, 101) @@ -538,13 +465,9 @@ async def test_did_find_lost_did(self, self_hostname, two_wallet_nodes, trusted) recovery_list = [bytes32.fromhex(did_wallet.get_my_DID())] await did_wallet.update_recovery_list(recovery_list, uint64(1)) assert did_wallet.did_info.backup_ids == recovery_list - async with did_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await did_wallet.create_update_spend(DEFAULT_TX_CONFIG, action_scope) - txs = await did_wallet.wallet_state_manager.add_pending_transactions(txs) - spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(did_wallet.id()) - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - await full_node_api.farm_blocks_to_wallet(1, wallet2) + async with did_wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await did_wallet.create_update_spend(DEFAULT_TX_CONFIG, action_scope) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node, timeout=20) await time_out_assert(15, did_wallet.get_confirmed_balance, 101) @@ -587,32 +510,25 @@ async def test_did_attest_after_recovery(self, self_hostname, two_wallet_nodes, await server_2.start_client(PeerInfo(self_hostname, server_1.get_port()), None) await server_3.start_client(PeerInfo(self_hostname, server_1.get_port()), None) await full_node_api.farm_blocks_to_wallet(1, wallet) + await full_node_api.farm_blocks_to_wallet(1, wallet2) - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node.wallet_state_manager, wallet, uint64(101), DEFAULT_TX_CONFIG, action_scope ) - spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(did_wallet.id()) - - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(15, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - await full_node_api.farm_blocks_to_wallet(1, wallet2) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) + await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2]) await time_out_assert(15, did_wallet.get_confirmed_balance, 101) await time_out_assert(15, did_wallet.get_unconfirmed_balance, 101) recovery_list = [bytes.fromhex(did_wallet.get_my_DID())] - async with wallet2.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet2.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet_2: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_2.wallet_state_manager, wallet2, uint64(101), DEFAULT_TX_CONFIG, action_scope, recovery_list ) - spend_bundle_list = await wallet_node_2.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_2.id() - ) - - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - await full_node_api.farm_blocks_to_wallet(1, wallet) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) + await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2]) await time_out_assert(25, did_wallet_2.get_confirmed_balance, 101) await time_out_assert(25, did_wallet_2.get_unconfirmed_balance, 101) assert did_wallet_2.did_info.backup_ids == recovery_list @@ -621,16 +537,10 @@ async def test_did_attest_after_recovery(self, self_hostname, two_wallet_nodes, recovery_list = [bytes.fromhex(did_wallet_2.get_my_DID())] await did_wallet.update_recovery_list(recovery_list, uint64(1)) assert did_wallet.did_info.backup_ids == recovery_list - async with did_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await did_wallet.create_update_spend(DEFAULT_TX_CONFIG, action_scope) - txs = await did_wallet.wallet_state_manager.add_pending_transactions(txs) - - spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(did_wallet.id()) - - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - await full_node_api.farm_blocks_to_wallet(1, wallet2) + async with did_wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await did_wallet.create_update_spend(DEFAULT_TX_CONFIG, action_scope) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) + await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2]) await time_out_assert(15, did_wallet.get_confirmed_balance, 101) await time_out_assert(15, did_wallet.get_unconfirmed_balance, 101) @@ -650,32 +560,21 @@ async def test_did_attest_after_recovery(self, self_hostname, two_wallet_nodes, await did_wallet_3.wallet_state_manager.get_unused_derivation_record(did_wallet_3.wallet_info.id) ).pubkey await time_out_assert(15, did_wallet.get_confirmed_balance, 101) - async with did_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - message_tx, message_spend_bundle, attest_data = await did_wallet.create_attestment( + async with did_wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + message_spend_bundle, attest_data = await did_wallet.create_attestment( coin.name(), new_ph, pubkey, DEFAULT_TX_CONFIG, action_scope ) - [message_tx] = await did_wallet.wallet_state_manager.add_pending_transactions([message_tx]) - assert message_spend_bundle is not None - spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(did_wallet.id()) - - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - await full_node_api.farm_blocks_to_wallet(1, wallet2) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) + await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2]) ( info, message_spend_bundle, ) = await did_wallet_3.load_attest_files_for_recovery_spend([attest_data]) - txs = await did_wallet_3.recovery_spend(coin, new_ph, info, pubkey, message_spend_bundle) - txs = await did_wallet_3.wallet_state_manager.add_pending_transactions(txs) - spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_3.id() - ) - - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - await full_node_api.farm_blocks_to_wallet(1, wallet) + async with did_wallet_3.wallet_state_manager.new_action_scope(push=True) as action_scope: + await did_wallet_3.recovery_spend(coin, new_ph, info, pubkey, message_spend_bundle, action_scope) + await full_node_api.process_transaction_records(action_scope.side_effects.transactions) + await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2]) await time_out_assert(15, did_wallet_3.get_confirmed_balance, 101) await time_out_assert(15, did_wallet_3.get_unconfirmed_balance, 101) @@ -694,35 +593,24 @@ async def test_did_attest_after_recovery(self, self_hostname, two_wallet_nodes, pubkey = ( await did_wallet_4.wallet_state_manager.get_unused_derivation_record(did_wallet_4.wallet_info.id) ).pubkey - async with did_wallet_3.wallet_state_manager.new_action_scope(push=False) as action_scope: - message_tx, message_spend_bundle, attest1 = await did_wallet_3.create_attestment( + async with did_wallet_3.wallet_state_manager.new_action_scope(push=True) as action_scope: + message_spend_bundle, attest1 = await did_wallet_3.create_attestment( coin.name(), new_ph, pubkey, DEFAULT_TX_CONFIG, action_scope ) - [message_tx] = await did_wallet_3.wallet_state_manager.add_pending_transactions([message_tx]) - assert message_spend_bundle is not None - spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_3.id() - ) - - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - await full_node_api.farm_blocks_to_wallet(1, wallet2) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) + await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2]) await time_out_assert(15, wallet.get_pending_change_balance, 0) ( test_info_list, test_message_spend_bundle, ) = await did_wallet_4.load_attest_files_for_recovery_spend([attest1]) - txs = await did_wallet_4.recovery_spend(coin, new_ph, test_info_list, pubkey, test_message_spend_bundle) - txs = await did_wallet_2.wallet_state_manager.add_pending_transactions(txs) - - spend_bundle_list = await wallet_node_2.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_4.id() - ) - - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(15, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) + async with did_wallet_4.wallet_state_manager.new_action_scope(push=True) as action_scope: + await did_wallet_4.recovery_spend( + coin, new_ph, test_info_list, pubkey, test_message_spend_bundle, action_scope + ) - await full_node_api.farm_blocks_to_wallet(1, wallet) + await full_node_api.process_transaction_records(action_scope.side_effects.transactions) + await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2]) await time_out_assert(15, did_wallet_4.get_confirmed_balance, 101) await time_out_assert(15, did_wallet_4.get_unconfirmed_balance, 101) @@ -767,7 +655,7 @@ async def test_did_transfer(self, self_hostname, two_wallet_nodes, with_recovery await server_3.start_client(PeerInfo(self_hostname, server_1.get_port()), None) await full_node_api.farm_blocks_to_wallet(1, wallet) - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet_1: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node.wallet_state_manager, wallet, @@ -780,25 +668,16 @@ async def test_did_transfer(self, self_hostname, two_wallet_nodes, with_recovery fee=fee, ) assert did_wallet_1.get_name() == "Profile 1" - spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_1.id() - ) - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - await full_node_api.farm_blocks_to_wallet(1, wallet2) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) + await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2]) await time_out_assert(15, did_wallet_1.get_confirmed_balance, 101) await time_out_assert(15, did_wallet_1.get_unconfirmed_balance, 101) # Transfer DID new_puzhash = await wallet2.get_new_puzzlehash() - async with did_wallet_1.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await did_wallet_1.transfer_did(new_puzhash, fee, with_recovery, DEFAULT_TX_CONFIG, action_scope) - txs = await did_wallet_1.wallet_state_manager.add_pending_transactions(txs) - spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_1.id() - ) - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - await full_node_api.farm_blocks_to_wallet(1, wallet2) + async with did_wallet_1.wallet_state_manager.new_action_scope(push=True) as action_scope: + await did_wallet_1.transfer_did(new_puzhash, fee, with_recovery, DEFAULT_TX_CONFIG, action_scope) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) + await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2]) # Check if the DID wallet is created in the wallet2 await time_out_assert(30, get_wallet_num, 2, wallet_node_2.wallet_state_manager) @@ -855,23 +734,19 @@ async def test_update_recovery_list(self, self_hostname, two_wallet_nodes, trust await server_3.start_client(PeerInfo(self_hostname, server_1.get_port()), None) await full_node_api.farm_blocks_to_wallet(1, wallet) - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet_1: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node.wallet_state_manager, wallet, uint64(101), DEFAULT_TX_CONFIG, action_scope, [] ) - spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_1.id() - ) - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - await full_node_api.farm_blocks_to_wallet(1, wallet) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) + await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2]) await time_out_assert(15, did_wallet_1.get_confirmed_balance, 101) await time_out_assert(15, did_wallet_1.get_unconfirmed_balance, 101) await did_wallet_1.update_recovery_list([bytes(ph)], 1) - async with did_wallet_1.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await did_wallet_1.create_update_spend(DEFAULT_TX_CONFIG, action_scope) - txs = await did_wallet_1.wallet_state_manager.add_pending_transactions(txs) - await full_node_api.farm_blocks_to_wallet(1, wallet) + async with did_wallet_1.wallet_state_manager.new_action_scope(push=True) as action_scope: + await did_wallet_1.create_update_spend(DEFAULT_TX_CONFIG, action_scope) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) + await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2]) await time_out_assert(15, did_wallet_1.get_confirmed_balance, 101) await time_out_assert(15, did_wallet_1.get_unconfirmed_balance, 101) assert did_wallet_1.did_info.backup_ids[0] == bytes(ph) @@ -909,7 +784,7 @@ async def test_get_info(self, self_hostname, two_wallet_nodes, trusted): await full_node_api.farm_blocks_to_wallet(count=2, wallet=wallet) did_amount = uint64(101) - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet_1: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node.wallet_state_manager, wallet, @@ -920,10 +795,8 @@ async def test_get_info(self, self_hostname, two_wallet_nodes, trusted): metadata={"twitter": "twitter"}, fee=fee, ) - transaction_records = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_1.id() - ) - await full_node_api.process_transaction_records(records=transaction_records) + + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node, timeout=15) assert await did_wallet_1.get_confirmed_balance() == did_amount @@ -953,12 +826,11 @@ async def test_get_info(self, self_hostname, two_wallet_nodes, trusted): await wallet.select_coins(odd_amount, DEFAULT_COIN_SELECTION_CONFIG.override(excluded_coin_ids=[coin_id])) ).pop() assert coin_1.amount % 2 == 0 - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.generate_signed_transaction( odd_amount, ph1, DEFAULT_TX_CONFIG.override(excluded_coin_ids=[coin_id]), action_scope, fee ) - [tx] = await wallet.wallet_state_manager.add_pending_transactions([tx]) - await full_node_api.process_transaction_records(records=[tx]) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_2, timeout=15) assert await wallet1.get_confirmed_balance() == odd_amount @@ -978,7 +850,6 @@ async def test_message_spend(self, self_hostname, two_wallet_nodes, trusted): wallet_node, server_2 = wallets[0] wallet_node_2, server_3 = wallets[1] wallet = wallet_node.wallet_state_manager.main_wallet - wallet1 = wallet_node_2.wallet_state_manager.main_wallet api_0 = WalletRpcApi(wallet_node) if trusted: wallet_node.config["trusted_peers"] = { @@ -996,16 +867,12 @@ async def test_message_spend(self, self_hostname, two_wallet_nodes, trusted): await full_node_api.farm_blocks_to_wallet(1, wallet) - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet_1: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node.wallet_state_manager, wallet, uint64(101), DEFAULT_TX_CONFIG, action_scope, [], fee=fee ) - spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_1.id() - ) - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - await full_node_api.farm_blocks_to_wallet(1, wallet1) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) + await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2]) await time_out_assert(15, did_wallet_1.get_confirmed_balance, 101) await time_out_assert(15, did_wallet_1.get_unconfirmed_balance, 101) response = await api_0.did_message_spend( @@ -1050,14 +917,11 @@ async def test_update_metadata(self, self_hostname, two_wallet_nodes, trusted): expected_confirmed_balance = await full_node_api.farm_blocks_to_wallet(count=2, wallet=wallet) did_amount = uint64(101) - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet_1: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node.wallet_state_manager, wallet, did_amount, DEFAULT_TX_CONFIG, action_scope, [], fee=fee ) - transaction_records = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_1.id() - ) - await full_node_api.process_transaction_records(records=transaction_records) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node, timeout=15) expected_confirmed_balance -= did_amount + fee @@ -1076,13 +940,10 @@ async def test_update_metadata(self, self_hostname, two_wallet_nodes, trusted): metadata = {} metadata["Twitter"] = "http://www.twitter.com" await did_wallet_1.update_metadata(metadata) - async with did_wallet_1.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await did_wallet_1.create_update_spend(DEFAULT_TX_CONFIG, action_scope, fee) - txs = await did_wallet_1.wallet_state_manager.add_pending_transactions(txs) - transaction_records = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_1.id() - ) - await full_node_api.process_transaction_records(records=transaction_records) + async with did_wallet_1.wallet_state_manager.new_action_scope(push=True) as action_scope: + await did_wallet_1.create_update_spend(DEFAULT_TX_CONFIG, action_scope, fee) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) + await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2]) expected_confirmed_balance -= fee @@ -1111,7 +972,6 @@ async def test_did_sign_message(self, self_hostname, two_wallet_nodes, trusted): wallet_node, server_2 = wallets[0] wallet_node_2, server_3 = wallets[1] wallet = wallet_node.wallet_state_manager.main_wallet - wallet2 = wallet_node_2.wallet_state_manager.main_wallet api_0 = WalletRpcApi(wallet_node) ph = await wallet.get_new_puzzlehash() @@ -1130,7 +990,7 @@ async def test_did_sign_message(self, self_hostname, two_wallet_nodes, trusted): await server_3.start_client(PeerInfo(self_hostname, server_1.get_port()), None) await full_node_api.farm_blocks_to_wallet(1, wallet) - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet_1: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node.wallet_state_manager, wallet, @@ -1143,12 +1003,8 @@ async def test_did_sign_message(self, self_hostname, two_wallet_nodes, trusted): fee=fee, ) assert did_wallet_1.get_name() == "Profile 1" - spend_bundle_list = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_1.id() - ) - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - await full_node_api.farm_blocks_to_wallet(1, wallet2) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) + await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2]) await time_out_assert(15, did_wallet_1.get_confirmed_balance, 101) # Test general string message = "Hello World" @@ -1264,7 +1120,7 @@ async def test_create_did_with_recovery_list(self, self_hostname, two_nodes_two_ # Node 0 sets up a DID Wallet with a backup set, but num_of_backup_ids_needed=0 # (a malformed solution, but legal for the clvm puzzle) recovery_list = [bytes.fromhex("00" * 32)] - async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet_0: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_0.wallet_state_manager, wallet_0, @@ -1275,16 +1131,8 @@ async def test_create_did_with_recovery_list(self, self_hostname, two_nodes_two_ num_of_backup_ids_needed=0, ) - spend_bundle_list = await wallet_node_0.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_0.id() - ) - - spend_bundle = spend_bundle_list[0].spend_bundle - assert spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - # Node 1 creates the DID Wallet with create_new_did_wallet_from_coin_spend - await full_node_api.farm_blocks_to_wallet(1, wallet_0) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) + await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0]) await time_out_assert(15, did_wallet_0.get_confirmed_balance, 101) await time_out_assert(15, did_wallet_0.get_unconfirmed_balance, 101) @@ -1332,7 +1180,7 @@ async def test_did_resync(self, self_hostname, two_wallet_nodes, trusted) -> Non await wallet_server_2.start_client(PeerInfo(self_hostname, uint16(full_node_server._port)), None) await full_node_api.farm_blocks_to_wallet(1, wallet) - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet_1: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_1.wallet_state_manager, wallet, @@ -1345,27 +1193,18 @@ async def test_did_resync(self, self_hostname, two_wallet_nodes, trusted) -> Non fee=fee, ) assert did_wallet_1.get_name() == "Profile 1" - spend_bundle_list = await wallet_node_1.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_1.id() - ) - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - await full_node_api.farm_blocks_to_wallet(1, wallet2) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) + await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_1, wallet_node_2]) await time_out_assert(15, did_wallet_1.get_confirmed_balance, 101) await time_out_assert(15, did_wallet_1.get_unconfirmed_balance, 101) # Transfer DID new_puzhash = await wallet2.get_new_puzzlehash() - async with did_wallet_1.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await did_wallet_1.transfer_did( + async with did_wallet_1.wallet_state_manager.new_action_scope(push=True) as action_scope: + await did_wallet_1.transfer_did( new_puzhash, fee, True, tx_config=DEFAULT_TX_CONFIG, action_scope=action_scope ) - txs = await did_wallet_1.wallet_state_manager.add_pending_transactions(txs) - spend_bundle_list = await wallet_node_1.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_1.id() - ) - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - await full_node_api.farm_blocks_to_wallet(1, wallet2) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) + await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_1, wallet_node_2]) # Check if the DID wallet is created in the wallet2 await time_out_assert(30, get_wallet_num, 2, wallet_node_2.wallet_state_manager) await time_out_assert(30, get_wallet_num, 1, wallet_node_1.wallet_state_manager) @@ -1415,10 +1254,9 @@ async def test_did_coin_records(wallet_environments: WalletTestFramework, monkey # Setup wallet_node = wallet_environments.environments[0].node wallet = wallet_environments.environments[0].xch_wallet - client = wallet_environments.environments[0].rpc_client # Generate DID wallet - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node.wallet_state_manager, wallet, uint64(1), DEFAULT_TX_CONFIG, action_scope ) @@ -1440,17 +1278,17 @@ async def test_did_coin_records(wallet_environments: WalletTestFramework, monkey ) for _ in range(0, 2): - async with did_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await did_wallet.transfer_did( + async with did_wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await did_wallet.transfer_did( await wallet.get_puzzle_hash(new=False), uint64(0), True, wallet_environments.tx_config, action_scope ) - spend_bundles = [tx.spend_bundle for tx in txs if tx.spend_bundle is not None] - assert len(spend_bundles) > 0 - await client.push_tx(SpendBundle.aggregate(spend_bundles)) await wallet_environments.process_pending_states( [ WalletStateTransition( - pre_block_balance_updates={}, + pre_block_balance_updates={ + 1: {"set_remainder": True}, + 2: {"set_remainder": True}, + }, post_block_balance_updates={ 1: {"set_remainder": True}, 2: {"set_remainder": True}, diff --git a/chia/_tests/wallet/nft_wallet/test_nft_1_offers.py b/chia/_tests/wallet/nft_wallet/test_nft_1_offers.py index 7e1b80622f2c..fbb679484a30 100644 --- a/chia/_tests/wallet/nft_wallet/test_nft_1_offers.py +++ b/chia/_tests/wallet/nft_wallet/test_nft_1_offers.py @@ -92,18 +92,11 @@ async def test_nft_offer_sell_nft( await full_node_api.farm_rewards_to_wallet(funds, wallet_maker, timeout=30) await full_node_api.farm_rewards_to_wallet(funds, wallet_taker, timeout=30) - async with wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet_maker: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_maker.wallet_state_manager, wallet_maker, uint64(1), DEFAULT_TX_CONFIG, action_scope ) - spend_bundle_list = await wallet_node_maker.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_maker.id() - ) - - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(20, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token)) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker, wallet_node_taker], timeout=20) await time_out_assert(20, wallet_maker.get_pending_change_balance, 0) @@ -126,8 +119,8 @@ async def test_nft_offer_sell_nft( ] ) - async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await nft_wallet_maker.generate_new_nft( + async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await nft_wallet_maker.generate_new_nft( metadata, DEFAULT_TX_CONFIG, action_scope, @@ -136,8 +129,7 @@ async def test_nft_offer_sell_nft( royalty_basis_pts, did_id, ) - txs = await nft_wallet_maker.wallet_state_manager.add_pending_transactions(txs) - for tx in txs: + for tx in action_scope.side_effects.transactions: if tx.spend_bundle is not None: assert compute_memos(tx.spend_bundle) await time_out_assert_not_none( @@ -171,7 +163,7 @@ async def test_nft_offer_sell_nft( offer_did_nft_for_xch = {nft_to_offer_asset_id: -1, wallet_maker.id(): xch_requested} async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make, error = await trade_manager_maker.create_offer_for_ids( offer_did_nft_for_xch, DEFAULT_TX_CONFIG, action_scope, {}, fee=maker_fee ) assert success is True @@ -185,18 +177,16 @@ async def test_nft_offer_sell_nft( [maker_offer], signing_response = await wallet_node_maker.wallet_state_manager.sign_offers( [Offer.from_bytes(trade_make.offer)] ) - async with trade_manager_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - trade_take, tx_records = await trade_manager_taker.respond_to_offer( + async with trade_manager_taker.wallet_state_manager.new_action_scope( + push=True, additional_signing_responses=signing_response + ) as action_scope: + trade_take = await trade_manager_taker.respond_to_offer( Offer.from_bytes(trade_make.offer), peer, DEFAULT_TX_CONFIG, action_scope, fee=uint64(taker_fee) ) - tx_records = await trade_manager_taker.wallet_state_manager.add_pending_transactions( - tx_records, additional_signing_responses=signing_response - ) await time_out_assert(20, mempool_not_empty, True, full_node_api) assert trade_take is not None - assert tx_records is not None async def maker_0_taker_1() -> bool: return await nft_wallet_maker.get_nft_count() == 0 and await nft_wallet_taker.get_nft_count() == 1 @@ -241,18 +231,11 @@ async def test_nft_offer_request_nft( await full_node_api.farm_rewards_to_wallet(funds, wallet_maker, timeout=30) await full_node_api.farm_rewards_to_wallet(funds, wallet_taker, timeout=30) - async with wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_taker.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet_taker: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_taker.wallet_state_manager, wallet_taker, uint64(1), DEFAULT_TX_CONFIG, action_scope ) - spend_bundle_list = await wallet_node_taker.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_taker.id() - ) - - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(20, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token)) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker, wallet_node_taker], timeout=20) await time_out_assert(20, wallet_taker.get_pending_change_balance, 0) @@ -275,8 +258,8 @@ async def test_nft_offer_request_nft( await time_out_assert(20, wallet_taker.get_unconfirmed_balance, funds - 1) await time_out_assert(20, wallet_taker.get_confirmed_balance, funds - 1) - async with nft_wallet_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await nft_wallet_taker.generate_new_nft( + async with nft_wallet_taker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await nft_wallet_taker.generate_new_nft( metadata, DEFAULT_TX_CONFIG, action_scope, @@ -285,8 +268,7 @@ async def test_nft_offer_request_nft( royalty_basis_pts, did_id, ) - txs = await nft_wallet_taker.wallet_state_manager.add_pending_transactions(txs) - for tx in txs: + for tx in action_scope.side_effects.transactions: if tx.spend_bundle is not None: assert compute_memos(tx.spend_bundle) await time_out_assert_not_none( @@ -323,7 +305,7 @@ async def test_nft_offer_request_nft( offer_dict = {nft_to_request_asset_id: 1, wallet_maker.id(): -xch_offered} async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make, error = await trade_manager_maker.create_offer_for_ids( offer_dict, DEFAULT_TX_CONFIG, action_scope, driver_dict, fee=maker_fee ) assert success is True @@ -336,17 +318,16 @@ async def test_nft_offer_request_nft( [maker_offer], signing_response = await wallet_node_maker.wallet_state_manager.sign_offers( [Offer.from_bytes(trade_make.offer)] ) - async with trade_manager_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - trade_take, tx_records = await trade_manager_taker.respond_to_offer( + async with trade_manager_taker.wallet_state_manager.new_action_scope( + push=True, additional_signing_responses=signing_response + ) as action_scope: + trade_take = await trade_manager_taker.respond_to_offer( Offer.from_bytes(trade_make.offer), peer, DEFAULT_TX_CONFIG, action_scope, fee=uint64(taker_fee) ) - tx_records = await trade_manager_taker.wallet_state_manager.add_pending_transactions( - tx_records, additional_signing_responses=signing_response - ) await time_out_assert(20, mempool_not_empty, True, full_node_api) assert trade_take is not None - await full_node_api.process_transaction_records(records=tx_records) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker, wallet_node_taker], timeout=20) async def maker_1_taker_0() -> bool: @@ -388,18 +369,11 @@ async def test_nft_offer_sell_did_to_did( await full_node_api.farm_rewards_to_wallet(funds, wallet_maker, timeout=30) await full_node_api.farm_rewards_to_wallet(funds, wallet_taker, timeout=30) - async with wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet_maker: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_maker.wallet_state_manager, wallet_maker, uint64(1), DEFAULT_TX_CONFIG, action_scope ) - spend_bundle_list = await wallet_node_maker.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_maker.id() - ) - - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(20, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token)) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker, wallet_node_taker], timeout=20) await time_out_assert(20, wallet_maker.get_pending_change_balance, 0) @@ -423,8 +397,8 @@ async def test_nft_offer_sell_did_to_did( await time_out_assert(20, wallet_maker.get_unconfirmed_balance, funds - 1) await time_out_assert(20, wallet_maker.get_confirmed_balance, funds - 1) - async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await nft_wallet_maker.generate_new_nft( + async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await nft_wallet_maker.generate_new_nft( metadata, DEFAULT_TX_CONFIG, action_scope, @@ -433,8 +407,7 @@ async def test_nft_offer_sell_did_to_did( royalty_basis_pts, did_id, ) - txs = await nft_wallet_maker.wallet_state_manager.add_pending_transactions(txs) - for tx in txs: + for tx in action_scope.side_effects.transactions: if tx.spend_bundle is not None: assert compute_memos(tx.spend_bundle) await time_out_assert_not_none( @@ -447,20 +420,11 @@ async def test_nft_offer_sell_did_to_did( await time_out_assert(20, get_nft_count, 1, nft_wallet_maker) # TAKER SETUP - WITH DID - async with wallet_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_taker.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet_taker: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_taker.wallet_state_manager, wallet_taker, uint64(1), DEFAULT_TX_CONFIG, action_scope ) - spend_bundle_list_taker = await wallet_node_taker.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_taker.id() - ) - - spend_bundle_taker = spend_bundle_list_taker[0].spend_bundle - await time_out_assert_not_none( - 5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle_taker.name() - ) - - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token)) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker, wallet_node_taker], timeout=20) await time_out_assert(20, wallet_taker.get_pending_change_balance, 0) @@ -487,7 +451,7 @@ async def test_nft_offer_sell_did_to_did( offer_did_nft_for_xch = {nft_to_offer_asset_id: -1, wallet_maker.id(): xch_requested} async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make, error = await trade_manager_maker.create_offer_for_ids( offer_did_nft_for_xch, DEFAULT_TX_CONFIG, action_scope, {}, fee=maker_fee ) assert success is True @@ -500,16 +464,15 @@ async def test_nft_offer_sell_did_to_did( [maker_offer], signing_response = await wallet_node_maker.wallet_state_manager.sign_offers( [Offer.from_bytes(trade_make.offer)] ) - async with trade_manager_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - trade_take, tx_records = await trade_manager_taker.respond_to_offer( + async with trade_manager_taker.wallet_state_manager.new_action_scope( + push=True, additional_signing_responses=signing_response + ) as action_scope: + trade_take = await trade_manager_taker.respond_to_offer( Offer.from_bytes(trade_make.offer), peer, DEFAULT_TX_CONFIG, action_scope, fee=uint64(taker_fee) ) - tx_records = await trade_manager_taker.wallet_state_manager.add_pending_transactions( - tx_records, additional_signing_responses=signing_response - ) + await time_out_assert(20, mempool_not_empty, True, full_node_api) assert trade_take is not None - assert tx_records is not None async def maker_0_taker_1() -> bool: return ( @@ -559,18 +522,11 @@ async def test_nft_offer_sell_nft_for_cat( await full_node_api.farm_rewards_to_wallet(funds, wallet_maker, timeout=30) await full_node_api.farm_rewards_to_wallet(funds, wallet_taker, timeout=30) - async with wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet_maker: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_maker.wallet_state_manager, wallet_maker, uint64(1), DEFAULT_TX_CONFIG, action_scope ) - spend_bundle_list = await wallet_node_maker.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_maker.id() - ) - - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(20, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token)) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker, wallet_node_taker], timeout=20) await time_out_assert(20, wallet_maker.get_pending_change_balance, 0) @@ -593,8 +549,8 @@ async def test_nft_offer_sell_nft_for_cat( ] ) - async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await nft_wallet_maker.generate_new_nft( + async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await nft_wallet_maker.generate_new_nft( metadata, DEFAULT_TX_CONFIG, action_scope, @@ -603,8 +559,7 @@ async def test_nft_offer_sell_nft_for_cat( royalty_basis_pts, did_id, ) - txs = await nft_wallet_maker.wallet_state_manager.add_pending_transactions(txs) - for tx in txs: + for tx in action_scope.side_effects.transactions: if tx.spend_bundle is not None: assert compute_memos(tx.spend_bundle) await time_out_assert_not_none( @@ -634,9 +589,9 @@ async def test_nft_offer_sell_nft_for_cat( # Trade them between maker and taker to ensure multiple coins for each cat cats_to_mint = 100000 cats_to_trade = uint64(10000) - async with wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: full_node_api.full_node.log.warning(f"Mempool size: {full_node_api.full_node.mempool_manager.mempool.size()}") - cat_wallet_maker, _ = await CATWallet.create_new_cat_wallet( + cat_wallet_maker = await CATWallet.create_new_cat_wallet( wallet_node_maker.wallet_state_manager, wallet_maker, {"identifier": "genesis_by_id"}, @@ -644,7 +599,7 @@ async def test_nft_offer_sell_nft_for_cat( DEFAULT_TX_CONFIG, action_scope, ) - await time_out_assert(20, mempool_not_empty, True, full_node_api) + await time_out_assert(20, mempool_not_empty, True, full_node_api) await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token)) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker, wallet_node_taker], timeout=20) @@ -658,16 +613,15 @@ async def test_nft_offer_sell_nft_for_cat( ph_taker_cat_1 = await wallet_taker.get_new_puzzlehash() ph_taker_cat_2 = await wallet_taker.get_new_puzzlehash() - async with cat_wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_tx_records = await cat_wallet_maker.generate_signed_transaction( + async with cat_wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await cat_wallet_maker.generate_signed_transaction( [cats_to_trade, cats_to_trade], [ph_taker_cat_1, ph_taker_cat_2], DEFAULT_TX_CONFIG, action_scope, memos=[[ph_taker_cat_1], [ph_taker_cat_2]], ) - cat_tx_records = await wallet_maker.wallet_state_manager.add_pending_transactions(cat_tx_records) - await full_node_api.process_transaction_records(records=cat_tx_records) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker, wallet_node_taker], timeout=20) maker_cat_balance = cats_to_mint - (2 * cats_to_trade) @@ -683,7 +637,7 @@ async def test_nft_offer_sell_nft_for_cat( offer_did_nft_for_xch = {nft_to_offer_asset_id: -1, cat_wallet_maker.id(): cats_requested} async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make, error = await trade_manager_maker.create_offer_for_ids( offer_did_nft_for_xch, DEFAULT_TX_CONFIG, action_scope, {}, fee=maker_fee ) @@ -697,16 +651,14 @@ async def test_nft_offer_sell_nft_for_cat( [maker_offer], signing_response = await wallet_node_maker.wallet_state_manager.sign_offers( [Offer.from_bytes(trade_make.offer)] ) - async with trade_manager_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - trade_take, tx_records = await trade_manager_taker.respond_to_offer( + async with trade_manager_taker.wallet_state_manager.new_action_scope( + push=True, additional_signing_responses=signing_response + ) as action_scope: + trade_take = await trade_manager_taker.respond_to_offer( Offer.from_bytes(trade_make.offer), peer, DEFAULT_TX_CONFIG, action_scope, fee=uint64(taker_fee) ) - tx_records = await trade_manager_taker.wallet_state_manager.add_pending_transactions( - tx_records, additional_signing_responses=signing_response - ) await time_out_assert(20, mempool_not_empty, True, full_node_api) assert trade_take is not None - assert tx_records is not None async def maker_0_taker_1() -> bool: return ( @@ -753,18 +705,11 @@ async def test_nft_offer_request_nft_for_cat( await full_node_api.farm_rewards_to_wallet(funds, wallet_maker, timeout=30) await full_node_api.farm_rewards_to_wallet(funds, wallet_taker, timeout=30) - async with wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_taker.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet_taker: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_taker.wallet_state_manager, wallet_taker, uint64(1), DEFAULT_TX_CONFIG, action_scope ) - spend_bundle_list = await wallet_node_taker.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_taker.id() - ) - - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(20, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token)) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker, wallet_node_taker], timeout=20) await time_out_assert(20, wallet_taker.get_pending_change_balance, 0) @@ -787,8 +732,8 @@ async def test_nft_offer_request_nft_for_cat( ] ) - async with nft_wallet_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await nft_wallet_taker.generate_new_nft( + async with nft_wallet_taker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await nft_wallet_taker.generate_new_nft( metadata, DEFAULT_TX_CONFIG, action_scope, @@ -797,8 +742,7 @@ async def test_nft_offer_request_nft_for_cat( royalty_basis_pts, did_id, ) - txs = await nft_wallet_taker.wallet_state_manager.add_pending_transactions(txs) - for tx in txs: + for tx in action_scope.side_effects.transactions: if tx.spend_bundle is not None: assert compute_memos(tx.spend_bundle) await time_out_assert_not_none( @@ -828,8 +772,8 @@ async def test_nft_offer_request_nft_for_cat( # Trade them between maker and taker to ensure multiple coins for each cat cats_to_mint = 100000 cats_to_trade = uint64(20000) - async with wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_wallet_maker, _ = await CATWallet.create_new_cat_wallet( + async with wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + cat_wallet_maker = await CATWallet.create_new_cat_wallet( wallet_node_maker.wallet_state_manager, wallet_maker, {"identifier": "genesis_by_id"}, @@ -837,7 +781,7 @@ async def test_nft_offer_request_nft_for_cat( DEFAULT_TX_CONFIG, action_scope, ) - await time_out_assert(20, mempool_not_empty, True, full_node_api) + await time_out_assert(20, mempool_not_empty, True, full_node_api) await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token)) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker, wallet_node_taker], timeout=20) @@ -861,12 +805,9 @@ async def test_nft_offer_request_nft_for_cat( extra_change = cats_to_mint - (2 * cats_to_trade) amounts.append(uint64(extra_change)) puzzle_hashes.append(ph_taker_cat_1) - async with cat_wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_tx_records = await cat_wallet_maker.generate_signed_transaction( - amounts, puzzle_hashes, DEFAULT_TX_CONFIG, action_scope - ) - cat_tx_records = await wallet_maker.wallet_state_manager.add_pending_transactions(cat_tx_records) - await full_node_api.process_transaction_records(records=cat_tx_records) + async with cat_wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await cat_wallet_maker.generate_signed_transaction(amounts, puzzle_hashes, DEFAULT_TX_CONFIG, action_scope) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker, wallet_node_taker], timeout=20) if test_change: @@ -888,7 +829,7 @@ async def test_nft_offer_request_nft_for_cat( offer_dict = {nft_to_request_asset_id: 1, cat_wallet_maker.id(): -cats_requested} async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make, error = await trade_manager_maker.create_offer_for_ids( offer_dict, DEFAULT_TX_CONFIG, action_scope, driver_dict, fee=maker_fee ) assert success is True @@ -901,16 +842,14 @@ async def test_nft_offer_request_nft_for_cat( [maker_offer], signing_response = await wallet_node_maker.wallet_state_manager.sign_offers( [Offer.from_bytes(trade_make.offer)] ) - async with trade_manager_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - trade_take, tx_records = await trade_manager_taker.respond_to_offer( + async with trade_manager_taker.wallet_state_manager.new_action_scope( + push=True, additional_signing_responses=signing_response + ) as action_scope: + trade_take = await trade_manager_taker.respond_to_offer( Offer.from_bytes(trade_make.offer), peer, DEFAULT_TX_CONFIG, action_scope, fee=uint64(taker_fee) ) - tx_records = await trade_manager_taker.wallet_state_manager.add_pending_transactions( - tx_records, additional_signing_responses=signing_response - ) await time_out_assert(20, mempool_not_empty, True, full_node_api) assert trade_take is not None - assert tx_records is not None async def maker_1_taker_0() -> bool: return ( @@ -961,18 +900,11 @@ async def test_nft_offer_sell_cancel( funds = sum(calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, 3)) await full_node_api.farm_rewards_to_wallet(funds, wallet_maker, timeout=30) - async with wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet_maker: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_maker.wallet_state_manager, wallet_maker, uint64(1), DEFAULT_TX_CONFIG, action_scope ) - spend_bundle_list = await wallet_node_maker.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_maker.id() - ) - - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(20, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token)) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker], timeout=20) await time_out_assert(20, wallet_maker.get_pending_change_balance, 0) @@ -995,8 +927,8 @@ async def test_nft_offer_sell_cancel( ] ) - async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await nft_wallet_maker.generate_new_nft( + async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await nft_wallet_maker.generate_new_nft( metadata, DEFAULT_TX_CONFIG, action_scope, @@ -1005,8 +937,7 @@ async def test_nft_offer_sell_cancel( royalty_basis_pts, did_id, ) - txs = await nft_wallet_maker.wallet_state_manager.add_pending_transactions(txs) - for tx in txs: + for tx in action_scope.side_effects.transactions: if tx.spend_bundle is not None: assert compute_memos(tx.spend_bundle) await time_out_assert_not_none( @@ -1032,23 +963,22 @@ async def test_nft_offer_sell_cancel( offer_did_nft_for_xch = {nft_to_offer_asset_id: -1, wallet_maker.id(): xch_requested} async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make, error = await trade_manager_maker.create_offer_for_ids( offer_did_nft_for_xch, DEFAULT_TX_CONFIG, action_scope, {}, fee=maker_fee ) FEE = uint64(2000000000000) - async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await trade_manager_maker.cancel_pending_offers( + async with trade_manager_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await trade_manager_maker.cancel_pending_offers( [trade_make.trade_id], DEFAULT_TX_CONFIG, action_scope, fee=FEE, secure=True ) - txs = await trade_manager_maker.wallet_state_manager.add_pending_transactions(txs) async def get_trade_and_status(trade_manager: Any, trade: Any) -> TradeStatus: trade_rec = await trade_manager.get_trade_by_id(trade.trade_id) return TradeStatus(trade_rec.status) await time_out_assert(20, get_trade_and_status, TradeStatus.PENDING_CANCEL, trade_manager_maker, trade_make) - await full_node_api.process_transaction_records(records=txs) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker], timeout=20) await time_out_assert(15, get_trade_and_status, TradeStatus.CANCELLED, trade_manager_maker, trade_make) @@ -1086,19 +1016,11 @@ async def test_nft_offer_sell_cancel_in_batch( ) await full_node_api.farm_rewards_to_wallet(funds, wallet_maker, timeout=30) - async with wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet_maker: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_maker.wallet_state_manager, wallet_maker, uint64(1), DEFAULT_TX_CONFIG, action_scope ) - spend_bundle_list = await wallet_node_maker.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_maker.id() - ) - - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - for _ in range(1, num_blocks): - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token)) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(15, wallet_maker.get_pending_change_balance, 0) await time_out_assert(10, wallet_maker.get_unconfirmed_balance, funds - 1) @@ -1120,8 +1042,8 @@ async def test_nft_offer_sell_cancel_in_batch( ] ) - async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await nft_wallet_maker.generate_new_nft( + async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await nft_wallet_maker.generate_new_nft( metadata, DEFAULT_TX_CONFIG, action_scope, @@ -1130,8 +1052,7 @@ async def test_nft_offer_sell_cancel_in_batch( royalty_basis_pts, did_id, ) - txs = await nft_wallet_maker.wallet_state_manager.add_pending_transactions(txs) - for tx in txs: + for tx in action_scope.side_effects.transactions: if tx.spend_bundle is not None: assert compute_memos(tx.spend_bundle) await time_out_assert_not_none( @@ -1158,23 +1079,22 @@ async def test_nft_offer_sell_cancel_in_batch( offer_did_nft_for_xch = {nft_to_offer_asset_id: -1, wallet_maker.id(): xch_requested} async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make, error = await trade_manager_maker.create_offer_for_ids( offer_did_nft_for_xch, DEFAULT_TX_CONFIG, action_scope, {}, fee=maker_fee ) FEE = uint64(2000000000000) - async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await trade_manager_maker.cancel_pending_offers( + async with trade_manager_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await trade_manager_maker.cancel_pending_offers( [trade_make.trade_id], DEFAULT_TX_CONFIG, action_scope, fee=FEE, secure=True ) - txs = await trade_manager_maker.wallet_state_manager.add_pending_transactions(txs) async def get_trade_and_status(trade_manager: Any, trade: Any) -> TradeStatus: trade_rec = await trade_manager.get_trade_by_id(trade.trade_id) return TradeStatus(trade_rec.status) await time_out_assert(15, get_trade_and_status, TradeStatus.PENDING_CANCEL, trade_manager_maker, trade_make) - await full_node_api.process_transaction_records(records=txs) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) for i in range(1, num_blocks): await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(bytes32([0] * 32))) @@ -1233,54 +1153,34 @@ async def test_complex_nft_offer( await full_node_api.farm_rewards_to_wallet(amount=funds_taker, wallet=wsm_taker.main_wallet, timeout=60) CAT_AMOUNT = uint64(100000000) - async with wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_wallet_maker, _ = await CATWallet.create_new_cat_wallet( + txs = [] + async with wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + cat_wallet_maker = await CATWallet.create_new_cat_wallet( wsm_maker, wallet_maker, {"identifier": "genesis_by_id"}, CAT_AMOUNT, DEFAULT_TX_CONFIG, action_scope ) - async with wallet_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_wallet_taker, _ = await CATWallet.create_new_cat_wallet( + txs.extend(action_scope.side_effects.transactions) + async with wallet_taker.wallet_state_manager.new_action_scope(push=True) as action_scope: + cat_wallet_taker = await CATWallet.create_new_cat_wallet( wsm_taker, wallet_taker, {"identifier": "genesis_by_id"}, CAT_AMOUNT, DEFAULT_TX_CONFIG, action_scope ) - cat_spend_bundle_maker = ( - await wallet_node_maker.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(wallet_maker.id()) - )[0].spend_bundle - cat_spend_bundle_taker = ( - await wallet_node_taker.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(wallet_taker.id()) - )[0].spend_bundle - await time_out_assert_not_none( - 5, full_node_api.full_node.mempool_manager.get_spendbundle, cat_spend_bundle_maker.name() - ) - await time_out_assert_not_none( - 5, full_node_api.full_node.mempool_manager.get_spendbundle, cat_spend_bundle_taker.name() - ) + txs.extend(action_scope.side_effects.transactions) # We'll need these later basic_nft_wallet_maker = await NFTWallet.create_new_nft_wallet(wsm_maker, wallet_maker, name="NFT WALLET MAKER") basic_nft_wallet_taker = await NFTWallet.create_new_nft_wallet(wsm_taker, wallet_taker, name="NFT WALLET TAKER") - async with wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet_maker: DIDWallet = await DIDWallet.create_new_did_wallet( wsm_maker, wallet_maker, uint64(1), DEFAULT_TX_CONFIG, action_scope ) - async with wallet_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: + txs.extend(action_scope.side_effects.transactions) + async with wallet_taker.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet_taker: DIDWallet = await DIDWallet.create_new_did_wallet( wsm_taker, wallet_taker, uint64(1), DEFAULT_TX_CONFIG, action_scope ) - did_spend_bundle_maker = ( - await wallet_node_maker.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(did_wallet_maker.id()) - )[0].spend_bundle - did_spend_bundle_taker = ( - await wallet_node_taker.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(did_wallet_taker.id()) - )[0].spend_bundle - - await time_out_assert_not_none( - 5, full_node_api.full_node.mempool_manager.get_spendbundle, did_spend_bundle_maker.name() - ) - await time_out_assert_not_none( - 5, full_node_api.full_node.mempool_manager.get_spendbundle, did_spend_bundle_taker.name() - ) + txs.extend(action_scope.side_effects.transactions) - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token)) + await full_node_api.process_transaction_records(records=txs) funds_maker = funds_maker - 1 - CAT_AMOUNT funds_taker = funds_taker - 1 - CAT_AMOUNT @@ -1331,8 +1231,8 @@ async def test_complex_nft_offer( ) return else: - async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await nft_wallet_maker.generate_new_nft( + async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await nft_wallet_maker.generate_new_nft( metadata, DEFAULT_TX_CONFIG, action_scope, @@ -1341,15 +1241,14 @@ async def test_complex_nft_offer( uint16(royalty_basis_pts_maker), did_id_maker, ) - txs = await nft_wallet_maker.wallet_state_manager.add_pending_transactions(txs) - for tx in txs: + for tx in action_scope.side_effects.transactions: if tx.spend_bundle is not None: await time_out_assert_not_none( 20, full_node_api.full_node.mempool_manager.get_spendbundle, tx.spend_bundle.name() ) - async with nft_wallet_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await nft_wallet_taker.generate_new_nft( + async with nft_wallet_taker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await nft_wallet_taker.generate_new_nft( metadata, DEFAULT_TX_CONFIG, action_scope, @@ -1358,8 +1257,7 @@ async def test_complex_nft_offer( royalty_basis_pts_taker_1, did_id_taker, ) - txs = await nft_wallet_taker.wallet_state_manager.add_pending_transactions(txs) - for tx in txs: + for tx in action_scope.side_effects.transactions: if tx.spend_bundle is not None: await time_out_assert_not_none( 20, full_node_api.full_node.mempool_manager.get_spendbundle, tx.spend_bundle.name() @@ -1377,8 +1275,8 @@ async def test_complex_nft_offer( await time_out_assert(30, get_nft_count, 1, nft_wallet_taker) # MAke one more NFT for the taker - async with nft_wallet_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await nft_wallet_taker.generate_new_nft( + async with nft_wallet_taker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await nft_wallet_taker.generate_new_nft( metadata, DEFAULT_TX_CONFIG, action_scope, @@ -1387,8 +1285,7 @@ async def test_complex_nft_offer( royalty_basis_pts_taker_2, did_id_taker, ) - txs = await nft_wallet_taker.wallet_state_manager.add_pending_transactions(txs) - for tx in txs: + for tx in action_scope.side_effects.transactions: if tx.spend_bundle is not None: await time_out_assert_not_none( 20, full_node_api.full_node.mempool_manager.get_spendbundle, tx.spend_bundle.name() @@ -1438,7 +1335,7 @@ async def test_complex_nft_offer( } async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make, error = await trade_manager_maker.create_offer_for_ids( complex_nft_offer, DEFAULT_TX_CONFIG, action_scope, driver_dict=driver_dict, fee=FEE ) assert error is None @@ -1450,8 +1347,10 @@ async def test_complex_nft_offer( ) if royalty_basis_pts_maker == 10000: with pytest.raises(ValueError): - async with trade_manager_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - trade_take, tx_records = await trade_manager_taker.respond_to_offer( + async with trade_manager_taker.wallet_state_manager.new_action_scope( + push=True, additional_signing_responses=signing_response + ) as action_scope: + trade_take = await trade_manager_taker.respond_to_offer( Offer.from_bytes(trade_make.offer), wallet_node_taker.get_full_node_peer(), DEFAULT_TX_CONFIG, @@ -1461,20 +1360,18 @@ async def test_complex_nft_offer( # all done for this test return else: - async with trade_manager_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - trade_take, tx_records = await trade_manager_taker.respond_to_offer( + async with trade_manager_taker.wallet_state_manager.new_action_scope( + push=True, additional_signing_responses=signing_response + ) as action_scope: + trade_take = await trade_manager_taker.respond_to_offer( maker_offer, wallet_node_taker.get_full_node_peer(), DEFAULT_TX_CONFIG, action_scope, fee=FEE, ) - tx_records = await trade_manager_taker.wallet_state_manager.add_pending_transactions( - tx_records, additional_signing_responses=signing_response - ) assert trade_take is not None - assert tx_records is not None - await full_node_api.process_transaction_records(records=tx_records) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker, wallet_node_taker], timeout=60) # Now let's make sure the final wallet state is correct @@ -1561,7 +1458,7 @@ async def get_cat_wallet_and_check_balance(asset_id: str, wsm: Any) -> uint128: } async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make, error = await trade_manager_maker.create_offer_for_ids( complex_nft_offer, DEFAULT_TX_CONFIG, action_scope, driver_dict=driver_dict, fee=uint64(0) ) assert error is None @@ -1571,19 +1468,17 @@ async def get_cat_wallet_and_check_balance(asset_id: str, wsm: Any) -> uint128: [maker_offer], signing_response = await wallet_node_maker.wallet_state_manager.sign_offers( [Offer.from_bytes(trade_make.offer)] ) - async with trade_manager_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - trade_take, tx_records = await trade_manager_taker.respond_to_offer( + async with trade_manager_taker.wallet_state_manager.new_action_scope( + push=True, additional_signing_responses=signing_response + ) as action_scope: + trade_take = await trade_manager_taker.respond_to_offer( Offer.from_bytes(trade_make.offer), wallet_node_taker.get_full_node_peer(), DEFAULT_TX_CONFIG, action_scope, fee=uint64(0), ) - tx_records = await trade_manager_taker.wallet_state_manager.add_pending_transactions( - tx_records, additional_signing_responses=signing_response - ) assert trade_take is not None - assert tx_records is not None await time_out_assert(20, mempool_not_empty, True, full_node_api) await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token)) diff --git a/chia/_tests/wallet/nft_wallet/test_nft_bulk_mint.py b/chia/_tests/wallet/nft_wallet/test_nft_bulk_mint.py index 4d0ff2b534f6..944e5895ad51 100644 --- a/chia/_tests/wallet/nft_wallet/test_nft_bulk_mint.py +++ b/chia/_tests/wallet/nft_wallet/test_nft_bulk_mint.py @@ -45,7 +45,6 @@ async def test_nft_mint_from_did( wallet_node_1, server_1 = wallets[1] wallet_0 = wallet_node_0.wallet_state_manager.main_wallet wallet_1 = wallet_node_1.wallet_state_manager.main_wallet - api_0 = WalletRpcApi(wallet_node_0) ph_maker = await wallet_0.get_new_puzzlehash() ph_token = bytes32.random(seeded_random) @@ -71,15 +70,11 @@ async def test_nft_mint_from_did( await time_out_assert(30, wallet_0.get_unconfirmed_balance, funds) await time_out_assert(30, wallet_0.get_confirmed_balance, funds) - async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_0.wallet_state_manager, wallet_0, uint64(1), DEFAULT_TX_CONFIG, action_scope ) - spend_bundle_list = await wallet_node_0.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(did_wallet.id()) - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token)) + await full_node_api.process_transaction_records(action_scope.side_effects.transactions) await time_out_assert(30, wallet_0.get_pending_change_balance, 0) hex_did_id = did_wallet.get_my_DID() @@ -113,8 +108,8 @@ async def test_nft_mint_from_did( target_list = [(await wallet_1.get_new_puzzlehash()) for x in range(mint_total)] - async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - tx_records = await nft_wallet_maker.mint_from_did( + async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await nft_wallet_maker.mint_from_did( metadata_list, DEFAULT_TX_CONFIG, action_scope, @@ -123,13 +118,11 @@ async def test_nft_mint_from_did( mint_total=mint_total, fee=fee, ) - sb = tx_records[0].spend_bundle - assert sb is not None - - bundle, _ = await nft_wallet_maker.wallet_state_manager.sign_bundle(sb.coin_spends) - await api_0.push_tx({"spend_bundle": bytes(bundle).hex()}) - - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, bundle.name()) + for record in action_scope.side_effects.transactions: + if record.spend_bundle is not None: + await time_out_assert_not_none( + 5, full_node_api.full_node.mempool_manager.get_spendbundle, record.spend_bundle.name() + ) await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token)) await time_out_assert(30, nft_count, mint_total, nft_wallet_taker) @@ -222,19 +215,11 @@ async def test_nft_mint_from_did_rpc( self_hostname, full_node_service.rpc_server.listen_port, full_node_service.root_path, full_node_service.config ) - async with wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet_maker: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_maker.wallet_state_manager, wallet_maker, uint64(1), DEFAULT_TX_CONFIG, action_scope ) - spend_bundle_list = await wallet_node_maker.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_maker.id() - ) - - spend_bundle = spend_bundle_list[0].spend_bundle - assert spend_bundle is not None - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token)) + await full_node_api.process_transaction_records(action_scope.side_effects.transactions) await time_out_assert(30, wallet_maker.get_pending_change_balance, 0) await time_out_assert(30, wallet_maker.get_unconfirmed_balance, funds - 1) @@ -418,19 +403,11 @@ async def test_nft_mint_from_did_rpc_no_royalties( self_hostname, full_node_service.rpc_server.listen_port, full_node_service.root_path, full_node_service.config ) - async with wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet_maker: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_maker.wallet_state_manager, wallet_maker, uint64(1), DEFAULT_TX_CONFIG, action_scope ) - spend_bundle_list = await wallet_node_maker.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_maker.id() - ) - - spend_bundle = spend_bundle_list[0].spend_bundle - assert spend_bundle is not None - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token)) + await full_node_api.process_transaction_records(action_scope.side_effects.transactions) await time_out_assert(30, wallet_maker.get_pending_change_balance, 0) await time_out_assert(30, wallet_maker.get_unconfirmed_balance, funds - 1) @@ -542,7 +519,6 @@ async def test_nft_mint_from_did_multiple_xch( wallet_node_1, server_1 = wallets[1] wallet_maker = wallet_node_0.wallet_state_manager.main_wallet wallet_taker = wallet_node_1.wallet_state_manager.main_wallet - api_0 = WalletRpcApi(wallet_node_0) ph_maker = await wallet_maker.get_new_puzzlehash() ph_taker = await wallet_taker.get_new_puzzlehash() ph_token = bytes32.random(seeded_random) @@ -569,15 +545,11 @@ async def test_nft_mint_from_did_multiple_xch( await time_out_assert(30, wallet_maker.get_unconfirmed_balance, funds) await time_out_assert(30, wallet_maker.get_confirmed_balance, funds) - async with wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_0.wallet_state_manager, wallet_maker, uint64(1), DEFAULT_TX_CONFIG, action_scope ) - spend_bundle_list = await wallet_node_0.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(did_wallet.id()) - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token)) + await full_node_api.process_transaction_records(action_scope.side_effects.transactions) await time_out_assert(30, wallet_maker.get_pending_change_balance, 0) hex_did_id = did_wallet.get_my_DID() @@ -619,8 +591,8 @@ async def test_nft_mint_from_did_multiple_xch( target_list = [ph_taker for x in range(mint_total)] - async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - tx_records = await nft_wallet_maker.mint_from_did( + async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await nft_wallet_maker.mint_from_did( metadata_list, DEFAULT_TX_CONFIG, action_scope, @@ -630,13 +602,10 @@ async def test_nft_mint_from_did_multiple_xch( xch_coins=xch_coins, fee=fee, ) - sb = tx_records[0].spend_bundle + sb = action_scope.side_effects.transactions[0].spend_bundle assert sb is not None - bundle, _ = await nft_wallet_maker.wallet_state_manager.sign_bundle(sb.coin_spends) - await api_0.push_tx({"spend_bundle": bytes(bundle).hex()}) - - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, bundle.name()) + await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, sb.name()) await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token)) await time_out_assert(30, nft_count, mint_total, nft_wallet_taker) @@ -662,7 +631,6 @@ async def test_nft_mint_from_xch( wallet_node_1, server_1 = wallets[1] wallet_0 = wallet_node_0.wallet_state_manager.main_wallet wallet_1 = wallet_node_1.wallet_state_manager.main_wallet - api_0 = WalletRpcApi(wallet_node_0) ph_maker = await wallet_0.get_new_puzzlehash() ph_token = bytes32.random(seeded_random) @@ -688,15 +656,11 @@ async def test_nft_mint_from_xch( await time_out_assert(30, wallet_0.get_unconfirmed_balance, funds) await time_out_assert(30, wallet_0.get_confirmed_balance, funds) - async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_0.wallet_state_manager, wallet_0, uint64(1), DEFAULT_TX_CONFIG, action_scope ) - spend_bundle_list = await wallet_node_0.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(did_wallet.id()) - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token)) + await full_node_api.process_transaction_records(action_scope.side_effects.transactions) await time_out_assert(30, wallet_0.get_pending_change_balance, 0) hex_did_id = did_wallet.get_my_DID() @@ -730,8 +694,8 @@ async def test_nft_mint_from_xch( target_list = [(await wallet_1.get_new_puzzlehash()) for x in range(mint_total)] - async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - tx_records = await nft_wallet_maker.mint_from_xch( + async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await nft_wallet_maker.mint_from_xch( metadata_list, DEFAULT_TX_CONFIG, action_scope, @@ -740,14 +704,8 @@ async def test_nft_mint_from_xch( mint_total=mint_total, fee=fee, ) - sb = tx_records[0].spend_bundle - assert sb is not None - bundle, _ = await nft_wallet_maker.wallet_state_manager.sign_bundle(sb.coin_spends) - await api_0.push_tx({"spend_bundle": bytes(bundle).hex()}) - - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, bundle.name()) - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token)) + await full_node_api.process_transaction_records(action_scope.side_effects.transactions) await time_out_assert(30, nft_count, mint_total, nft_wallet_taker) await time_out_assert(30, nft_count, 0, nft_wallet_maker) @@ -838,19 +796,11 @@ async def test_nft_mint_from_xch_rpc( self_hostname, full_node_service.rpc_server.listen_port, full_node_service.root_path, full_node_service.config ) - async with wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet_maker: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_maker.wallet_state_manager, wallet_maker, uint64(1), DEFAULT_TX_CONFIG, action_scope ) - spend_bundle_list = await wallet_node_maker.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( - did_wallet_maker.id() - ) - - spend_bundle = spend_bundle_list[0].spend_bundle - assert spend_bundle is not None - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token)) + await full_node_api.process_transaction_records(action_scope.side_effects.transactions) await time_out_assert(30, wallet_maker.get_pending_change_balance, 0) await time_out_assert(30, wallet_maker.get_unconfirmed_balance, funds - 1) @@ -973,7 +923,6 @@ async def test_nft_mint_from_xch_multiple_xch( wallet_node_1, server_1 = wallets[1] wallet_maker = wallet_node_0.wallet_state_manager.main_wallet wallet_taker = wallet_node_1.wallet_state_manager.main_wallet - api_0 = WalletRpcApi(wallet_node_0) ph_maker = await wallet_maker.get_new_puzzlehash() ph_taker = await wallet_taker.get_new_puzzlehash() ph_token = bytes32.random(seeded_random) @@ -1000,15 +949,11 @@ async def test_nft_mint_from_xch_multiple_xch( await time_out_assert(30, wallet_maker.get_unconfirmed_balance, funds) await time_out_assert(30, wallet_maker.get_confirmed_balance, funds) - async with wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_0.wallet_state_manager, wallet_maker, uint64(1), DEFAULT_TX_CONFIG, action_scope ) - spend_bundle_list = await wallet_node_0.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(did_wallet.id()) - spend_bundle = spend_bundle_list[0].spend_bundle - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token)) + await full_node_api.process_transaction_records(action_scope.side_effects.transactions) await time_out_assert(30, wallet_maker.get_pending_change_balance, 0) hex_did_id = did_wallet.get_my_DID() @@ -1050,8 +995,8 @@ async def test_nft_mint_from_xch_multiple_xch( target_list = [ph_taker for x in range(mint_total)] - async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - tx_records = await nft_wallet_maker.mint_from_xch( + async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await nft_wallet_maker.mint_from_xch( metadata_list, DEFAULT_TX_CONFIG, action_scope, @@ -1061,14 +1006,8 @@ async def test_nft_mint_from_xch_multiple_xch( xch_coins=xch_coins, fee=fee, ) - sb = tx_records[0].spend_bundle - assert sb is not None - - bundle, _ = await nft_wallet_maker.wallet_state_manager.sign_bundle(sb.coin_spends) - await api_0.push_tx({"spend_bundle": bytes(bundle).hex()}) - await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, bundle.name()) - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token)) + await full_node_api.process_transaction_records(action_scope.side_effects.transactions) await time_out_assert(30, nft_count, mint_total, nft_wallet_taker) await time_out_assert(30, nft_count, 0, nft_wallet_maker) diff --git a/chia/_tests/wallet/nft_wallet/test_nft_offers.py b/chia/_tests/wallet/nft_wallet/test_nft_offers.py index ee5d80b99289..75645d675338 100644 --- a/chia/_tests/wallet/nft_wallet/test_nft_offers.py +++ b/chia/_tests/wallet/nft_wallet/test_nft_offers.py @@ -102,10 +102,9 @@ async def test_nft_offer_with_fee( ] ) - async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await nft_wallet_maker.generate_new_nft(metadata, tx_config, action_scope) - txs = await nft_wallet_maker.wallet_state_manager.add_pending_transactions(txs) - for tx in txs: + async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await nft_wallet_maker.generate_new_nft(metadata, tx_config, action_scope) + for tx in action_scope.side_effects.transactions: if tx.spend_bundle is not None: await time_out_assert_not_none( 20, full_node_api.full_node.mempool_manager.get_spendbundle, tx.spend_bundle.name() @@ -137,7 +136,7 @@ async def test_nft_offer_with_fee( ).index async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make, error = await trade_manager_maker.create_offer_for_ids( offer_nft_for_xch, tx_config, action_scope, driver_dict, fee=maker_fee ) assert success is True @@ -150,21 +149,18 @@ async def test_nft_offer_with_fee( [Offer.from_bytes(trade_make.offer)] ) peer = wallet_node_1.get_full_node_peer() - async with trade_manager_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - trade_take, tx_records = await trade_manager_taker.respond_to_offer( + async with trade_manager_taker.wallet_state_manager.new_action_scope( + push=True, additional_signing_responses=signing_response + ) as action_scope: + trade_take = await trade_manager_taker.respond_to_offer( Offer.from_bytes(trade_make.offer), peer, tx_config, action_scope, fee=taker_fee, ) - tx_records = await trade_manager_taker.wallet_state_manager.add_pending_transactions( - tx_records, additional_signing_responses=signing_response - ) - assert trade_take is not None - assert tx_records is not None - await full_node_api.process_transaction_records(records=tx_records) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=20) await time_out_assert(20, get_trade_and_status, TradeStatus.CONFIRMED, trade_manager_maker, trade_make) @@ -217,7 +213,7 @@ async def test_nft_offer_with_fee( offer_xch_for_nft = {wallet_maker.id(): -xch_offered, nft_to_buy_asset_id: 1} async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make, error = await trade_manager_maker.create_offer_for_ids( offer_xch_for_nft, tx_config, action_scope, driver_dict_to_buy, fee=maker_fee ) assert success is True @@ -229,17 +225,14 @@ async def test_nft_offer_with_fee( [maker_offer], signing_response = await wallet_node_0.wallet_state_manager.sign_offers( [Offer.from_bytes(trade_make.offer)] ) - async with trade_manager_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - trade_take, tx_records = await trade_manager_taker.respond_to_offer( + async with trade_manager_taker.wallet_state_manager.new_action_scope( + push=True, additional_signing_responses=signing_response + ) as action_scope: + trade_take = await trade_manager_taker.respond_to_offer( Offer.from_bytes(trade_make.offer), peer, tx_config, action_scope, fee=taker_fee ) - tx_records = await trade_manager_taker.wallet_state_manager.add_pending_transactions( - tx_records, additional_signing_responses=signing_response - ) - assert trade_take is not None - assert tx_records is not None - await full_node_api.process_transaction_records(records=tx_records) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=20) await time_out_assert(20, get_trade_and_status, TradeStatus.CONFIRMED, trade_manager_maker, trade_make) @@ -315,10 +308,9 @@ async def test_nft_offer_cancellations( ] ) - async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await nft_wallet_maker.generate_new_nft(metadata, DEFAULT_TX_CONFIG, action_scope) - txs = await nft_wallet_maker.wallet_state_manager.add_pending_transactions(txs) - for tx in txs: + async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await nft_wallet_maker.generate_new_nft(metadata, DEFAULT_TX_CONFIG, action_scope) + for tx in action_scope.side_effects.transactions: if tx.spend_bundle is not None: await time_out_assert_not_none( 20, full_node_api.full_node.mempool_manager.get_spendbundle, tx.spend_bundle.name() @@ -343,7 +335,7 @@ async def test_nft_offer_cancellations( offer_nft_for_xch = {wallet_maker.id(): xch_request, nft_asset_id: -1} async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make, error = await trade_manager_maker.create_offer_for_ids( offer_nft_for_xch, DEFAULT_TX_CONFIG, action_scope, driver_dict, fee=maker_fee ) assert success is True @@ -355,14 +347,13 @@ async def test_nft_offer_cancellations( cancel_fee = uint64(10) - async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await trade_manager_maker.cancel_pending_offers( + async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await trade_manager_maker.cancel_pending_offers( [trade_make.trade_id], DEFAULT_TX_CONFIG, action_scope, fee=cancel_fee, secure=True ) - txs = await trade_manager_maker.wallet_state_manager.add_pending_transactions(txs) await time_out_assert(20, get_trade_and_status, TradeStatus.PENDING_CANCEL, trade_manager_maker, trade_make) - await full_node_api.process_transaction_records(records=txs) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=20) await time_out_assert(20, get_trade_and_status, TradeStatus.CANCELLED, trade_manager_maker, trade_make) @@ -440,10 +431,9 @@ async def test_nft_offer_with_metadata_update( ] ) - async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await nft_wallet_maker.generate_new_nft(metadata, DEFAULT_TX_CONFIG, action_scope) - txs = await nft_wallet_maker.wallet_state_manager.add_pending_transactions(txs) - for tx in txs: + async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await nft_wallet_maker.generate_new_nft(metadata, DEFAULT_TX_CONFIG, action_scope) + for tx in action_scope.side_effects.transactions: if tx.spend_bundle is not None: await time_out_assert_not_none( 20, full_node_api.full_node.mempool_manager.get_spendbundle, tx.spend_bundle.name() @@ -460,13 +450,12 @@ async def test_nft_offer_with_metadata_update( url_to_add = "https://new_url.com" key = "mu" fee_for_update = uint64(10) - async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await nft_wallet_maker.update_metadata( + async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await nft_wallet_maker.update_metadata( nft_to_update, key, url_to_add, DEFAULT_TX_CONFIG, action_scope, fee=fee_for_update ) mempool_mgr = full_node_api.full_node.mempool_manager - txs = await nft_wallet_maker.wallet_state_manager.add_pending_transactions(txs) - for tx in txs: + for tx in action_scope.side_effects.transactions: if tx.spend_bundle is not None: await time_out_assert_not_none(20, mempool_mgr.get_spendbundle, tx.spend_bundle.name()) @@ -493,7 +482,7 @@ async def test_nft_offer_with_metadata_update( offer_nft_for_xch = {wallet_maker.id(): xch_request, nft_asset_id: -1} async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make, error = await trade_manager_maker.create_offer_for_ids( offer_nft_for_xch, DEFAULT_TX_CONFIG, action_scope, driver_dict, fee=maker_fee ) assert success is True @@ -506,17 +495,13 @@ async def test_nft_offer_with_metadata_update( [Offer.from_bytes(trade_make.offer)] ) peer = wallet_node_1.get_full_node_peer() - async with trade_manager_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - trade_take, tx_records = await trade_manager_taker.respond_to_offer( + async with trade_manager_taker.wallet_state_manager.new_action_scope( + push=True, additional_signing_responses=signing_response + ) as action_scope: + trade_take = await trade_manager_taker.respond_to_offer( Offer.from_bytes(trade_make.offer), peer, DEFAULT_TX_CONFIG, action_scope, fee=taker_fee ) - tx_records = await trade_manager_taker.wallet_state_manager.add_pending_transactions( - tx_records, additional_signing_responses=signing_response - ) - assert trade_take is not None - assert tx_records is not None - - await full_node_api.process_transaction_records(records=tx_records) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=20) await time_out_assert(20, get_trade_and_status, TradeStatus.CONFIRMED, trade_manager_maker, trade_make) @@ -597,10 +582,9 @@ async def test_nft_offer_nft_for_cat( ] ) - async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await nft_wallet_maker.generate_new_nft(metadata, tx_config, action_scope) - txs = await nft_wallet_maker.wallet_state_manager.add_pending_transactions(txs) - for tx in txs: + async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await nft_wallet_maker.generate_new_nft(metadata, tx_config, action_scope) + for tx in action_scope.side_effects.transactions: if tx.spend_bundle is not None: await time_out_assert_not_none( 20, full_node_api.full_node.mempool_manager.get_spendbundle, tx.spend_bundle.name() @@ -614,8 +598,8 @@ async def test_nft_offer_nft_for_cat( assert await nft_wallet_taker.get_nft_count() == 0 # Create two new CATs and wallets for maker and taker cats_to_mint = 10000 - async with wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_wallet_maker, _ = await CATWallet.create_new_cat_wallet( + async with wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + cat_wallet_maker = await CATWallet.create_new_cat_wallet( wallet_node_0.wallet_state_manager, wallet_maker, {"identifier": "genesis_by_id"}, @@ -623,12 +607,12 @@ async def test_nft_offer_nft_for_cat( tx_config, action_scope, ) - await time_out_assert(20, mempool_not_empty, True, full_node_api) + await time_out_assert(20, mempool_not_empty, True, full_node_api) await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(token_ph)) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=20) - async with wallet_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_wallet_taker, _ = await CATWallet.create_new_cat_wallet( + async with wallet_taker.wallet_state_manager.new_action_scope(push=True) as action_scope: + cat_wallet_taker = await CATWallet.create_new_cat_wallet( wallet_node_1.wallet_state_manager, wallet_taker, {"identifier": "genesis_by_id"}, @@ -636,7 +620,7 @@ async def test_nft_offer_nft_for_cat( tx_config, action_scope, ) - await time_out_assert(20, mempool_not_empty, True, full_node_api) + await time_out_assert(20, mempool_not_empty, True, full_node_api) await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(token_ph)) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=20) @@ -677,7 +661,7 @@ async def test_nft_offer_nft_for_cat( ).index async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make, error = await trade_manager_maker.create_offer_for_ids( offer_nft_for_cat, tx_config, action_scope, driver_dict, fee=maker_fee ) assert success is True @@ -690,21 +674,18 @@ async def test_nft_offer_nft_for_cat( [Offer.from_bytes(trade_make.offer)] ) peer = wallet_node_1.get_full_node_peer() - async with trade_manager_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - trade_take, tx_records = await trade_manager_taker.respond_to_offer( + async with trade_manager_taker.wallet_state_manager.new_action_scope( + push=True, additional_signing_responses=signing_response + ) as action_scope: + trade_take = await trade_manager_taker.respond_to_offer( Offer.from_bytes(trade_make.offer), peer, tx_config, action_scope, fee=taker_fee, ) - tx_records = await trade_manager_taker.wallet_state_manager.add_pending_transactions( - tx_records, additional_signing_responses=signing_response - ) - assert trade_take is not None - assert tx_records is not None - await full_node_api.process_transaction_records(records=tx_records) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=20) await time_out_assert(20, get_trade_and_status, TradeStatus.CONFIRMED, trade_manager_maker, trade_make) @@ -769,7 +750,7 @@ async def test_nft_offer_nft_for_cat( } async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make, error = await trade_manager_maker.create_offer_for_ids( offer_multi_cats_for_nft, tx_config, action_scope, driver_dict_to_buy, fee=maker_fee ) assert success is True @@ -781,17 +762,14 @@ async def test_nft_offer_nft_for_cat( [maker_offer], signing_response = await wallet_node_0.wallet_state_manager.sign_offers( [Offer.from_bytes(trade_make.offer)] ) - async with trade_manager_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - trade_take, tx_records = await trade_manager_taker.respond_to_offer( + async with trade_manager_taker.wallet_state_manager.new_action_scope( + push=True, additional_signing_responses=signing_response + ) as action_scope: + trade_take = await trade_manager_taker.respond_to_offer( Offer.from_bytes(trade_make.offer), peer, tx_config, action_scope, fee=taker_fee ) - tx_records = await trade_manager_taker.wallet_state_manager.add_pending_transactions( - tx_records, additional_signing_responses=signing_response - ) - assert trade_take is not None - assert tx_records is not None - await full_node_api.process_transaction_records(records=tx_records) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) # check balances: taker wallet down an NFT, up cats await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=20) @@ -875,10 +853,9 @@ async def test_nft_offer_nft_for_nft( ] ) - async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await nft_wallet_maker.generate_new_nft(metadata, DEFAULT_TX_CONFIG, action_scope) - txs = await nft_wallet_maker.wallet_state_manager.add_pending_transactions(txs) - for tx in txs: + async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await nft_wallet_maker.generate_new_nft(metadata, DEFAULT_TX_CONFIG, action_scope) + for tx in action_scope.side_effects.transactions: if tx.spend_bundle is not None: await time_out_assert_not_none( 20, full_node_api.full_node.mempool_manager.get_spendbundle, tx.spend_bundle.name() @@ -891,10 +868,9 @@ async def test_nft_offer_nft_for_nft( ] ) - async with nft_wallet_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await nft_wallet_taker.generate_new_nft(metadata_2, DEFAULT_TX_CONFIG, action_scope) - txs = await nft_wallet_taker.wallet_state_manager.add_pending_transactions(txs) - for tx in txs: + async with nft_wallet_taker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await nft_wallet_taker.generate_new_nft(metadata_2, DEFAULT_TX_CONFIG, action_scope) + for tx in action_scope.side_effects.transactions: if tx.spend_bundle is not None: await time_out_assert_not_none( 20, full_node_api.full_node.mempool_manager.get_spendbundle, tx.spend_bundle.name() @@ -928,7 +904,7 @@ async def test_nft_offer_nft_for_nft( offer_nft_for_nft = {nft_to_take_asset_id: 1, nft_to_offer_asset_id: -1} async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make, error = await trade_manager_maker.create_offer_for_ids( offer_nft_for_nft, DEFAULT_TX_CONFIG, action_scope, driver_dict, fee=maker_fee ) assert success is True @@ -941,17 +917,14 @@ async def test_nft_offer_nft_for_nft( [Offer.from_bytes(trade_make.offer)] ) peer = wallet_node_1.get_full_node_peer() - async with trade_manager_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - trade_take, tx_records = await trade_manager_taker.respond_to_offer( + async with trade_manager_taker.wallet_state_manager.new_action_scope( + push=True, additional_signing_responses=signing_response + ) as action_scope: + trade_take = await trade_manager_taker.respond_to_offer( Offer.from_bytes(trade_make.offer), peer, DEFAULT_TX_CONFIG, action_scope, fee=taker_fee ) - tx_records = await trade_manager_taker.wallet_state_manager.add_pending_transactions( - tx_records, additional_signing_responses=signing_response - ) - assert trade_take is not None - assert tx_records is not None - await full_node_api.process_transaction_records(records=tx_records) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=20) await time_out_assert(20, get_trade_and_status, TradeStatus.CONFIRMED, trade_manager_maker, trade_make) @@ -1033,10 +1006,9 @@ async def test_nft_offer_nft0_and_xch_for_cat( ] ) - async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await nft_wallet_maker.generate_new_nft(metadata, tx_config, action_scope) - txs = await nft_wallet_maker.wallet_state_manager.add_pending_transactions(txs) - for tx in txs: + async with nft_wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + await nft_wallet_maker.generate_new_nft(metadata, tx_config, action_scope) + for tx in action_scope.side_effects.transactions: if tx.spend_bundle is not None: await time_out_assert_not_none( 20, full_node_api.full_node.mempool_manager.get_spendbundle, tx.spend_bundle.name() @@ -1050,8 +1022,8 @@ async def test_nft_offer_nft0_and_xch_for_cat( assert await nft_wallet_taker.get_nft_count() == 0 # Create two new CATs and wallets for maker and taker cats_to_mint = 10000 - async with wallet_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_wallet_maker, _ = await CATWallet.create_new_cat_wallet( + async with wallet_maker.wallet_state_manager.new_action_scope(push=True) as action_scope: + cat_wallet_maker = await CATWallet.create_new_cat_wallet( wallet_node_0.wallet_state_manager, wallet_maker, {"identifier": "genesis_by_id"}, @@ -1059,12 +1031,12 @@ async def test_nft_offer_nft0_and_xch_for_cat( tx_config, action_scope, ) - await time_out_assert(20, mempool_not_empty, True, full_node_api) + await time_out_assert(20, mempool_not_empty, True, full_node_api) await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(token_ph)) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=20) - async with wallet_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_wallet_taker, _ = await CATWallet.create_new_cat_wallet( + async with wallet_taker.wallet_state_manager.new_action_scope(push=True) as action_scope: + cat_wallet_taker = await CATWallet.create_new_cat_wallet( wallet_node_1.wallet_state_manager, wallet_taker, {"identifier": "genesis_by_id"}, @@ -1072,7 +1044,7 @@ async def test_nft_offer_nft0_and_xch_for_cat( tx_config, action_scope, ) - await time_out_assert(20, mempool_not_empty, True, full_node_api) + await time_out_assert(20, mempool_not_empty, True, full_node_api) await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(token_ph)) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=20) @@ -1119,7 +1091,7 @@ async def test_nft_offer_nft0_and_xch_for_cat( ).index async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make, error = await trade_manager_maker.create_offer_for_ids( offer_nft_for_cat, tx_config, action_scope, driver_dict, fee=maker_fee ) assert success is True @@ -1133,8 +1105,10 @@ async def test_nft_offer_nft0_and_xch_for_cat( taker_fee = uint64(1) peer = wallet_node_1.get_full_node_peer() - async with trade_manager_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - trade_take, tx_records = await trade_manager_taker.respond_to_offer( + async with trade_manager_taker.wallet_state_manager.new_action_scope( + push=True, additional_signing_responses=signing_response + ) as action_scope: + trade_take = await trade_manager_taker.respond_to_offer( maker_offer, peer, tx_config, @@ -1142,13 +1116,7 @@ async def test_nft_offer_nft0_and_xch_for_cat( fee=taker_fee, ) - assert trade_take is not None - assert tx_records is not None - - tx_records = await trade_manager_taker.wallet_state_manager.add_pending_transactions( - tx_records, additional_signing_responses=signing_response - ) - await full_node_api.process_transaction_records(records=tx_records) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=20) await time_out_assert(20, get_trade_and_status, TradeStatus.CONFIRMED, trade_manager_maker, trade_make) @@ -1213,7 +1181,7 @@ async def test_nft_offer_nft0_and_xch_for_cat( } async with trade_manager_maker.wallet_state_manager.new_action_scope(push=False) as action_scope: - success, trade_make, _, error = await trade_manager_maker.create_offer_for_ids( + success, trade_make, error = await trade_manager_maker.create_offer_for_ids( offer_multi_cats_for_nft, tx_config, action_scope, driver_dict_to_buy, fee=maker_fee ) assert success is True @@ -1226,18 +1194,14 @@ async def test_nft_offer_nft0_and_xch_for_cat( taker_fee = uint64(1) - async with trade_manager_taker.wallet_state_manager.new_action_scope(push=False) as action_scope: - trade_take, tx_records = await trade_manager_taker.respond_to_offer( + async with trade_manager_taker.wallet_state_manager.new_action_scope( + push=True, additional_signing_responses=signing_response + ) as action_scope: + trade_take = await trade_manager_taker.respond_to_offer( maker_offer, peer, tx_config, action_scope, fee=taker_fee ) - assert trade_take is not None - assert tx_records is not None - - tx_records = await trade_manager_taker.wallet_state_manager.add_pending_transactions( - tx_records, additional_signing_responses=signing_response - ) - await full_node_api.process_transaction_records(records=tx_records) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) # check balances: taker wallet down an NFT, up cats await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=20) diff --git a/chia/_tests/wallet/nft_wallet/test_nft_wallet.py b/chia/_tests/wallet/nft_wallet/test_nft_wallet.py index 753f0eb3d802..f26ca00c18d6 100644 --- a/chia/_tests/wallet/nft_wallet/test_nft_wallet.py +++ b/chia/_tests/wallet/nft_wallet/test_nft_wallet.py @@ -140,34 +140,21 @@ async def test_nft_wallet_creation_automatically( [("u", ["https://www.chia.net/img/branding/chia-logo.svg"]), ("h", "0xD4584AD463139FA8C0D9F68F4B59F185")] ) - async with nft_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await nft_wallet_0.generate_new_nft(metadata, DEFAULT_TX_CONFIG, action_scope) - txs = await nft_wallet_0.wallet_state_manager.add_pending_transactions(txs) - for tx in txs: - if tx.spend_bundle is not None: - await time_out_assert_not_none( - 30, full_node_api.full_node.mempool_manager.get_spendbundle, tx.spend_bundle.name() - ) + async with nft_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await nft_wallet_0.generate_new_nft(metadata, DEFAULT_TX_CONFIG, action_scope) - for _ in range(1, num_blocks): - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph1)) + await full_node_api.process_transaction_records(action_scope.side_effects.transactions) await time_out_assert(30, get_nft_count, 1, nft_wallet_0) coins = await nft_wallet_0.get_current_nfts() assert len(coins) == 1, "nft not generated" - async with nft_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await nft_wallet_0.generate_signed_transaction( + async with nft_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await nft_wallet_0.generate_signed_transaction( [uint64(coins[0].coin.amount)], [ph1], DEFAULT_TX_CONFIG, action_scope, coins={coins[0].coin} ) - assert len(txs) == 1 - txs = await wallet_node_0.wallet_state_manager.add_pending_transactions(txs) - assert txs[0].spend_bundle is not None - await time_out_assert_not_none( - 30, full_node_api.full_node.mempool_manager.get_spendbundle, txs[0].spend_bundle.name() - ) - for _ in range(1, num_blocks): - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph1)) + + await full_node_api.process_transaction_records(action_scope.side_effects.transactions) async def num_wallets() -> int: return len(await wallet_node_1.wallet_state_manager.get_all_wallet_info_entries()) @@ -212,10 +199,9 @@ async def test_nft_wallet_creation_and_transfer(wallet_environments: WalletTestF metadata = Program.to( [("u", ["https://www.chia.net/img/branding/chia-logo.svg"]), ("h", "0xD4584AD463139FA8C0D9F68F4B59F185")] ) - async with nft_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await nft_wallet_0.generate_new_nft(metadata, DEFAULT_TX_CONFIG, action_scope) - txs = await nft_wallet_0.wallet_state_manager.add_pending_transactions(txs) - for tx in txs: + async with nft_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await nft_wallet_0.generate_new_nft(metadata, DEFAULT_TX_CONFIG, action_scope) + for tx in action_scope.side_effects.transactions: if tx.spend_bundle is not None: # ensure hints are generated assert len(compute_memos(tx.spend_bundle)) > 0 @@ -293,10 +279,9 @@ async def test_nft_wallet_creation_and_transfer(wallet_environments: WalletTestF new_metadata = Program.to([("u", ["https://www.test.net/logo.svg"]), ("h", "0xD4584AD463139FA8C0D9F68F4B59F181")]) - async with nft_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await nft_wallet_0.generate_new_nft(new_metadata, DEFAULT_TX_CONFIG, action_scope) - txs = await nft_wallet_0.wallet_state_manager.add_pending_transactions(txs) - for tx in txs: + async with nft_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await nft_wallet_0.generate_new_nft(new_metadata, DEFAULT_TX_CONFIG, action_scope) + for tx in action_scope.side_effects.transactions: if tx.spend_bundle is not None: # ensure hints are generated assert len(compute_memos(tx.spend_bundle)) > 0 @@ -345,19 +330,17 @@ async def test_nft_wallet_creation_and_transfer(wallet_environments: WalletTestF nft_wallet_1 = await NFTWallet.create_new_nft_wallet( wallet_node_1.wallet_state_manager, wallet_1, name="NFT WALLET 2" ) - async with nft_wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await nft_wallet_0.generate_signed_transaction( + async with nft_wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await nft_wallet_0.generate_signed_transaction( [uint64(coins[1].coin.amount)], [await wallet_1.get_puzzle_hash(False)], DEFAULT_TX_CONFIG, action_scope, coins={coins[1].coin}, ) - assert len(txs) == 1 - txs = await wallet_node_0.wallet_state_manager.add_pending_transactions(txs) - assert txs[0].spend_bundle is not None + assert action_scope.side_effects.transactions[0].spend_bundle is not None - assert len(compute_memos(txs[0].spend_bundle)) > 0 + assert len(compute_memos(action_scope.side_effects.transactions[0].spend_bundle)) > 0 await wallet_environments.process_pending_states( [ @@ -403,19 +386,17 @@ async def test_nft_wallet_creation_and_transfer(wallet_environments: WalletTestF assert len(coins) == 1 # Send it back to original owner - async with nft_wallet_1.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await nft_wallet_1.generate_signed_transaction( + async with nft_wallet_1.wallet_state_manager.new_action_scope(push=True) as action_scope: + await nft_wallet_1.generate_signed_transaction( [uint64(coins[0].coin.amount)], [await wallet_0.get_puzzle_hash(False)], DEFAULT_TX_CONFIG, action_scope, coins={coins[0].coin}, ) - assert len(txs) == 1 - txs = await wallet_node_1.wallet_state_manager.add_pending_transactions(txs) - assert txs[0].spend_bundle is not None + assert action_scope.side_effects.transactions[0].spend_bundle is not None - assert len(compute_memos(txs[0].spend_bundle)) > 0 + assert len(compute_memos(action_scope.side_effects.transactions[0].spend_bundle)) > 0 await wallet_environments.process_pending_states( [ @@ -540,9 +521,8 @@ async def test_nft_wallet_rpc_creation_and_list( assert tr1.get("success") sb = tr1["spend_bundle"] - await time_out_assert_not_none(30, full_node_api.full_node.mempool_manager.get_spendbundle, sb.name()) - for _ in range(1, num_blocks): - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) + transactions = [TransactionRecord.from_json_dict_convenience(tx) for tx in tr1["transactions"]] + await full_node_api.process_transaction_records(transactions) await wait_rpc_state_condition(30, api_0.nft_get_nfts, [dict(wallet_id=nft_wallet_0_id)], lambda x: x["nft_list"]) tr2 = await api_0.nft_mint_nft( @@ -560,9 +540,8 @@ async def test_nft_wallet_rpc_creation_and_list( assert isinstance(tr2, dict) assert tr2.get("success") sb = tr2["spend_bundle"] - await time_out_assert_not_none(30, full_node_api.full_node.mempool_manager.get_spendbundle, sb.name()) - for _ in range(1, num_blocks): - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) + transactions = [TransactionRecord.from_json_dict_convenience(tx) for tx in tr2["transactions"]] + await full_node_api.process_transaction_records(transactions) coins_response = await wait_rpc_state_condition( 5, api_0.nft_get_nfts, [{"wallet_id": nft_wallet_0_id}], lambda x: x["success"] and len(x["nft_list"]) == 2 ) @@ -664,9 +643,8 @@ async def test_nft_wallet_rpc_update_metadata( assert resp.get("success") sb = resp["spend_bundle"] - await time_out_assert_not_none(30, full_node_api.full_node.mempool_manager.get_spendbundle, sb.name()) - for _ in range(1, num_blocks): - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) + transactions = [TransactionRecord.from_json_dict_convenience(tx) for tx in resp["transactions"]] + await full_node_api.process_transaction_records(transactions) coins_response = await wait_rpc_state_condition( 5, api_0.nft_get_nfts, [dict(wallet_id=nft_wallet_0_id)], lambda x: x["nft_list"] ) @@ -703,9 +681,8 @@ async def test_nft_wallet_rpc_update_metadata( assert coins[0].pending_transaction sb = tr1["spend_bundle"] assert isinstance(sb, SpendBundle) - await time_out_assert_not_none(30, full_node_api.full_node.mempool_manager.get_spendbundle, sb.name()) - for _ in range(1, num_blocks): - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) + transactions = [TransactionRecord.from_json_dict_convenience(tx) for tx in tr1["transactions"]] + await full_node_api.process_transaction_records(transactions) # check that new URI was added coins_response = await wait_rpc_state_condition( 5, @@ -734,9 +711,8 @@ async def test_nft_wallet_rpc_update_metadata( assert isinstance(tr1, dict) assert tr1.get("success") sb = tr1["spend_bundle"] - await time_out_assert_not_none(30, full_node_api.full_node.mempool_manager.get_spendbundle, sb.name()) - for _ in range(1, num_blocks): - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) + transactions = [TransactionRecord.from_json_dict_convenience(tx) for tx in tr1["transactions"]] + await full_node_api.process_transaction_records(transactions) coins_response = await wait_rpc_state_condition( 5, api_0.nft_get_nfts, @@ -791,16 +767,11 @@ async def test_nft_with_did_wallet_creation( await time_out_assert(30, wallet_0.get_unconfirmed_balance, funds) await time_out_assert(30, wallet_0.get_confirmed_balance, funds) - async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet = await DIDWallet.create_new_did_wallet( wallet_node_0.wallet_state_manager, wallet_0, uint64(1), DEFAULT_TX_CONFIG, action_scope ) - spend_bundle_list = await wallet_node_0.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(did_wallet.id()) - spend_bundle = spend_bundle_list[0].spend_bundle - assert spend_bundle is not None - await time_out_assert_not_none(30, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(30, wallet_0.get_pending_change_balance, 0) hex_did_id = did_wallet.get_my_DID() hmr_did_id = encode_puzzle_hash(bytes32.from_hexstr(hex_did_id), AddressType.DID.hrp(wallet_node_0.config)) @@ -865,12 +836,11 @@ async def test_nft_with_did_wallet_creation( matched += 1 assert matched > 0 - await time_out_assert_not_none(30, full_node_api.full_node.mempool_manager.get_spendbundle, sb.name()) - - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) + transactions = [TransactionRecord.from_json_dict_convenience(tx) for tx in resp["transactions"]] + await full_node_api.process_transaction_records(transactions) - await time_out_assert(30, wallet_0.get_unconfirmed_balance, 5999999999999 - 1) - await time_out_assert(30, wallet_0.get_confirmed_balance, 5999999999999 - 1) + await time_out_assert(30, wallet_0.get_unconfirmed_balance, 3999999999999 - 1) + await time_out_assert(30, wallet_0.get_confirmed_balance, 3999999999999 - 1) # Create a NFT without DID, this will go the unassigned NFT wallet resp = await api_0.nft_mint_nft( { @@ -885,11 +855,10 @@ async def test_nft_with_did_wallet_creation( # ensure hints are generated assert len(compute_memos(sb)) > 0 - await time_out_assert_not_none(30, full_node_api.full_node.mempool_manager.get_spendbundle, sb.name()) - - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) - await time_out_assert(30, wallet_0.get_unconfirmed_balance, 7999999999998 - 1) - await time_out_assert(30, wallet_0.get_confirmed_balance, 7999999999998 - 1) + transactions = [TransactionRecord.from_json_dict_convenience(tx) for tx in resp["transactions"]] + await full_node_api.process_transaction_records(transactions) + await time_out_assert(30, wallet_0.get_unconfirmed_balance, 3999999999998 - 1) + await time_out_assert(30, wallet_0.get_confirmed_balance, 3999999999998 - 1) # Check DID NFT coins_response = await wait_rpc_state_condition( 5, api_0.nft_get_nfts, [dict(wallet_id=nft_wallet_0_id)], lambda x: x["nft_list"] @@ -958,17 +927,11 @@ async def test_nft_rpc_mint(self_hostname: str, two_wallet_nodes: OldSimulatorsA await time_out_assert(30, wallet_0.get_unconfirmed_balance, funds) await time_out_assert(30, wallet_0.get_confirmed_balance, funds) - async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet = await DIDWallet.create_new_did_wallet( wallet_node_0.wallet_state_manager, wallet_0, uint64(1), DEFAULT_TX_CONFIG, action_scope ) - spend_bundle_list = await wallet_node_0.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(did_wallet.id()) - spend_bundle = spend_bundle_list[0].spend_bundle - assert spend_bundle is not None - await time_out_assert_not_none(30, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - for _ in range(1, num_blocks): - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(30, wallet_0.get_pending_change_balance, 0) did_id = encode_puzzle_hash(bytes32.from_hexstr(did_wallet.get_my_DID()), AddressType.DID.hrp(wallet_node_0.config)) @@ -979,8 +942,8 @@ async def test_nft_rpc_mint(self_hostname: str, two_wallet_nodes: OldSimulatorsA assert res.get("success") nft_wallet_0_id = res["wallet_id"] - await time_out_assert(30, wallet_0.get_unconfirmed_balance, 5999999999999) - await time_out_assert(30, wallet_0.get_confirmed_balance, 5999999999999) + await time_out_assert(30, wallet_0.get_unconfirmed_balance, 3999999999999) + await time_out_assert(30, wallet_0.get_confirmed_balance, 3999999999999) # Create a NFT with DID royalty_address = ph1 data_hash_param = "0xD4584AD463139FA8C0D9F68F4B59F185" @@ -1013,12 +976,10 @@ async def test_nft_rpc_mint(self_hostname: str, two_wallet_nodes: OldSimulatorsA # ensure hints are generated assert len(compute_memos(sb)) > 0 - await time_out_assert_not_none(30, full_node_api.full_node.mempool_manager.get_spendbundle, sb.name()) - - for _ in range(1, num_blocks): - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) - await time_out_assert(30, wallet_0.get_unconfirmed_balance, 9999999999998) - await time_out_assert(30, wallet_0.get_confirmed_balance, 9999999999998) + transactions = [TransactionRecord.from_json_dict_convenience(tx) for tx in resp["transactions"]] + await full_node_api.process_transaction_records(transactions) + await time_out_assert(30, wallet_0.get_unconfirmed_balance, 3999999999998) + await time_out_assert(30, wallet_0.get_confirmed_balance, 3999999999998) coins_response = await wait_rpc_state_condition( 5, api_0.nft_get_nfts, [dict(wallet_id=nft_wallet_0_id)], lambda x: x["nft_list"] ) @@ -1081,16 +1042,11 @@ async def test_nft_transfer_nft_with_did( await time_out_assert(30, wallet_0.get_unconfirmed_balance, funds) await time_out_assert(30, wallet_0.get_confirmed_balance, funds) # Create DID - async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet = await DIDWallet.create_new_did_wallet( wallet_node_0.wallet_state_manager, wallet_0, uint64(1), DEFAULT_TX_CONFIG, action_scope ) - spend_bundle_list = await wallet_node_0.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(did_wallet.id()) - spend_bundle = spend_bundle_list[0].spend_bundle - assert spend_bundle is not None - await time_out_assert_not_none(30, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(30, wallet_0.get_pending_change_balance, 0) hex_did_id = did_wallet.get_my_DID() hmr_did_id = encode_puzzle_hash(bytes32.from_hexstr(hex_did_id), AddressType.DID.hrp(wallet_node_0.config)) @@ -1122,8 +1078,8 @@ async def test_nft_transfer_nft_with_did( coins_response = await wait_rpc_state_condition( 5, api_0.nft_get_nfts, [dict(wallet_id=nft_wallet_0_id)], lambda x: x["nft_list"] ) - await time_out_assert(30, wallet_0.get_unconfirmed_balance, 5999999999898) - await time_out_assert(30, wallet_0.get_confirmed_balance, 5999999999898) + await time_out_assert(30, wallet_0.get_unconfirmed_balance, 3999999999898) + await time_out_assert(30, wallet_0.get_confirmed_balance, 3999999999898) coins: List[NFTInfo] = coins_response["nft_list"] assert len(coins) == 1 assert coins[0].owner_did is not None @@ -1134,16 +1090,9 @@ async def test_nft_transfer_nft_with_did( await full_node_api.wait_for_wallet_synced(wallet_node_0, 20) await full_node_api.wait_for_wallet_synced(wallet_node_1, 20) # transfer DID to the other wallet - async with did_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await did_wallet.transfer_did(ph1, uint64(0), True, DEFAULT_TX_CONFIG, action_scope) - txs = await did_wallet.wallet_state_manager.add_pending_transactions(txs) - for tx in txs: - if tx.spend_bundle is not None: - await time_out_assert_not_none( - 30, full_node_api.full_node.mempool_manager.get_spendbundle, tx.spend_bundle.name() - ) - for _ in range(1, num_blocks): - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph1)) + async with did_wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await did_wallet.transfer_did(ph1, uint64(0), True, DEFAULT_TX_CONFIG, action_scope) + await full_node_api.process_transaction_records(action_scope.side_effects.transactions) await full_node_api.wait_for_wallet_synced(wallet_node_0, 20) await full_node_api.wait_for_wallet_synced(wallet_node_1, 20) await time_out_assert(15, len, 2, wallet_0.wallet_state_manager.wallets) @@ -1161,8 +1110,8 @@ async def test_nft_transfer_nft_with_did( assert len(compute_memos(sb)) > 0 await time_out_assert_not_none(30, full_node_api.full_node.mempool_manager.get_spendbundle, sb.name()) await make_new_block_with(resp, full_node_api, ph1) - await time_out_assert(30, wallet_0.get_unconfirmed_balance, 5999999999798) - await time_out_assert(30, wallet_0.get_confirmed_balance, 5999999999798) + await time_out_assert(30, wallet_0.get_unconfirmed_balance, 3999999999798) + await time_out_assert(30, wallet_0.get_confirmed_balance, 3999999999798) await time_out_assert(30, len, 1, wallet_0.wallet_state_manager.wallets) # wait for all wallets to be created @@ -1188,14 +1137,13 @@ async def test_nft_transfer_nft_with_did( dict(wallet_id=nft_wallet_id_1, did_id=hmr_did_id, nft_coin_id=nft_coin_id.hex(), fee=fee) ) txs = [TransactionRecord.from_json_dict_convenience(tx) for tx in resp["transactions"]] - txs = await wallet_node_1.wallet_state_manager.add_pending_transactions(txs) - await make_new_block_with(resp, full_node_api, ph) + await full_node_api.process_transaction_records(txs) coins_response = await wait_rpc_state_condition( 5, api_1.nft_get_by_did, [dict(did_id=hmr_did_id)], lambda x: x.get("wallet_id", 0) > 0 ) - await time_out_assert(30, wallet_1.get_unconfirmed_balance, 12000000000100) - await time_out_assert(30, wallet_1.get_confirmed_balance, 12000000000100) + await time_out_assert(30, wallet_1.get_unconfirmed_balance, 8000000000100) + await time_out_assert(30, wallet_1.get_confirmed_balance, 8000000000100) nft_wallet_1_id = coins_response.get("wallet_id") assert nft_wallet_1_id # Check NFT DID is set now @@ -1223,10 +1171,8 @@ async def test_update_metadata_for_nft_did( wallet_node_0, server_0 = wallets[0] wallet_node_1, server_1 = wallets[1] wallet_0 = wallet_node_0.wallet_state_manager.main_wallet - wallet_1 = wallet_node_1.wallet_state_manager.main_wallet api_0 = WalletRpcApi(wallet_node_0) ph = await wallet_0.get_new_puzzlehash() - ph1 = await wallet_1.get_new_puzzlehash() if trusted: wallet_node_0.config["trusted_peers"] = { @@ -1251,18 +1197,11 @@ async def test_update_metadata_for_nft_did( await time_out_assert(30, wallet_0.get_unconfirmed_balance, funds) await time_out_assert(30, wallet_0.get_confirmed_balance, funds) - async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet = await DIDWallet.create_new_did_wallet( wallet_node_0.wallet_state_manager, wallet_0, uint64(1), DEFAULT_TX_CONFIG, action_scope ) - spend_bundle_list = await wallet_node_0.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(did_wallet.id()) - - spend_bundle = spend_bundle_list[0].spend_bundle - assert spend_bundle is not None - await time_out_assert_not_none(30, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - for _ in range(1, num_blocks): - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(30, wallet_0.get_pending_change_balance, 0) hex_did_id = did_wallet.get_my_DID() hmr_did_id = encode_puzzle_hash(bytes32.from_hexstr(hex_did_id), AddressType.DID.hrp(wallet_node_0.config)) @@ -1291,10 +1230,8 @@ async def test_update_metadata_for_nft_did( # ensure hints are generated assert len(compute_memos(sb)) > 0 - await time_out_assert_not_none(30, full_node_api.full_node.mempool_manager.get_spendbundle, sb.name()) - - for _ in range(1, num_blocks): - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) + transactions = [TransactionRecord.from_json_dict_convenience(tx) for tx in resp["transactions"]] + await full_node_api.process_transaction_records(transactions) # Check DID NFT @@ -1323,12 +1260,11 @@ async def test_update_metadata_for_nft_did( assert coins_response["nft_list"][0].pending_transaction sb = tr1["spend_bundle"] - await time_out_assert_not_none(30, full_node_api.full_node.mempool_manager.get_spendbundle, sb.name()) - for _ in range(1, num_blocks): - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph1)) + transactions = [TransactionRecord.from_json_dict_convenience(tx) for tx in tr1["transactions"]] + await full_node_api.process_transaction_records(transactions) # check that new URI was added - await time_out_assert(30, wallet_0.get_unconfirmed_balance, 11999999999898) - await time_out_assert(30, wallet_0.get_confirmed_balance, 11999999999898) + await time_out_assert(30, wallet_0.get_unconfirmed_balance, 3999999999898) + await time_out_assert(30, wallet_0.get_confirmed_balance, 3999999999898) coins_response = await wait_rpc_state_condition( 5, api_0.nft_get_info, @@ -1383,17 +1319,11 @@ async def test_nft_bulk_set_did(self_hostname: str, two_wallet_nodes: OldSimulat await time_out_assert(30, wallet_0.get_unconfirmed_balance, funds) await time_out_assert(30, wallet_0.get_confirmed_balance, funds) - async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet = await DIDWallet.create_new_did_wallet( wallet_node_0.wallet_state_manager, wallet_0, uint64(1), DEFAULT_TX_CONFIG, action_scope ) - spend_bundle_list = await wallet_node_0.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(did_wallet.id()) - spend_bundle = spend_bundle_list[0].spend_bundle - assert spend_bundle is not None - await time_out_assert_not_none(30, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - for _ in range(1, num_blocks): - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(30, wallet_0.get_pending_change_balance, 0) await time_out_assert(30, wallet_0.get_confirmed_balance, 3999999999999) hex_did_id = did_wallet.get_my_DID() @@ -1486,7 +1416,7 @@ async def test_nft_bulk_set_did(self_hostname: str, two_wallet_nodes: OldSimulat assert len(sb.coin_spends) == 5 tx_num = resp["tx_num"] assert isinstance(tx_num, int) - assert tx_num == 4 + assert tx_num == 5 # 1 for each NFT being spent (3), 1 for fee tx, 1 for did tx coins_response = await wait_rpc_state_condition( 30, api_0.nft_get_nfts, [{"wallet_id": nft_wallet_0_id}], lambda x: len(x["nft_list"]) == 2 ) @@ -1559,17 +1489,11 @@ async def test_nft_bulk_transfer(self_hostname: str, two_wallet_nodes: OldSimula await time_out_assert(30, wallet_0.get_unconfirmed_balance, funds) await time_out_assert(30, wallet_0.get_confirmed_balance, funds) - async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet = await DIDWallet.create_new_did_wallet( wallet_node_0.wallet_state_manager, wallet_0, uint64(1), DEFAULT_TX_CONFIG, action_scope ) - spend_bundle_list = await wallet_node_0.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(did_wallet.id()) - spend_bundle = spend_bundle_list[0].spend_bundle - assert spend_bundle is not None - await time_out_assert_not_none(30, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - for _ in range(1, num_blocks): - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(30, wallet_0.get_pending_change_balance, 0) await time_out_assert(30, wallet_0.get_confirmed_balance, 3999999999999) hex_did_id = did_wallet.get_my_DID() @@ -1712,18 +1636,11 @@ async def test_nft_set_did(self_hostname: str, two_wallet_nodes: OldSimulatorsAn await time_out_assert(30, wallet_0.get_unconfirmed_balance, funds) await time_out_assert(30, wallet_0.get_confirmed_balance, funds) - async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet = await DIDWallet.create_new_did_wallet( wallet_node_0.wallet_state_manager, wallet_0, uint64(1), DEFAULT_TX_CONFIG, action_scope ) - spend_bundle_list = await wallet_node_0.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(did_wallet.id()) - spend_bundle = spend_bundle_list[0].spend_bundle - assert spend_bundle is not None - await time_out_assert_not_none(30, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - for _ in range(1, num_blocks): - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) - await time_out_assert(30, wallet_0.get_pending_change_balance, 0) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) hex_did_id = did_wallet.get_my_DID() hmr_did_id = encode_puzzle_hash(bytes32.from_hexstr(hex_did_id), AddressType.DID.hrp(wallet_node_0.config)) @@ -1760,17 +1677,11 @@ async def test_nft_set_did(self_hostname: str, two_wallet_nodes: OldSimulatorsAn nft_coin_id = coins[0].nft_coin_id # Test set None -> DID1 - async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet1 = await DIDWallet.create_new_did_wallet( wallet_node_0.wallet_state_manager, wallet_0, uint64(1), DEFAULT_TX_CONFIG, action_scope ) - spend_bundle_list = await wallet_node_0.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(did_wallet1.id()) - - spend_bundle = spend_bundle_list[0].spend_bundle - assert spend_bundle is not None - await time_out_assert_not_none(30, full_node_api.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) - - await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await time_out_assert(30, did_wallet1.get_spendable_balance, 1) resp = await api_0.nft_set_nft_did( dict(wallet_id=nft_wallet_0_id, did_id=hmr_did_id, nft_coin_id=nft_coin_id.hex()) diff --git a/chia/_tests/wallet/rpc/test_wallet_rpc.py b/chia/_tests/wallet/rpc/test_wallet_rpc.py index a0a6f0b49b02..7d226ed00724 100644 --- a/chia/_tests/wallet/rpc/test_wallet_rpc.py +++ b/chia/_tests/wallet/rpc/test_wallet_rpc.py @@ -416,8 +416,8 @@ async def test_get_balance(wallet_rpc_environment: WalletRpcTestEnvironment): full_node_api: FullNodeSimulator = env.full_node.api wallet_rpc_client = env.wallet_1.rpc_client await full_node_api.farm_blocks_to_wallet(2, wallet) - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - cat_wallet, tx_records = await CATWallet.create_new_cat_wallet( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + cat_wallet = await CATWallet.create_new_cat_wallet( wallet_node.wallet_state_manager, wallet, {"identifier": "genesis_by_id"}, @@ -425,7 +425,7 @@ async def test_get_balance(wallet_rpc_environment: WalletRpcTestEnvironment): DEFAULT_TX_CONFIG, action_scope, ) - await full_node_api.wait_transaction_records_entered_mempool(tx_records) + await full_node_api.wait_transaction_records_entered_mempool(action_scope.side_effects.transactions) await full_node_api.wait_for_wallet_synced(wallet_node) await assert_get_balance(wallet_rpc_client, wallet_node, wallet) await assert_get_balance(wallet_rpc_client, wallet_node, cat_wallet) @@ -466,18 +466,17 @@ async def test_get_farmed_amount_with_fee(wallet_rpc_environment: WalletRpcTestE await generate_funds(full_node_api, env.wallet_1) fee_amount = 100 - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.generate_signed_transaction( amount=uint64(5), puzzle_hash=bytes32([0] * 32), tx_config=DEFAULT_TX_CONFIG, action_scope=action_scope, fee=uint64(fee_amount), ) - [tx] = await wallet.wallet_state_manager.add_pending_transactions([tx]) our_ph = await wallet.get_new_puzzlehash() - await full_node_api.wait_transaction_records_entered_mempool(records=[tx]) + await full_node_api.wait_transaction_records_entered_mempool(records=action_scope.side_effects.transactions) await full_node_api.farm_blocks_to_puzzlehash(count=2, farm_to=our_ph, guarantee_transaction_blocks=True) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node, timeout=20) @@ -562,7 +561,7 @@ async def test_create_signed_transaction( ) assert len(selected_coin) == 1 - tx = ( + txs = ( await wallet_1_rpc.create_signed_transactions( outputs, coins=selected_coin, @@ -574,12 +573,12 @@ async def test_create_signed_transaction( ), push=True, ) - ).signed_tx + ).transactions change_expected = not selected_coin or selected_coin[0].amount - amount_total > 0 - assert_tx_amounts(tx, outputs, amount_fee=amount_fee, change_expected=change_expected, is_cat=is_cat) + assert_tx_amounts(txs[-1], outputs, amount_fee=amount_fee, change_expected=change_expected, is_cat=is_cat) # Farm the transaction and make sure the wallet balance reflects it correct - spend_bundle = tx.spend_bundle + spend_bundle = txs[0].spend_bundle assert spend_bundle is not None await farm_transaction(full_node_api, wallet_1_node, spend_bundle) await time_out_assert(20, get_confirmed_balance, generated_funds - amount_total, wallet_1_rpc, wallet_id) @@ -1101,7 +1100,7 @@ async def test_cat_endpoints(wallet_rpc_environment: WalletRpcTestEnvironment): ["the cat memo"], ) tx_res = await client.cat_spend(cat_0_id, DEFAULT_TX_CONFIG, uint64(4), addr_1, uint64(0), ["the cat memo"]) - assert tx_res.transaction.wallet_id == cat_0_id + spend_bundle = tx_res.transaction.spend_bundle assert spend_bundle is not None assert uncurry_puzzle(spend_bundle.coin_spends[0].puzzle_reveal.to_program()).mod == CAT_MOD @@ -1111,10 +1110,9 @@ async def test_cat_endpoints(wallet_rpc_environment: WalletRpcTestEnvironment): # Test CAT spend with a fee tx_res = await client.cat_spend(cat_0_id, DEFAULT_TX_CONFIG, uint64(1), addr_1, uint64(5_000_000), ["the cat memo"]) - assert tx_res.transaction.wallet_id == cat_0_id + spend_bundle = tx_res.transaction.spend_bundle assert spend_bundle is not None - assert uncurry_puzzle(spend_bundle.coin_spends[0].puzzle_reveal.to_program()).mod == CAT_MOD await farm_transaction(full_node_api, wallet_node, spend_bundle) # Test CAT spend with a fee and pre-specified removals / coins @@ -1124,11 +1122,10 @@ async def test_cat_endpoints(wallet_rpc_environment: WalletRpcTestEnvironment): tx_res = await client.cat_spend( cat_0_id, DEFAULT_TX_CONFIG, uint64(1), addr_1, uint64(5_000_000), ["the cat memo"], removals=removals ) - assert tx_res.transaction.wallet_id == cat_0_id + spend_bundle = tx_res.transaction.spend_bundle assert spend_bundle is not None - assert removals[0] in tx_res.transaction.removals - assert uncurry_puzzle(spend_bundle.coin_spends[0].puzzle_reveal.to_program()).mod == CAT_MOD + assert removals[0] in {removal for tx in tx_res.transactions for removal in tx.removals} await farm_transaction(full_node_api, wallet_node, spend_bundle) # Test unacknowledged CAT @@ -1502,8 +1499,6 @@ async def test_did_endpoints(wallet_rpc_environment: WalletRpcTestEnvironment): await wallet_1_rpc.update_did_metadata(wallet_1_id, {"Twitter": "Https://test"}, DEFAULT_TX_CONFIG) await wallet_1_rpc.update_did_metadata(did_wallet_id_0, {"Twitter": "Https://test"}, DEFAULT_TX_CONFIG) - await farm_transaction_block(full_node_api, wallet_1_node) - res = await wallet_1_rpc.get_did_metadata(did_wallet_id_0) assert res["metadata"]["Twitter"] == "Https://test" diff --git a/chia/_tests/wallet/simple_sync/test_simple_sync_protocol.py b/chia/_tests/wallet/simple_sync/test_simple_sync_protocol.py index 9b6a1fd1d614..a4c1a3a20007 100644 --- a/chia/_tests/wallet/simple_sync/test_simple_sync_protocol.py +++ b/chia/_tests/wallet/simple_sync/test_simple_sync_protocol.py @@ -171,17 +171,14 @@ async def test_subscribe_for_ph(simulator_and_wallet: OldSimulatorsAndWallets, s await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node, timeout=20) - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx_record] = await wallet.generate_signed_transaction( - uint64(10), puzzle_hash, DEFAULT_TX_CONFIG, action_scope, uint64(0) - ) + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.generate_signed_transaction(uint64(10), puzzle_hash, DEFAULT_TX_CONFIG, action_scope, uint64(0)) + [tx_record] = action_scope.side_effects.transactions assert tx_record.spend_bundle is not None assert len(tx_record.spend_bundle.removals()) == 1 spent_coin = tx_record.spend_bundle.removals()[0] assert spent_coin.puzzle_hash == puzzle_hash - [tx_record] = await wallet.wallet_state_manager.add_pending_transactions([tx_record]) - await full_node_api.process_transaction_records(records=[tx_record]) # Let's make sure the wallet can handle a non ephemeral launcher @@ -189,24 +186,20 @@ async def test_subscribe_for_ph(simulator_and_wallet: OldSimulatorsAndWallets, s await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node, timeout=20) - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx_record] = await wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.generate_signed_transaction( uint64(10), SINGLETON_LAUNCHER_HASH, DEFAULT_TX_CONFIG, action_scope, uint64(0) ) - [tx_record] = await wallet.wallet_state_manager.add_pending_transactions([tx_record]) - await full_node_api.process_transaction_records(records=[tx_record]) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node, timeout=20) # Send a transaction to make sure the wallet is still running - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx_record] = await wallet.generate_signed_transaction( - uint64(10), junk_ph, DEFAULT_TX_CONFIG, action_scope, uint64(0) - ) - [tx_record] = await wallet.wallet_state_manager.add_pending_transactions([tx_record]) + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.generate_signed_transaction(uint64(10), junk_ph, DEFAULT_TX_CONFIG, action_scope, uint64(0)) - await full_node_api.process_transaction_records(records=[tx_record]) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) all_messages = await get_all_messages_in_queue(incoming_queue) @@ -262,13 +255,12 @@ async def test_subscribe_for_coin_id(simulator_and_wallet: OldSimulatorsAndWalle coins = set() coins.add(coin_to_spend) - async with standard_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx_record] = await standard_wallet.generate_signed_transaction( + async with standard_wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await standard_wallet.generate_signed_transaction( uint64(10), puzzle_hash, DEFAULT_TX_CONFIG, action_scope, uint64(0), coins=coins ) - [tx_record] = await standard_wallet.wallet_state_manager.add_pending_transactions([tx_record]) - await full_node_api.process_transaction_records(records=[tx_record]) + await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) all_messages = await get_all_messages_in_queue(incoming_queue) @@ -286,10 +278,12 @@ async def test_subscribe_for_coin_id(simulator_and_wallet: OldSimulatorsAndWalle await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node, timeout=20) async with standard_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx_record] = await standard_wallet.generate_signed_transaction( + await standard_wallet.generate_signed_transaction( uint64(10), puzzle_hash, DEFAULT_TX_CONFIG, action_scope, uint64(0) ) + [tx_record] = action_scope.side_effects.transactions + added_target = None assert tx_record.spend_bundle is not None for coin in tx_record.spend_bundle.additions(): diff --git a/chia/_tests/wallet/sync/test_wallet_sync.py b/chia/_tests/wallet/sync/test_wallet_sync.py index ec2d59d042a4..d110660bf628 100644 --- a/chia/_tests/wallet/sync/test_wallet_sync.py +++ b/chia/_tests/wallet/sync/test_wallet_sync.py @@ -576,11 +576,9 @@ async def test_request_additions_success(simulator_and_wallet: OldSimulatorsAndW payees.append(Payment(payee_ph, uint64(i + 100))) payees.append(Payment(payee_ph, uint64(i + 200))) - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await wallet.generate_signed_transaction( - uint64(0), ph, DEFAULT_TX_CONFIG, action_scope, primaries=payees - ) - [tx] = await wallet.wallet_state_manager.add_pending_transactions([tx]) + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.generate_signed_transaction(uint64(0), ph, DEFAULT_TX_CONFIG, action_scope, primaries=payees) + [tx] = action_scope.side_effects.transactions assert tx.spend_bundle is not None await full_node_api.send_transaction(SendTransaction(tx.spend_bundle)) await full_node_api.wait_transaction_records_entered_mempool([tx]) @@ -792,11 +790,9 @@ async def test_dusted_wallet( payees.append(Payment(payee_ph, uint64(dust_value))) # construct and send tx - async with farm_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await farm_wallet.generate_signed_transaction( - uint64(0), ph, DEFAULT_TX_CONFIG, action_scope, primaries=payees - ) - [tx] = await farm_wallet.wallet_state_manager.add_pending_transactions([tx]) + async with farm_wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await farm_wallet.generate_signed_transaction(uint64(0), ph, DEFAULT_TX_CONFIG, action_scope, primaries=payees) + [tx] = action_scope.side_effects.transactions assert tx.spend_bundle is not None await full_node_api.send_transaction(SendTransaction(tx.spend_bundle)) await full_node_api.wait_transaction_records_entered_mempool([tx]) @@ -853,11 +849,11 @@ async def test_dusted_wallet( # This greatly speeds up the overall process if dust_remaining % 100 == 0 and dust_remaining != new_dust: # construct and send tx - async with farm_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await farm_wallet.generate_signed_transaction( + async with farm_wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await farm_wallet.generate_signed_transaction( uint64(0), ph, DEFAULT_TX_CONFIG, action_scope, primaries=payees ) - [tx] = await farm_wallet.wallet_state_manager.add_pending_transactions([tx]) + [tx] = action_scope.side_effects.transactions assert tx.spend_bundle is not None await full_node_api.send_transaction(SendTransaction(tx.spend_bundle)) @@ -874,11 +870,11 @@ async def test_dusted_wallet( # Only need to create tx if there was new dust to be added if new_dust >= 1: # construct and send tx - async with farm_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await farm_wallet.generate_signed_transaction( + async with farm_wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await farm_wallet.generate_signed_transaction( uint64(0), ph, DEFAULT_TX_CONFIG, action_scope, primaries=payees ) - [tx] = await farm_wallet.wallet_state_manager.add_pending_transactions([tx]) + [tx] = action_scope.side_effects.transactions assert tx.spend_bundle is not None await full_node_api.send_transaction(SendTransaction(tx.spend_bundle)) @@ -923,11 +919,9 @@ async def test_dusted_wallet( payees.append(Payment(payee_ph, uint64(xch_spam_amount))) # construct and send tx - async with farm_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await farm_wallet.generate_signed_transaction( - uint64(0), ph, DEFAULT_TX_CONFIG, action_scope, primaries=payees - ) - [tx] = await farm_wallet.wallet_state_manager.add_pending_transactions([tx]) + async with farm_wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await farm_wallet.generate_signed_transaction(uint64(0), ph, DEFAULT_TX_CONFIG, action_scope, primaries=payees) + [tx] = action_scope.side_effects.transactions assert tx.spend_bundle is not None await full_node_api.send_transaction(SendTransaction(tx.spend_bundle)) @@ -964,11 +958,9 @@ async def test_dusted_wallet( payees.append(Payment(payee_ph, uint64(dust_value))) # construct and send tx - async with farm_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await farm_wallet.generate_signed_transaction( - uint64(0), ph, DEFAULT_TX_CONFIG, action_scope, primaries=payees - ) - [tx] = await farm_wallet.wallet_state_manager.add_pending_transactions([tx]) + async with farm_wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await farm_wallet.generate_signed_transaction(uint64(0), ph, DEFAULT_TX_CONFIG, action_scope, primaries=payees) + [tx] = action_scope.side_effects.transactions assert tx.spend_bundle is not None await full_node_api.send_transaction(SendTransaction(tx.spend_bundle)) @@ -1025,11 +1017,9 @@ async def test_dusted_wallet( large_dust_balance += dust_value # construct and send tx - async with farm_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await farm_wallet.generate_signed_transaction( - uint64(0), ph, DEFAULT_TX_CONFIG, action_scope, primaries=payees - ) - [tx] = await farm_wallet.wallet_state_manager.add_pending_transactions([tx]) + async with farm_wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await farm_wallet.generate_signed_transaction(uint64(0), ph, DEFAULT_TX_CONFIG, action_scope, primaries=payees) + [tx] = action_scope.side_effects.transactions assert tx.spend_bundle is not None await full_node_api.send_transaction(SendTransaction(tx.spend_bundle)) @@ -1063,11 +1053,9 @@ async def test_dusted_wallet( payees = [Payment(payee_ph, uint64(balance))] # construct and send tx - async with dust_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await dust_wallet.generate_signed_transaction( - uint64(0), ph, DEFAULT_TX_CONFIG, action_scope, primaries=payees - ) - [tx] = await dust_wallet.wallet_state_manager.add_pending_transactions([tx]) + async with dust_wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dust_wallet.generate_signed_transaction(uint64(0), ph, DEFAULT_TX_CONFIG, action_scope, primaries=payees) + [tx] = action_scope.side_effects.transactions assert tx.spend_bundle is not None await full_node_api.send_transaction(SendTransaction(tx.spend_bundle)) @@ -1109,11 +1097,11 @@ async def test_dusted_wallet( # This greatly speeds up the overall process if coins_remaining % 100 == 0 and coins_remaining != spam_filter_after_n_txs: # construct and send tx - async with farm_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await farm_wallet.generate_signed_transaction( + async with farm_wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await farm_wallet.generate_signed_transaction( uint64(0), ph, DEFAULT_TX_CONFIG, action_scope, primaries=payees ) - [tx] = await farm_wallet.wallet_state_manager.add_pending_transactions([tx]) + [tx] = action_scope.side_effects.transactions assert tx.spend_bundle is not None await full_node_api.send_transaction(SendTransaction(tx.spend_bundle)) await full_node_api.wait_transaction_records_entered_mempool([tx]) @@ -1126,11 +1114,9 @@ async def test_dusted_wallet( coins_remaining -= 1 # construct and send tx - async with farm_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await farm_wallet.generate_signed_transaction( - uint64(0), ph, DEFAULT_TX_CONFIG, action_scope, primaries=payees - ) - [tx] = await farm_wallet.wallet_state_manager.add_pending_transactions([tx]) + async with farm_wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await farm_wallet.generate_signed_transaction(uint64(0), ph, DEFAULT_TX_CONFIG, action_scope, primaries=payees) + [tx] = action_scope.side_effects.transactions assert tx.spend_bundle is not None await full_node_api.send_transaction(SendTransaction(tx.spend_bundle)) @@ -1158,11 +1144,9 @@ async def test_dusted_wallet( payees = [Payment(payee_ph, uint64(1))] # construct and send tx - async with dust_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await dust_wallet.generate_signed_transaction( - uint64(0), ph, DEFAULT_TX_CONFIG, action_scope, primaries=payees - ) - [tx] = await dust_wallet.wallet_state_manager.add_pending_transactions([tx]) + async with dust_wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await dust_wallet.generate_signed_transaction(uint64(0), ph, DEFAULT_TX_CONFIG, action_scope, primaries=payees) + [tx] = action_scope.side_effects.transactions assert tx.spend_bundle is not None await full_node_api.send_transaction(SendTransaction(tx.spend_bundle)) @@ -1206,10 +1190,9 @@ async def test_dusted_wallet( metadata = Program.to( [("u", ["https://www.chia.net/img/branding/chia-logo.svg"]), ("h", "0xD4584AD463139FA8C0D9F68F4B59F185")] ) - async with farm_nft_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await farm_nft_wallet.generate_new_nft(metadata, DEFAULT_TX_CONFIG, action_scope) - txs = await farm_nft_wallet.wallet_state_manager.add_pending_transactions(txs) - for tx in txs: + async with farm_nft_wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await farm_nft_wallet.generate_new_nft(metadata, DEFAULT_TX_CONFIG, action_scope) + for tx in action_scope.side_effects.transactions: if tx.spend_bundle is not None: assert len(compute_memos(tx.spend_bundle)) > 0 await time_out_assert_not_none( @@ -1232,12 +1215,12 @@ async def test_dusted_wallet( nft_coins = await farm_nft_wallet.get_current_nfts() # Send the NFT to the dust wallet - async with farm_nft_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await farm_nft_wallet.generate_signed_transaction( + async with farm_nft_wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await farm_nft_wallet.generate_signed_transaction( [uint64(nft_coins[0].coin.amount)], [dust_ph], DEFAULT_TX_CONFIG, action_scope, coins={nft_coins[0].coin} ) - assert len(txs) == 1 - txs = await farm_wallet_node.wallet_state_manager.add_pending_transactions(txs) + assert len(action_scope.side_effects.transactions) == 1 + txs = await farm_wallet_node.wallet_state_manager.add_pending_transactions(action_scope.side_effects.transactions) assert txs[0].spend_bundle is not None assert len(compute_memos(txs[0].spend_bundle)) > 0 @@ -1396,11 +1379,11 @@ async def assert_coin_state_retry() -> None: await assert_coin_state_retry() - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.generate_signed_transaction( uint64(1_000_000_000_000), bytes32([0] * 32), DEFAULT_TX_CONFIG, action_scope, memos=[ph] ) - [tx] = await wallet_node.wallet_state_manager.add_pending_transactions([tx]) + [tx] = action_scope.side_effects.transactions await time_out_assert(30, wallet.get_confirmed_balance, 2_000_000_000_000) async def tx_in_mempool() -> bool: diff --git a/chia/_tests/wallet/test_notifications.py b/chia/_tests/wallet/test_notifications.py index 3e48dc3eb42d..6c1c63dbc9cf 100644 --- a/chia/_tests/wallet/test_notifications.py +++ b/chia/_tests/wallet/test_notifications.py @@ -140,11 +140,11 @@ async def track_coin_state(*args: Any) -> bool: allow_height = peak.height + 1 if case == "allow_larger": allow_larger_height = peak.height + 1 - async with notification_manager_1.wallet_state_manager.new_action_scope(push=False) as action_scope: - tx = await notification_manager_1.send_new_notification( + async with notification_manager_1.wallet_state_manager.new_action_scope(push=True) as action_scope: + await notification_manager_1.send_new_notification( ph_2, msg, AMOUNT, DEFAULT_TX_CONFIG, action_scope, fee=FEE ) - [tx] = await wsm_1.add_pending_transactions([tx]) + [tx] = action_scope.side_effects.transactions await time_out_assert_not_none( 5, full_node_api.full_node.mempool_manager.get_spendbundle, diff --git a/chia/_tests/wallet/test_signer_protocol.py b/chia/_tests/wallet/test_signer_protocol.py index 0af767e306f9..08134434dfe5 100644 --- a/chia/_tests/wallet/test_signer_protocol.py +++ b/chia/_tests/wallet/test_signer_protocol.py @@ -613,7 +613,8 @@ async def test_signer_commands(wallet_environments: WalletTestFramework) -> None AMOUNT = uint64(1) async with wallet_state_manager.new_action_scope(sign=False, push=False) as action_scope: - [tx] = await wallet.generate_signed_transaction(AMOUNT, bytes32([0] * 32), DEFAULT_TX_CONFIG, action_scope) + await wallet.generate_signed_transaction(AMOUNT, bytes32([0] * 32), DEFAULT_TX_CONFIG, action_scope) + [tx] = action_scope.side_effects.transactions runner = CliRunner() with runner.isolated_filesystem(): diff --git a/chia/_tests/wallet/test_wallet.py b/chia/_tests/wallet/test_wallet.py index 9dc8ad7f1903..199627c53043 100644 --- a/chia/_tests/wallet/test_wallet.py +++ b/chia/_tests/wallet/test_wallet.py @@ -74,15 +74,14 @@ async def test_wallet_make_transaction(self, wallet_environments: WalletTestFram tx_amount = 10 - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.generate_signed_transaction( uint64(tx_amount), bytes32([0] * 32), DEFAULT_TX_CONFIG, action_scope, uint64(0), ) - [tx] = await wallet.wallet_state_manager.add_pending_transactions([tx]) await wallet_environments.process_pending_states( [ @@ -126,14 +125,15 @@ async def test_wallet_reuse_address(self, wallet_environments: WalletTestFramewo tx_amount = 10 - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.generate_signed_transaction( uint64(tx_amount), bytes32([0] * 32), DEFAULT_TX_CONFIG.override(reuse_puzhash=True), action_scope, uint64(0), ) + [tx] = action_scope.side_effects.transactions assert tx.spend_bundle is not None assert len(tx.spend_bundle.coin_spends) == 1 new_puzhash = [c.puzzle_hash.hex() for c in tx.additions] @@ -188,8 +188,8 @@ async def test_wallet_clawback_claim_auto( # Transfer to normal wallet for _ in range(0, number_of_coins): - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx1] = await wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.generate_signed_transaction( uint64(tx_amount), normal_puzhash, DEFAULT_TX_CONFIG, @@ -197,7 +197,6 @@ async def test_wallet_clawback_claim_auto( uint64(0), puzzle_decorator_override=[{"decorator": "CLAWBACK", "clawback_timelock": 10}], ) - [tx1] = await wallet.wallet_state_manager.add_pending_transactions([tx1]) await wallet_environments.process_pending_states( [ @@ -233,8 +232,8 @@ async def test_wallet_clawback_claim_auto( 20, wsm_1.coin_store.count_small_unspent, number_of_coins, tx_amount * 2, CoinType.CLAWBACK ) - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx_bad] = await wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.generate_signed_transaction( uint64(tx_amount), normal_puzhash, DEFAULT_TX_CONFIG, @@ -242,7 +241,7 @@ async def test_wallet_clawback_claim_auto( uint64(0), puzzle_decorator_override=[{"decorator": "CLAWBACK", "clawback_timelock": 10}], ) - [tx_bad] = await wallet.wallet_state_manager.add_pending_transactions([tx_bad]) + [tx_bad] = action_scope.side_effects.transactions await wallet_environments.process_pending_states( [ @@ -339,8 +338,8 @@ async def test_wallet_clawback_clawback(self, wallet_environments: WalletTestFra tx_amount = 500 normal_puzhash = await wallet_1.get_new_puzzlehash() # Transfer to normal wallet - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.generate_signed_transaction( uint64(tx_amount), normal_puzhash, DEFAULT_TX_CONFIG, @@ -350,8 +349,6 @@ async def test_wallet_clawback_clawback(self, wallet_environments: WalletTestFra memos=[b"Test"], ) - [tx] = await wallet.wallet_state_manager.add_pending_transactions([tx]) - await wallet_environments.process_pending_states( [ WalletStateTransition( @@ -388,6 +385,7 @@ async def test_wallet_clawback_clawback(self, wallet_environments: WalletTestFra dict(type_filter={"values": [TransactionType.INCOMING_CLAWBACK_SEND], "mode": 1}, wallet_id=1) ) # clawback merkle coin + [tx] = action_scope.side_effects.transactions merkle_coin = tx.additions[0] if tx.additions[0].amount == tx_amount else tx.additions[1] interested_coins = await wsm_2.interested_store.get_interested_coin_ids() assert merkle_coin.name() in set(interested_coins) @@ -483,8 +481,8 @@ async def test_wallet_clawback_sent_self(self, wallet_environments: WalletTestFr tx_amount = 500 normal_puzhash = await wallet.get_new_puzzlehash() # Transfer to normal wallet - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.generate_signed_transaction( uint64(tx_amount), normal_puzhash, DEFAULT_TX_CONFIG, @@ -494,8 +492,6 @@ async def test_wallet_clawback_sent_self(self, wallet_environments: WalletTestFr memos=[b"Test"], ) - [tx] = await wallet.wallet_state_manager.add_pending_transactions([tx]) - await wallet_environments.process_pending_states( [ WalletStateTransition( @@ -528,6 +524,7 @@ async def test_wallet_clawback_sent_self(self, wallet_environments: WalletTestFr # Check merkle coins await time_out_assert(20, wsm.coin_store.count_small_unspent, 1, 1000, CoinType.CLAWBACK) # Claim merkle coin + [tx] = action_scope.side_effects.transactions merkle_coin = tx.additions[0] if tx.additions[0].amount == tx_amount else tx.additions[1] test_fee = 10 resp = await api_0.spend_clawback_coins( @@ -602,8 +599,8 @@ async def test_wallet_clawback_claim_manual(self, wallet_environments: WalletTes tx_amount = 500 normal_puzhash = await wallet_1.get_new_puzzlehash() # Transfer to normal wallet - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.generate_signed_transaction( uint64(tx_amount), normal_puzhash, DEFAULT_TX_CONFIG, @@ -612,8 +609,6 @@ async def test_wallet_clawback_claim_manual(self, wallet_environments: WalletTes puzzle_decorator_override=[{"decorator": "CLAWBACK", "clawback_timelock": 5}], ) - [tx] = await wallet.wallet_state_manager.add_pending_transactions([tx]) - await wallet_environments.process_pending_states( [ WalletStateTransition( @@ -662,6 +657,7 @@ async def test_wallet_clawback_claim_manual(self, wallet_environments: WalletTes ) # Claim merkle coin + [tx] = action_scope.side_effects.transactions merkle_coin = tx.additions[0] if tx.additions[0].amount == tx_amount else tx.additions[1] test_fee = 10 resp = await api_1.spend_clawback_coins( @@ -736,8 +732,8 @@ async def test_wallet_clawback_reorg(self, wallet_environments: WalletTestFramew tx_amount = 500 normal_puzhash = await wallet_1.get_new_puzzlehash() # Transfer to normal wallet - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.generate_signed_transaction( uint64(tx_amount), normal_puzhash, DEFAULT_TX_CONFIG, @@ -746,8 +742,6 @@ async def test_wallet_clawback_reorg(self, wallet_environments: WalletTestFramew puzzle_decorator_override=[{"decorator": "CLAWBACK", "clawback_timelock": 5}], ) - [tx] = await wallet.wallet_state_manager.add_pending_transactions([tx]) - await wallet_environments.process_pending_states( [ WalletStateTransition( @@ -921,8 +915,8 @@ async def test_get_clawback_coins(self, wallet_environments: WalletTestFramework tx_amount = 500 # Transfer to normal wallet - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.generate_signed_transaction( uint64(tx_amount), bytes32([0] * 32), DEFAULT_TX_CONFIG, @@ -931,8 +925,6 @@ async def test_get_clawback_coins(self, wallet_environments: WalletTestFramework puzzle_decorator_override=[{"decorator": "CLAWBACK", "clawback_timelock": 500}], ) - [tx] = await wallet.wallet_state_manager.add_pending_transactions([tx]) - await wallet_environments.process_pending_states( [ WalletStateTransition( @@ -965,6 +957,7 @@ async def test_get_clawback_coins(self, wallet_environments: WalletTestFramework # Check merkle coins await time_out_assert(20, wsm.coin_store.count_small_unspent, 1, 1000, CoinType.CLAWBACK) # clawback merkle coin + [tx] = action_scope.side_effects.transactions merkle_coin = tx.additions[0] if tx.additions[0].amount == tx_amount else tx.additions[1] resp = await env.rpc_api.get_coin_records({"wallet_id": 1, "coin_type": 1}) assert len(resp["coin_records"]) == 1 @@ -992,8 +985,8 @@ async def test_clawback_resync(self, self_hostname: str, wallet_environments: Wa tx_amount = 500 # Transfer to normal wallet - async with wallet_1.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx1] = await wallet_1.generate_signed_transaction( + async with wallet_1.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet_1.generate_signed_transaction( uint64(tx_amount), wallet_2_puzhash, DEFAULT_TX_CONFIG, @@ -1002,9 +995,9 @@ async def test_clawback_resync(self, self_hostname: str, wallet_environments: Wa puzzle_decorator_override=[{"decorator": "CLAWBACK", "clawback_timelock": 5}], ) + [tx1] = action_scope.side_effects.transactions clawback_coin_id_1 = tx1.additions[0].name() assert tx1.spend_bundle is not None - [tx1] = await wallet_1.wallet_state_manager.add_pending_transactions([tx1]) await wallet_environments.process_pending_states( [ @@ -1040,8 +1033,8 @@ async def test_clawback_resync(self, self_hostname: str, wallet_environments: Wa await time_out_assert(20, wsm_2.coin_store.count_small_unspent, 1, 1000, CoinType.CLAWBACK) tx_amount2 = 700 - async with wallet_1.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx2] = await wallet_1.generate_signed_transaction( + async with wallet_1.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet_1.generate_signed_transaction( uint64(tx_amount2), wallet_1_puzhash, DEFAULT_TX_CONFIG, @@ -1049,9 +1042,9 @@ async def test_clawback_resync(self, self_hostname: str, wallet_environments: Wa uint64(0), puzzle_decorator_override=[{"decorator": "CLAWBACK", "clawback_timelock": 5}], ) + [tx2] = action_scope.side_effects.transactions clawback_coin_id_2 = tx2.additions[0].name() assert tx2.spend_bundle is not None - [tx2] = await wallet_1.wallet_state_manager.add_pending_transactions([tx2]) await wallet_environments.process_pending_states( [ @@ -1314,25 +1307,23 @@ async def test_wallet_send_to_three_peers( await full_node_1.add_block(block) await full_node_2.add_block(block) - async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await wallet_0.wallet_state_manager.main_wallet.generate_signed_transaction( + async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet_0.wallet_state_manager.main_wallet.generate_signed_transaction( uint64(10), bytes32(32 * b"0"), DEFAULT_TX_CONFIG, action_scope, uint64(0), ) - assert tx.spend_bundle is not None - [tx] = await wallet_0.wallet_state_manager.main_wallet.wallet_state_manager.add_pending_transactions([tx]) - await full_node_api_0.wait_transaction_records_entered_mempool(records=[tx]) + await full_node_api_0.wait_transaction_records_entered_mempool(records=action_scope.side_effects.transactions) # wallet0 <-> sever1 await wallet_server_0.start_client(PeerInfo(self_hostname, server_1.get_port()), wallet_0.on_connect) - await full_node_api_1.wait_transaction_records_entered_mempool(records=[tx]) + await full_node_api_1.wait_transaction_records_entered_mempool(records=action_scope.side_effects.transactions) # wallet0 <-> sever2 await wallet_server_0.start_client(PeerInfo(self_hostname, server_2.get_port()), wallet_0.on_connect) - await full_node_api_2.wait_transaction_records_entered_mempool(records=[tx]) + await full_node_api_2.wait_transaction_records_entered_mempool(records=action_scope.side_effects.transactions) @pytest.mark.parametrize( "wallet_environments", @@ -1348,15 +1339,14 @@ async def test_wallet_make_transaction_hop(self, wallet_environments: WalletTest wallet_1 = env_1.xch_wallet tx_amount = 10 - async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await wallet_0.generate_signed_transaction( + async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet_0.generate_signed_transaction( uint64(tx_amount), await wallet_1.get_puzzle_hash(False), DEFAULT_TX_CONFIG, action_scope, uint64(0), ) - [tx] = await wallet_0.wallet_state_manager.add_pending_transactions([tx]) await wallet_environments.process_pending_states( [ @@ -1396,11 +1386,10 @@ async def test_wallet_make_transaction_hop(self, wallet_environments: WalletTest ) tx_amount = 5 - async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await wallet_1.generate_signed_transaction( + async with wallet_1.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet_1.generate_signed_transaction( uint64(tx_amount), await wallet_0.get_puzzle_hash(False), DEFAULT_TX_CONFIG, action_scope, uint64(0) ) - [tx] = await wallet_1.wallet_state_manager.add_pending_transactions([tx]) await wallet_environments.process_pending_states( [ @@ -1454,21 +1443,20 @@ async def test_wallet_make_transaction_with_fee(self, wallet_environments: Walle tx_amount = 1_750_000_000_000 # ensures we grab both coins tx_fee = 10 - async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await wallet_0.generate_signed_transaction( + async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet_0.generate_signed_transaction( uint64(tx_amount), await wallet_1.get_new_puzzlehash(), DEFAULT_TX_CONFIG, action_scope, uint64(tx_fee), ) + [tx] = action_scope.side_effects.transactions assert tx.spend_bundle is not None fees = estimate_fees(tx.spend_bundle) assert fees == tx_fee - [tx] = await wallet_0.wallet_state_manager.add_pending_transactions([tx]) - await wallet_environments.process_pending_states( [ WalletStateTransition( @@ -1523,16 +1511,16 @@ async def test_wallet_make_transaction_with_memo(self, wallet_environments: Wall tx_amount = 1_750_000_000_000 # ensures we grab both coins tx_fee = 10 ph_2 = await wallet_1.get_new_puzzlehash() - async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await wallet_0.generate_signed_transaction( + async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet_0.generate_signed_transaction( uint64(tx_amount), ph_2, DEFAULT_TX_CONFIG, action_scope, uint64(tx_fee), memos=[ph_2] ) + [tx] = action_scope.side_effects.transactions assert tx.spend_bundle is not None fees = estimate_fees(tx.spend_bundle) assert fees == tx_fee - [tx] = await wallet_0.wallet_state_manager.add_pending_transactions([tx]) tx_id = tx.name.hex() memos = await env_0.rpc_api.get_transaction_memo(dict(transaction_id=tx_id)) # test json serialization @@ -1597,13 +1585,10 @@ async def test_wallet_create_hit_max_send_amount(self, wallet_environments: Wall ph = await wallet.get_puzzle_hash(False) primaries = [Payment(ph, uint64(1000000000 + i)) for i in range(int(wallet.max_send_quantity) + 1)] - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx_split_coins] = await wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.generate_signed_transaction( uint64(1), ph, DEFAULT_TX_CONFIG, action_scope, uint64(0), primaries=primaries ) - assert tx_split_coins.spend_bundle is not None - - [tx_split_coins] = await wallet.wallet_state_manager.add_pending_transactions([tx_split_coins]) await wallet_environments.process_pending_states( [ @@ -1637,7 +1622,7 @@ async def test_wallet_create_hit_max_send_amount(self, wallet_environments: Wall # 1) Generate transaction that is under the limit async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [transaction_record] = await wallet.generate_signed_transaction( + await wallet.generate_signed_transaction( uint64(max_sent_amount - 1), ph, DEFAULT_TX_CONFIG, @@ -1645,11 +1630,11 @@ async def test_wallet_create_hit_max_send_amount(self, wallet_environments: Wall uint64(0), ) - assert transaction_record.amount == uint64(max_sent_amount - 1) + assert action_scope.side_effects.transactions[0].amount == uint64(max_sent_amount - 1) # 2) Generate transaction that is equal to limit async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [transaction_record] = await wallet.generate_signed_transaction( + await wallet.generate_signed_transaction( uint64(max_sent_amount), ph, DEFAULT_TX_CONFIG, @@ -1657,7 +1642,7 @@ async def test_wallet_create_hit_max_send_amount(self, wallet_environments: Wall uint64(0), ) - assert transaction_record.amount == uint64(max_sent_amount) + assert action_scope.side_effects.transactions[0].amount == uint64(max_sent_amount) # 3) Generate transaction that is greater than limit with pytest.raises( @@ -1688,13 +1673,14 @@ async def test_wallet_prevent_fee_theft(self, wallet_environments: WalletTestFra tx_amount = 1_750_000_000_000 tx_fee = 2_000_000_000_000 async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await wallet.generate_signed_transaction( + await wallet.generate_signed_transaction( uint64(tx_amount), bytes32([0] * 32), DEFAULT_TX_CONFIG, action_scope, uint64(tx_fee), ) + [tx] = action_scope.side_effects.transactions assert tx.spend_bundle is not None stolen_cs: Optional[CoinSpend] = None @@ -1762,12 +1748,10 @@ async def test_wallet_tx_reorg(self, wallet_environments: WalletTestFramework) - assert reorg_height is not None await full_node_api.farm_blocks_to_puzzlehash(count=3) - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.generate_signed_transaction( uint64(tx_amount), await wallet_2.get_puzzle_hash(False), DEFAULT_TX_CONFIG, action_scope, coins={coin} ) - assert tx.spend_bundle is not None - [tx] = await wallet.wallet_state_manager.add_pending_transactions([tx]) await wallet_environments.process_pending_states( [ @@ -1867,6 +1851,7 @@ async def test_wallet_tx_reorg(self, wallet_environments: WalletTestFramework) - unconfirmed = await wsm.tx_store.get_unconfirmed_for_wallet(int(wallet.id())) assert len(unconfirmed) == 0 + [tx] = action_scope.side_effects.transactions tx_record = await wsm.tx_store.get_transaction_record(tx.name) assert tx_record is not None removed = tx_record.removals[0] @@ -2064,8 +2049,8 @@ async def test_wallet_transaction_options(self, wallet_environments: WalletTestF coins = await wallet.select_coins(uint64(AMOUNT_TO_SEND), DEFAULT_TX_CONFIG.coin_selection_config) coin_list = list(coins) - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.generate_signed_transaction( uint64(AMOUNT_TO_SEND), bytes32([0] * 32), DEFAULT_TX_CONFIG, @@ -2074,6 +2059,7 @@ async def test_wallet_transaction_options(self, wallet_environments: WalletTestF coins=coins, origin_id=coin_list[2].name(), ) + [tx] = action_scope.side_effects.transactions assert tx.spend_bundle is not None paid_coin = [coin for coin in tx.spend_bundle.additions() if coin.amount == AMOUNT_TO_SEND][0] assert paid_coin.parent_coin_info == coin_list[2].name() diff --git a/chia/_tests/wallet/test_wallet_action_scope.py b/chia/_tests/wallet/test_wallet_action_scope.py index 54583e96bc9c..cec1412b4ca4 100644 --- a/chia/_tests/wallet/test_wallet_action_scope.py +++ b/chia/_tests/wallet/test_wallet_action_scope.py @@ -71,7 +71,7 @@ async def test_wallet_action_scope() -> None: assert wsm.most_recent_call == ([STD_TX], True, False, True, [], []) async with wsm.new_action_scope( # type: ignore[attr-defined] - push=False, merge_spends=True, sign=True, additional_signing_responses=[] + push=False, merge_spends=True, sign=True, additional_signing_responses=[], extra_spends=[] ) as action_scope: async with action_scope.use() as interface: interface.side_effects.transactions = [] diff --git a/chia/_tests/wallet/test_wallet_node.py b/chia/_tests/wallet/test_wallet_node.py index fb5df20e6323..580879b966f4 100644 --- a/chia/_tests/wallet/test_wallet_node.py +++ b/chia/_tests/wallet/test_wallet_node.py @@ -640,9 +640,9 @@ async def send_transaction( ) # Generate the transaction - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await wallet.generate_signed_transaction(uint64(0), bytes32([0] * 32), DEFAULT_TX_CONFIG, action_scope) - [tx] = await wallet.wallet_state_manager.add_pending_transactions([tx]) + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.generate_signed_transaction(uint64(0), bytes32([0] * 32), DEFAULT_TX_CONFIG, action_scope) + [tx] = action_scope.side_effects.transactions # Make sure it is sent to the peer await wallet_node._resend_queue() diff --git a/chia/_tests/wallet/test_wallet_retry.py b/chia/_tests/wallet/test_wallet_retry.py index b06c1628cc97..39d7e941163f 100644 --- a/chia/_tests/wallet/test_wallet_retry.py +++ b/chia/_tests/wallet/test_wallet_retry.py @@ -54,11 +54,9 @@ async def test_wallet_tx_retry( await farm_blocks(full_node_1, reward_ph, 2) await full_node_1.wait_for_wallet_synced(wallet_node=wallet_node_1, timeout=wait_secs) - async with wallet_1.wallet_state_manager.new_action_scope(push=False) as action_scope: - [transaction] = await wallet_1.generate_signed_transaction( - uint64(100), reward_ph, DEFAULT_TX_CONFIG, action_scope - ) - [transaction] = await wallet_1.wallet_state_manager.add_pending_transactions([transaction]) + async with wallet_1.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet_1.generate_signed_transaction(uint64(100), reward_ph, DEFAULT_TX_CONFIG, action_scope) + [transaction] = action_scope.side_effects.transactions sb1: Optional[SpendBundle] = transaction.spend_bundle assert sb1 is not None diff --git a/chia/_tests/wallet/test_wallet_state_manager.py b/chia/_tests/wallet/test_wallet_state_manager.py index 8644e3bd51b3..699c075054e7 100644 --- a/chia/_tests/wallet/test_wallet_state_manager.py +++ b/chia/_tests/wallet/test_wallet_state_manager.py @@ -121,15 +121,20 @@ async def test_commit_transactions_to_db(wallet_environments: WalletTestFramewor ) ) - async with wsm.new_action_scope(push=False) as action_scope: - [tx1] = await wsm.main_wallet.generate_signed_transaction( + async with wsm.new_action_scope( + push=False, + merge_spends=False, + sign=False, + extra_spends=[], + ) as action_scope: + await wsm.main_wallet.generate_signed_transaction( uint64(0), bytes32([0] * 32), wallet_environments.tx_config, action_scope, coins={coins[0]}, ) - [tx2] = await wsm.main_wallet.generate_signed_transaction( + await wsm.main_wallet.generate_signed_transaction( uint64(0), bytes32([0] * 32), wallet_environments.tx_config, @@ -137,6 +142,8 @@ async def test_commit_transactions_to_db(wallet_environments: WalletTestFramewor coins={coins[1]}, ) + created_txs = action_scope.side_effects.transactions + def flatten_spend_bundles(txs: List[TransactionRecord]) -> List[SpendBundle]: return [tx.spend_bundle for tx in txs if tx.spend_bundle is not None] @@ -144,14 +151,8 @@ def flatten_spend_bundles(txs: List[TransactionRecord]) -> List[SpendBundle]: len(await wsm.tx_store.get_all_transactions_for_wallet(wsm.main_wallet.id(), type=TransactionType.OUTGOING_TX)) == 0 ) - new_txs = await wsm.add_pending_transactions( - [tx1, tx2], - push=False, - merge_spends=False, - sign=False, - extra_spends=[], - ) - bundles = flatten_spend_bundles(new_txs) + + bundles = flatten_spend_bundles(created_txs) assert len(bundles) == 2 for bundle in bundles: assert bundle.aggregated_signature == G2Element() @@ -161,12 +162,12 @@ def flatten_spend_bundles(txs: List[TransactionRecord]) -> List[SpendBundle]: ) extra_coin_spend = make_spend( - Coin(bytes32(b"1" * 32), bytes32(b"1" * 32), uint64(0)), Program.to(1), Program.to([None]) + Coin(bytes32(b"1" * 32), bytes32(b"1" * 32), uint64(0)), Program.to(1), Program.to([]) ) extra_spend = SpendBundle([extra_coin_spend], G2Element()) new_txs = await wsm.add_pending_transactions( - [tx1, tx2], + created_txs, push=False, merge_spends=False, sign=False, @@ -183,7 +184,7 @@ def flatten_spend_bundles(txs: List[TransactionRecord]) -> List[SpendBundle]: assert extra_coin_spend in [spend for bundle in bundles for spend in bundle.coin_spends] new_txs = await wsm.add_pending_transactions( - [tx1, tx2], + created_txs, push=False, merge_spends=True, sign=False, @@ -199,7 +200,7 @@ def flatten_spend_bundles(txs: List[TransactionRecord]) -> List[SpendBundle]: ) assert extra_coin_spend in [spend for bundle in bundles for spend in bundle.coin_spends] - [tx1, tx2] = await wsm.add_pending_transactions([tx1, tx2], push=True, merge_spends=True, sign=True) + new_txs = await wsm.add_pending_transactions(created_txs, push=True, merge_spends=True, sign=True) bundles = flatten_spend_bundles(new_txs) assert len(bundles) == 1 assert ( @@ -207,4 +208,4 @@ def flatten_spend_bundles(txs: List[TransactionRecord]) -> List[SpendBundle]: == 2 ) - await wallet_environments.full_node.wait_transaction_records_entered_mempool([tx1, tx2]) + await wallet_environments.full_node.wait_transaction_records_entered_mempool(new_txs) diff --git a/chia/_tests/wallet/vc_wallet/test_vc_wallet.py b/chia/_tests/wallet/vc_wallet/test_vc_wallet.py index 997836be00b7..9d9ce11f3037 100644 --- a/chia/_tests/wallet/vc_wallet/test_vc_wallet.py +++ b/chia/_tests/wallet/vc_wallet/test_vc_wallet.py @@ -149,7 +149,7 @@ async def test_vc_lifecycle(wallet_environments: WalletTestFramework) -> None: } # Generate DID as an "authorized provider" - async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: did_id: bytes32 = bytes32.from_hexstr( ( await DIDWallet.create_new_did_wallet( @@ -349,7 +349,7 @@ async def test_vc_lifecycle(wallet_environments: WalletTestFramework) -> None: assert await wallet_node_0.wallet_state_manager.get_wallet_for_asset_id(cr_cat_wallet_0.get_asset_id()) is not None wallet_1_ph = await wallet_1.get_new_puzzlehash() wallet_1_addr = encode_puzzle_hash(wallet_1_ph, "txch") - tx = ( + txs = ( await client_0.cat_spend( cr_cat_wallet_0.id(), wallet_environments.tx_config, @@ -358,8 +358,7 @@ async def test_vc_lifecycle(wallet_environments: WalletTestFramework) -> None: uint64(2000000000), memos=["hey"], ) - ).transaction - [tx] = await wallet_node_0.wallet_state_manager.add_pending_transactions([tx]) + ).transactions await wallet_environments.process_pending_states( [ WalletStateTransition( @@ -422,7 +421,7 @@ async def test_vc_lifecycle(wallet_environments: WalletTestFramework) -> None: ] ) assert await wallet_node_1.wallet_state_manager.wallets[env_1.dealias_wallet_id("crcat")].match_hinted_coin( - next(c for c in tx.additions if c.amount == 90), wallet_1_ph + next(c for tx in txs for c in tx.additions if c.amount == 90), wallet_1_ph ) pending_tx = await client_1.get_transactions( env_1.dealias_wallet_id("crcat"), @@ -656,7 +655,7 @@ async def test_self_revoke(wallet_environments: WalletTestFramework) -> None: } # Generate DID as an "authorized provider" - async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope: did_wallet: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_0.wallet_state_manager, wallet_0, uint64(1), DEFAULT_TX_CONFIG, action_scope ) @@ -699,11 +698,9 @@ async def test_self_revoke(wallet_environments: WalletTestFramework) -> None: ) # Send the DID to oblivion - async with did_wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - txs = await did_wallet.transfer_did( - bytes32([0] * 32), uint64(0), False, wallet_environments.tx_config, action_scope - ) - txs = await did_wallet.wallet_state_manager.add_pending_transactions(txs) + async with did_wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await did_wallet.transfer_did(bytes32([0] * 32), uint64(0), False, wallet_environments.tx_config, action_scope) + await wallet_environments.process_pending_states( [ WalletStateTransition( diff --git a/chia/data_layer/data_layer_wallet.py b/chia/data_layer/data_layer_wallet.py index 43050ca1ae7b..8ca682d42ee7 100644 --- a/chia/data_layer/data_layer_wallet.py +++ b/chia/data_layer/data_layer_wallet.py @@ -306,7 +306,7 @@ async def generate_new_reporter( action_scope: WalletActionScope, fee: uint64 = uint64(0), extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> Tuple[TransactionRecord, bytes32]: + ) -> bytes32: """ Creates the initial singleton, which includes spending an origin coin, the launcher, and creating a singleton """ @@ -326,7 +326,8 @@ async def generate_new_reporter( ) announcement_message: bytes32 = genesis_launcher_solution.get_tree_hash() announcement = AssertCoinAnnouncement(asserted_id=launcher_coin.name(), asserted_msg=announcement_message) - [create_launcher_tx_record] = await self.standard_wallet.generate_signed_transaction( + + await self.standard_wallet.generate_signed_transaction( amount=uint64(1), puzzle_hash=SINGLETON_LAUNCHER.get_tree_hash(), tx_config=tx_config, @@ -337,7 +338,6 @@ async def generate_new_reporter( primaries=None, extra_conditions=(*extra_conditions, announcement), ) - assert create_launcher_tx_record is not None and create_launcher_tx_record.spend_bundle is not None launcher_cs: CoinSpend = CoinSpend( launcher_coin, @@ -345,10 +345,10 @@ async def generate_new_reporter( SerializedProgram.from_program(genesis_launcher_solution), ) launcher_sb: SpendBundle = SpendBundle([launcher_cs], G2Element()) - full_spend: SpendBundle = SpendBundle.aggregate([create_launcher_tx_record.spend_bundle, launcher_sb]) - # Delete from standard transaction so we don't push duplicate spends - std_record: TransactionRecord = dataclasses.replace(create_launcher_tx_record, spend_bundle=full_spend) + async with action_scope.use() as interface: + interface.side_effects.extra_spends.append(launcher_sb) + singleton_record = SingletonRecord( coin_id=Coin(launcher_coin.name(), full_puzzle.get_tree_hash(), uint64(1)).name(), launcher_id=launcher_coin.name(), @@ -368,7 +368,7 @@ async def generate_new_reporter( await self.wallet_state_manager.dl_store.add_singleton_record(singleton_record) await self.wallet_state_manager.add_interested_puzzle_hashes([singleton_record.launcher_id], [self.id()]) - return std_record, launcher_coin.name() + return launcher_coin.name() async def create_tandem_xch_tx( self, @@ -376,8 +376,8 @@ async def create_tandem_xch_tx( announcement_to_assert: AssertAnnouncement, tx_config: TXConfig, action_scope: WalletActionScope, - ) -> TransactionRecord: - [chia_tx] = await self.standard_wallet.generate_signed_transaction( + ) -> None: + await self.standard_wallet.generate_signed_transaction( amount=uint64(0), puzzle_hash=await self.standard_wallet.get_puzzle_hash(new=not tx_config.reuse_puzhash), tx_config=tx_config, @@ -386,8 +386,6 @@ async def create_tandem_xch_tx( negative_change_allowed=False, extra_conditions=(announcement_to_assert,), ) - assert chia_tx.spend_bundle is not None - return chia_tx async def create_update_state_spend( self, @@ -401,7 +399,7 @@ async def create_update_state_spend( add_pending_singleton: bool = True, announce_new_state: bool = False, extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> List[TransactionRecord]: + ) -> None: singleton_record, parent_lineage = await self.get_spendable_singleton_info(launcher_id) if root_hash is None: @@ -591,19 +589,12 @@ async def create_update_state_spend( ) assert dl_tx.spend_bundle is not None if fee > 0: - chia_tx = await self.create_tandem_xch_tx( + await self.create_tandem_xch_tx( fee, AssertAnnouncement(True, asserted_origin_id=current_coin.name(), asserted_msg=b"$"), tx_config, action_scope, ) - assert chia_tx.spend_bundle is not None - aggregate_bundle = SpendBundle.aggregate([dl_tx.spend_bundle, chia_tx.spend_bundle]) - dl_tx = dataclasses.replace(dl_tx, spend_bundle=aggregate_bundle, name=aggregate_bundle.name()) - chia_tx = dataclasses.replace(chia_tx, spend_bundle=None) - txs: List[TransactionRecord] = [dl_tx, chia_tx] - else: - txs = [dl_tx] if add_pending_singleton: await self.wallet_state_manager.dl_store.add_singleton_record( @@ -614,7 +605,8 @@ async def create_update_state_spend( second_singleton_record, ) - return txs + async with action_scope.use() as interface: + interface.side_effects.transactions.append(dl_tx) async def generate_signed_transaction( self, @@ -627,7 +619,7 @@ async def generate_signed_transaction( memos: Optional[List[List[bytes]]] = None, # ignored extra_conditions: Tuple[Condition, ...] = tuple(), **kwargs: Unpack[GSTOptionalArgs], - ) -> List[TransactionRecord]: + ) -> None: launcher_id: Optional[bytes32] = kwargs.get("launcher_id", None) new_root_hash: Optional[bytes32] = kwargs.get("new_root_hash", None) add_pending_singleton: bool = kwargs.get("add_pending_singleton", True) @@ -649,7 +641,7 @@ async def generate_signed_transaction( if len(amounts) != 1 or len(puzzle_hashes) != 1: raise ValueError("The wallet can only send one DL coin to one place at a time") - return await self.create_update_state_spend( + await self.create_update_state_spend( launcher_id, new_root_hash, tx_config, @@ -725,8 +717,8 @@ async def create_new_mirror( action_scope: WalletActionScope, fee: uint64 = uint64(0), extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> List[TransactionRecord]: - [create_mirror_tx_record] = await self.standard_wallet.generate_signed_transaction( + ) -> None: + await self.standard_wallet.generate_signed_transaction( amount=amount, puzzle_hash=create_mirror_puzzle().get_tree_hash(), tx_config=tx_config, @@ -736,8 +728,6 @@ async def create_new_mirror( memos=[launcher_id, *(url for url in urls)], extra_conditions=extra_conditions, ) - assert create_mirror_tx_record.spend_bundle is not None - return [create_mirror_tx_record] async def delete_mirror( self, @@ -747,7 +737,7 @@ async def delete_mirror( action_scope: WalletActionScope, fee: uint64 = uint64(0), extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> List[TransactionRecord]: + ) -> None: mirror: Mirror = await self.get_mirror(mirror_id) mirror_coin: Coin = (await self.wallet_state_manager.wallet_node.get_coin_state([mirror.coin_id], peer=peer))[ 0 @@ -781,30 +771,32 @@ async def delete_mirror( ), ) mirror_bundle: SpendBundle = SpendBundle([mirror_spend], G2Element()) - txs = [ - TransactionRecord( - confirmed_at_height=uint32(0), - created_at_time=uint64(int(time.time())), - to_puzzle_hash=new_puzhash, - amount=uint64(mirror_coin.amount), - fee_amount=fee, - confirmed=False, - sent=uint32(10), - spend_bundle=mirror_bundle, - additions=mirror_bundle.additions(), - removals=mirror_bundle.removals(), - memos=list(compute_memos(mirror_bundle).items()), - wallet_id=self.id(), # This is being called before the wallet is created so we're using a temp ID of 0 - sent_to=[], - trade_id=None, - type=uint32(TransactionType.OUTGOING_TX.value), - name=mirror_bundle.name(), - valid_times=parse_timelock_info(extra_conditions), + + async with action_scope.use() as interface: + interface.side_effects.transactions.append( + TransactionRecord( + confirmed_at_height=uint32(0), + created_at_time=uint64(int(time.time())), + to_puzzle_hash=new_puzhash, + amount=uint64(mirror_coin.amount), + fee_amount=fee, + confirmed=False, + sent=uint32(10), + spend_bundle=mirror_bundle, + additions=mirror_bundle.additions(), + removals=mirror_bundle.removals(), + memos=list(compute_memos(mirror_bundle).items()), + wallet_id=self.id(), # This is being called before the wallet is created so we're using a ID of 0 + sent_to=[], + trade_id=None, + type=uint32(TransactionType.OUTGOING_TX.value), + name=mirror_bundle.name(), + valid_times=parse_timelock_info(extra_conditions), + ) ) - ] if excess_fee > 0: - [chia_tx] = await self.wallet_state_manager.main_wallet.generate_signed_transaction( + await self.wallet_state_manager.main_wallet.generate_signed_transaction( uint64(1), new_puzhash, tx_config, @@ -812,16 +804,6 @@ async def delete_mirror( fee=uint64(excess_fee), extra_conditions=(AssertCoinAnnouncement(asserted_id=mirror_coin.name(), asserted_msg=b"$"),), ) - assert txs[0].spend_bundle is not None - assert chia_tx.spend_bundle is not None - txs = [ - dataclasses.replace( - txs[0], spend_bundle=SpendBundle.aggregate([txs[0].spend_bundle, chia_tx.spend_bundle]) - ), - dataclasses.replace(chia_tx, spend_bundle=None), - ] - - return txs ########### # SYNCING # @@ -984,35 +966,30 @@ async def potentially_handle_resubmit(self, launcher_id: bytes32) -> None: # pr if not root_changed: # The root never changed so let's attempt a rebase try: - all_txs: List[TransactionRecord] = [] - for singleton in unconfirmed_singletons: - for tx in relevant_dl_txs: - if any(c.name() == singleton.coin_id for c in tx.additions): - if tx.spend_bundle is not None: - # This executes the puzzles - fee = uint64(estimate_fees(tx.spend_bundle)) - else: - fee = uint64(0) - - assert self.wallet_state_manager.wallet_node.logged_in_fingerprint is not None - - async with self.wallet_state_manager.new_action_scope(push=False) as action_scope: - all_txs.extend( - await self.create_update_state_spend( - launcher_id, - singleton.root, - TXConfigLoader().autofill( - constants=self.wallet_state_manager.constants, - config=self.wallet_state_manager.config, - logged_in_fingerprint=( - self.wallet_state_manager.wallet_node.logged_in_fingerprint - ), + async with self.wallet_state_manager.new_action_scope(push=True) as action_scope: + for singleton in unconfirmed_singletons: + for tx in relevant_dl_txs: + if any(c.name() == singleton.coin_id for c in tx.additions): + if tx.spend_bundle is not None: + # This executes the puzzles + fee = uint64(estimate_fees(tx.spend_bundle)) + else: + fee = uint64(0) + + assert self.wallet_state_manager.wallet_node.logged_in_fingerprint is not None + await self.create_update_state_spend( + launcher_id, + singleton.root, + TXConfigLoader().autofill( + constants=self.wallet_state_manager.constants, + config=self.wallet_state_manager.config, + logged_in_fingerprint=( + self.wallet_state_manager.wallet_node.logged_in_fingerprint ), - action_scope=action_scope, - fee=fee, - ) + ), + action_scope=action_scope, + fee=fee, ) - await self.wallet_state_manager.add_pending_transactions(all_txs) except Exception as e: self.log.warning(f"Something went wrong during attempted DL resubmit: {str(e)}") # Something went wrong so let's delete anything pending that was created @@ -1151,7 +1128,7 @@ async def make_update_offer( action_scope: WalletActionScope, fee: uint64 = uint64(0), extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> Tuple[Offer, List[TransactionRecord]]: + ) -> Offer: dl_wallet = None for wallet in wallet_state_manager.wallets.values(): if wallet.type() == WalletType.DATA_LAYER.value: @@ -1162,7 +1139,6 @@ async def make_update_offer( offered_launchers: List[bytes32] = [k for k, v in offer_dict.items() if v < 0 and k is not None] fee_left_to_pay: uint64 = fee - all_bundles: List[SpendBundle] = [] all_transactions: List[TransactionRecord] = [] for launcher in offered_launchers: try: @@ -1171,48 +1147,62 @@ async def make_update_offer( this_solver = solver["0x" + launcher.hex()] new_root: bytes32 = this_solver["new_root"] new_ph: bytes32 = await wallet_state_manager.main_wallet.get_puzzle_hash(new=not tx_config.reuse_puzhash) - txs: List[TransactionRecord] = await dl_wallet.generate_signed_transaction( - [uint64(1)], - [new_ph], - tx_config, - action_scope, - fee=fee_left_to_pay, - launcher_id=launcher, - new_root_hash=new_root, - add_pending_singleton=False, - announce_new_state=True, - extra_conditions=extra_conditions, - ) - fee_left_to_pay = uint64(0) - extra_conditions = tuple() + async with wallet_state_manager.new_action_scope(push=False) as inner_action_scope: + await dl_wallet.generate_signed_transaction( + [uint64(1)], + [new_ph], + tx_config, + inner_action_scope, + fee=fee_left_to_pay, + launcher_id=launcher, + new_root_hash=new_root, + add_pending_singleton=False, + announce_new_state=True, + extra_conditions=extra_conditions, + ) + fee_left_to_pay = uint64(0) + extra_conditions = tuple() + + async with inner_action_scope.use() as interface: + dl_spend: CoinSpend = next( + cs + for tx in interface.side_effects.transactions + for cs in tx.spend_bundle.coin_spends + if tx.spend_bundle is not None and match_dl_singleton(cs.puzzle_reveal)[0] + ) + dl_solution: Program = dl_spend.solution.to_program() + old_graftroot: Program = dl_solution.at("rrffrf") + new_graftroot: Program = create_graftroot_offer_puz( + [bytes32(dep["launcher_id"]) for dep in this_solver["dependencies"]], + [list(v for v in dep["values_to_prove"]) for dep in this_solver["dependencies"]], + old_graftroot, + ) - assert txs[0].spend_bundle is not None - dl_spend: CoinSpend = next( - cs for cs in txs[0].spend_bundle.coin_spends if match_dl_singleton(cs.puzzle_reveal)[0] - ) - all_other_spends: List[CoinSpend] = [cs for cs in txs[0].spend_bundle.coin_spends if cs != dl_spend] - dl_solution: Program = dl_spend.solution.to_program() - old_graftroot: Program = dl_solution.at("rrffrf") - new_graftroot: Program = create_graftroot_offer_puz( - [bytes32(dep["launcher_id"]) for dep in this_solver["dependencies"]], - [list(v for v in dep["values_to_prove"]) for dep in this_solver["dependencies"]], - old_graftroot, - ) + new_solution: Program = dl_solution.replace(rrffrf=new_graftroot, rrffrrf=Program.to([None] * 5)) + new_spend: CoinSpend = dl_spend.replace(solution=SerializedProgram.from_program(new_solution)) + async with inner_action_scope.use() as interface: + for i, tx in enumerate(interface.side_effects.transactions): + if tx.spend_bundle is not None and dl_spend in tx.spend_bundle.coin_spends: + break + else: + # No test coverage for this line because it should never be reached + raise RuntimeError("Internal logic error while constructing update offer") # pragma: no cover + new_bundle = SpendBundle( + [ + *( + cs + for cs in interface.side_effects.transactions[i].spend_bundle.coin_spends + if cs != dl_spend + ), + new_spend, + ], + G2Element(), + ) + interface.side_effects.transactions[i] = dataclasses.replace( + interface.side_effects.transactions[i], spend_bundle=new_bundle, name=new_bundle.name() + ) - new_solution: Program = dl_solution.replace(rrffrf=new_graftroot, rrffrrf=Program.to([None] * 5)) - new_spend: CoinSpend = dl_spend.replace(solution=SerializedProgram.from_program(new_solution)) - new_bundle: SpendBundle = txs[0].spend_bundle.replace( - coin_spends=[*all_other_spends, new_spend], - ) - all_bundles.append(new_bundle) - all_transactions.append( - dataclasses.replace( - txs[0], - spend_bundle=new_bundle, - name=new_bundle.name(), - ) - ) - all_transactions.extend(txs[1:]) + all_transactions.extend(inner_action_scope.side_effects.transactions) # create some dummy requested payments requested_payments = { @@ -1220,7 +1210,15 @@ async def make_update_offer( for k, v in offer_dict.items() if v > 0 } - return Offer(requested_payments, SpendBundle.aggregate(all_bundles), driver_dict), all_transactions + + async with action_scope.use() as interface: + interface.side_effects.transactions.extend(all_transactions) + + return Offer( + requested_payments, + SpendBundle.aggregate([tx.spend_bundle for tx in all_transactions if tx.spend_bundle is not None]), + driver_dict, + ) @staticmethod async def finish_graftroot_solutions(offer: Offer, solver: Solver) -> Offer: diff --git a/chia/pools/pool_wallet.py b/chia/pools/pool_wallet.py index 1d11eda4bb88..84e35fb7f3fd 100644 --- a/chia/pools/pool_wallet.py +++ b/chia/pools/pool_wallet.py @@ -42,9 +42,9 @@ from chia.types.blockchain_format.serialized_program import SerializedProgram from chia.types.blockchain_format.sized_bytes import bytes32 from chia.types.coin_spend import CoinSpend, compute_additions -from chia.types.spend_bundle import SpendBundle, estimate_fees +from chia.types.spend_bundle import SpendBundle from chia.util.ints import uint32, uint64, uint128 -from chia.wallet.conditions import AssertCoinAnnouncement, Condition, ConditionValidTimes, parse_timelock_info +from chia.wallet.conditions import AssertCoinAnnouncement, Condition, ConditionValidTimes from chia.wallet.derive_keys import find_owner_sk from chia.wallet.transaction_record import TransactionRecord from chia.wallet.util.transaction_type import TransactionType @@ -393,7 +393,7 @@ async def create_new_pool_wallet_transaction( p2_singleton_delay_time: Optional[uint64] = None, p2_singleton_delayed_ph: Optional[bytes32] = None, extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> Tuple[TransactionRecord, bytes32, bytes32]: + ) -> Tuple[bytes32, bytes32]: """ A "plot NFT", or pool wallet, represents the idea of a set of plots that all pay to the same pooling puzzle. This puzzle is a `chia singleton` that is @@ -403,7 +403,6 @@ async def create_new_pool_wallet_transaction( Call under the wallet state manager lock """ - amount = 1 standard_wallet = main_wallet if p2_singleton_delayed_ph is None: @@ -421,7 +420,7 @@ async def create_new_pool_wallet_transaction( # Verify Parameters - raise if invalid PoolWallet._verify_initial_target_state(initial_target_state) - spend_bundle, singleton_puzzle_hash, launcher_coin_id = await PoolWallet.generate_launcher_spend( + singleton_puzzle_hash, launcher_coin_id = await PoolWallet.generate_launcher_spend( standard_wallet, uint64(1), fee, @@ -434,32 +433,11 @@ async def create_new_pool_wallet_transaction( extra_conditions=extra_conditions, ) - if spend_bundle is None: - raise ValueError("failed to generate ID for wallet") - - standard_wallet_record = TransactionRecord( - confirmed_at_height=uint32(0), - created_at_time=uint64(int(time.time())), - to_puzzle_hash=singleton_puzzle_hash, - amount=uint64(amount), - fee_amount=fee, - confirmed=False, - sent=uint32(0), - spend_bundle=spend_bundle, - additions=spend_bundle.additions(), - removals=spend_bundle.removals(), - wallet_id=wallet_state_manager.main_wallet.id(), - sent_to=[], - memos=[], - trade_id=None, - type=uint32(TransactionType.OUTGOING_TX.value), - name=spend_bundle.name(), - valid_times=parse_timelock_info(extra_conditions), - ) p2_singleton_puzzle_hash: bytes32 = launcher_id_to_p2_puzzle_hash( launcher_coin_id, p2_singleton_delay_time, p2_singleton_delayed_ph ) - return standard_wallet_record, p2_singleton_puzzle_hash, launcher_coin_id + + return p2_singleton_puzzle_hash, launcher_coin_id async def _get_owner_key_cache(self) -> Tuple[PrivateKey, uint32]: if self._owner_sk_and_index is None: @@ -479,8 +457,8 @@ async def generate_fee_transaction( tx_config: TXConfig, action_scope: WalletActionScope, extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> TransactionRecord: - [fee_tx] = await self.standard_wallet.generate_signed_transaction( + ) -> None: + await self.standard_wallet.generate_signed_transaction( uint64(0), (await self.standard_wallet.get_new_puzzlehash()), tx_config, @@ -491,11 +469,10 @@ async def generate_fee_transaction( primaries=None, extra_conditions=extra_conditions, ) - return fee_tx async def generate_travel_transactions( self, fee: uint64, tx_config: TXConfig, action_scope: WalletActionScope - ) -> Tuple[TransactionRecord, Optional[TransactionRecord]]: + ) -> None: # target_state is contained within pool_wallet_state pool_wallet_info: PoolWalletInfo = await self.get_current_state() @@ -563,34 +540,31 @@ async def generate_travel_transactions( unsigned_spend_bundle = SpendBundle([outgoing_coin_spend], G2Element()) assert unsigned_spend_bundle.removals()[0].puzzle_hash == singleton.puzzle_hash assert unsigned_spend_bundle.removals()[0].name() == singleton.name() - fee_tx: Optional[TransactionRecord] = None if fee > 0: - fee_tx = await self.generate_fee_transaction(fee, tx_config, action_scope) - assert fee_tx.spend_bundle is not None - unsigned_spend_bundle = SpendBundle.aggregate([unsigned_spend_bundle, fee_tx.spend_bundle]) - fee_tx = dataclasses.replace(fee_tx, spend_bundle=None) - - tx_record = TransactionRecord( - confirmed_at_height=uint32(0), - created_at_time=uint64(int(time.time())), - to_puzzle_hash=new_full_puzzle.get_tree_hash(), - amount=uint64(1), - fee_amount=fee, - confirmed=False, - sent=uint32(0), - spend_bundle=unsigned_spend_bundle, - additions=unsigned_spend_bundle.additions(), - removals=unsigned_spend_bundle.removals(), - wallet_id=self.id(), - sent_to=[], - trade_id=None, - memos=[], - type=uint32(TransactionType.OUTGOING_TX.value), - name=unsigned_spend_bundle.name(), - valid_times=ConditionValidTimes(), - ) - - return tx_record, fee_tx + await self.generate_fee_transaction(fee, tx_config, action_scope) + + async with action_scope.use() as interface: + interface.side_effects.transactions.append( + TransactionRecord( + confirmed_at_height=uint32(0), + created_at_time=uint64(int(time.time())), + to_puzzle_hash=new_full_puzzle.get_tree_hash(), + amount=uint64(1), + fee_amount=fee, + confirmed=False, + sent=uint32(0), + spend_bundle=unsigned_spend_bundle, + additions=unsigned_spend_bundle.additions(), + removals=unsigned_spend_bundle.removals(), + wallet_id=self.id(), + sent_to=[], + trade_id=None, + memos=[], + type=uint32(TransactionType.OUTGOING_TX.value), + name=unsigned_spend_bundle.name(), + valid_times=ConditionValidTimes(), + ) + ) @staticmethod async def generate_launcher_spend( @@ -604,7 +578,7 @@ async def generate_launcher_spend( tx_config: TXConfig, action_scope: WalletActionScope, extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> Tuple[SpendBundle, bytes32, bytes32]: + ) -> Tuple[bytes32, bytes32]: """ Creates the initial singleton, which includes spending an origin coin, the launcher, and creating a singleton with the "pooling" inner state, which can be either self pooling or using a pool @@ -650,7 +624,16 @@ async def generate_launcher_spend( pool_state_bytes = Program.to([("p", bytes(initial_target_state)), ("t", delay_time), ("h", delay_ph)]) announcement_message = Program.to([puzzle_hash, amount, pool_state_bytes]).get_tree_hash() - [create_launcher_tx_record] = await standard_wallet.generate_signed_transaction( + genesis_launcher_solution: Program = Program.to([puzzle_hash, amount, pool_state_bytes]) + + launcher_cs: CoinSpend = CoinSpend( + launcher_coin, + SerializedProgram.from_program(genesis_launcher_puz), + SerializedProgram.from_program(genesis_launcher_solution), + ) + launcher_sb: SpendBundle = SpendBundle([launcher_cs], G2Element()) + + await standard_wallet.generate_signed_transaction( amount, genesis_launcher_puz.get_tree_hash(), tx_config, @@ -664,24 +647,15 @@ async def generate_launcher_spend( AssertCoinAnnouncement(asserted_id=launcher_coin.name(), asserted_msg=announcement_message), ), ) - assert create_launcher_tx_record.spend_bundle is not None - genesis_launcher_solution: Program = Program.to([puzzle_hash, amount, pool_state_bytes]) - - launcher_cs: CoinSpend = CoinSpend( - launcher_coin, - SerializedProgram.from_program(genesis_launcher_puz), - SerializedProgram.from_program(genesis_launcher_solution), - ) - launcher_sb: SpendBundle = SpendBundle([launcher_cs], G2Element()) + async with action_scope.use() as interface: + interface.side_effects.extra_spends.append(launcher_sb) - # Current inner will be updated when state is verified on the blockchain - full_spend: SpendBundle = SpendBundle.aggregate([create_launcher_tx_record.spend_bundle, launcher_sb]) - return full_spend, puzzle_hash, launcher_coin.name() + return puzzle_hash, launcher_coin.name() async def join_pool( self, target_state: PoolState, fee: uint64, tx_config: TXConfig, action_scope: WalletActionScope - ) -> Tuple[uint64, TransactionRecord, Optional[TransactionRecord]]: + ) -> uint64: if target_state.state != FARMING_TO_POOL.value: raise ValueError(f"join_pool must be called with target_state={FARMING_TO_POOL} (FARMING_TO_POOL)") if self.target_state is not None: @@ -723,12 +697,10 @@ async def join_pool( self.target_state = target_state self.next_transaction_fee = fee self.next_tx_config = tx_config - travel_tx, fee_tx = await self.generate_travel_transactions(fee, tx_config, action_scope) - return total_fee, travel_tx, fee_tx + await self.generate_travel_transactions(fee, tx_config, action_scope) + return total_fee - async def self_pool( - self, fee: uint64, tx_config: TXConfig, action_scope: WalletActionScope - ) -> Tuple[uint64, TransactionRecord, Optional[TransactionRecord]]: + async def self_pool(self, fee: uint64, tx_config: TXConfig, action_scope: WalletActionScope) -> uint64: if await self.have_unconfirmed_transaction(): raise ValueError( "Cannot self pool due to unconfirmed transaction. If this is stuck, delete the unconfirmed transaction." @@ -763,12 +735,12 @@ async def self_pool( ) self.next_transaction_fee = fee self.next_tx_config = tx_config - travel_tx, fee_tx = await self.generate_travel_transactions(fee, tx_config, action_scope) - return total_fee, travel_tx, fee_tx + await self.generate_travel_transactions(fee, tx_config, action_scope) + return total_fee async def claim_pool_rewards( self, fee: uint64, max_spends_in_tx: Optional[int], tx_config: TXConfig, action_scope: WalletActionScope - ) -> Tuple[TransactionRecord, Optional[TransactionRecord]]: + ) -> None: # Search for p2_puzzle_hash coins, and spend them with the singleton if await self.have_unconfirmed_transaction(): raise ValueError( @@ -837,11 +809,8 @@ async def claim_pool_rewards( claim_spend: SpendBundle = SpendBundle(all_spends, G2Element()) # If fee is 0, no signatures are required to absorb - full_spend: SpendBundle = claim_spend - - fee_tx = None if fee > 0: - fee_tx = await self.generate_fee_transaction( + await self.generate_fee_transaction( fee, tx_config, action_scope, @@ -849,34 +818,31 @@ async def claim_pool_rewards( AssertCoinAnnouncement(asserted_id=first_coin_record.coin.name(), asserted_msg=b"$"), ), ) - assert fee_tx.spend_bundle is not None - full_spend = SpendBundle.aggregate([fee_tx.spend_bundle, claim_spend]) - fee_tx = dataclasses.replace(fee_tx, spend_bundle=None) - assert estimate_fees(full_spend) == fee current_time = uint64(int(time.time())) # The claim spend, minus the fee amount from the main wallet - absorb_transaction: TransactionRecord = TransactionRecord( - confirmed_at_height=uint32(0), - created_at_time=current_time, - to_puzzle_hash=current_state.current.target_puzzle_hash, - amount=uint64(total_amount), - fee_amount=fee, # This will not be double counted in self.standard_wallet - confirmed=False, - sent=uint32(0), - spend_bundle=full_spend, - additions=full_spend.additions(), - removals=full_spend.removals(), - wallet_id=uint32(self.wallet_id), - sent_to=[], - memos=[], - trade_id=None, - type=uint32(TransactionType.OUTGOING_TX.value), - name=full_spend.name(), - valid_times=ConditionValidTimes(), - ) - - return absorb_transaction, fee_tx + async with action_scope.use() as interface: + interface.side_effects.transactions.append( + TransactionRecord( + confirmed_at_height=uint32(0), + created_at_time=current_time, + to_puzzle_hash=current_state.current.target_puzzle_hash, + amount=uint64(total_amount), + fee_amount=fee, # This will not be double counted in self.standard_wallet + confirmed=False, + sent=uint32(0), + spend_bundle=claim_spend, + additions=claim_spend.additions(), + removals=claim_spend.removals(), + wallet_id=uint32(self.wallet_id), + sent_to=[], + memos=[], + trade_id=None, + type=uint32(TransactionType.OUTGOING_TX.value), + name=claim_spend.name(), + valid_times=ConditionValidTimes(), + ) + ) async def new_peak(self, peak_height: uint32) -> None: # This gets called from the WalletStateManager whenever there is a new peak @@ -920,14 +886,10 @@ async def new_peak(self, peak_height: uint32) -> None: assert self.target_state.relative_lock_height >= self.MINIMUM_RELATIVE_LOCK_HEIGHT assert self.target_state.pool_url is not None - async with self.wallet_state_manager.new_action_scope(push=False) as action_scope: - travel_tx, fee_tx = await self.generate_travel_transactions( + async with self.wallet_state_manager.new_action_scope(push=True) as action_scope: + await self.generate_travel_transactions( self.next_transaction_fee, self.next_tx_config, action_scope ) - txs = [travel_tx] - if fee_tx is not None: - txs.append(fee_tx) - await self.wallet_state_manager.add_pending_transactions(txs) async def have_unconfirmed_transaction(self) -> bool: unconfirmed: List[TransactionRecord] = await self.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( diff --git a/chia/rpc/util.py b/chia/rpc/util.py index 7e682fb787b7..924a12bc830b 100644 --- a/chia/rpc/util.py +++ b/chia/rpc/util.py @@ -152,7 +152,11 @@ async def rpc_endpoint(self, request: Dict[str, Any], *args, **kwargs) -> Dict[s ): raise ValueError("Relative timelocks are not currently supported in the RPC") - async with self.service.wallet_state_manager.new_action_scope(push=False) as action_scope: + async with self.service.wallet_state_manager.new_action_scope( + push=request.get("push", push), + merge_spends=request.get("merge_spends", merge_spends), + sign=request.get("sign", self.service.config.get("auto_sign_txs", True)), + ) as action_scope: response: Dict[str, Any] = await func( self, request, @@ -168,10 +172,9 @@ async def rpc_endpoint(self, request: Dict[str, Any], *args, **kwargs) -> Dict[s # unfortunately, this API isn't solely a tx endpoint return response - tx_records: List[TransactionRecord] = [ - TransactionRecord.from_json_dict_convenience(tx) for tx in response["transactions"] - ] - unsigned_txs = await self.service.wallet_state_manager.gather_signing_info_for_txs(tx_records) + unsigned_txs = await self.service.wallet_state_manager.gather_signing_info_for_txs( + action_scope.side_effects.transactions + ) if request.get("CHIP-0029", False): response["unsigned_transactions"] = [ @@ -186,39 +189,16 @@ async def rpc_endpoint(self, request: Dict[str, Any], *args, **kwargs) -> Dict[s else: response["unsigned_transactions"] = [tx.to_json_dict() for tx in unsigned_txs] - new_txs: List[TransactionRecord] = [] - if request.get("sign", self.service.config.get("auto_sign_txs", True)): - new_txs, signing_responses = await self.service.wallet_state_manager.sign_transactions( - tx_records, response.get("signing_responses", []), "signing_responses" in response - ) - if request.get("CHIP-0029", False): - response["signing_responses"] = [ - json_serialize_with_clvm_streamable( - sr, - translation_layer=( - ALL_TRANSLATION_LAYERS[request["translation"]] if "translation" in request else None - ), - ) - for sr in signing_responses - ] - else: - response["signing_responses"] = [sr.to_json_dict() for sr in signing_responses] - else: - new_txs = tx_records # pragma: no cover - - if request.get("push", push): - new_txs = await self.service.wallet_state_manager.add_pending_transactions( - new_txs, merge_spends=merge_spends, sign=False - ) - response["transactions"] = [ - TransactionRecord.to_json_dict_convenience(tx, self.service.config) for tx in new_txs + TransactionRecord.to_json_dict_convenience(tx, self.service.config) + for tx in action_scope.side_effects.transactions ] # Some backwards compatibility code here because transaction information being returned was not uniform # until the "transactions" key was applied to all of them. Unfortunately, since .add_pending_transactions # now applies transformations to the transactions, we have to special case edit all of the previous # spots where the information was being surfaced outside of the knowledge of this wrapper. + new_txs = action_scope.side_effects.transactions if "transaction" in response: if ( func.__name__ == "create_new_wallet" @@ -228,14 +208,18 @@ async def rpc_endpoint(self, request: Dict[str, Any], *args, **kwargs) -> Dict[s or func.__name__ == "pw_absorb_rewards" ): # Theses RPCs return not "convenience" for some reason - response["transaction"] = new_txs[0].to_json_dict() + response["transaction"] = new_txs[-1].to_json_dict() else: response["transaction"] = response["transactions"][0] if "tx_record" in response: response["tx_record"] = response["transactions"][0] - if "fee_transaction" in response and response["fee_transaction"] is not None: + if "fee_transaction" in response: # Theses RPCs return not "convenience" for some reason - response["fee_transaction"] = new_txs[1].to_json_dict() + fee_transactions = [tx for tx in new_txs if tx.wallet_id == 1] + if len(fee_transactions) == 0: + response["fee_transaction"] = None + else: + response["fee_transaction"] = fee_transactions[0].to_json_dict() if "transaction_id" in response: response["transaction_id"] = new_txs[0].name if "transaction_ids" in response: diff --git a/chia/rpc/wallet_rpc_api.py b/chia/rpc/wallet_rpc_api.py index 3939d4c52f16..b03f37b996eb 100644 --- a/chia/rpc/wallet_rpc_api.py +++ b/chia/rpc/wallet_rpc_api.py @@ -718,7 +718,7 @@ async def create_new_wallet( if not push: raise ValueError("Test CAT minting must be pushed automatically") # pragma: no cover async with self.service.wallet_state_manager.lock: - cat_wallet, txs = await CATWallet.create_new_cat_wallet( + cat_wallet = await CATWallet.create_new_cat_wallet( wallet_state_manager, main_wallet, {"identifier": "genesis_by_id"}, @@ -734,7 +734,7 @@ async def create_new_wallet( "type": cat_wallet.type(), "asset_id": asset_id, "wallet_id": cat_wallet.id(), - "transactions": [tx.to_json_dict_convenience(self.service.config) for tx in txs], + "transactions": None, # tx_endpoint wrapper will take care of this } else: raise ValueError( @@ -800,6 +800,7 @@ async def create_new_wallet( "type": did_wallet.type(), "my_did": my_did_id, "wallet_id": did_wallet.id(), + "transactions": None, # tx_endpoint wrapper will take care of this } elif request["did_type"] == "recovery": @@ -839,7 +840,7 @@ async def create_new_wallet( else: raise ValueError("DAO rules must be specified for wallet creation") async with self.service.wallet_state_manager.lock: - dao_wallet, txs = await DAOWallet.create_new_dao_and_wallet( + dao_wallet = await DAOWallet.create_new_dao_and_wallet( wallet_state_manager, main_wallet, uint64(request.get("amount_of_cats", None)), @@ -870,9 +871,7 @@ async def create_new_wallet( "treasury_id": dao_wallet.dao_info.treasury_id, "cat_wallet_id": dao_wallet.dao_info.cat_wallet_id, "dao_cat_wallet_id": dao_wallet.dao_info.dao_cat_wallet_id, - "transactions": ( - [tx.to_json_dict_convenience(self.service.config) for tx in txs] if mode == "new" else [] - ), + "transactions": None, # tx_endpoint wrapper will take care of this } elif request["wallet_type"] == "nft_wallet": for wallet in self.service.wallet_state_manager.wallets.values(): @@ -938,7 +937,7 @@ async def create_new_wallet( if "p2_singleton_delayed_ph" in request: delayed_address = bytes32.from_hexstr(request["p2_singleton_delayed_ph"]) - tr, p2_singleton_puzzle_hash, launcher_id = await PoolWallet.create_new_pool_wallet_transaction( + p2_singleton_puzzle_hash, launcher_id = await PoolWallet.create_new_pool_wallet_transaction( wallet_state_manager, main_wallet, initial_target_state, @@ -954,8 +953,8 @@ async def create_new_wallet( raise ValueError(str(e)) return { "total_fee": fee * 2, - "transaction": tr, - "transactions": [tr.to_json_dict_convenience(self.service.config)], + "transaction": None, # tx_endpoint wrapper will take care of this + "transactions": None, # tx_endpoint wrapper will take care of this "launcher_id": launcher_id.hex(), "p2_singleton_puzzle_hash": p2_singleton_puzzle_hash.hex(), } @@ -1171,7 +1170,7 @@ async def send_transaction( fee: uint64 = uint64(request.get("fee", 0)) async with self.service.wallet_state_manager.lock: - [tx] = await wallet.generate_signed_transaction( + await wallet.generate_signed_transaction( amount, puzzle_hash, tx_config, @@ -1183,11 +1182,10 @@ async def send_transaction( ) # Transaction may not have been included in the mempool yet. Use get_transaction to check. - json_tx = tx.to_json_dict_convenience(self.service.config) return { - "transaction": json_tx, - "transactions": [json_tx], - "transaction_id": tx.name, + "transaction": None, # tx_endpoint wrapper will take care of this + "transactions": None, # tx_endpoint wrapper will take care of this + "transaction_id": None, # tx_endpoint wrapper will take care of this } async def send_transaction_multi(self, request: Dict[str, Any]) -> EndpointResult: @@ -1251,14 +1249,13 @@ async def spend_clawback_coins( batch_size = request.get( "batch_size", self.service.wallet_state_manager.config.get("auto_claim", {}).get("batch_size", 50) ) - tx_list: List[TransactionRecord] = [] for coin_id, coin_record in coin_records.coin_id_to_record.items(): try: metadata = coin_record.parsed_metadata() assert isinstance(metadata, ClawbackMetadata) coins[coin_record.coin] = metadata if len(coins) >= batch_size: - new_txs = await self.service.wallet_state_manager.spend_clawback_coins( + await self.service.wallet_state_manager.spend_clawback_coins( coins, tx_fee, tx_config, @@ -1266,33 +1263,31 @@ async def spend_clawback_coins( request.get("force", False), extra_conditions=extra_conditions, ) - tx_list.extend(new_txs) - tx_config = dataclasses.replace( - tx_config, - excluded_coin_ids=[ - *tx_config.excluded_coin_ids, - *(c.name() for tx in new_txs for c in tx.removals), - ], - ) + async with action_scope.use() as interface: + tx_config = dataclasses.replace( + tx_config, + excluded_coin_ids=[ + *tx_config.excluded_coin_ids, + *(c.name() for tx in interface.side_effects.transactions for c in tx.removals), + ], + ) coins = {} except Exception as e: log.error(f"Failed to spend clawback coin {coin_id.hex()}: %s", e) if len(coins) > 0: - tx_list.extend( - await self.service.wallet_state_manager.spend_clawback_coins( - coins, - tx_fee, - tx_config, - action_scope, - request.get("force", False), - extra_conditions=extra_conditions, - ) + await self.service.wallet_state_manager.spend_clawback_coins( + coins, + tx_fee, + tx_config, + action_scope, + request.get("force", False), + extra_conditions=extra_conditions, ) return { "success": True, - "transaction_ids": [tx.name.hex() for tx in tx_list if tx.type == TransactionType.OUTGOING_CLAWBACK.value], - "transactions": [tx.to_json_dict_convenience(self.service.config) for tx in tx_list], + "transaction_ids": None, # tx_endpoint wrapper will take care of this + "transactions": None, # tx_endpoint wrapper will take care of this } async def delete_unconfirmed_transactions(self, request: Dict[str, Any]) -> EndpointResult: @@ -1534,7 +1529,7 @@ async def send_notification( tx_config: TXConfig = DEFAULT_TX_CONFIG, extra_conditions: Tuple[Condition, ...] = tuple(), ) -> EndpointResult: - tx: TransactionRecord = await self.service.wallet_state_manager.notification_manager.send_new_notification( + await self.service.wallet_state_manager.notification_manager.send_new_notification( bytes32.from_hexstr(request["target"]), bytes.fromhex(request["message"]), uint64(request["amount"]), @@ -1544,8 +1539,7 @@ async def send_notification( extra_conditions=extra_conditions, ) - json_tx = tx.to_json_dict_convenience(self.service.config) - return {"tx": json_tx, "transactions": [json_tx]} + return {"tx": None, "transactions": None} # tx_endpoint wrapper will take care of this async def verify_signature(self, request: Dict[str, Any]) -> EndpointResult: """ @@ -1785,7 +1779,7 @@ async def cat_spend( ) if hold_lock: async with self.service.wallet_state_manager.lock: - txs: List[TransactionRecord] = await wallet.generate_signed_transaction( + await wallet.generate_signed_transaction( amounts, puzzle_hashes, tx_config, @@ -1797,7 +1791,7 @@ async def cat_spend( extra_conditions=extra_conditions, ) else: - txs = await wallet.generate_signed_transaction( + await wallet.generate_signed_transaction( amounts, puzzle_hashes, tx_config, @@ -1809,12 +1803,10 @@ async def cat_spend( extra_conditions=extra_conditions, ) - # Return the first transaction, which is expected to be the CAT spend. If a fee is - # included, it is currently ordered after the CAT spend. return { - "transaction": txs[0].to_json_dict_convenience(self.service.config), - "transactions": [tx.to_json_dict_convenience(self.service.config) for tx in txs], - "transaction_id": txs[0].name, + "transaction": None, # tx_endpoint wrapper will take care of this + "transactions": None, # tx_endpoint wrapper will take care of this + "transaction_id": None, # tx_endpoint wrapper will take care of this } async def cat_get_asset_id(self, request: Dict[str, Any]) -> EndpointResult: @@ -1890,11 +1882,11 @@ async def create_offer_for_ids( extra_conditions=extra_conditions, ) if result[0]: - success, trade_record, tx_records, error = result + success, trade_record, error = result return { "offer": Offer.from_bytes(trade_record.offer).to_bech32(), "trade_record": trade_record.to_json_dict_convenience(), - "transactions": [tx.to_json_dict_convenience(self.service.config) for tx in tx_records], + "transactions": None, # tx_endpoint wrapper will take care of this } raise ValueError(result[2]) @@ -2044,23 +2036,27 @@ async def take_offer( else: solver = Solver(info=maybe_marshalled_solver) - async with self.service.wallet_state_manager.new_action_scope(push=False) as action_scope: - peer = self.service.get_full_node_peer() - trade_record, tx_records = await self.service.wallet_state_manager.trade_manager.respond_to_offer( - offer, - peer, - tx_config, - action_scope, - fee=fee, - solver=solver, - extra_conditions=extra_conditions, + peer = self.service.get_full_node_peer() + trade_record = await self.service.wallet_state_manager.trade_manager.respond_to_offer( + offer, + peer, + tx_config, + action_scope, + fee=fee, + solver=solver, + extra_conditions=extra_conditions, + ) + + async with action_scope.use() as interface: + interface.side_effects.signing_responses.append( + SigningResponse(bytes(offer._bundle.aggregated_signature), trade_record.trade_id) ) return { "trade_record": trade_record.to_json_dict_convenience(), "offer": Offer.from_bytes(trade_record.offer).to_bech32(), - "transactions": [tx.to_json_dict_convenience(self.service.config) for tx in tx_records], - "signing_responses": [SigningResponse(bytes(offer._bundle.aggregated_signature), trade_record.trade_id)], + "transactions": None, # tx_endpoint wrapper will take care of this + "signing_responses": None, # tx_endpoint wrapper will take care of this } async def get_offer(self, request: Dict[str, Any]) -> EndpointResult: @@ -2127,11 +2123,11 @@ async def cancel_offer( trade_id = bytes32.from_hexstr(request["trade_id"]) fee: uint64 = uint64(request.get("fee", 0)) async with self.service.wallet_state_manager.lock: - txs = await wsm.trade_manager.cancel_pending_offers( + await wsm.trade_manager.cancel_pending_offers( [bytes32(trade_id)], tx_config, action_scope, fee=fee, secure=secure, extra_conditions=extra_conditions ) - return {"transactions": [tx.to_json_dict_convenience(self.service.config) for tx in txs]} + return {"transactions": None} # tx_endpoint wrapper will take care of this @tx_endpoint(push=True, merge_spends=False) async def cancel_offers( @@ -2150,8 +2146,6 @@ async def cancel_offers( else: asset_id = request.get("asset_id", "xch") - all_txs: List[TransactionRecord] = [] - start: int = 0 end: int = start + batch_size trade_mgr = self.service.wallet_state_manager.trade_manager @@ -2184,16 +2178,14 @@ async def cancel_offers( break async with self.service.wallet_state_manager.lock: - all_txs.extend( - await trade_mgr.cancel_pending_offers( - list(records.keys()), - tx_config, - action_scope, - batch_fee, - secure, - records, - extra_conditions=extra_conditions, - ) + await trade_mgr.cancel_pending_offers( + list(records.keys()), + tx_config, + action_scope, + batch_fee, + secure, + records, + extra_conditions=extra_conditions, ) log.info(f"Cancelled offers {start} to {end} ...") @@ -2203,7 +2195,7 @@ async def cancel_offers( start = end end += batch_size - return {"success": True, "transactions": [tx.to_json_dict_convenience(self.service.config) for tx in all_txs]} + return {"transactions": None} # tx_endpoint wrapper will take care of this ########################################################################################## # Distributed Identities @@ -2242,12 +2234,12 @@ async def did_update_recovery_ids( update_success = await wallet.update_recovery_list(recovery_list, new_amount_verifications_required) # Update coin with new ID info if update_success: - txs = await wallet.create_update_spend( + await wallet.create_update_spend( tx_config, action_scope, fee=uint64(request.get("fee", 0)), extra_conditions=extra_conditions ) return { "success": True, - "transactions": [tx.to_json_dict_convenience(self.service.config) for tx in txs], + "transactions": None, # tx_endpoint wrapper will take care of this } else: return {"success": False, "transactions": []} # pragma: no cover @@ -2263,7 +2255,7 @@ async def did_message_spend( wallet_id = uint32(request["wallet_id"]) wallet = self.service.wallet_state_manager.get_wallet(id=wallet_id, required_type=DIDWallet) - tx = await wallet.create_message_spend( + await wallet.create_message_spend( tx_config, action_scope, extra_conditions=( @@ -2274,8 +2266,8 @@ async def did_message_spend( ) return { "success": True, - "spend_bundle": tx.spend_bundle, - "transactions": [tx.to_json_dict_convenience(self.service.config)], + "spend_bundle": None, # tx_endpoint wrapper will take care of this + "transactions": None, # tx_endpoint wrapper will take care of this } async def did_get_info(self, request: Dict[str, Any]) -> EndpointResult: @@ -2535,16 +2527,14 @@ async def did_update_metadata( update_success = await wallet.update_metadata(metadata) # Update coin with new ID info if update_success: - txs = await wallet.create_update_spend( + await wallet.create_update_spend( tx_config, action_scope, uint64(request.get("fee", 0)), extra_conditions=extra_conditions ) return { "wallet_id": wallet_id, "success": True, - "spend_bundle": SpendBundle.aggregate( - [tx.spend_bundle for tx in txs if tx.spend_bundle is not None] - ), - "transactions": [tx.to_json_dict_convenience(self.service.config) for tx in txs], + "spend_bundle": None, # tx_endpoint wrapper will take care of this + "transactions": None, # tx_endpoint wrapper will take care of this } else: return {"success": False, "error": f"Couldn't update metadata with input: {metadata}"} @@ -2591,7 +2581,6 @@ async def did_recovery_spend(self, request: Dict[str, Any]) -> EndpointResult: wallet = self.service.wallet_state_manager.get_wallet(id=wallet_id, required_type=DIDWallet) if len(request["attest_data"]) < wallet.did_info.num_of_backup_ids_needed: return {"success": False, "reason": "insufficient messages"} - spend_bundle = None async with self.service.wallet_state_manager.lock: ( info_list, @@ -2611,25 +2600,23 @@ async def did_recovery_spend(self, request: Dict[str, Any]) -> EndpointResult: puzhash = wallet.did_info.temp_puzhash assert wallet.did_info.temp_coin is not None - tx = ( + async with self.service.wallet_state_manager.new_action_scope( + push=request.get("push", True) + ) as action_scope: await wallet.recovery_spend( wallet.did_info.temp_coin, puzhash, info_list, pubkey, message_spend_bundle, + action_scope, ) - )[0] - if request.get("push", True): - await self.service.wallet_state_manager.add_pending_transactions([tx]) - if spend_bundle: - return { - "success": True, - "spend_bundle": tx.spend_bundle, - "transactions": [tx.to_json_dict_convenience(self.service.config)], - } - else: - return {"success": False} + [tx] = action_scope.side_effects.transactions + return { + "success": True, + "spend_bundle": tx.spend_bundle, + "transactions": [tx.to_json_dict_convenience(self.service.config)], + } async def did_get_pubkey(self, request: Dict[str, Any]) -> EndpointResult: wallet_id = uint32(request["wallet_id"]) @@ -2652,7 +2639,7 @@ async def did_create_attest( info = await wallet.get_info_for_recovery() coin = bytes32.from_hexstr(request["coin_name"]) pubkey = G1Element.from_bytes(hexstr_to_bytes(request["pubkey"])) - tx, message_spend_bundle, attest_data = await wallet.create_attestment( + message_spend_bundle, attest_data = await wallet.create_attestment( coin, bytes32.from_hexstr(request["puzhash"]), pubkey, @@ -2661,13 +2648,12 @@ async def did_create_attest( extra_conditions=extra_conditions, ) if info is not None: - assert tx.spend_bundle is not None return { "success": True, "message_spend_bundle": bytes(message_spend_bundle).hex(), "info": [info[0].hex(), info[1].hex(), info[2]], "attest_data": attest_data, - "transactions": [tx.to_json_dict_convenience(self.service.config)], + "transactions": None, # tx_endpoint wrapper will take care of this } else: return {"success": False} @@ -2728,7 +2714,7 @@ async def did_transfer_did( did_wallet = self.service.wallet_state_manager.get_wallet(id=wallet_id, required_type=DIDWallet) puzzle_hash: bytes32 = decode_puzzle_hash(request["inner_address"]) async with self.service.wallet_state_manager.lock: - txs: List[TransactionRecord] = await did_wallet.transfer_did( + await did_wallet.transfer_did( puzzle_hash, uint64(request.get("fee", 0)), request.get("with_recovery_info", True), @@ -2739,9 +2725,9 @@ async def did_transfer_did( return { "success": True, - "transaction": txs[0].to_json_dict_convenience(self.service.config), - "transactions": [tx.to_json_dict_convenience(self.service.config) for tx in txs], - "transaction_id": txs[0].name, + "transaction": None, # tx_endpoint wrapper will take care of this + "transactions": None, # tx_endpoint wrapper will take care of this + "transaction_id": None, # tx_endpoint wrapper will take care of this } ########################################################################################## @@ -2773,7 +2759,7 @@ async def dao_add_funds_to_treasury( assert amount if wallet_type not in [WalletType.STANDARD_WALLET, WalletType.CAT]: # pragma: no cover raise ValueError(f"Cannot fund a treasury with assets from a {wallet_type.name} wallet") - funding_tx = await dao_wallet.create_add_funds_to_treasury_spend( + await dao_wallet.create_add_funds_to_treasury_spend( uint64(amount), tx_config, action_scope, @@ -2783,9 +2769,9 @@ async def dao_add_funds_to_treasury( ) return { "success": True, - "tx_id": funding_tx.name, - "tx": funding_tx, - "transactions": [funding_tx.to_json_dict_convenience(self.service.config)], + "tx_id": None, # tx_endpoint wrapper will take care of this + "tx": None, # tx_endpoint wrapper will take care of this + "transactions": None, # tx_endpoint wrapper will take care of this } async def dao_get_treasury_balance(self, request: Dict[str, Any]) -> EndpointResult: @@ -2831,7 +2817,7 @@ async def dao_send_to_lockup( ) amount = uint64(request["amount"]) fee = uint64(request.get("fee", 0)) - txs = await dao_cat_wallet.enter_dao_cat_voting_mode( + await dao_cat_wallet.enter_dao_cat_voting_mode( amount, tx_config, action_scope, @@ -2840,9 +2826,9 @@ async def dao_send_to_lockup( ) return { "success": True, - "tx_id": txs[0].name, - "txs": txs, - "transactions": [tx.to_json_dict_convenience(self.service.config) for tx in txs], + "tx_id": None, + "txs": None, + "transactions": None, # tx_endpoint wrapper will take care of this } async def dao_get_proposals(self, request: Dict[str, Any]) -> EndpointResult: @@ -2897,7 +2883,7 @@ async def dao_exit_lockup( fee = uint64(request.get("fee", 0)) if not coins: # pragma: no cover raise ValueError("There are not coins available to exit lockup") - [exit_tx] = await dao_cat_wallet.exit_vote_state( + await dao_cat_wallet.exit_vote_state( coins, tx_config, action_scope, @@ -2906,9 +2892,9 @@ async def dao_exit_lockup( ) return { "success": True, - "tx_id": exit_tx.name, - "tx": exit_tx, - "transactions": [exit_tx.to_json_dict_convenience(self.service.config)], + "tx_id": None, # tx_endpoint wrapper will take care of this + "tx": None, # tx_endpoint wrapper will take care of this + "transactions": None, # tx_endpoint wrapper will take care of this } @tx_endpoint(push=True) @@ -2983,7 +2969,7 @@ async def dao_create_proposal( vote_amount = request.get("vote_amount") fee = uint64(request.get("fee", 0)) - [proposal_tx] = await dao_wallet.generate_new_proposal( + await dao_wallet.generate_new_proposal( proposed_puzzle, tx_config, action_scope, @@ -2991,20 +2977,24 @@ async def dao_create_proposal( fee=fee, extra_conditions=extra_conditions, ) - assert proposal_tx is not None - assert isinstance(proposal_tx.removals, List) - for coin in proposal_tx.removals: - if coin.puzzle_hash == SINGLETON_LAUNCHER_PUZZLE_HASH: - proposal_id = coin.name() - break - else: # pragma: no cover - raise ValueError("Could not find proposal ID in transaction") + async with action_scope.use() as interface: + found: bool = False + for tx in interface.side_effects.transactions: + for coin in tx.removals: + if coin.puzzle_hash == SINGLETON_LAUNCHER_PUZZLE_HASH: + proposal_id = coin.name() + found = True + if found: + break + else: # pragma: no cover + raise ValueError("Could not find proposal ID in transaction") return { "success": True, - "proposal_id": proposal_id, - "tx_id": proposal_tx.name.hex(), - "tx": proposal_tx, - "transactions": [proposal_tx.to_json_dict_convenience(self.service.config)], + # Semantics guarantee proposal_id here + "proposal_id": proposal_id, # pylint: disable=possibly-used-before-assignment + "tx_id": None, # tx_endpoint wrapper will take care of this + "tx": None, # tx_endpoint wrapper will take care of this + "transactions": None, # tx_endpoint wrapper will take care of this } @tx_endpoint(push=True) @@ -3022,7 +3012,7 @@ async def dao_vote_on_proposal( if "vote_amount" in request: vote_amount = uint64(request["vote_amount"]) fee = uint64(request.get("fee", 0)) - [vote_tx] = await dao_wallet.generate_proposal_vote_spend( + await dao_wallet.generate_proposal_vote_spend( bytes32.from_hexstr(request["proposal_id"]), vote_amount, request["is_yes_vote"], # bool @@ -3031,12 +3021,11 @@ async def dao_vote_on_proposal( fee, extra_conditions=extra_conditions, ) - assert vote_tx is not None return { "success": True, - "tx_id": vote_tx.name, - "tx": vote_tx, - "transactions": [vote_tx.to_json_dict_convenience(self.service.config)], + "tx_id": None, # tx_endpoint wrapper will take care of this + "tx": None, # tx_endpoint wrapper will take care of this + "transactions": None, # tx_endpoint wrapper will take care of this } async def dao_parse_proposal(self, request: Dict[str, Any]) -> EndpointResult: @@ -3065,7 +3054,7 @@ async def dao_close_proposal( else: genesis_id = None self_destruct = request.get("self_destruct", None) - tx = await dao_wallet.create_proposal_close_spend( + await dao_wallet.create_proposal_close_spend( bytes32.from_hexstr(request["proposal_id"]), tx_config, action_scope, @@ -3074,12 +3063,11 @@ async def dao_close_proposal( self_destruct=self_destruct, extra_conditions=extra_conditions, ) - assert tx is not None return { "success": True, - "tx_id": tx.name, - "tx": tx, - "transactions": [tx.to_json_dict_convenience(self.service.config)], + "tx_id": None, # tx_endpoint wrapper will take care of this + "tx": None, # tx_endpoint wrapper will take care of this + "transactions": None, # tx_endpoint wrapper will take care of this } @tx_endpoint(push=True) @@ -3094,19 +3082,18 @@ async def dao_free_coins_from_finished_proposals( fee = uint64(request.get("fee", 0)) dao_wallet = self.service.wallet_state_manager.get_wallet(id=wallet_id, required_type=DAOWallet) assert dao_wallet is not None - tx = await dao_wallet.free_coins_from_finished_proposals( + await dao_wallet.free_coins_from_finished_proposals( tx_config, action_scope, fee=fee, extra_conditions=extra_conditions, ) - assert tx is not None return { "success": True, - "tx_id": tx.name, - "tx": tx, - "transactions": [tx.to_json_dict_convenience(self.service.config)], + "tx_id": None, # tx_endpoint wrapper will take care of this + "tx": None, # tx_endpoint wrapper will take care of this + "transactions": None, # tx_endpoint wrapper will take care of this } ########################################################################################## @@ -3170,7 +3157,7 @@ async def nft_mint_nft( else: did_id = decode_puzzle_hash(did_id) - txs = await nft_wallet.generate_new_nft( + nft_id = await nft_wallet.generate_new_nft( metadata, tx_config, action_scope, @@ -3181,17 +3168,13 @@ async def nft_mint_nft( fee, extra_conditions=extra_conditions, ) - nft_id = None - spend_bundle = SpendBundle.aggregate([tx.spend_bundle for tx in txs if tx.spend_bundle is not None]) - for cs in spend_bundle.coin_spends: - if cs.coin.puzzle_hash == nft_puzzles.LAUNCHER_PUZZLE_HASH: - nft_id = encode_puzzle_hash(cs.coin.name(), AddressType.NFT.hrp(self.service.config)) + nft_id_bech32 = encode_puzzle_hash(nft_id, AddressType.NFT.hrp(self.service.config)) return { "wallet_id": wallet_id, "success": True, - "spend_bundle": spend_bundle, - "nft_id": nft_id, - "transactions": [tx.to_json_dict_convenience(self.service.config) for tx in txs], + "spend_bundle": None, # tx_endpoint wrapper will take care of this + "nft_id": nft_id_bech32, + "transactions": None, # tx_endpoint wrapper will take care of this } async def nft_count_nfts(self, request: Dict[str, Any]) -> EndpointResult: @@ -3253,7 +3236,7 @@ async def nft_set_nft_did( return {"success": False, "error": "The NFT doesn't support setting a DID."} fee = uint64(request.get("fee", 0)) - txs = await nft_wallet.set_nft_did( + await nft_wallet.set_nft_did( nft_coin_info, did_id, tx_config, @@ -3264,8 +3247,8 @@ async def nft_set_nft_did( return { "wallet_id": wallet_id, "success": True, - "spend_bundle": SpendBundle.aggregate([tx.spend_bundle for tx in txs if tx.spend_bundle is not None]), - "transactions": [tx.to_json_dict_convenience(self.service.config) for tx in txs], + "spend_bundle": None, # tx_endpoint wrapper will take care of this + "transactions": None, # tx_endpoint wrapper will take care of this } @tx_endpoint(push=True) @@ -3291,7 +3274,6 @@ async def nft_set_did_bulk( if did_id != b"": did_id = decode_puzzle_hash(did_id) nft_dict: Dict[uint32, List[NFTCoinInfo]] = {} - tx_list: List[TransactionRecord] = [] coin_ids = [] nft_ids = [] fee = uint64(request.get("fee", 0)) @@ -3325,45 +3307,30 @@ async def nft_set_did_bulk( for wallet_id, nft_list in nft_dict.items(): nft_wallet = self.service.wallet_state_manager.get_wallet(id=wallet_id, required_type=NFTWallet) if not first: - tx_list.extend( - await nft_wallet.set_bulk_nft_did( - nft_list, did_id, tx_config, action_scope, extra_conditions=extra_conditions - ) + await nft_wallet.set_bulk_nft_did( + nft_list, did_id, tx_config, action_scope, extra_conditions=extra_conditions ) else: - tx_list.extend( - await nft_wallet.set_bulk_nft_did( - nft_list, did_id, tx_config, action_scope, fee, nft_ids, extra_conditions=extra_conditions - ) + await nft_wallet.set_bulk_nft_did( + nft_list, did_id, tx_config, action_scope, fee, nft_ids, extra_conditions=extra_conditions ) for coin in nft_list: coin_ids.append(coin.coin.name()) first = False - spend_bundles: List[SpendBundle] = [] - refined_tx_list: List[TransactionRecord] = [] - for tx in tx_list: - if tx.spend_bundle is not None: - spend_bundles.append(tx.spend_bundle) - refined_tx_list.append(dataclasses.replace(tx, spend_bundle=None)) - - if len(spend_bundles) > 0: - spend_bundle = SpendBundle.aggregate(spend_bundles) - # Add all spend bundles to the first tx - refined_tx_list[0] = dataclasses.replace(refined_tx_list[0], spend_bundle=spend_bundle) - - for id in coin_ids: - await nft_wallet.update_coin_status(id, True) - for wallet_id in nft_dict.keys(): - self.service.wallet_state_manager.state_changed("nft_coin_did_set", wallet_id) + + for id in coin_ids: + await nft_wallet.update_coin_status(id, True) + for wallet_id in nft_dict.keys(): + self.service.wallet_state_manager.state_changed("nft_coin_did_set", wallet_id) + + async with action_scope.use() as interface: return { "wallet_id": list(nft_dict.keys()), "success": True, - "spend_bundle": spend_bundle, - "tx_num": len(refined_tx_list), - "transactions": [tx.to_json_dict_convenience(self.service.config) for tx in refined_tx_list], + "spend_bundle": None, # Backwards compat code in @tx_endpoint wrapper will fix this + "tx_num": len(interface.side_effects.transactions), + "transactions": None, # tx_endpoint wrapper will take care of this } - else: - raise ValueError("Couldn't set DID on given NFT") @tx_endpoint(push=True) async def nft_transfer_bulk( @@ -3390,7 +3357,6 @@ async def nft_transfer_bulk( else: return dict(success=False, error="target_address parameter missing") nft_dict: Dict[uint32, List[NFTCoinInfo]] = {} - tx_list: List[TransactionRecord] = [] coin_ids = [] fee = uint64(request.get("fee", 0)) @@ -3417,44 +3383,29 @@ async def nft_transfer_bulk( for wallet_id, nft_list in nft_dict.items(): nft_wallet = self.service.wallet_state_manager.get_wallet(id=wallet_id, required_type=NFTWallet) if not first: - tx_list.extend( - await nft_wallet.bulk_transfer_nft( - nft_list, puzzle_hash, tx_config, action_scope, extra_conditions=extra_conditions - ) + await nft_wallet.bulk_transfer_nft( + nft_list, puzzle_hash, tx_config, action_scope, extra_conditions=extra_conditions ) else: - tx_list.extend( - await nft_wallet.bulk_transfer_nft( - nft_list, puzzle_hash, tx_config, action_scope, fee, extra_conditions=extra_conditions - ) + await nft_wallet.bulk_transfer_nft( + nft_list, puzzle_hash, tx_config, action_scope, fee, extra_conditions=extra_conditions ) for coin in nft_list: coin_ids.append(coin.coin.name()) first = False - spend_bundles: List[SpendBundle] = [] - refined_tx_list: List[TransactionRecord] = [] - for tx in tx_list: - if tx.spend_bundle is not None: - spend_bundles.append(tx.spend_bundle) - refined_tx_list.append(dataclasses.replace(tx, spend_bundle=None)) - - if len(spend_bundles) > 0: - spend_bundle = SpendBundle.aggregate(spend_bundles) - # Add all spend bundles to the first tx - refined_tx_list[0] = dataclasses.replace(refined_tx_list[0], spend_bundle=spend_bundle) - for id in coin_ids: - await nft_wallet.update_coin_status(id, True) - for wallet_id in nft_dict.keys(): - self.service.wallet_state_manager.state_changed("nft_coin_did_set", wallet_id) + + for id in coin_ids: + await nft_wallet.update_coin_status(id, True) + for wallet_id in nft_dict.keys(): + self.service.wallet_state_manager.state_changed("nft_coin_did_set", wallet_id) + async with action_scope.use() as interface: return { "wallet_id": list(nft_dict.keys()), "success": True, - "spend_bundle": spend_bundle, - "tx_num": len(refined_tx_list), - "transactions": [tx.to_json_dict_convenience(self.service.config) for tx in refined_tx_list], + "spend_bundle": None, # tx_endpoint wrapper will take care of this + "tx_num": len(interface.side_effects.transactions), + "transactions": None, # tx_endpoint wrapper will take care of this } - else: - raise ValueError("Couldn't transfer given NFTs") async def nft_get_by_did(self, request: Dict[str, Any]) -> EndpointResult: did_id: Optional[bytes32] = None @@ -3537,7 +3488,7 @@ async def nft_transfer_nft( assert nft_coin_info is not None fee = uint64(request.get("fee", 0)) - txs = await nft_wallet.generate_signed_transaction( + await nft_wallet.generate_signed_transaction( [uint64(nft_coin_info.coin.amount)], [puzzle_hash], tx_config, @@ -3548,16 +3499,12 @@ async def nft_transfer_nft( new_did_inner_hash=b"", extra_conditions=extra_conditions, ) - spend_bundle: Optional[SpendBundle] = None - for tx in txs: - if tx.spend_bundle is not None: - spend_bundle = tx.spend_bundle await nft_wallet.update_coin_status(nft_coin_info.coin.name(), True) return { "wallet_id": wallet_id, "success": True, - "spend_bundle": spend_bundle, - "transactions": [tx.to_json_dict_convenience(self.service.config) for tx in txs], + "spend_bundle": None, # tx_endpoint wrapper will take care of this + "transactions": None, # tx_endpoint wrapper will take care of this } except Exception as e: log.exception(f"Failed to transfer NFT: {e}") @@ -3651,14 +3598,14 @@ async def nft_add_uri( nft_coin_info = await nft_wallet.get_nft_coin_by_id(nft_coin_id) fee = uint64(request.get("fee", 0)) - txs = await nft_wallet.update_metadata( + await nft_wallet.update_metadata( nft_coin_info, key, uri, tx_config, action_scope, fee=fee, extra_conditions=extra_conditions ) return { "wallet_id": wallet_id, "success": True, - "spend_bundle": SpendBundle.aggregate([tx.spend_bundle for tx in txs if tx.spend_bundle is not None]), - "transactions": [tx.to_json_dict_convenience(self.service.config) for tx in txs], + "spend_bundle": None, # tx_endpoint wrapper will take care of this + "transactions": None, # tx_endpoint wrapper will take care of this } async def nft_calculate_royalties(self, request: Dict[str, Any]) -> EndpointResult: @@ -3761,7 +3708,7 @@ async def nft_mint_bulk( fee = uint64(request.get("fee", 0)) if mint_from_did: - txs = await nft_wallet.mint_from_did( + await nft_wallet.mint_from_did( metadata_list, mint_number_start=mint_number_start, mint_total=mint_total, @@ -3778,7 +3725,7 @@ async def nft_mint_bulk( extra_conditions=extra_conditions, ) else: - txs = await nft_wallet.mint_from_xch( + await nft_wallet.mint_from_xch( metadata_list, mint_number_start=mint_number_start, mint_total=mint_total, @@ -3790,21 +3737,20 @@ async def nft_mint_bulk( action_scope=action_scope, extra_conditions=extra_conditions, ) - sb = txs[0].spend_bundle - assert sb is not None + async with action_scope.use() as interface: + sb = SpendBundle.aggregate( + [tx.spend_bundle for tx in interface.side_effects.transactions if tx.spend_bundle is not None] + ) nft_id_list = [] for cs in sb.coin_spends: if cs.coin.puzzle_hash == nft_puzzles.LAUNCHER_PUZZLE_HASH: nft_id_list.append(encode_puzzle_hash(cs.coin.name(), AddressType.NFT.hrp(self.service.config))) - ### - # Temporary signing workaround (delete when minting functions return transaction records) - sb, _ = await self.service.wallet_state_manager.sign_bundle(sb.coin_spends) - ### + return { "success": True, - "spend_bundle": sb, + "spend_bundle": None, # tx_endpoint wrapper will take care of this "nft_id_list": nft_id_list, - "transactions": [tx.to_json_dict_convenience(self.service.config) for tx in txs], + "transactions": None, # tx_endpoint wrapper will take care of this } async def get_coin_records(self, request: Dict[str, Any]) -> EndpointResult: @@ -3943,7 +3889,7 @@ async def create_signed_transaction( async def _generate_signed_transaction() -> EndpointResult: if isinstance(wallet, Wallet): - [tx] = await wallet.generate_signed_transaction( + await wallet.generate_signed_transaction( amount_0, bytes32(puzzle_hash_0), tx_config, @@ -3978,13 +3924,13 @@ async def _generate_signed_transaction() -> EndpointResult: ), ), ) - signed_tx = tx.to_json_dict_convenience(self.service.config) - return {"signed_txs": [signed_tx], "signed_tx": signed_tx, "transactions": [signed_tx]} + # tx_endpoint wrapper will take care of this + return {"signed_txs": None, "signed_tx": None, "transactions": None} else: assert isinstance(wallet, CATWallet) - txs = await wallet.generate_signed_transaction( + await wallet.generate_signed_transaction( [amount_0] + [output.amount for output in additional_outputs], [bytes32(puzzle_hash_0)] + [output.puzzle_hash for output in additional_outputs], tx_config, @@ -4018,9 +3964,8 @@ async def _generate_signed_transaction() -> EndpointResult: ), ), ) - signed_txs = [tx.to_json_dict_convenience(self.service.config) for tx in txs] - - return {"signed_txs": signed_txs, "signed_tx": signed_txs[0], "transactions": signed_txs} + # tx_endpoint wrapper will take care of this + return {"signed_txs": None, "signed_tx": None, "transactions": None} if hold_lock: async with self.service.wallet_state_manager.lock: @@ -4062,16 +4007,12 @@ async def pw_join_pool( ) async with self.service.wallet_state_manager.lock: - total_fee, tx, fee_tx = await wallet.join_pool(new_target_state, fee, tx_config, action_scope) + total_fee = await wallet.join_pool(new_target_state, fee, tx_config, action_scope) return { "total_fee": total_fee, - "transaction": tx, - "fee_transaction": fee_tx, - "transactions": [ - transaction.to_json_dict_convenience(self.service.config) - for transaction in (tx, fee_tx) - if transaction is not None - ], + "transaction": None, # tx_endpoint wrapper will take care of this + "fee_transaction": None, # tx_endpoint wrapper will take care of this + "transactions": None, # tx_endpoint wrapper will take care of this } @tx_endpoint(push=True) @@ -4093,16 +4034,12 @@ async def pw_self_pool( raise ValueError("Wallet needs to be fully synced.") async with self.service.wallet_state_manager.lock: - total_fee, tx, fee_tx = await wallet.self_pool(fee, tx_config, action_scope) + total_fee = await wallet.self_pool(fee, tx_config, action_scope) return { "total_fee": total_fee, - "transaction": tx, - "fee_transaction": fee_tx, - "transactions": [ - transaction.to_json_dict_convenience(self.service.config) - for transaction in (tx, fee_tx) - if transaction is not None - ], + "transaction": None, # tx_endpoint wrapper will take care of this + "fee_transaction": None, # tx_endpoint wrapper will take care of this + "transactions": None, # tx_endpoint wrapper will take care of this } @tx_endpoint(push=True) @@ -4123,15 +4060,13 @@ async def pw_absorb_rewards( assert isinstance(wallet, PoolWallet) async with self.service.wallet_state_manager.lock: - transaction, fee_tx = await wallet.claim_pool_rewards(fee, max_spends_in_tx, tx_config, action_scope) + await wallet.claim_pool_rewards(fee, max_spends_in_tx, tx_config, action_scope) state: PoolWalletInfo = await wallet.get_current_state() return { "state": state.to_json_dict(), - "transaction": transaction, - "fee_transaction": fee_tx, - "transactions": [ - tx.to_json_dict_convenience(self.service.config) for tx in (transaction, fee_tx) if tx is not None - ], + "transaction": None, # tx_endpoint wrapper will take care of this + "fee_transaction": None, # tx_endpoint wrapper will take care of this + "transactions": None, # tx_endpoint wrapper will take care of this } async def pw_status(self, request: Dict[str, Any]) -> EndpointResult: @@ -4170,7 +4105,7 @@ async def create_new_dl( try: async with self.service.wallet_state_manager.lock: - std_tx, launcher_id = await dl_wallet.generate_new_reporter( + launcher_id = await dl_wallet.generate_new_reporter( bytes32.from_hexstr(request["root"]), tx_config, action_scope, @@ -4182,8 +4117,7 @@ async def create_new_dl( return {"success": False, "error": str(e)} return { - "success": True, - "transactions": [std_tx.to_json_dict_convenience(self.service.config)], + "transactions": None, # tx_endpoint wrapper will take care of this "launcher_id": launcher_id, } @@ -4259,7 +4193,7 @@ async def dl_update_root( wallet = self.service.wallet_state_manager.get_dl_wallet() async with self.service.wallet_state_manager.lock: - records = await wallet.create_update_state_spend( + await wallet.create_update_state_spend( bytes32.from_hexstr(request["launcher_id"]), bytes32.from_hexstr(request["new_root"]), tx_config, @@ -4267,10 +4201,11 @@ async def dl_update_root( fee=uint64(request.get("fee", 0)), extra_conditions=extra_conditions, ) - return { - "tx_record": records[0].to_json_dict_convenience(self.service.config), - "transactions": [tx.to_json_dict_convenience(self.service.config) for tx in records], - } + + return { + "tx_record": None, # tx_endpoint wrapper will take care of this + "transactions": None, # tx_endpoint wrapper will take care of this + } @tx_endpoint(push=True) async def dl_update_multiple( @@ -4288,10 +4223,9 @@ async def dl_update_multiple( async with self.service.wallet_state_manager.lock: # TODO: This method should optionally link the singletons with announcements. # Otherwise spends are vulnerable to signature subtraction. - tx_records: List[TransactionRecord] = [] fee_per_launcher = uint64(request.get("fee", 0) // len(request["updates"])) for launcher, root in request["updates"].items(): - records = await wallet.create_update_state_spend( + await wallet.create_update_state_spend( bytes32.from_hexstr(launcher), bytes32.from_hexstr(root), tx_config, @@ -4299,10 +4233,9 @@ async def dl_update_multiple( fee=fee_per_launcher, extra_conditions=extra_conditions, ) - tx_records.extend(records) return { - "transactions": [rec.to_json_dict_convenience(self.service.config) for rec in tx_records], + "transactions": None, # tx_endpoint wrapper will take care of this } async def dl_history(self, request: Dict[str, Any]) -> EndpointResult: @@ -4361,7 +4294,7 @@ async def dl_new_mirror( dl_wallet = self.service.wallet_state_manager.get_dl_wallet() async with self.service.wallet_state_manager.lock: - txs = await dl_wallet.create_new_mirror( + await dl_wallet.create_new_mirror( bytes32.from_hexstr(request["launcher_id"]), request["amount"], [bytes(url, "utf8") for url in request["urls"]], @@ -4372,7 +4305,7 @@ async def dl_new_mirror( ) return { - "transactions": [tx.to_json_dict_convenience(self.service.config) for tx in txs], + "transactions": None, # tx_endpoint wrapper will take care of this } @tx_endpoint(push=True) @@ -4390,7 +4323,7 @@ async def dl_delete_mirror( dl_wallet = self.service.wallet_state_manager.get_dl_wallet() async with self.service.wallet_state_manager.lock: - txs = await dl_wallet.delete_mirror( + await dl_wallet.delete_mirror( bytes32.from_hexstr(request["coin_id"]), self.service.get_full_node_peer(), tx_config, @@ -4400,7 +4333,7 @@ async def dl_delete_mirror( ) return { - "transactions": [tx.to_json_dict_convenience(self.service.config) for tx in txs], + "transactions": None, # tx_endpoint wrapper will take care of this } async def dl_verify_proof( @@ -4450,12 +4383,12 @@ class VCMint(Streamable): puzhash = decode_puzzle_hash(parsed_request.target_address) vc_wallet: VCWallet = await self.service.wallet_state_manager.get_or_create_vc_wallet() - vc_record, tx_list = await vc_wallet.launch_new_vc( + vc_record = await vc_wallet.launch_new_vc( did_id, tx_config, action_scope, puzhash, parsed_request.fee, extra_conditions=extra_conditions ) return { "vc_record": vc_record.to_json_dict(), - "transactions": [tx.to_json_dict_convenience(self.service.config) for tx in tx_list], + "transactions": None, # tx_endpoint wrapper will take care of this } async def vc_get(self, request: Dict[str, Any]) -> EndpointResult: @@ -4534,7 +4467,7 @@ class VCSpend(Streamable): vc_wallet: VCWallet = await self.service.wallet_state_manager.get_or_create_vc_wallet() - txs = await vc_wallet.generate_signed_transaction( + await vc_wallet.generate_signed_transaction( parsed_request.vc_id, tx_config, action_scope, @@ -4546,7 +4479,7 @@ class VCSpend(Streamable): ) return { - "transactions": [tx.to_json_dict_convenience(self.service.config) for tx in txs], + "transactions": None, # tx_endpoint wrapper will take care of this } async def vc_add_proofs(self, request: Dict[str, Any]) -> EndpointResult: @@ -4605,7 +4538,7 @@ class VCRevoke(Streamable): parsed_request = VCRevoke.from_json_dict(request) vc_wallet: VCWallet = await self.service.wallet_state_manager.get_or_create_vc_wallet() - txs = await vc_wallet.revoke_vc( + await vc_wallet.revoke_vc( parsed_request.vc_parent_id, self.service.get_full_node_peer(), tx_config, @@ -4615,7 +4548,7 @@ class VCRevoke(Streamable): ) return { - "transactions": [tx.to_json_dict_convenience(self.service.config) for tx in txs], + "transactions": None, # tx_endpoint wrapper will take care of this } @tx_endpoint(push=True) @@ -4645,7 +4578,7 @@ class CRCATApprovePending(Streamable): cr_cat_wallet = self.service.wallet_state_manager.wallets[parsed_request.wallet_id] assert isinstance(cr_cat_wallet, CRCATWallet) - txs = await cr_cat_wallet.claim_pending_approval_balance( + await cr_cat_wallet.claim_pending_approval_balance( parsed_request.min_amount_to_claim, tx_config, action_scope, @@ -4654,7 +4587,7 @@ class CRCATApprovePending(Streamable): ) return { - "transactions": [tx.to_json_dict_convenience(self.service.config) for tx in txs], + "transactions": None, # tx_endpoint wrapper will take care of this } @marshal diff --git a/chia/rpc/wallet_rpc_client.py b/chia/rpc/wallet_rpc_client.py index d2b459948930..f13aa196eaea 100644 --- a/chia/rpc/wallet_rpc_client.py +++ b/chia/rpc/wallet_rpc_client.py @@ -68,6 +68,7 @@ def parse_result_transactions(result: Dict[str, Any]) -> Dict[str, Any]: result["transaction"] = TransactionRecord.from_json_dict(result["transaction"]) + result["transactions"] = [TransactionRecord.from_json_dict_convenience(tx) for tx in result["transactions"]] if result["fee_transaction"]: result["fee_transaction"] = TransactionRecord.from_json_dict(result["fee_transaction"]) return result diff --git a/chia/simulator/full_node_simulator.py b/chia/simulator/full_node_simulator.py index 61c994642061..47b890ec20ec 100644 --- a/chia/simulator/full_node_simulator.py +++ b/chia/simulator/full_node_simulator.py @@ -682,16 +682,15 @@ async def create_coins_with_amounts( outputs_group = [output for _, output in zip(range(per_transaction_record_group), outputs_iterator)] if len(outputs_group) > 0: - async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope: - [tx] = await wallet.generate_signed_transaction( + async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope: + await wallet.generate_signed_transaction( amount=outputs_group[0].amount, puzzle_hash=outputs_group[0].puzzle_hash, tx_config=DEFAULT_TX_CONFIG, action_scope=action_scope, primaries=outputs_group[1:], ) - [tx] = await wallet.wallet_state_manager.add_pending_transactions([tx]) - transaction_records.append(tx) + transaction_records.extend(action_scope.side_effects.transactions) else: break diff --git a/chia/wallet/cat_wallet/cat_wallet.py b/chia/wallet/cat_wallet/cat_wallet.py index a11bc69e53a4..d8ed0b6858b2 100644 --- a/chia/wallet/cat_wallet/cat_wallet.py +++ b/chia/wallet/cat_wallet/cat_wallet.py @@ -6,7 +6,7 @@ import traceback from typing import TYPE_CHECKING, Any, ClassVar, Dict, List, Optional, Set, Tuple, cast -from chia_rs import G1Element, G2Element +from chia_rs import G1Element from typing_extensions import Unpack from chia.consensus.default_constants import DEFAULT_CONSTANTS @@ -113,7 +113,8 @@ async def create_new_cat_wallet( action_scope: WalletActionScope, fee: uint64 = uint64(0), name: Optional[str] = None, - ) -> Tuple[CATWallet, List[TransactionRecord]]: + push: bool = True, + ) -> CATWallet: self = CATWallet() self.standard_wallet = wallet self.log = logging.getLogger(__name__) @@ -136,9 +137,7 @@ async def create_new_cat_wallet( self.wallet_info = await wallet_state_manager.user_store.create_wallet(name, WalletType.CAT, info_as_string) try: - chia_tx, spend_bundle = await ALL_LIMITATIONS_PROGRAMS[ - cat_tail_info["identifier"] - ].generate_issuance_bundle( + spend_bundle = await ALL_LIMITATIONS_PROGRAMS[cat_tail_info["identifier"]].generate_issuance_bundle( self, cat_tail_info, amount, @@ -186,20 +185,20 @@ async def create_new_cat_wallet( fee_amount=fee, confirmed=False, sent=uint32(10), - spend_bundle=None, + spend_bundle=spend_bundle, additions=[cat_coin], removals=list(filter(lambda rem: rem.name() == cat_pid, spend_bundle.removals())), wallet_id=self.id(), sent_to=[], trade_id=None, type=uint32(TransactionType.INCOMING_TX.value), - name=bytes32.secret(), + name=spend_bundle.name(), memos=[], valid_times=ConditionValidTimes(), ) - chia_tx = dataclasses.replace(chia_tx, spend_bundle=spend_bundle, name=spend_bundle.name()) - tx_list = await self.wallet_state_manager.add_pending_transactions([chia_tx, cat_record]) - return self, tx_list + async with action_scope.use() as interface: + interface.side_effects.transactions.append(cat_record) + return self @staticmethod async def get_or_create_wallet_for_cat( @@ -567,61 +566,66 @@ async def create_tandem_xch_tx( tx_config: TXConfig, action_scope: WalletActionScope, extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> Tuple[TransactionRecord, Optional[AssertCoinAnnouncement]]: + ) -> Optional[AssertCoinAnnouncement]: """ This function creates a non-CAT transaction to pay fees, contribute funds for issuance, and absorb melt value. It is meant to be called in `generate_unsigned_spendbundle` and as such should be called under the wallet_state_manager lock """ announcement: Optional[AssertCoinAnnouncement] = None - if fee > amount_to_claim: - chia_coins = await self.standard_wallet.select_coins( - fee, - tx_config.coin_selection_config, - ) - origin_id = list(chia_coins)[0].name() - [chia_tx] = await self.standard_wallet.generate_signed_transaction( - uint64(0), - (await self.standard_wallet.get_puzzle_hash(not tx_config.reuse_puzhash)), - tx_config, - action_scope, - fee=uint64(fee - amount_to_claim), - coins=chia_coins, - origin_id=origin_id, # We specify this so that we know the coin that is making the announcement - negative_change_allowed=False, - extra_conditions=extra_conditions, - ) - assert chia_tx.spend_bundle is not None - else: - chia_coins = await self.standard_wallet.select_coins( - fee, - tx_config.coin_selection_config, - ) - origin_id = list(chia_coins)[0].name() - selected_amount = sum(c.amount for c in chia_coins) - [chia_tx] = await self.standard_wallet.generate_signed_transaction( - uint64(selected_amount + amount_to_claim - fee), - (await self.standard_wallet.get_puzzle_hash(not tx_config.reuse_puzhash)), - tx_config, - action_scope, - coins=chia_coins, - negative_change_allowed=True, - extra_conditions=extra_conditions, - ) - assert chia_tx.spend_bundle is not None + async with self.wallet_state_manager.new_action_scope(push=False) as inner_action_scope: + if fee > amount_to_claim: + chia_coins = await self.standard_wallet.select_coins( + fee, + tx_config.coin_selection_config, + ) + origin_id = list(chia_coins)[0].name() + await self.standard_wallet.generate_signed_transaction( + uint64(0), + (await self.standard_wallet.get_puzzle_hash(not tx_config.reuse_puzhash)), + tx_config, + inner_action_scope, + fee=uint64(fee - amount_to_claim), + coins=chia_coins, + origin_id=origin_id, # We specify this so that we know the coin that is making the announcement + negative_change_allowed=False, + extra_conditions=extra_conditions, + ) + else: + chia_coins = await self.standard_wallet.select_coins( + fee, + tx_config.coin_selection_config, + ) + origin_id = list(chia_coins)[0].name() + selected_amount = sum(c.amount for c in chia_coins) + await self.standard_wallet.generate_signed_transaction( + uint64(selected_amount + amount_to_claim - fee), + (await self.standard_wallet.get_puzzle_hash(not tx_config.reuse_puzhash)), + tx_config, + inner_action_scope, + coins=chia_coins, + negative_change_allowed=True, + extra_conditions=extra_conditions, + ) - message = None - for spend in chia_tx.spend_bundle.coin_spends: + message = None + for tx in inner_action_scope.side_effects.transactions: + if tx.spend_bundle is None: + continue + for spend in tx.spend_bundle.coin_spends: if spend.coin.name() == origin_id: conditions = spend.puzzle_reveal.to_program().run(spend.solution.to_program()).as_python() for condition in conditions: if condition[0] == ConditionOpcode.CREATE_COIN_ANNOUNCEMENT: message = condition[1] - assert message is not None - announcement = AssertCoinAnnouncement(asserted_id=origin_id, asserted_msg=message) + assert message is not None + announcement = AssertCoinAnnouncement(asserted_id=origin_id, asserted_msg=message) - return chia_tx, announcement + async with action_scope.use() as interface: + interface.side_effects.transactions.extend(inner_action_scope.side_effects.transactions) + + return announcement async def generate_unsigned_spendbundle( self, @@ -632,7 +636,7 @@ async def generate_unsigned_spendbundle( cat_discrepancy: Optional[Tuple[int, Program, Program]] = None, # (extra_delta, tail_reveal, tail_solution) coins: Optional[Set[Coin]] = None, extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> Tuple[SpendBundle, Optional[TransactionRecord]]: + ) -> SpendBundle: if cat_discrepancy is not None: extra_delta, tail_reveal, tail_solution = cat_discrepancy else: @@ -680,7 +684,6 @@ async def generate_unsigned_spendbundle( # Loop through the coins we've selected and gather the information we need to spend them spendable_cat_list = [] - chia_tx = None first = True announcement: CreateCoinAnnouncement @@ -702,7 +705,7 @@ async def generate_unsigned_spendbundle( announcement = CreateCoinAnnouncement(std_hash(b"".join([c.name() for c in cat_coins])), coin.name()) if need_chia_transaction: if fee > regular_chia_to_claim: - chia_tx, _ = await self.create_tandem_xch_tx( + await self.create_tandem_xch_tx( fee, uint64(regular_chia_to_claim), tx_config, @@ -714,7 +717,7 @@ async def generate_unsigned_spendbundle( conditions=(*extra_conditions, announcement), ) elif regular_chia_to_claim > fee: # pragma: no cover - chia_tx, xch_announcement = await self.create_tandem_xch_tx( + xch_announcement = await self.create_tandem_xch_tx( fee, uint64(regular_chia_to_claim), tx_config, @@ -753,19 +756,8 @@ async def generate_unsigned_spendbundle( spendable_cat_list.append(new_spendable_cat) cat_spend_bundle = unsigned_spend_bundle_for_spendable_cats(CAT_MOD, spendable_cat_list) - chia_spend_bundle = SpendBundle([], G2Element()) - if chia_tx is not None and chia_tx.spend_bundle is not None: - chia_spend_bundle = chia_tx.spend_bundle - return ( - SpendBundle.aggregate( - [ - cat_spend_bundle, - chia_spend_bundle, - ] - ), - chia_tx, - ) + return cat_spend_bundle async def generate_signed_transaction( self, @@ -778,7 +770,7 @@ async def generate_signed_transaction( memos: Optional[List[List[bytes]]] = None, extra_conditions: Tuple[Condition, ...] = tuple(), **kwargs: Unpack[GSTOptionalArgs], - ) -> List[TransactionRecord]: + ) -> None: # (extra_delta, tail_reveal, tail_solution) cat_discrepancy: Optional[Tuple[int, Program, Program]] = kwargs.get("cat_discrepancy", None) if memos is None: @@ -794,7 +786,7 @@ async def generate_signed_transaction( payments.append(Payment(puzhash, amount, memos_with_hint)) payment_sum = sum(p.amount for p in payments) - spend_bundle, chia_tx = await self.generate_unsigned_spendbundle( + spend_bundle = await self.generate_unsigned_spendbundle( payments, tx_config, action_scope, @@ -803,59 +795,36 @@ async def generate_signed_transaction( coins=coins, extra_conditions=extra_conditions, ) - if chia_tx is not None: - other_tx_removals: Set[Coin] = {removal for removal in chia_tx.removals} - other_tx_additions: Set[Coin] = {removal for removal in chia_tx.additions} - else: - other_tx_removals = set() - other_tx_additions = set() - tx_list = [ - TransactionRecord( - confirmed_at_height=uint32(0), - created_at_time=uint64(int(time.time())), - to_puzzle_hash=puzzle_hashes[0], - amount=uint64(payment_sum), - fee_amount=fee, - confirmed=False, - sent=uint32(0), - spend_bundle=spend_bundle, - additions=list(set(spend_bundle.additions()) - other_tx_additions), - removals=list(set(spend_bundle.removals()) - other_tx_removals), - wallet_id=self.id(), - sent_to=[], - trade_id=None, - type=uint32(TransactionType.OUTGOING_TX.value), - name=spend_bundle.name(), - memos=list(compute_memos(spend_bundle).items()), - valid_times=parse_timelock_info(extra_conditions), - ) - ] - if chia_tx is not None: - tx_list.append( + async with action_scope.use() as interface: + other_tx_removals: Set[Coin] = { + removal for tx in interface.side_effects.transactions for removal in tx.removals + } + other_tx_additions: Set[Coin] = { + removal for tx in interface.side_effects.transactions for removal in tx.additions + } + interface.side_effects.transactions.append( TransactionRecord( - confirmed_at_height=chia_tx.confirmed_at_height, - created_at_time=chia_tx.created_at_time, - to_puzzle_hash=chia_tx.to_puzzle_hash, - amount=chia_tx.amount, - fee_amount=chia_tx.fee_amount, - confirmed=chia_tx.confirmed, - sent=chia_tx.sent, - spend_bundle=None, - additions=chia_tx.additions, - removals=chia_tx.removals, - wallet_id=chia_tx.wallet_id, - sent_to=chia_tx.sent_to, - trade_id=chia_tx.trade_id, - type=chia_tx.type, - name=chia_tx.name, - memos=[], + confirmed_at_height=uint32(0), + created_at_time=uint64(int(time.time())), + to_puzzle_hash=puzzle_hashes[0], + amount=uint64(payment_sum), + fee_amount=fee, + confirmed=False, + sent=uint32(0), + spend_bundle=spend_bundle, + additions=list(set(spend_bundle.additions()) - other_tx_additions), + removals=list(set(spend_bundle.removals()) - other_tx_removals), + wallet_id=self.id(), + sent_to=[], + trade_id=None, + type=uint32(TransactionType.OUTGOING_TX.value), + name=spend_bundle.name(), + memos=list(compute_memos(spend_bundle).items()), valid_times=parse_timelock_info(extra_conditions), ) ) - return tx_list - async def add_lineage(self, name: bytes32, lineage: Optional[LineageProof]) -> None: """ Lineage proofs are stored as a list of parent coins and the lineage proof you will need if they are the diff --git a/chia/wallet/cat_wallet/dao_cat_wallet.py b/chia/wallet/cat_wallet/dao_cat_wallet.py index 667a32d993ca..704ccc026eef 100644 --- a/chia/wallet/cat_wallet/dao_cat_wallet.py +++ b/chia/wallet/cat_wallet/dao_cat_wallet.py @@ -400,7 +400,7 @@ async def exit_vote_state( action_scope: WalletActionScope, fee: uint64 = uint64(0), extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> List[TransactionRecord]: + ) -> None: extra_delta, limitations_solution = 0, Program.to([]) limitations_program_reveal = Program.to([]) spendable_cat_list = [] @@ -456,15 +456,11 @@ async def exit_vote_state( spend_bundle = unsigned_spend_bundle_for_spendable_cats(CAT_MOD, spendable_cat_list) if fee > 0: # pragma: no cover - chia_tx = await self.standard_wallet.create_tandem_xch_tx( + await self.standard_wallet.create_tandem_xch_tx( fee, tx_config, action_scope, ) - assert chia_tx.spend_bundle is not None - full_spend = SpendBundle.aggregate([spend_bundle, chia_tx.spend_bundle]) - else: - full_spend = spend_bundle record = TransactionRecord( confirmed_at_height=uint32(0), @@ -474,14 +470,14 @@ async def exit_vote_state( fee_amount=fee, confirmed=False, sent=uint32(10), - spend_bundle=full_spend, - additions=full_spend.additions(), - removals=full_spend.removals(), + spend_bundle=spend_bundle, + additions=spend_bundle.additions(), + removals=spend_bundle.removals(), wallet_id=self.id(), sent_to=[], trade_id=None, type=uint32(TransactionType.INCOMING_TX.value), - name=full_spend.name(), + name=spend_bundle.name(), memos=[], valid_times=parse_timelock_info(extra_conditions), ) @@ -498,7 +494,8 @@ async def exit_vote_state( new_locked_coins, ) await self.save_info(dao_cat_info) - return [record] + async with action_scope.use() as interface: + interface.side_effects.transactions.append(record) async def remove_active_proposal( self, @@ -566,15 +563,9 @@ async def remove_active_proposal( spend_bundle = unsigned_spend_bundle_for_spendable_cats(CAT_MOD, spendable_cat_list) if fee > 0: # pragma: no cover - chia_tx = await self.standard_wallet.create_tandem_xch_tx( - fee, tx_config=tx_config, action_scope=action_scope - ) - assert chia_tx.spend_bundle is not None - full_spend = SpendBundle.aggregate([spend_bundle, chia_tx.spend_bundle]) - else: - full_spend = spend_bundle + await self.standard_wallet.create_tandem_xch_tx(fee, tx_config=tx_config, action_scope=action_scope) - return full_spend + return spend_bundle def get_asset_id(self) -> str: return bytes(self.dao_cat_info.limitations_program_hash).hex() diff --git a/chia/wallet/dao_wallet/dao_wallet.py b/chia/wallet/dao_wallet/dao_wallet.py index 585c12641901..649cc7b64843 100644 --- a/chia/wallet/dao_wallet/dao_wallet.py +++ b/chia/wallet/dao_wallet/dao_wallet.py @@ -126,7 +126,7 @@ async def create_new_dao_and_wallet( name: Optional[str] = None, fee: uint64 = uint64(0), fee_for_cat: uint64 = uint64(0), - ) -> Tuple[DAOWallet, List[TransactionRecord]]: + ) -> DAOWallet: """ Create a brand new DAO wallet This must be called under the wallet state manager lock @@ -175,7 +175,7 @@ async def create_new_dao_and_wallet( std_wallet_id = self.standard_wallet.wallet_id try: - txs = await self.generate_new_dao( + await self.generate_new_dao( amount_of_cats, tx_config, action_scope, @@ -201,7 +201,7 @@ async def create_new_dao_and_wallet( ) await self.save_info(dao_info) - return self, txs + return self @staticmethod async def create_new_dao_wallet_for_existing_dao( @@ -613,7 +613,7 @@ async def generate_new_dao( fee: uint64 = uint64(0), fee_for_cat: uint64 = uint64(0), extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> List[TransactionRecord]: + ) -> None: """ Create a new DAO treasury using the dao_rules object. This does the first spend to create the launcher and eve coins. @@ -689,7 +689,7 @@ async def generate_new_dao( "treasury_id": launcher_coin.name(), "coins": different_coins, } - new_cat_wallet, _ = await CATWallet.create_new_cat_wallet( + new_cat_wallet = await CATWallet.create_new_cat_wallet( self.wallet_state_manager, self.standard_wallet, cat_tail_info, @@ -697,6 +697,7 @@ async def generate_new_dao( DEFAULT_TX_CONFIG, action_scope, fee=fee_for_cat, + push=False, ) assert new_cat_wallet is not None else: # pragma: no cover @@ -731,7 +732,8 @@ async def generate_new_dao( full_treasury_puzzle_hash = full_treasury_puzzle.get_tree_hash() announcement_message = Program.to([full_treasury_puzzle_hash, 1, bytes(0x80)]).get_tree_hash() - tx_records: List[TransactionRecord] = await self.standard_wallet.generate_signed_transaction( + + await self.standard_wallet.generate_signed_transaction( uint64(1), genesis_launcher_puz.get_tree_hash(), tx_config, @@ -744,7 +746,6 @@ async def generate_new_dao( AssertCoinAnnouncement(asserted_id=launcher_coin.name(), asserted_msg=announcement_message), ), ) - tx_record: TransactionRecord = tx_records[0] genesis_launcher_solution = Program.to([full_treasury_puzzle_hash, 1, bytes(0x80)]) @@ -758,8 +759,6 @@ async def generate_new_dao( ) await self.add_parent(launcher_coin.name(), launcher_proof) - assert tx_record.spend_bundle is not None - eve_coin = Coin(launcher_coin.name(), full_treasury_puzzle_hash, uint64(1)) dao_info = DAOInfo( launcher_coin.name(), @@ -776,8 +775,7 @@ async def generate_new_dao( ) await self.save_info(dao_info) eve_spend = await self.generate_treasury_eve_spend(dao_treasury_puzzle, eve_coin) - - full_spend = SpendBundle.aggregate([tx_record.spend_bundle, launcher_sb, eve_spend]) + new_spend = SpendBundle.aggregate([launcher_sb, eve_spend]) treasury_record = TransactionRecord( confirmed_at_height=uint32(0), @@ -787,18 +785,17 @@ async def generate_new_dao( fee_amount=fee, confirmed=False, sent=uint32(10), - spend_bundle=full_spend, - additions=full_spend.additions(), - removals=full_spend.removals(), + spend_bundle=new_spend, + additions=new_spend.additions(), + removals=new_spend.removals(), wallet_id=self.id(), sent_to=[], trade_id=None, type=uint32(TransactionType.INCOMING_TX.value), - name=full_spend.name(), + name=eve_coin.name(), memos=[], valid_times=parse_timelock_info(extra_conditions), ) - regular_record = dataclasses.replace(tx_record, spend_bundle=None) funding_inner_puzhash = get_p2_singleton_puzhash(self.dao_info.treasury_id) await self.wallet_state_manager.add_interested_puzzle_hashes([funding_inner_puzhash], [self.id()]) @@ -806,7 +803,8 @@ async def generate_new_dao( await self.wallet_state_manager.add_interested_coin_ids([launcher_coin.name()], [self.wallet_id]) await self.wallet_state_manager.add_interested_coin_ids([eve_coin.name()], [self.wallet_id]) - return [treasury_record, regular_record] + async with action_scope.use() as interface: + interface.side_effects.transactions.append(treasury_record) async def generate_treasury_eve_spend( self, inner_puz: Program, eve_coin: Coin, fee: uint64 = uint64(0) @@ -853,7 +851,7 @@ async def generate_new_proposal( vote_amount: Optional[uint64] = None, fee: uint64 = uint64(0), extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> List[TransactionRecord]: + ) -> None: dao_rules = get_treasury_rules_from_puzzle(self.dao_info.current_treasury_innerpuz) coins = await self.standard_wallet.select_coins( uint64(fee + dao_rules.proposal_minimum_amount), @@ -893,7 +891,7 @@ async def generate_new_proposal( [full_proposal_puzzle_hash, dao_rules.proposal_minimum_amount, bytes(0x80)] ).get_tree_hash() - tx_records: List[TransactionRecord] = await self.standard_wallet.generate_signed_transaction( + await self.standard_wallet.generate_signed_transaction( uint64(dao_rules.proposal_minimum_amount), genesis_launcher_puz.get_tree_hash(), tx_config, @@ -905,7 +903,6 @@ async def generate_new_proposal( AssertCoinAnnouncement(asserted_id=launcher_coin.name(), asserted_msg=announcement_message), ), ) - tx_record: TransactionRecord = tx_records[0] genesis_launcher_solution = Program.to( [full_proposal_puzzle_hash, dao_rules.proposal_minimum_amount, bytes(0x80)] @@ -937,31 +934,31 @@ async def generate_new_proposal( launcher_coin=launcher_coin, vote_amount=vote_amount, ) - assert tx_record - assert tx_record.spend_bundle is not None - - full_spend = SpendBundle.aggregate([tx_record.spend_bundle, eve_spend, launcher_sb]) - record = TransactionRecord( - confirmed_at_height=uint32(0), - created_at_time=uint64(int(time.time())), - to_puzzle_hash=full_proposal_puzzle.get_tree_hash(), - amount=uint64(dao_rules.proposal_minimum_amount), - fee_amount=fee, - confirmed=False, - sent=uint32(10), - 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(), - memos=[], - valid_times=parse_timelock_info(extra_conditions), - ) - return [record] + full_spend = SpendBundle.aggregate([eve_spend, launcher_sb]) + + async with action_scope.use() as interface: + interface.side_effects.transactions.append( + TransactionRecord( + confirmed_at_height=uint32(0), + created_at_time=uint64(int(time.time())), + to_puzzle_hash=full_proposal_puzzle.get_tree_hash(), + amount=uint64(dao_rules.proposal_minimum_amount), + fee_amount=fee, + confirmed=False, + sent=uint32(10), + 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(), + memos=[], + valid_times=parse_timelock_info(extra_conditions), + ) + ) async def generate_proposal_eve_spend( self, @@ -1037,7 +1034,7 @@ async def generate_proposal_vote_spend( action_scope: WalletActionScope, fee: uint64 = uint64(0), extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> List[TransactionRecord]: + ) -> None: self.log.info(f"Trying to create a proposal close spend with ID: {proposal_id}") proposal_info = None for pi in self.dao_info.proposals_list: @@ -1114,18 +1111,17 @@ async def generate_proposal_vote_spend( ] ) full_proposal_puzzle = curry_singleton(proposal_id, proposal_info.current_innerpuz) - list_of_coinspends = [make_spend(proposal_info.current_coin, full_proposal_puzzle, fullsol)] - unsigned_spend_bundle = SpendBundle(list_of_coinspends, G2Element()) + list_of_coinspends = [ + make_spend(proposal_info.current_coin, full_proposal_puzzle, fullsol), + *dao_cat_spend.coin_spends, + ] + spend_bundle = SpendBundle(list_of_coinspends, G2Element()) if fee > 0: - chia_tx = await self.standard_wallet.create_tandem_xch_tx( + await self.standard_wallet.create_tandem_xch_tx( fee, tx_config, action_scope, ) - assert chia_tx.spend_bundle is not None - spend_bundle = unsigned_spend_bundle.aggregate([unsigned_spend_bundle, dao_cat_spend, chia_tx.spend_bundle]) - else: - spend_bundle = unsigned_spend_bundle.aggregate([unsigned_spend_bundle, dao_cat_spend]) record = TransactionRecord( confirmed_at_height=uint32(0), @@ -1146,7 +1142,8 @@ async def generate_proposal_vote_spend( memos=[], valid_times=parse_timelock_info(extra_conditions), ) - return [record] + async with action_scope.use() as interface: + interface.side_effects.transactions.append(record) async def create_proposal_close_spend( self, @@ -1157,7 +1154,7 @@ async def create_proposal_close_spend( fee: uint64 = uint64(0), self_destruct: bool = False, extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> TransactionRecord: + ) -> None: self.log.info(f"Trying to create a proposal close spend with ID: {proposal_id}") proposal_info = None for pi in self.dao_info.proposals_list: @@ -1485,11 +1482,8 @@ async def create_proposal_close_spend( # pylint: disable-next=E0606 spend_bundle = SpendBundle([proposal_cs, timer_cs, treasury_cs], AugSchemeMPL.aggregate([])) if fee > 0: - chia_tx = await self.standard_wallet.create_tandem_xch_tx(fee, tx_config, action_scope) - assert chia_tx.spend_bundle is not None - full_spend = SpendBundle.aggregate([spend_bundle, chia_tx.spend_bundle]) - else: - full_spend = SpendBundle.aggregate([spend_bundle]) + await self.standard_wallet.create_tandem_xch_tx(fee, tx_config, action_scope) + full_spend = spend_bundle if cat_spend_bundle is not None: full_spend = full_spend.aggregate([full_spend, cat_spend_bundle]) if delegated_puzzle_sb is not None: @@ -1514,7 +1508,8 @@ async def create_proposal_close_spend( memos=[], valid_times=parse_timelock_info(extra_conditions), ) - return record + async with action_scope.use() as interface: + interface.side_effects.transactions.append(record) async def fetch_proposed_puzzle_reveal(self, proposal_id: bytes32) -> Program: wallet_node: Any = self.wallet_state_manager.wallet_node @@ -1549,11 +1544,11 @@ async def _create_treasury_fund_transaction( action_scope: WalletActionScope, fee: uint64 = uint64(0), extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> List[TransactionRecord]: + ) -> None: if funding_wallet.type() == WalletType.STANDARD_WALLET.value: p2_singleton_puzhash = get_p2_singleton_puzhash(self.dao_info.treasury_id, asset_id=None) wallet: Wallet = funding_wallet # type: ignore[assignment] - return await wallet.generate_signed_transaction( + await wallet.generate_signed_transaction( amount, p2_singleton_puzhash, tx_config, @@ -1566,7 +1561,7 @@ async def _create_treasury_fund_transaction( # generate_signed_transaction has a different type signature in Wallet and CATWallet # CATWallet uses a List of amounts and a List of puzhashes as the first two arguments p2_singleton_puzhash = get_p2_singleton_puzhash(self.dao_info.treasury_id) - tx_records: List[TransactionRecord] = await cat_wallet.generate_signed_transaction( + await cat_wallet.generate_signed_transaction( [amount], [p2_singleton_puzhash], tx_config, @@ -1574,7 +1569,6 @@ async def _create_treasury_fund_transaction( fee=fee, extra_conditions=extra_conditions, ) - return tx_records else: # pragma: no cover raise ValueError(f"Assets of type {funding_wallet.type()} are not currently supported.") @@ -1586,13 +1580,12 @@ async def create_add_funds_to_treasury_spend( fee: uint64 = uint64(0), funding_wallet_id: uint32 = uint32(1), extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> TransactionRecord: + ) -> None: # set up the p2_singleton funding_wallet = self.wallet_state_manager.wallets[funding_wallet_id] - tx_record = await self._create_treasury_fund_transaction( + await self._create_treasury_fund_transaction( funding_wallet, amount, tx_config, action_scope, fee, extra_conditions=extra_conditions ) - return tx_record[0] async def fetch_singleton_lineage_proof(self, coin: Coin) -> LineageProof: wallet_node: Any = self.wallet_state_manager.wallet_node @@ -1613,9 +1606,8 @@ async def free_coins_from_finished_proposals( action_scope: WalletActionScope, fee: uint64 = uint64(0), extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> TransactionRecord: + ) -> None: dao_cat_wallet: DAOCATWallet = self.wallet_state_manager.wallets[self.dao_info.dao_cat_wallet_id] - full_spend = None spends = [] closed_list = [] finished_puz = None @@ -1642,9 +1634,7 @@ async def free_coins_from_finished_proposals( full_spend = SpendBundle.aggregate(spends) if fee > 0: - chia_tx = await self.standard_wallet.create_tandem_xch_tx(fee, tx_config, action_scope) - assert chia_tx.spend_bundle is not None - full_spend = full_spend.aggregate([full_spend, chia_tx.spend_bundle]) + await self.standard_wallet.create_tandem_xch_tx(fee, tx_config, action_scope) assert isinstance(finished_puz, Program) record = TransactionRecord( @@ -1666,7 +1656,8 @@ async def free_coins_from_finished_proposals( memos=[], valid_times=parse_timelock_info(extra_conditions), ) - return record + async with action_scope.use() as interface: + interface.side_effects.transactions.append(record) async def parse_proposal(self, proposal_id: bytes32) -> Dict[str, Any]: for prop_info in self.dao_info.proposals_list: diff --git a/chia/wallet/did_wallet/did_wallet.py b/chia/wallet/did_wallet/did_wallet.py index 7c6015be8ea5..2573625b535e 100644 --- a/chia/wallet/did_wallet/did_wallet.py +++ b/chia/wallet/did_wallet/did_wallet.py @@ -142,13 +142,11 @@ async def create_new_did_wallet( raise ValueError("Not enough balance") try: - txs = await self.generate_new_decentralised_id(amount, tx_config, action_scope, fee, extra_conditions) + await self.generate_new_decentralised_id(amount, tx_config, action_scope, fee, extra_conditions) except Exception: await wallet_state_manager.user_store.delete_wallet(self.id()) raise - await self.wallet_state_manager.add_pending_transactions(txs) - await self.wallet_state_manager.add_new_wallet(self) return self @@ -559,8 +557,6 @@ def get_my_DID(self) -> str: return core.hex() async def set_name(self, new_name: str): - import dataclasses - new_info = dataclasses.replace(self.wallet_info, name=new_name) self.wallet_info = new_info await self.wallet_state_manager.user_store.update_wallet(self.wallet_info) @@ -574,7 +570,7 @@ async def create_update_spend( action_scope: WalletActionScope, fee: uint64 = uint64(0), extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> List[TransactionRecord]: + ) -> None: assert self.did_info.current_inner is not None assert self.did_info.origin_coin is not None coin = await self.get_coin() @@ -638,17 +634,13 @@ async def create_update_spend( spend_bundle = SpendBundle(list_of_coinspends, G2Element()) if fee > 0: coin_name = coin.name() - chia_tx = await self.standard_wallet.create_tandem_xch_tx( + await self.standard_wallet.create_tandem_xch_tx( fee, tx_config, action_scope, extra_conditions=(AssertCoinAnnouncement(asserted_id=coin_name, asserted_msg=coin_name),), ) - else: - chia_tx = None - if chia_tx is not None and chia_tx.spend_bundle is not None: - spend_bundle = SpendBundle.aggregate([spend_bundle, chia_tx.spend_bundle]) - chia_tx = dataclasses.replace(chia_tx, spend_bundle=None) + did_record = TransactionRecord( confirmed_at_height=uint32(0), created_at_time=uint64(int(time.time())), @@ -669,11 +661,8 @@ async def create_update_spend( valid_times=parse_timelock_info(extra_conditions), ) - txs = [did_record] - if chia_tx is not None: - txs.append(chia_tx) - - return txs + async with action_scope.use() as interface: + interface.side_effects.transactions.append(did_record) async def transfer_did( self, @@ -683,7 +672,7 @@ async def transfer_did( tx_config: TXConfig, action_scope: WalletActionScope, extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> List[TransactionRecord]: + ) -> None: """ Transfer the current DID to another owner :param new_puzhash: New owner's p2_puzzle @@ -739,17 +728,13 @@ async def transfer_did( spend_bundle = SpendBundle(list_of_coinspends, G2Element()) if fee > 0: coin_name = coin.name() - chia_tx = await self.standard_wallet.create_tandem_xch_tx( + await self.standard_wallet.create_tandem_xch_tx( fee, tx_config, action_scope, extra_conditions=(AssertCoinAnnouncement(asserted_id=coin_name, asserted_msg=coin_name),), ) - else: - chia_tx = None - if chia_tx is not None and chia_tx.spend_bundle is not None: - spend_bundle = SpendBundle.aggregate([spend_bundle, chia_tx.spend_bundle]) - chia_tx = dataclasses.replace(chia_tx, spend_bundle=None) + did_record = TransactionRecord( confirmed_at_height=uint32(0), created_at_time=uint64(int(time.time())), @@ -769,10 +754,9 @@ async def transfer_did( memos=list(compute_memos(spend_bundle).items()), valid_times=parse_timelock_info(extra_conditions), ) - txs = [did_record] - if chia_tx is not None: - txs.append(chia_tx) - return txs + + async with action_scope.use() as interface: + interface.side_effects.transactions.append(did_record) # The message spend can tests\wallet\rpc\test_wallet_rpc.py send messages and also change your innerpuz async def create_message_spend( @@ -780,7 +764,7 @@ async def create_message_spend( tx_config: TXConfig, action_scope: WalletActionScope, extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> TransactionRecord: + ) -> None: assert self.did_info.current_inner is not None assert self.did_info.origin_coin is not None coin = await self.get_coin() @@ -827,7 +811,7 @@ async def create_message_spend( ) list_of_coinspends = [make_spend(coin, full_puzzle, fullsol)] unsigned_spend_bundle = SpendBundle(list_of_coinspends, G2Element()) - return TransactionRecord( + tx = TransactionRecord( confirmed_at_height=uint32(0), created_at_time=uint64(int(time.time())), to_puzzle_hash=p2_ph, @@ -846,11 +830,11 @@ async def create_message_spend( memos=list(compute_memos(unsigned_spend_bundle).items()), valid_times=parse_timelock_info(extra_conditions), ) + async with action_scope.use() as interface: + interface.side_effects.transactions.append(tx) # This is used to cash out, or update the id_list - async def create_exit_spend( - self, puzhash: bytes32, tx_config: TXConfig, action_scope: WalletActionScope - ) -> List[TransactionRecord]: + async def create_exit_spend(self, puzhash: bytes32, tx_config: TXConfig, action_scope: WalletActionScope) -> None: assert self.did_info.current_inner is not None assert self.did_info.origin_coin is not None coin = await self.get_coin() @@ -881,26 +865,28 @@ async def create_exit_spend( list_of_coinspends = [make_spend(coin, full_puzzle, fullsol)] spend_bundle = SpendBundle(list_of_coinspends, G2Element()) - did_record = TransactionRecord( - confirmed_at_height=uint32(0), - created_at_time=uint64(int(time.time())), - to_puzzle_hash=await self.standard_wallet.get_puzzle_hash(False), - amount=uint64(coin.amount), - fee_amount=uint64(0), - confirmed=False, - sent=uint32(0), - spend_bundle=spend_bundle, - additions=spend_bundle.additions(), - removals=spend_bundle.removals(), - wallet_id=self.wallet_info.id, - sent_to=[], - trade_id=None, - type=uint32(TransactionType.OUTGOING_TX.value), - name=bytes32.secret(), - memos=list(compute_memos(spend_bundle).items()), - valid_times=ConditionValidTimes(), - ) - return [did_record] + async with action_scope.use() as interface: + interface.side_effects.transactions.append( + TransactionRecord( + confirmed_at_height=uint32(0), + created_at_time=uint64(int(time.time())), + to_puzzle_hash=await self.standard_wallet.get_puzzle_hash(False), + amount=uint64(coin.amount), + fee_amount=uint64(0), + confirmed=False, + sent=uint32(0), + spend_bundle=spend_bundle, + additions=spend_bundle.additions(), + removals=spend_bundle.removals(), + wallet_id=self.wallet_info.id, + sent_to=[], + trade_id=None, + type=uint32(TransactionType.OUTGOING_TX.value), + name=bytes32.secret(), + memos=list(compute_memos(spend_bundle).items()), + valid_times=ConditionValidTimes(), + ) + ) # Pushes a SpendBundle to create a message coin on the blockchain # Returns a SpendBundle for the recoverer to spend the message coin @@ -912,7 +898,7 @@ async def create_attestment( tx_config: TXConfig, action_scope: WalletActionScope, extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> Tuple[TransactionRecord, SpendBundle, str]: + ) -> Tuple[SpendBundle, str]: """ Create an attestment TODO: @@ -984,9 +970,11 @@ async def create_attestment( memos=list(compute_memos(spend_bundle).items()), valid_times=parse_timelock_info(extra_conditions), ) + async with action_scope.use() as interface: + interface.side_effects.transactions.append(did_record) attest_str: str = f"{self.get_my_DID()}:{bytes(message_spend_bundle).hex()}:{coin.parent_coin_info.hex()}:" attest_str += f"{self.did_info.current_inner.get_tree_hash().hex()}:{coin.amount}" - return did_record, message_spend_bundle, attest_str + return message_spend_bundle, attest_str async def get_info_for_recovery(self) -> Optional[Tuple[bytes32, bytes32, uint64]]: assert self.did_info.current_inner is not None @@ -1038,7 +1026,8 @@ async def recovery_spend( parent_innerpuzhash_amounts_for_recovery_ids: List[Tuple[bytes, bytes, int]], pubkey: G1Element, spend_bundle: SpendBundle, - ) -> List[TransactionRecord]: + action_scope: WalletActionScope, + ) -> None: assert self.did_info.origin_coin is not None # innersol is mode new_amount_or_p2_solution new_inner_puzhash parent_innerpuzhash_amounts_for_recovery_ids pubkey recovery_list_reveal my_id) # noqa @@ -1077,25 +1066,28 @@ async def recovery_spend( spend_bundle = spend_bundle.aggregate([spend_bundle, SpendBundle(list_of_coinspends, G2Element())]) - did_record = TransactionRecord( - confirmed_at_height=uint32(0), - created_at_time=uint64(int(time.time())), - to_puzzle_hash=await self.standard_wallet.get_puzzle_hash(False), - amount=uint64(coin.amount), - fee_amount=uint64(0), - confirmed=False, - sent=uint32(0), - spend_bundle=spend_bundle, - additions=spend_bundle.additions(), - removals=spend_bundle.removals(), - wallet_id=self.wallet_info.id, - sent_to=[], - trade_id=None, - type=uint32(TransactionType.OUTGOING_TX.value), - name=bytes32.secret(), - memos=list(compute_memos(spend_bundle).items()), - valid_times=ConditionValidTimes(), - ) + async with action_scope.use() as interface: + interface.side_effects.transactions.append( + TransactionRecord( + confirmed_at_height=uint32(0), + created_at_time=uint64(int(time.time())), + to_puzzle_hash=await self.standard_wallet.get_puzzle_hash(False), + amount=uint64(coin.amount), + fee_amount=uint64(0), + confirmed=False, + sent=uint32(0), + spend_bundle=spend_bundle, + additions=spend_bundle.additions(), + removals=spend_bundle.removals(), + wallet_id=self.wallet_info.id, + sent_to=[], + trade_id=None, + type=uint32(TransactionType.OUTGOING_TX.value), + name=bytes32.secret(), + memos=list(compute_memos(spend_bundle).items()), + valid_times=ConditionValidTimes(), + ) + ) new_did_info = DIDInfo( origin_coin=self.did_info.origin_coin, backup_ids=self.did_info.backup_ids, @@ -1109,7 +1101,6 @@ async def recovery_spend( metadata=self.did_info.metadata, ) await self.save_info(new_did_info) - return [did_record] async def get_new_p2_inner_hash(self) -> bytes32: puzzle = await self.get_new_p2_inner_puzzle() @@ -1219,7 +1210,7 @@ async def generate_new_decentralised_id( action_scope: WalletActionScope, fee: uint64 = uint64(0), extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> List[TransactionRecord]: + ) -> None: """ This must be called under the wallet state manager lock """ @@ -1237,7 +1228,7 @@ async def generate_new_decentralised_id( announcement_message = Program.to([did_puzzle_hash, amount, bytes(0x80)]).get_tree_hash() - [tx_record] = await self.standard_wallet.generate_signed_transaction( + await self.standard_wallet.generate_signed_transaction( amount=amount, puzzle_hash=genesis_launcher_puz.get_tree_hash(), tx_config=tx_config, @@ -1285,8 +1276,7 @@ async def generate_new_decentralised_id( ) await self.save_info(did_info) eve_spend = await self.generate_eve_spend(eve_coin, did_full_puz, did_inner) - assert tx_record.spend_bundle is not None - full_spend = SpendBundle.aggregate([tx_record.spend_bundle, eve_spend, launcher_sb]) + full_spend = SpendBundle.aggregate([eve_spend, launcher_sb]) assert self.did_info.origin_coin is not None assert self.did_info.current_inner is not None @@ -1309,8 +1299,8 @@ async def generate_new_decentralised_id( memos=[], valid_times=ConditionValidTimes(), ) - regular_record = dataclasses.replace(tx_record, spend_bundle=None) - return [did_record, regular_record] + async with action_scope.use() as interface: + interface.side_effects.transactions.append(did_record) async def generate_eve_spend( self, diff --git a/chia/wallet/nft_wallet/nft_wallet.py b/chia/wallet/nft_wallet/nft_wallet.py index 552e31175963..fb1fee9c4917 100644 --- a/chia/wallet/nft_wallet/nft_wallet.py +++ b/chia/wallet/nft_wallet/nft_wallet.py @@ -303,7 +303,7 @@ async def get_did_approval_info( tx_config: TXConfig, action_scope: WalletActionScope, did_id: Optional[bytes32] = None, - ) -> Tuple[bytes32, SpendBundle]: + ) -> bytes32: """Get DID spend with announcement created we need to transfer NFT with did with current inner hash of DID We also store `did_id` and then iterate to find the did wallet as we'd otherwise have to subscribe to @@ -311,23 +311,21 @@ async def get_did_approval_info( """ if did_id is None: did_id = self.did_id + did_inner_hash: bytes32 for _, wallet in self.wallet_state_manager.wallets.items(): self.log.debug("Checking wallet type %s", wallet.type()) if wallet.type() == WalletType.DECENTRALIZED_ID: self.log.debug("Found a DID wallet, checking did: %r == %r", wallet.get_my_DID(), did_id) if bytes32.fromhex(wallet.get_my_DID()) == did_id: self.log.debug("Creating announcement from DID for nft_ids: %s", nft_ids) - did_bundle = ( - await wallet.create_message_spend( - tx_config, action_scope, extra_conditions=(CreatePuzzleAnnouncement(id) for id in nft_ids) - ) - ).spend_bundle - self.log.debug("Sending DID announcement from puzzle: %s", did_bundle.removals()) + await wallet.create_message_spend( + tx_config, action_scope, extra_conditions=(CreatePuzzleAnnouncement(id) for id in nft_ids) + ) did_inner_hash = wallet.did_info.current_inner.get_tree_hash() break else: raise ValueError(f"Missing DID Wallet for did_id: {did_id}") - return did_inner_hash, did_bundle + return did_inner_hash async def generate_new_nft( self, @@ -340,7 +338,7 @@ async def generate_new_nft( did_id: Optional[bytes] = None, fee: uint64 = uint64(0), extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> List[TransactionRecord]: + ) -> bytes32: """ This must be called under the wallet state manager lock """ @@ -391,7 +389,7 @@ async def generate_new_nft( "Creating transaction for launcher: %s and other coins: %s (%s)", origin, coins, announcement_message ) # store the launcher transaction in the wallet state - [tx_record] = await self.standard_wallet.generate_signed_transaction( + await self.standard_wallet.generate_signed_transaction( uint64(amount), nft_puzzles.LAUNCHER_PUZZLE_HASH, tx_config, @@ -413,19 +411,14 @@ async def generate_new_nft( eve_coin = Coin(launcher_coin.name(), eve_fullpuz_hash, uint64(amount)) - if tx_record.spend_bundle is None: - raise ValueError("Couldn't produce a launcher spend") # pragma: no cover - - bundles_to_agg = [tx_record.spend_bundle, launcher_sb] + async with action_scope.use() as interface: + interface.side_effects.extra_spends.append(launcher_sb) # Create inner solution for eve spend did_inner_hash = b"" if did_id is not None: if did_id != b"": - did_inner_hash, did_bundle = await self.get_did_approval_info( - [launcher_coin.name()], tx_config, action_scope - ) - bundles_to_agg.append(did_bundle) + did_inner_hash = await self.get_did_approval_info([launcher_coin.name()], tx_config, action_scope) nft_coin = NFTCoinInfo( nft_id=launcher_coin.name(), coin=eve_coin, @@ -435,7 +428,7 @@ async def generate_new_nft( minter_did=bytes32(did_id) if did_id is not None and did_id != b"" else None, ) # Don't set fee, it is covered in the tx_record - txs = await self.generate_signed_transaction( + await self.generate_signed_transaction( [uint64(eve_coin.amount)], [target_puzzle_hash], tx_config, @@ -445,8 +438,8 @@ async def generate_new_nft( new_did_inner_hash=did_inner_hash, memos=[[target_puzzle_hash]], ) - txs.append(dataclasses.replace(tx_record, spend_bundle=SpendBundle.aggregate(bundles_to_agg))) - return txs + + return launcher_coin.name() async def update_metadata( self, @@ -457,7 +450,7 @@ async def update_metadata( action_scope: WalletActionScope, fee: uint64 = uint64(0), extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> List[TransactionRecord]: + ) -> None: uncurried_nft = UncurriedNFT.uncurry(*nft_coin_info.full_puzzle.uncurry()) assert uncurried_nft is not None puzzle_hash = uncurried_nft.p2_puzzle.get_tree_hash() @@ -467,7 +460,7 @@ async def update_metadata( nft_coin_info.coin.name(), uncurried_nft.metadata, ) - txs = await self.generate_signed_transaction( + await self.generate_signed_transaction( [uint64(nft_coin_info.coin.amount)], [puzzle_hash], tx_config, @@ -479,7 +472,6 @@ async def update_metadata( ) await self.update_coin_status(nft_coin_info.coin.name(), True) self.wallet_state_manager.state_changed("nft_coin_updated", self.wallet_info.id) - return txs async def get_current_nfts(self, start_index: int = 0, count: int = 50) -> List[NFTCoinInfo]: return await self.nft_store.get_nft_list(wallet_id=self.id(), start_index=start_index, count=count) @@ -589,7 +581,7 @@ async def generate_signed_transaction( memos: Optional[List[List[bytes]]] = None, extra_conditions: Tuple[Condition, ...] = tuple(), **kwargs: Unpack[GSTOptionalArgs], - ) -> List[TransactionRecord]: + ) -> None: nft_coin: Optional[NFTCoinInfo] = kwargs.get("nft_coin", None) new_owner: Optional[bytes] = kwargs.get("new_owner", None) new_did_inner_hash: Optional[bytes] = kwargs.get("new_did_inner_hash", None) @@ -609,7 +601,7 @@ async def generate_signed_transaction( payments.append(Payment(puzhash, amount, memos_with_hint)) payment_sum = sum(p.amount for p in payments) - unsigned_spend_bundle, chia_tx = await self.generate_unsigned_spendbundle( + unsigned_spend_bundle = await self.generate_unsigned_spendbundle( payments, tx_config, action_scope, @@ -623,17 +615,15 @@ async def generate_signed_transaction( extra_conditions=extra_conditions, ) spend_bundle = SpendBundle.aggregate([unsigned_spend_bundle] + additional_bundles) - if chia_tx is not None and chia_tx.spend_bundle is not None: - spend_bundle = SpendBundle.aggregate([spend_bundle, chia_tx.spend_bundle]) - chia_tx = dataclasses.replace(chia_tx, spend_bundle=None) - other_tx_removals: Set[Coin] = {removal for removal in chia_tx.removals} - other_tx_additions: Set[Coin] = {addition for addition in chia_tx.additions} - else: - other_tx_removals = set() - other_tx_additions = set() - tx_list = [ - TransactionRecord( + async with action_scope.use() as interface: + other_tx_removals: Set[Coin] = { + removal for tx in interface.side_effects.transactions for removal in tx.removals + } + other_tx_additions: Set[Coin] = { + addition for tx in interface.side_effects.transactions for addition in tx.additions + } + tx = TransactionRecord( confirmed_at_height=uint32(0), created_at_time=uint64(int(time.time())), to_puzzle_hash=puzzle_hashes[0], @@ -651,13 +641,9 @@ async def generate_signed_transaction( name=spend_bundle.name(), memos=list(compute_memos(spend_bundle).items()), valid_times=parse_timelock_info(extra_conditions), - ), - ] - - if chia_tx is not None: - tx_list.append(chia_tx) + ) - return tx_list + interface.side_effects.transactions.append(tx) async def generate_unsigned_spendbundle( self, @@ -672,7 +658,7 @@ async def generate_unsigned_spendbundle( metadata_update: Optional[Tuple[str, str]] = None, nft_coin: Optional[NFTCoinInfo] = None, extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> Tuple[SpendBundle, Optional[TransactionRecord]]: + ) -> SpendBundle: if nft_coin is None: if coins is None or not len(coins) == 1: # Make sure the user is specifying which specific NFT coin to use @@ -684,14 +670,12 @@ async def generate_unsigned_spendbundle( coin_name = nft_coin.coin.name() if fee > 0: - chia_tx = await self.standard_wallet.create_tandem_xch_tx( + await self.standard_wallet.create_tandem_xch_tx( fee, tx_config, action_scope, extra_conditions=(AssertCoinAnnouncement(asserted_id=coin_name, asserted_msg=coin_name),), ) - else: - chia_tx = None unft = UncurriedNFT.uncurry(*nft_coin.full_puzzle.uncurry()) assert unft is not None @@ -743,7 +727,7 @@ async def generate_unsigned_spendbundle( nft_spend_bundle = SpendBundle([coin_spend], G2Element()) - return nft_spend_bundle, chia_tx + return nft_spend_bundle @staticmethod def royalty_calculation( @@ -774,7 +758,7 @@ async def make_nft1_offer( action_scope: WalletActionScope, fee: uint64, extra_conditions: Tuple[Condition, ...], - ) -> Tuple[Offer, List[TransactionRecord]]: + ) -> Offer: # First, let's take note of all the royalty enabled NFTs royalty_nft_asset_dict: Dict[bytes32, int] = {} for asset, amount in offer_dict.items(): @@ -918,48 +902,48 @@ async def make_nft1_offer( wallet = await wallet_state_manager.get_wallet_for_asset_id(asset.hex()) # First, sending all the coins to the OFFER_MOD - if wallet.type() == WalletType.STANDARD_WALLET: - payments = royalty_payments[asset] if asset in royalty_payments else [] - payment_sum = sum(p.amount for _, p in payments) - [tx] = await wallet.generate_signed_transaction( - abs(amount), - OFFER_MOD_HASH, - tx_config, - action_scope, - primaries=[Payment(OFFER_MOD_HASH, uint64(payment_sum))] if payment_sum > 0 else [], - fee=fee, - coins=offered_coins_by_asset[asset], - extra_conditions=(*extra_conditions, *announcements_to_assert), - ) - txs = [tx] - elif asset not in fungible_asset_dict: - assert asset is not None - txs = await wallet.generate_signed_transaction( - [abs(amount)], - [OFFER_MOD_HASH], - tx_config, - action_scope, - fee=fee_left_to_pay, - coins=offered_coins_by_asset[asset], - trade_prices_list=[ - list(price) - for price in trade_prices - if math.floor(price[0] * (offered_royalty_percentages[asset] / 10000)) != 0 - ], - extra_conditions=(*extra_conditions, *announcements_to_assert), - ) - else: - payments = royalty_payments[asset] if asset in royalty_payments else [] - txs = await wallet.generate_signed_transaction( - [abs(amount), sum(p.amount for _, p in payments)], - [OFFER_MOD_HASH, OFFER_MOD_HASH], - tx_config, - action_scope, - fee=fee_left_to_pay, - coins=offered_coins_by_asset[asset], - extra_conditions=(*extra_conditions, *announcements_to_assert), - ) - all_transactions.extend(txs) + async with wallet_state_manager.new_action_scope(push=False) as inner_action_scope: + if wallet.type() == WalletType.STANDARD_WALLET: + payments = royalty_payments[asset] if asset in royalty_payments else [] + payment_sum = sum(p.amount for _, p in payments) + await wallet.generate_signed_transaction( + abs(amount), + OFFER_MOD_HASH, + tx_config, + inner_action_scope, + primaries=[Payment(OFFER_MOD_HASH, uint64(payment_sum))] if payment_sum > 0 else [], + fee=fee, + coins=offered_coins_by_asset[asset], + extra_conditions=(*extra_conditions, *announcements_to_assert), + ) + elif asset not in fungible_asset_dict: + assert asset is not None + await wallet.generate_signed_transaction( + [abs(amount)], + [OFFER_MOD_HASH], + tx_config, + inner_action_scope, + fee=fee_left_to_pay, + coins=offered_coins_by_asset[asset], + trade_prices_list=[ + list(price) + for price in trade_prices + if math.floor(price[0] * (offered_royalty_percentages[asset] / 10000)) != 0 + ], + extra_conditions=(*extra_conditions, *announcements_to_assert), + ) + else: + payments = royalty_payments[asset] if asset in royalty_payments else [] + await wallet.generate_signed_transaction( + [abs(amount), sum(p.amount for _, p in payments)], + [OFFER_MOD_HASH, OFFER_MOD_HASH], + tx_config, + inner_action_scope, + fee=fee_left_to_pay, + coins=offered_coins_by_asset[asset], + extra_conditions=(*extra_conditions, *announcements_to_assert), + ) + all_transactions.extend(inner_action_scope.side_effects.transactions) fee_left_to_pay = uint64(0) extra_conditions = tuple() @@ -1013,7 +997,7 @@ async def make_nft1_offer( offer_puzzle = construct_puzzle(driver_dict[asset], OFFER_MOD) royalty_ph = offer_puzzle.get_tree_hash() if royalty_coin is None: - for tx in txs: + for tx in inner_action_scope.side_effects.transactions: if tx.spend_bundle is not None: for coin in tx.spend_bundle.additions(): royalty_payment_amount: int = sum(p.amount for _, p in payments) @@ -1070,7 +1054,10 @@ async def make_nft1_offer( txs_bundle = SpendBundle.aggregate([tx.spend_bundle for tx in all_transactions if tx.spend_bundle is not None]) aggregate_bundle = SpendBundle.aggregate([txs_bundle, *additional_bundles]) offer = Offer(notarized_payments, aggregate_bundle, driver_dict) - return offer, all_transactions + async with action_scope.use() as interface: + interface.side_effects.transactions.extend(all_transactions) + + return offer async def set_bulk_nft_did( self, @@ -1081,21 +1068,22 @@ async def set_bulk_nft_did( fee: uint64 = uint64(0), announcement_ids: List[bytes32] = [], extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> List[TransactionRecord]: + ) -> None: self.log.debug("Setting NFT DID with parameters: nft=%s did=%s", nft_list, did_id) - did_inner_hash = b"" nft_ids = [] - nft_tx_record = [] - spend_bundles = [] first = True for nft_coin_info in nft_list: nft_ids.append(nft_coin_info.nft_id) - if did_id != b"": - did_inner_hash, did_bundle = await self.get_did_approval_info( - announcement_ids, tx_config, action_scope, bytes32(did_id) - ) - if len(announcement_ids) > 0: - spend_bundles.append(did_bundle) + if did_id != b"" and len(announcement_ids) > 0: + await self.get_did_approval_info(announcement_ids, tx_config, action_scope, bytes32(did_id)) + + for _, wallet in self.wallet_state_manager.wallets.items(): + if wallet.type() == WalletType.DECENTRALIZED_ID: + if bytes32.fromhex(wallet.get_my_DID()) == did_id: + did_inner_hash = wallet.did_info.current_inner.get_tree_hash() + break + else: + raise ValueError(f"No DID wallet with id: {did_id.hex()}") for nft_coin_info in nft_list: unft = UncurriedNFT.uncurry(*nft_coin_info.full_puzzle.uncurry()) @@ -1104,33 +1092,19 @@ async def set_bulk_nft_did( if not first: fee = uint64(0) extra_conditions = tuple() - nft_tx_record.extend( - await self.generate_signed_transaction( - [uint64(nft_coin_info.coin.amount)], - puzzle_hashes_to_sign, - tx_config, - action_scope, - fee, - {nft_coin_info.coin}, - new_owner=did_id, - new_did_inner_hash=did_inner_hash, - extra_conditions=extra_conditions, - ) + await self.generate_signed_transaction( + [uint64(nft_coin_info.coin.amount)], + puzzle_hashes_to_sign, + tx_config, + action_scope, + fee, + {nft_coin_info.coin}, + new_owner=did_id, + new_did_inner_hash=did_inner_hash, + extra_conditions=extra_conditions, ) first = False - refined_tx_list: List[TransactionRecord] = [] - for tx in nft_tx_record: - if tx.spend_bundle is not None: - spend_bundles.append(tx.spend_bundle) - refined_tx_list.append(dataclasses.replace(tx, spend_bundle=None)) - - if len(spend_bundles) > 0: - spend_bundle = SpendBundle.aggregate(spend_bundles) - # Add all spend bundles to the first tx - refined_tx_list[0] = dataclasses.replace(refined_tx_list[0], spend_bundle=spend_bundle) - return refined_tx_list - async def bulk_transfer_nft( self, nft_list: List[NFTCoinInfo], @@ -1139,41 +1113,26 @@ async def bulk_transfer_nft( action_scope: WalletActionScope, fee: uint64 = uint64(0), extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> List[TransactionRecord]: + ) -> None: self.log.debug("Transfer NFTs %s to %s", nft_list, puzzle_hash.hex()) - nft_tx_record = [] - spend_bundles = [] first = True for nft_coin_info in nft_list: if not first: fee = uint64(0) extra_conditions = tuple() - nft_tx_record.extend( - await self.generate_signed_transaction( - [uint64(nft_coin_info.coin.amount)], - [puzzle_hash], - tx_config, - action_scope, - coins={nft_coin_info.coin}, - fee=fee, - new_owner=b"", - new_did_inner_hash=b"", - extra_conditions=extra_conditions, - ) + await self.generate_signed_transaction( + [uint64(nft_coin_info.coin.amount)], + [puzzle_hash], + tx_config, + action_scope, + coins={nft_coin_info.coin}, + fee=fee, + new_owner=b"", + new_did_inner_hash=b"", + extra_conditions=extra_conditions, ) first = False - refined_tx_list: List[TransactionRecord] = [] - for tx in nft_tx_record: - if tx.spend_bundle is not None: - spend_bundles.append(tx.spend_bundle) - refined_tx_list.append(dataclasses.replace(tx, spend_bundle=None)) - - if len(spend_bundles) > 0: - spend_bundle = SpendBundle.aggregate(spend_bundles) - # Add all spend bundles to the first tx - refined_tx_list[0] = dataclasses.replace(refined_tx_list[0], spend_bundle=spend_bundle) - return refined_tx_list async def set_nft_did( self, @@ -1183,21 +1142,17 @@ async def set_nft_did( action_scope: WalletActionScope, fee: uint64 = uint64(0), extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> List[TransactionRecord]: + ) -> None: self.log.debug("Setting NFT DID with parameters: nft=%s did=%s", nft_coin_info, did_id) unft = UncurriedNFT.uncurry(*nft_coin_info.full_puzzle.uncurry()) assert unft is not None nft_id = unft.singleton_launcher_id puzzle_hashes_to_sign = [unft.p2_puzzle.get_tree_hash()] did_inner_hash = b"" - additional_bundles = [] if did_id != b"": - did_inner_hash, did_bundle = await self.get_did_approval_info( - [nft_id], tx_config, action_scope, bytes32(did_id) - ) - additional_bundles.append(did_bundle) + did_inner_hash = await self.get_did_approval_info([nft_id], tx_config, action_scope, bytes32(did_id)) - nft_tx_record = await self.generate_signed_transaction( + await self.generate_signed_transaction( [uint64(nft_coin_info.coin.amount)], puzzle_hashes_to_sign, tx_config, @@ -1206,13 +1161,11 @@ async def set_nft_did( {nft_coin_info.coin}, new_owner=did_id, new_did_inner_hash=did_inner_hash, - additional_bundles=additional_bundles, extra_conditions=extra_conditions, ) await self.update_coin_status(nft_coin_info.coin.name(), True) self.wallet_state_manager.state_changed("nft_coin_did_set", self.wallet_info.id) - return nft_tx_record async def mint_from_did( self, @@ -1230,7 +1183,7 @@ async def mint_from_did( did_lineage_parent: Optional[bytes32] = None, fee: Optional[uint64] = uint64(0), extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> List[TransactionRecord]: + ) -> None: """ Minting NFTs from the DID linked wallet, also used for bulk minting NFTs. - The DID is spent along with an intermediate launcher puzzle which @@ -1317,7 +1270,6 @@ async def mint_from_did( intermediate_coin_spends = [] launcher_spends = [] launcher_ids = [] - eve_spends: List[SpendBundle] = [] p2_inner_puzzle = await self.standard_wallet.get_new_puzzle() p2_inner_ph = p2_inner_puzzle.get_tree_hash() @@ -1396,20 +1348,25 @@ async def mint_from_did( target_ph = target_list[mint_number - mint_number_start] else: target_ph = p2_inner_ph - eve_txs = await self.generate_signed_transaction( - [uint64(eve_coin.amount)], - [target_ph], - tx_config, - action_scope, - nft_coin=nft_coin, - new_owner=b"", - new_did_inner_hash=b"", - additional_bundles=[], - memos=[[target_ph]], + async with self.wallet_state_manager.new_action_scope(push=False) as inner_action_scope: + await self.generate_signed_transaction( + [uint64(eve_coin.amount)], + [target_ph], + tx_config, + inner_action_scope, + nft_coin=nft_coin, + new_owner=b"", + new_did_inner_hash=b"", + additional_bundles=[], + memos=[[target_ph]], + ) + + async with action_scope.use() as interface: + interface.side_effects.transactions.extend(inner_action_scope.side_effects.transactions) + + eve_sb = next( + tx.spend_bundle for tx in inner_action_scope.side_effects.transactions if tx.spend_bundle is not None ) - eve_sb = eve_txs[0].spend_bundle - assert eve_sb is not None - eve_spends.append(eve_sb) # Extract Puzzle Announcement from eve spend eve_sol = eve_sb.coin_spends[0].solution.to_program() conds = eve_fullpuz.run(eve_sol) @@ -1497,14 +1454,23 @@ async def mint_from_did( did_spend = make_spend(did_coin, did_full_puzzle, did_full_sol) # Collect up all the coin spends and sign them - list_of_coinspends = [did_spend] + intermediate_coin_spends + launcher_spends + list_of_coinspends = [did_spend] + intermediate_coin_spends + launcher_spends + xch_spend.coin_spends unsigned_spend_bundle = SpendBundle(list_of_coinspends, G2Element()) # Aggregate everything into a single spend bundle - total_spend = SpendBundle.aggregate([unsigned_spend_bundle, xch_spend, *eve_spends]) - - tx_record: TransactionRecord = dataclasses.replace(eve_txs[0], spend_bundle=total_spend) - return [tx_record] + async with action_scope.use() as interface: + # This should not be looked to for best practice. I think many of the spends generated above could call + # wallet methods that generate transactions and prevent most of the need for this. Refactoring this function + # is out of scope so for now we're using this hack. + if interface.side_effects.transactions[0].spend_bundle is None: + new_spend = unsigned_spend_bundle + else: + new_spend = SpendBundle.aggregate( + [interface.side_effects.transactions[0].spend_bundle, unsigned_spend_bundle] + ) + interface.side_effects.transactions[0] = dataclasses.replace( + interface.side_effects.transactions[0], spend_bundle=new_spend, name=new_spend.name() + ) async def mint_from_xch( self, @@ -1518,7 +1484,7 @@ async def mint_from_xch( xch_change_ph: Optional[bytes32] = None, fee: Optional[uint64] = uint64(0), extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> List[TransactionRecord]: + ) -> None: """ Minting NFTs from a single XCH spend using intermediate launcher puzzle :param metadata_list: A list of dicts containing the metadata for each NFT to be minted @@ -1566,7 +1532,6 @@ async def mint_from_xch( intermediate_coin_spends = [] launcher_spends = [] launcher_ids = [] - eve_spends: List[SpendBundle] = [] p2_inner_puzzle = await self.standard_wallet.get_new_puzzle() p2_inner_ph = p2_inner_puzzle.get_tree_hash() @@ -1640,20 +1605,25 @@ async def mint_from_xch( target_ph = target_list[mint_number - mint_number_start] else: target_ph = p2_inner_ph - eve_txs = await self.generate_signed_transaction( - [uint64(eve_coin.amount)], - [target_ph], - tx_config, - action_scope, - nft_coin=nft_coin, - new_owner=b"", - new_did_inner_hash=b"", - additional_bundles=[], - memos=[[target_ph]], + async with self.wallet_state_manager.new_action_scope(push=False) as inner_action_scope: + await self.generate_signed_transaction( + [uint64(eve_coin.amount)], + [target_ph], + tx_config, + inner_action_scope, + nft_coin=nft_coin, + new_owner=b"", + new_did_inner_hash=b"", + additional_bundles=[], + memos=[[target_ph]], + ) + + async with action_scope.use() as interface: + interface.side_effects.transactions.extend(inner_action_scope.side_effects.transactions) + + eve_sb = next( + tx.spend_bundle for tx in inner_action_scope.side_effects.transactions if tx.spend_bundle is not None ) - eve_sb = eve_txs[0].spend_bundle - assert eve_sb is not None - eve_spends.append(eve_sb) # Extract Puzzle Announcement from eve spend eve_sol = eve_sb.coin_spends[0].solution.to_program() conds = eve_fullpuz.run(eve_sol) @@ -1693,16 +1663,25 @@ async def mint_from_xch( else: solution = self.standard_wallet.make_solution(primaries=[], conditions=(primary_announcement,)) xch_spends.append(make_spend(xch_coin, puzzle, solution)) - xch_spend = SpendBundle(xch_spends, G2Element()) - # Collect up all the coin spends - list_of_coinspends = intermediate_coin_spends + launcher_spends + # Collect up all the coin spends and sign them + list_of_coinspends = intermediate_coin_spends + launcher_spends + xch_spends unsigned_spend_bundle = SpendBundle(list_of_coinspends, G2Element()) # Aggregate everything into a single spend bundle - total_spend = SpendBundle.aggregate([unsigned_spend_bundle, xch_spend, *eve_spends]) - tx_record: TransactionRecord = dataclasses.replace(eve_txs[0], spend_bundle=total_spend) - return [tx_record] + async with action_scope.use() as interface: + # This should not be looked to for best practice. I think many of the spends generated above could call + # wallet methods that generate transactions and prevent most of the need for this. Refactoring this function + # is out of scope so for now we're using this hack. + if interface.side_effects.transactions[0].spend_bundle is None: + new_spend = unsigned_spend_bundle + else: + new_spend = SpendBundle.aggregate( + [interface.side_effects.transactions[0].spend_bundle, unsigned_spend_bundle] + ) + interface.side_effects.transactions[0] = dataclasses.replace( + interface.side_effects.transactions[0], spend_bundle=new_spend, name=new_spend.name() + ) async def select_coins( self, diff --git a/chia/wallet/notification_manager.py b/chia/wallet/notification_manager.py index 66796b4b398e..bfff091183b2 100644 --- a/chia/wallet/notification_manager.py +++ b/chia/wallet/notification_manager.py @@ -1,6 +1,5 @@ from __future__ import annotations -import dataclasses import logging from typing import Any, Dict, List, Optional, Set, Tuple @@ -16,7 +15,6 @@ from chia.util.ints import uint32, uint64 from chia.wallet.conditions import AssertCoinAnnouncement, Condition from chia.wallet.notification_store import Notification, NotificationStore -from chia.wallet.transaction_record import TransactionRecord from chia.wallet.util.compute_memos import compute_memos_for_spend from chia.wallet.util.notifications import construct_notification from chia.wallet.util.tx_config import TXConfig @@ -92,7 +90,7 @@ async def send_new_notification( action_scope: WalletActionScope, fee: uint64 = uint64(0), extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> TransactionRecord: + ) -> None: coins: Set[Coin] = await self.wallet_state_manager.main_wallet.select_coins( uint64(amount + fee), tx_config.coin_selection_config ) @@ -106,7 +104,7 @@ async def send_new_notification( Program.to(None), ) extra_spend_bundle = SpendBundle([notification_spend], G2Element()) - [chia_tx] = await self.wallet_state_manager.main_wallet.generate_signed_transaction( + await self.wallet_state_manager.main_wallet.generate_signed_transaction( amount, notification_hash, tx_config, @@ -120,7 +118,5 @@ async def send_new_notification( AssertCoinAnnouncement(asserted_id=notification_coin.name(), asserted_msg=b""), ), ) - full_tx: TransactionRecord = dataclasses.replace( - chia_tx, spend_bundle=SpendBundle.aggregate([chia_tx.spend_bundle, extra_spend_bundle]) - ) - return full_tx + async with action_scope.use() as interface: + interface.side_effects.extra_spends.append(extra_spend_bundle) diff --git a/chia/wallet/puzzles/tails.py b/chia/wallet/puzzles/tails.py index b713d3f6637e..a8519ad87719 100644 --- a/chia/wallet/puzzles/tails.py +++ b/chia/wallet/puzzles/tails.py @@ -58,7 +58,7 @@ def solve(args: List[Program], solution_dict: Dict) -> Program: @classmethod async def generate_issuance_bundle( cls, wallet, cat_tail_info: Dict, amount: uint64, tx_config: TXConfig, action_scope: WalletActionScope - ) -> Tuple[TransactionRecord, SpendBundle]: + ) -> SpendBundle: raise NotImplementedError("Need to implement 'generate_issuance_bundle' on limitations programs") @@ -93,7 +93,7 @@ async def generate_issuance_bundle( tx_config: TXConfig, action_scope: WalletActionScope, fee: uint64 = uint64(0), - ) -> Tuple[TransactionRecord, SpendBundle]: + ) -> SpendBundle: coins = await wallet.standard_wallet.select_coins(amount + fee, tx_config.coin_selection_config) origin = coins.copy().pop() @@ -109,10 +109,13 @@ async def generate_issuance_bundle( minted_cat_puzzle_hash: bytes32 = construct_cat_puzzle(CAT_MOD, tail.get_tree_hash(), cat_inner).get_tree_hash() - [tx_record] = await wallet.standard_wallet.generate_signed_transaction( - amount, minted_cat_puzzle_hash, tx_config, action_scope, fee, coins, origin_id=origin_id - ) - assert tx_record.spend_bundle is not None + async with wallet.wallet_state_manager.new_action_scope(push=False) as inner_action_scope: + await wallet.standard_wallet.generate_signed_transaction( + amount, minted_cat_puzzle_hash, tx_config, inner_action_scope, fee, coins, origin_id=origin_id + ) + + async with action_scope.use() as interface: + interface.side_effects.transactions = inner_action_scope.side_effects.transactions inner_tree_hash = cat_inner.get_tree_hash() inner_solution = wallet.standard_wallet.add_condition_to_solution( @@ -123,7 +126,12 @@ async def generate_issuance_bundle( CAT_MOD, [ SpendableCAT( - list(filter(lambda a: a.amount == amount, tx_record.additions))[0], + list( + filter( + lambda a: a.amount == amount, + [add for tx in inner_action_scope.side_effects.transactions for add in tx.additions], + ) + )[0], tail.get_tree_hash(), cat_inner, inner_solution, @@ -135,7 +143,7 @@ async def generate_issuance_bundle( if wallet.cat_info.my_tail is None: await wallet.save_info(CATInfo(tail.get_tree_hash(), tail)) - return tx_record, SpendBundle.aggregate([tx_record.spend_bundle, eve_spend]) + return eve_spend class GenesisByPuzhash(LimitationsProgram): @@ -248,7 +256,7 @@ async def generate_issuance_bundle( tx_config: TXConfig, action_scope: WalletActionScope, fee: uint64 = uint64(0), - ) -> Tuple[TransactionRecord, SpendBundle]: + ) -> SpendBundle: if "coins" in tail_info: coins: List[Coin] = tail_info["coins"] origin_id = coins.copy().pop().name() @@ -275,10 +283,20 @@ async def generate_issuance_bundle( minted_cat_puzzle_hash: bytes32 = construct_cat_puzzle(CAT_MOD, tail.get_tree_hash(), cat_inner).get_tree_hash() - tx_records: List[TransactionRecord] = await wallet.standard_wallet.generate_signed_transaction( - amount, minted_cat_puzzle_hash, tx_config, action_scope, fee, coins=set(coins), origin_id=origin_id - ) - tx_record: TransactionRecord = tx_records[0] + async with wallet.wallet_state_manager.new_action_scope(push=False) as inner_action_scope: + await wallet.standard_wallet.generate_signed_transaction( + amount, + minted_cat_puzzle_hash, + tx_config, + inner_action_scope, + fee, + coins=set(coins), + origin_id=origin_id, + ) + + async with action_scope.use() as interface: + interface.side_effects.transactions.extend(inner_action_scope.side_effects.transactions) + tx_record: TransactionRecord = inner_action_scope.side_effects.transactions[0] assert tx_record.spend_bundle is not None payment = Payment(cat_inner.get_tree_hash(), amount) inner_solution = wallet.standard_wallet.add_condition_to_solution( @@ -303,7 +321,7 @@ async def generate_issuance_bundle( if wallet.cat_info.my_tail is None: await wallet.save_info(CATInfo(tail.get_tree_hash(), tail)) - return tx_record, SpendBundle.aggregate([tx_record.spend_bundle, eve_spend]) + return eve_spend # This should probably be much more elegant than just a dictionary with strings as identifiers diff --git a/chia/wallet/trade_manager.py b/chia/wallet/trade_manager.py index 4126306b50c1..4b7a0ca62439 100644 --- a/chia/wallet/trade_manager.py +++ b/chia/wallet/trade_manager.py @@ -6,7 +6,7 @@ from collections import deque from typing import TYPE_CHECKING, Any, Deque, Dict, List, Optional, Set, Tuple, Union -from typing_extensions import Literal, Never +from typing_extensions import Literal from chia.data_layer.data_layer_wallet import DataLayerWallet from chia.protocols.wallet_protocol import CoinState @@ -251,7 +251,7 @@ async def cancel_pending_offers( secure: bool = True, # Cancel with a transaction on chain trade_cache: Dict[bytes32, TradeRecord] = {}, # Optional pre-fetched trade records for optimization extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> List[TransactionRecord]: + ) -> None: """This will create a transaction that includes coins that were offered""" # Need to do some pre-figuring of announcements that will be need to be made @@ -284,7 +284,6 @@ async def cancel_pending_offers( announcement_assertions.rotate(1) all_txs: List[TransactionRecord] = [] - bundles: List[SpendBundle] = [] fee_to_pay: uint64 = fee for trade, cancellation_coins in zip(trade_records, all_cancellation_coins): self.log.info(f"Secure-Cancel pending offer with id trade_id {trade.trade_id.hex()}") @@ -327,74 +326,86 @@ async def cancel_pending_offers( selected_coins.add(coin) else: selected_coins = {coin} - [tx] = await wallet.generate_signed_transaction( - uint64(sum(c.amount for c in selected_coins) - fee_to_pay), - new_ph, - tx_config.override( - excluded_coin_ids=[], - ), - action_scope, - origin_id=coin.name(), - fee=fee_to_pay, - coins=selected_coins, - extra_conditions=(*extra_conditions, *announcement_conditions), - ) - if tx is not None and tx.spend_bundle is not None: - bundles.append(tx.spend_bundle) - cancellation_additions.extend(tx.spend_bundle.additions()) - all_txs.append(dataclasses.replace(tx, spend_bundle=None)) + async with self.wallet_state_manager.new_action_scope(push=False) as inner_action_scope: + await wallet.generate_signed_transaction( + uint64(sum(c.amount for c in selected_coins) - fee_to_pay), + new_ph, + tx_config.override( + excluded_coin_ids=[], + ), + inner_action_scope, + origin_id=coin.name(), + fee=fee_to_pay, + coins=selected_coins, + extra_conditions=(*extra_conditions, *announcement_conditions), + ) else: # ATTENTION: new_wallets assert isinstance(wallet, (CATWallet, DataLayerWallet, NFTWallet)) - txs = await wallet.generate_signed_transaction( - [coin.amount], - [new_ph], - tx_config.override( - excluded_coin_ids=[], - ), - action_scope, - fee=fee_to_pay, - coins={coin}, - extra_conditions=(*extra_conditions, *announcement_conditions), - ) - for tx in txs: - if tx is not None and tx.spend_bundle is not None: - bundles.append(tx.spend_bundle) - cancellation_additions.extend(tx.spend_bundle.additions()) - all_txs.append(dataclasses.replace(tx, spend_bundle=None)) + async with self.wallet_state_manager.new_action_scope(push=False) as inner_action_scope: + await wallet.generate_signed_transaction( + [coin.amount], + [new_ph], + tx_config.override( + excluded_coin_ids=[], + ), + inner_action_scope, + fee=fee_to_pay, + coins={coin}, + extra_conditions=(*extra_conditions, *announcement_conditions), + ) + + cancellation_additions.extend( + [ + add + for tx in inner_action_scope.side_effects.transactions + if tx.spend_bundle is not None + for add in tx.spend_bundle.additions() + ] + ) + all_txs.extend(inner_action_scope.side_effects.transactions) fee_to_pay = uint64(0) extra_conditions = tuple() - all_txs.append( - TransactionRecord( - confirmed_at_height=uint32(0), - created_at_time=uint64(int(time.time())), - to_puzzle_hash=new_ph, - amount=uint64(coin.amount), - fee_amount=fee, - confirmed=False, - sent=uint32(10), - spend_bundle=None, - additions=cancellation_additions, - removals=[coin], - wallet_id=wallet.id(), - sent_to=[], - trade_id=None, - type=uint32(TransactionType.INCOMING_TX.value), - name=cancellation_additions[0].name(), - memos=[], - valid_times=valid_times, - ) + incoming_tx = TransactionRecord( + confirmed_at_height=uint32(0), + created_at_time=uint64(int(time.time())), + to_puzzle_hash=new_ph, + amount=uint64(coin.amount), + fee_amount=fee, + confirmed=False, + sent=uint32(10), + spend_bundle=None, + additions=cancellation_additions, + removals=[coin], + wallet_id=wallet.id(), + sent_to=[], + trade_id=None, + type=uint32(TransactionType.INCOMING_TX.value), + name=cancellation_additions[0].name(), + memos=[], + valid_times=valid_times, ) + all_txs.append(incoming_tx) await self.trade_store.set_status(trade.trade_id, TradeStatus.PENDING_CANCEL) - # Aggregate spend bundles to the first tx - if len(all_txs) > 0: - all_txs[0] = dataclasses.replace(all_txs[0], spend_bundle=SpendBundle.aggregate(bundles)) - - all_txs = [dataclasses.replace(tx, fee_amount=fee) for tx in all_txs] - return all_txs + if secure: + async with action_scope.use() as interface: + # We have to combine the spend bundle for these since they are tied with announcements + all_tx_names = [tx.name for tx in all_txs] + interface.side_effects.transactions = [ + tx for tx in interface.side_effects.transactions if tx.name not in all_tx_names + ] + final_spend_bundle = SpendBundle.aggregate( + [tx.spend_bundle for tx in all_txs if tx.spend_bundle is not None] + ) + interface.side_effects.transactions.append( + dataclasses.replace(all_txs[0], spend_bundle=final_spend_bundle, name=final_spend_bundle.name()) + ) + interface.side_effects.transactions.extend( + [dataclasses.replace(tx, spend_bundle=None, fee_amount=fee) for tx in all_txs[1:]] + ) async def save_trade(self, trade: TradeRecord, offer: Offer) -> None: offer_name: bytes32 = offer.name() @@ -421,9 +432,7 @@ async def create_offer_for_ids( validate_only: bool = False, extra_conditions: Tuple[Condition, ...] = tuple(), taking: bool = False, - ) -> Union[ - Tuple[Literal[True], TradeRecord, List[TransactionRecord], None], Tuple[Literal[False], None, List[Never], str] - ]: + ) -> Union[Tuple[Literal[True], TradeRecord, None], Tuple[Literal[False], None, str]]: if driver_dict is None: driver_dict = {} if solver is None: @@ -441,7 +450,7 @@ async def create_offer_for_ids( if not result[0] or result[1] is None: raise Exception(f"Error creating offer: {result[2]}") - success, created_offer, tx_records, error = result + success, created_offer, error = result now = uint64(int(time.time())) trade_offer: TradeRecord = TradeRecord( @@ -462,7 +471,7 @@ async def create_offer_for_ids( if success is True and trade_offer is not None and not validate_only: await self.save_trade(trade_offer, created_offer) - return success, trade_offer, tx_records, error + return success, trade_offer, error async def _create_offer_for_ids( self, @@ -474,9 +483,7 @@ async def _create_offer_for_ids( fee: uint64 = uint64(0), extra_conditions: Tuple[Condition, ...] = tuple(), taking: bool = False, - ) -> Union[ - Tuple[Literal[True], Offer, List[TransactionRecord], None], Tuple[Literal[False], None, List[Never], str] - ]: + ) -> Union[Tuple[Literal[True], Offer, None], Tuple[Literal[False], None, str]]: """ Offer is dictionary of wallet ids and amount """ @@ -580,20 +587,18 @@ async def _create_offer_for_ids( requested_payments, driver_dict, taking ) - potential_special_offer: Optional[Tuple[Offer, List[TransactionRecord]]] = ( - await self.check_for_special_offer_making( - offer_dict_no_ints, - driver_dict, - tx_config, - action_scope, - solver, - fee, - extra_conditions, - ) + potential_special_offer: Optional[Offer] = await self.check_for_special_offer_making( + offer_dict_no_ints, + driver_dict, + tx_config, + action_scope, + solver, + fee, + extra_conditions, ) if potential_special_offer is not None: - return True, potential_special_offer[0], potential_special_offer[1], None + return True, potential_special_offer, None all_coins: List[Coin] = [c for coins in coins_to_offer.values() for c in coins] notarized_payments: Dict[Optional[bytes32], List[NotarizedPayment]] = Offer.notarize_payments( @@ -611,64 +616,67 @@ async def _create_offer_for_ids( wallet = self.wallet_state_manager.wallets.get(uint32(id)) else: wallet = await self.wallet_state_manager.get_wallet_for_asset_id(id.hex()) - # This should probably not switch on whether or not we're spending XCH but it has to for now - assert wallet is not None - if wallet.type() == WalletType.STANDARD_WALLET: - assert isinstance(wallet, Wallet) - [tx] = await wallet.generate_signed_transaction( - uint64(abs(offer_dict[id])), - Offer.ph(), - tx_config, - action_scope, - fee=fee_left_to_pay, - coins=selected_coins, - extra_conditions=(*extra_conditions, *announcements_to_assert), - ) - all_transactions.append(tx) - elif wallet.type() == WalletType.NFT: - assert isinstance(wallet, NFTWallet) - # This is to generate the tx for specific nft assets, i.e. not using - # wallet_id as the selector which would select any coins from nft_wallet - amounts = [coin.amount for coin in selected_coins] - txs = await wallet.generate_signed_transaction( - # [abs(offer_dict[id])], - amounts, - [Offer.ph()], - tx_config, - action_scope, - fee=fee_left_to_pay, - coins=selected_coins, - extra_conditions=(*extra_conditions, *announcements_to_assert), - ) - all_transactions.extend(txs) - else: - # ATTENTION: new_wallets - assert isinstance(wallet, (CATWallet, DataLayerWallet)) - txs = await wallet.generate_signed_transaction( - [uint64(abs(offer_dict[id]))], - [Offer.ph()], - tx_config, - action_scope, - fee=fee_left_to_pay, - coins=selected_coins, - extra_conditions=(*extra_conditions, *announcements_to_assert), - add_authorizations_to_cr_cats=False, - ) - all_transactions.extend(txs) + async with self.wallet_state_manager.new_action_scope(push=False) as inner_action_scope: + # This should probably not switch on whether or not we're spending XCH but it has to for now + assert wallet is not None + if wallet.type() == WalletType.STANDARD_WALLET: + assert isinstance(wallet, Wallet) + await wallet.generate_signed_transaction( + uint64(abs(offer_dict[id])), + Offer.ph(), + tx_config, + inner_action_scope, + fee=fee_left_to_pay, + coins=selected_coins, + extra_conditions=(*extra_conditions, *announcements_to_assert), + ) + elif wallet.type() == WalletType.NFT: + assert isinstance(wallet, NFTWallet) + # This is to generate the tx for specific nft assets, i.e. not using + # wallet_id as the selector which would select any coins from nft_wallet + amounts = [coin.amount for coin in selected_coins] + await wallet.generate_signed_transaction( + # [abs(offer_dict[id])], + amounts, + [Offer.ph()], + tx_config, + inner_action_scope, + fee=fee_left_to_pay, + coins=selected_coins, + extra_conditions=(*extra_conditions, *announcements_to_assert), + ) + else: + # ATTENTION: new_wallets + assert isinstance(wallet, (CATWallet, DataLayerWallet)) + await wallet.generate_signed_transaction( + [uint64(abs(offer_dict[id]))], + [Offer.ph()], + tx_config, + inner_action_scope, + fee=fee_left_to_pay, + coins=selected_coins, + extra_conditions=(*extra_conditions, *announcements_to_assert), + add_authorizations_to_cr_cats=False, + ) + + all_transactions.extend(inner_action_scope.side_effects.transactions) fee_left_to_pay = uint64(0) extra_conditions = tuple() + async with action_scope.use() as interface: + interface.side_effects.transactions.extend(all_transactions) + total_spend_bundle = SpendBundle.aggregate( [x.spend_bundle for x in all_transactions if x.spend_bundle is not None] ) offer = Offer(notarized_payments, total_spend_bundle, driver_dict) - return True, offer, all_transactions, None + return True, offer, None except Exception as e: self.log.exception("Error creating trade offer") - return False, None, [], str(e) + return False, None, str(e) async def maybe_create_wallets_for_offer(self, offer: Offer) -> None: for key in offer.arbitrage(): @@ -829,7 +837,7 @@ async def respond_to_offer( solver: Optional[Solver] = None, fee: uint64 = uint64(0), extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> Tuple[TradeRecord, List[TransactionRecord]]: + ) -> TradeRecord: if solver is None: solver = Solver({}) take_offer_dict: Dict[Union[bytes32, int], int] = {} @@ -855,24 +863,26 @@ async def respond_to_offer( valid: bool = await self.check_offer_validity(offer, peer) if not valid: raise ValueError("This offer is no longer valid") - result = await self._create_offer_for_ids( - take_offer_dict, - tx_config, - action_scope, - offer.driver_dict, - solver, - fee=fee, - extra_conditions=extra_conditions, - taking=True, - ) - if not result[0] or result[1] is None: - raise ValueError(result[2]) + # We need to sandbox the transactions here because we're going to make our own + async with self.wallet_state_manager.new_action_scope(push=False) as inner_action_scope: + result = await self._create_offer_for_ids( + take_offer_dict, + tx_config, + inner_action_scope, + offer.driver_dict, + solver, + fee=fee, + extra_conditions=extra_conditions, + taking=True, + ) + if not result[0] or result[1] is None: + raise ValueError(result[2]) - success, take_offer, _, error = result + success, take_offer, error = result - complete_offer, valid_spend_solver = await self.check_for_final_modifications( - Offer.aggregate([offer, take_offer]), solver, tx_config, action_scope - ) + complete_offer, valid_spend_solver = await self.check_for_final_modifications( + Offer.aggregate([offer, take_offer]), solver, tx_config, inner_action_scope + ) self.log.info("COMPLETE OFFER: %s", complete_offer.to_bech32()) assert complete_offer.is_valid() final_spend_bundle: SpendBundle = complete_offer.to_valid_spend( @@ -920,7 +930,10 @@ async def respond_to_offer( valid_times=ConditionValidTimes(), ) - return trade_record, [push_tx, *tx_records] + async with action_scope.use() as interface: + interface.side_effects.transactions.extend([push_tx, *tx_records]) + + return trade_record async def check_for_special_offer_making( self, @@ -931,7 +944,7 @@ async def check_for_special_offer_making( solver: Solver, fee: uint64 = uint64(0), extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> Optional[Tuple[Offer, List[TransactionRecord]]]: + ) -> Optional[Offer]: for puzzle_info in driver_dict.values(): if ( puzzle_info.check_type([AssetType.SINGLETON.value, AssetType.METADATA.value, AssetType.OWNERSHIP.value]) diff --git a/chia/wallet/vc_wallet/cr_cat_wallet.py b/chia/wallet/vc_wallet/cr_cat_wallet.py index 02e313dc7284..736369a24c44 100644 --- a/chia/wallet/vc_wallet/cr_cat_wallet.py +++ b/chia/wallet/vc_wallet/cr_cat_wallet.py @@ -1,6 +1,5 @@ from __future__ import annotations -import dataclasses import logging import time import traceback @@ -90,7 +89,8 @@ async def create_new_cat_wallet( action_scope: WalletActionScope, fee: uint64 = uint64(0), name: Optional[str] = None, - ) -> Tuple[CATWallet, List[TransactionRecord]]: # pragma: no cover + push: bool = False, + ) -> CATWallet: # pragma: no cover raise NotImplementedError("create_new_cat_wallet is a legacy method and is not available on CR-CAT wallets") @staticmethod @@ -407,7 +407,7 @@ async def _generate_unsigned_spendbundle( coins: Optional[Set[Coin]] = None, extra_conditions: Tuple[Condition, ...] = tuple(), add_authorizations_to_cr_cats: bool = True, - ) -> Tuple[SpendBundle, List[TransactionRecord]]: + ) -> SpendBundle: if cat_discrepancy is not None: extra_delta, tail_reveal, tail_solution = cat_discrepancy else: @@ -477,7 +477,6 @@ async def _generate_unsigned_spendbundle( vc: Optional[VerifiedCredential] = None vc_announcements_to_make: List[bytes] = [] inner_spends: List[Tuple[CRCAT, int, Program, Program]] = [] - chia_tx = None first = True announcement: CreateCoinAnnouncement coin_ids: List[bytes32] = [coin.name() for coin in cat_coins] @@ -512,7 +511,7 @@ async def _generate_unsigned_spendbundle( announcement = CreateCoinAnnouncement(std_hash(b"".join([c.name() for c in cat_coins])), coin.name()) if need_chia_transaction: if fee > regular_chia_to_claim: - chia_tx, _ = await self.create_tandem_xch_tx( + await self.create_tandem_xch_tx( fee, uint64(regular_chia_to_claim), tx_config, @@ -524,7 +523,7 @@ async def _generate_unsigned_spendbundle( conditions=(*extra_conditions, announcement), ) elif regular_chia_to_claim > fee: - chia_tx, xch_announcement = await self.create_tandem_xch_tx( + xch_announcement = await self.create_tandem_xch_tx( fee, uint64(regular_chia_to_claim), tx_config, @@ -586,7 +585,7 @@ async def _generate_unsigned_spendbundle( vc.wrap_inner_with_backdoor().get_tree_hash() if add_authorizations_to_cr_cats else None, ) if add_authorizations_to_cr_cats: - vc_txs: List[TransactionRecord] = await vc_wallet.generate_signed_transaction( + await vc_wallet.generate_signed_transaction( vc.launcher_id, tx_config, action_scope, @@ -596,29 +595,8 @@ async def _generate_unsigned_spendbundle( *(CreatePuzzleAnnouncement(ann) for ann in vc_announcements_to_make), ), ) - else: - vc_txs = [] - - return ( - SpendBundle( - [ - *coin_spends, - *(spend for tx in vc_txs if tx.spend_bundle is not None for spend in tx.spend_bundle.coin_spends), - *( - ( - spend - for bundle in [chia_tx.spend_bundle] - if bundle is not None - for spend in bundle.coin_spends - ) - if chia_tx is not None - else [] - ), - ], - G2Element(), - ), - [*vc_txs, *([chia_tx] if chia_tx is not None else [])], - ) + + return SpendBundle(coin_spends, G2Element()) async def generate_signed_transaction( self, @@ -631,7 +609,7 @@ async def generate_signed_transaction( memos: Optional[List[List[bytes]]] = None, extra_conditions: Tuple[Condition, ...] = tuple(), **kwargs: Unpack[GSTOptionalArgs], - ) -> List[TransactionRecord]: + ) -> None: # (extra_delta, tail_reveal, tail_solution) cat_discrepancy: Optional[Tuple[int, Program, Program]] = kwargs.get("cat_discrepancy", None) add_authorizations_to_cr_cats: bool = kwargs.get("add_authorizations_to_cr_cats", True) @@ -659,7 +637,7 @@ async def generate_signed_transaction( ) ) - spend_bundle, other_txs = await self._generate_unsigned_spendbundle( + spend_bundle = await self._generate_unsigned_spendbundle( payments, tx_config, action_scope, @@ -670,32 +648,37 @@ async def generate_signed_transaction( add_authorizations_to_cr_cats=add_authorizations_to_cr_cats, ) - other_tx_removals: Set[Coin] = {removal for tx in other_txs for removal in tx.removals} - other_tx_additions: Set[Coin] = {removal for tx in other_txs for removal in tx.additions} - tx_list = [ - TransactionRecord( - confirmed_at_height=uint32(0), - created_at_time=uint64(int(time.time())), - to_puzzle_hash=payment.puzzle_hash, - amount=payment.amount, - fee_amount=fee, - confirmed=False, - sent=uint32(0), - spend_bundle=spend_bundle if i == 0 else None, - additions=list(set(spend_bundle.additions()) - other_tx_additions) if i == 0 else [], - removals=list(set(spend_bundle.removals()) - other_tx_removals) if i == 0 else [], - wallet_id=self.id(), - sent_to=[], - trade_id=None, - type=uint32(TransactionType.OUTGOING_TX.value), - name=spend_bundle.name(), - memos=list(compute_memos(spend_bundle).items()), - valid_times=parse_timelock_info(extra_conditions), - ) - for i, payment in enumerate(payments) - ] + async with action_scope.use() as interface: + other_tx_removals: Set[Coin] = { + removal for tx in interface.side_effects.transactions for removal in tx.removals + } + other_tx_additions: Set[Coin] = { + addition for tx in interface.side_effects.transactions for addition in tx.additions + } + tx_list = [ + TransactionRecord( + confirmed_at_height=uint32(0), + created_at_time=uint64(int(time.time())), + to_puzzle_hash=payment.puzzle_hash, + amount=payment.amount, + fee_amount=fee, + confirmed=False, + sent=uint32(0), + spend_bundle=spend_bundle if i == 0 else None, + additions=list(set(spend_bundle.additions()) - other_tx_additions) if i == 0 else [], + removals=list(set(spend_bundle.removals()) - other_tx_removals) if i == 0 else [], + wallet_id=self.id(), + sent_to=[], + trade_id=None, + type=uint32(TransactionType.OUTGOING_TX.value), + name=spend_bundle.name() if i == 0 else payment.as_condition().get_tree_hash(), + memos=list(compute_memos(spend_bundle).items()), + valid_times=parse_timelock_info(extra_conditions), + ) + for i, payment in enumerate(payments) + ] - return [*tx_list, *(dataclasses.replace(tx, spend_bundle=None) for tx in other_txs)] + interface.side_effects.transactions.extend(tx_list) async def claim_pending_approval_balance( self, @@ -709,7 +692,7 @@ async def claim_pending_approval_balance( excluded_coin_amounts: Optional[List[uint64]] = None, reuse_puzhash: Optional[bool] = None, extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> List[TransactionRecord]: + ) -> None: # Select the relevant CR-CAT coins crcat_records: Set[WalletCoinRecord] = await self.wallet_state_manager.coin_store.get_unspent_coins_for_wallet( self.id(), CoinType.CRCAT_PENDING @@ -779,21 +762,16 @@ async def claim_pending_approval_balance( # Make the Fee TX if fee > 0: - chia_tx, _ = await self.create_tandem_xch_tx( + await self.create_tandem_xch_tx( fee, uint64(0), tx_config, action_scope, extra_conditions=tuple(expected_announcements), ) - if chia_tx.spend_bundle is None: - raise RuntimeError("Did not get spendbundle for fee transaction") # pragma: no cover - claim_bundle = SpendBundle.aggregate([claim_bundle, chia_tx.spend_bundle]) - else: - chia_tx = None # Make the VC TX - vc_txs: List[TransactionRecord] = await vc_wallet.generate_signed_transaction( + await vc_wallet.generate_signed_transaction( vc.launcher_id, tx_config, action_scope, @@ -804,38 +782,31 @@ async def claim_pending_approval_balance( *(CreatePuzzleAnnouncement(crcat.expected_announcement()) for crcat, _ in crcats_and_puzhashes), ), ) - claim_bundle = SpendBundle.aggregate( - [claim_bundle, *(tx.spend_bundle for tx in vc_txs if tx.spend_bundle is not None)] - ) - other_txs: List[TransactionRecord] = [ - *(dataclasses.replace(tx, spend_bundle=None) for tx in vc_txs), - *((dataclasses.replace(chia_tx, spend_bundle=None),) if chia_tx is not None else []), - ] - other_additions: Set[Coin] = {rem for tx in other_txs for rem in tx.additions} - other_removals: Set[Coin] = {rem for tx in other_txs for rem in tx.removals} - return [ - TransactionRecord( - confirmed_at_height=uint32(0), - created_at_time=uint64(int(time.time())), - to_puzzle_hash=await self.wallet_state_manager.main_wallet.get_puzzle_hash(False), - amount=uint64(sum(c.amount for c in coins)), - fee_amount=fee, - confirmed=False, - sent=uint32(0), - spend_bundle=claim_bundle, - additions=list(set(claim_bundle.additions()) - other_additions), - removals=list(set(claim_bundle.removals()) - other_removals), - wallet_id=self.id(), - sent_to=[], - trade_id=None, - type=uint32(TransactionType.INCOMING_TX.value), - name=claim_bundle.name(), - memos=list(compute_memos(claim_bundle).items()), - valid_times=parse_timelock_info(extra_conditions), - ), - *other_txs, - ] + async with action_scope.use() as interface: + other_additions: Set[Coin] = {rem for tx in interface.side_effects.transactions for rem in tx.additions} + other_removals: Set[Coin] = {rem for tx in interface.side_effects.transactions for rem in tx.removals} + interface.side_effects.transactions.append( + TransactionRecord( + confirmed_at_height=uint32(0), + created_at_time=uint64(int(time.time())), + to_puzzle_hash=await self.wallet_state_manager.main_wallet.get_puzzle_hash(False), + amount=uint64(sum(c.amount for c in coins)), + fee_amount=fee, + confirmed=False, + sent=uint32(0), + spend_bundle=claim_bundle, + additions=list(set(claim_bundle.additions()) - other_additions), + removals=list(set(claim_bundle.removals()) - other_removals), + wallet_id=self.id(), + sent_to=[], + trade_id=None, + type=uint32(TransactionType.INCOMING_TX.value), + name=claim_bundle.name(), + memos=list(compute_memos(claim_bundle).items()), + valid_times=parse_timelock_info(extra_conditions), + ) + ) async def match_puzzle_info(self, puzzle_driver: PuzzleInfo) -> bool: if ( diff --git a/chia/wallet/vc_wallet/vc_wallet.py b/chia/wallet/vc_wallet/vc_wallet.py index d4a6ee82411b..9af19f509a34 100644 --- a/chia/wallet/vc_wallet/vc_wallet.py +++ b/chia/wallet/vc_wallet/vc_wallet.py @@ -1,6 +1,5 @@ from __future__ import annotations -import dataclasses import logging import time import traceback @@ -169,7 +168,7 @@ async def launch_new_vc( inner_puzzle_hash: Optional[bytes32] = None, fee: uint64 = uint64(0), extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> Tuple[VCRecord, List[TransactionRecord]]: + ) -> VCRecord: """ Given the DID ID of a proof provider, mint a brand new VC with an empty slot for proofs. @@ -208,27 +207,30 @@ async def launch_new_vc( add_list: List[Coin] = list(spend_bundle.additions()) rem_list: List[Coin] = list(spend_bundle.removals()) vc_record: VCRecord = VCRecord(vc, uint32(0)) - tx = TransactionRecord( - confirmed_at_height=uint32(0), - created_at_time=now, - to_puzzle_hash=inner_puzzle_hash, - amount=uint64(1), - fee_amount=uint64(fee), - confirmed=False, - sent=uint32(0), - spend_bundle=spend_bundle, - additions=add_list, - removals=rem_list, - wallet_id=uint32(1), - sent_to=[], - trade_id=None, - type=uint32(TransactionType.OUTGOING_TX.value), - name=spend_bundle.name(), - memos=list(compute_memos(spend_bundle).items()), - valid_times=parse_timelock_info(extra_conditions), - ) + async with action_scope.use() as interface: + interface.side_effects.transactions.append( + TransactionRecord( + confirmed_at_height=uint32(0), + created_at_time=now, + to_puzzle_hash=inner_puzzle_hash, + amount=uint64(1), + fee_amount=uint64(fee), + confirmed=False, + sent=uint32(0), + spend_bundle=spend_bundle, + additions=add_list, + removals=rem_list, + wallet_id=uint32(1), + sent_to=[], + trade_id=None, + type=uint32(TransactionType.OUTGOING_TX.value), + name=spend_bundle.name(), + memos=list(compute_memos(spend_bundle).items()), + valid_times=parse_timelock_info(extra_conditions), + ) + ) - return vc_record, [tx] + return vc_record async def generate_signed_transaction( self, @@ -239,7 +241,7 @@ async def generate_signed_transaction( new_inner_puzhash: Optional[bytes32] = None, extra_conditions: Tuple[Condition, ...] = tuple(), **kwargs: Unpack[GSTOptionalArgs], - ) -> List[TransactionRecord]: + ) -> None: new_proof_hash: Optional[bytes32] = kwargs.get( "new_proof_hash", None ) # Requires that this key posesses the DID to update the specified VC @@ -268,15 +270,14 @@ async def generate_signed_transaction( if fee > 0: coin_name = vc_record.vc.coin.name() - chia_tx = await self.wallet_state_manager.main_wallet.create_tandem_xch_tx( + await self.wallet_state_manager.main_wallet.create_tandem_xch_tx( fee, tx_config, action_scope, extra_conditions=(AssertCoinAnnouncement(asserted_id=coin_name, asserted_msg=coin_name),), ) extra_conditions += (CreateCoinAnnouncement(coin_name),) - else: - chia_tx = None + if new_proof_hash is not None: if self_revoke: raise ValueError("Cannot add new proofs and revoke at the same time") @@ -303,8 +304,7 @@ async def generate_signed_transaction( conditions=extra_conditions, ) did_announcement, coin_spend, vc = vc_record.vc.do_spend(inner_puzzle, innersol, new_proof_hash) - spend_bundles = [SpendBundle([coin_spend], G2Element())] - tx_list: List[TransactionRecord] = [] + spend_bundle = SpendBundle([coin_spend], G2Element()) if did_announcement is not None: # Need to spend DID for _, wallet in self.wallet_state_manager.wallets.items(): @@ -312,46 +312,38 @@ async def generate_signed_transaction( assert isinstance(wallet, DIDWallet) if bytes32.fromhex(wallet.get_my_DID()) == vc_record.vc.proof_provider: self.log.debug("Creating announcement from DID for vc: %s", vc_id.hex()) - did_tx = await wallet.create_message_spend( - tx_config, action_scope, extra_conditions=(did_announcement,) - ) - assert did_tx.spend_bundle is not None - spend_bundles.append(did_tx.spend_bundle) - tx_list.append(dataclasses.replace(did_tx, spend_bundle=None)) + await wallet.create_message_spend(tx_config, action_scope, extra_conditions=(did_announcement,)) break else: raise ValueError( f"Cannot find the required DID {vc_record.vc.proof_provider.hex()}." ) # pragma: no cover - add_list: List[Coin] = list(spend_bundles[0].additions()) - rem_list: List[Coin] = list(spend_bundles[0].removals()) - if chia_tx is not None and chia_tx.spend_bundle is not None: - spend_bundles.append(chia_tx.spend_bundle) - tx_list.append(dataclasses.replace(chia_tx, spend_bundle=None)) - spend_bundle = SpendBundle.aggregate(spend_bundles) + add_list: List[Coin] = list(spend_bundle.additions()) + rem_list: List[Coin] = list(spend_bundle.removals()) now = uint64(int(time.time())) - tx_list.append( - TransactionRecord( - confirmed_at_height=uint32(0), - created_at_time=now, - to_puzzle_hash=new_inner_puzhash, - amount=uint64(1), - fee_amount=uint64(fee), - confirmed=False, - sent=uint32(0), - spend_bundle=spend_bundle, - additions=add_list, - removals=rem_list, - wallet_id=self.id(), - sent_to=[], - trade_id=None, - type=uint32(TransactionType.OUTGOING_TX.value), - name=spend_bundle.name(), - memos=list(compute_memos(spend_bundle).items()), - valid_times=parse_timelock_info(extra_conditions), + + async with action_scope.use() as interface: + interface.side_effects.transactions.append( + TransactionRecord( + confirmed_at_height=uint32(0), + created_at_time=now, + to_puzzle_hash=new_inner_puzhash, + amount=uint64(1), + fee_amount=uint64(fee), + confirmed=False, + sent=uint32(0), + spend_bundle=spend_bundle, + additions=add_list, + removals=rem_list, + wallet_id=self.id(), + sent_to=[], + trade_id=None, + type=uint32(TransactionType.OUTGOING_TX.value), + name=spend_bundle.name(), + memos=list(compute_memos(spend_bundle).items()), + valid_times=parse_timelock_info(extra_conditions), + ) ) - ) - return tx_list async def revoke_vc( self, @@ -361,7 +353,7 @@ async def revoke_vc( action_scope: WalletActionScope, fee: uint64 = uint64(0), extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> List[TransactionRecord]: + ) -> None: vc_coin_states: List[CoinState] = await self.wallet_state_manager.wallet_node.get_coin_state( [parent_id], peer=peer ) @@ -380,13 +372,14 @@ async def revoke_vc( did_wallet = wallet break else: - return await self.generate_signed_transaction( + await self.generate_signed_transaction( vc.launcher_id, tx_config, action_scope, fee, self_revoke=True, ) + return recovery_info: Optional[Tuple[bytes32, bytes32, uint64]] = await did_wallet.get_info_for_recovery() if recovery_info is None: @@ -403,28 +396,20 @@ async def revoke_vc( nonce: bytes32 = SerializedProgram.to(sorted_coin_list).get_tree_hash() vc_announcement: AssertCoinAnnouncement = AssertCoinAnnouncement(asserted_id=vc.coin.name(), asserted_msg=nonce) + if fee > 0: + await self.wallet_state_manager.main_wallet.create_tandem_xch_tx( + fee, tx_config, action_scope, extra_conditions=(vc_announcement,) + ) + # Assemble final bundle expected_did_announcement, vc_spend = vc.activate_backdoor(provider_inner_puzhash, announcement_nonce=nonce) - did_tx: TransactionRecord = await did_wallet.create_message_spend( + await did_wallet.create_message_spend( tx_config, action_scope, extra_conditions=(*extra_conditions, expected_did_announcement, vc_announcement), ) - assert did_tx.spend_bundle is not None - final_bundle: SpendBundle = SpendBundle.aggregate([SpendBundle([vc_spend], G2Element()), did_tx.spend_bundle]) - did_tx = dataclasses.replace(did_tx, spend_bundle=final_bundle, name=final_bundle.name()) - if fee > 0: - chia_tx: TransactionRecord = await self.wallet_state_manager.main_wallet.create_tandem_xch_tx( - fee, tx_config, action_scope, extra_conditions=(vc_announcement,) - ) - assert did_tx.spend_bundle is not None - assert chia_tx.spend_bundle is not None - new_bundle = SpendBundle.aggregate([chia_tx.spend_bundle, did_tx.spend_bundle]) - did_tx = dataclasses.replace(did_tx, spend_bundle=new_bundle, name=new_bundle.name()) - chia_tx = dataclasses.replace(chia_tx, spend_bundle=None) - return [did_tx, chia_tx] - else: - return [did_tx] # pragma: no cover + async with action_scope.use() as interface: + interface.side_effects.extra_spends.append(SpendBundle([vc_spend], G2Element())) async def add_vc_authorization( self, offer: Offer, solver: Solver, tx_config: TXConfig, action_scope: WalletActionScope @@ -552,27 +537,20 @@ async def add_vc_authorization( else: raise ValueError("Wallet cannot verify all spends in specified offer") # pragma: no cover - vc_spends: List[SpendBundle] = [] - for launcher_id, vc in vcs.items(): - vc_spends.append( - SpendBundle.aggregate( - [ - tx.spend_bundle - for tx in ( - await self.generate_signed_transaction( - launcher_id, - tx_config, - action_scope, - extra_conditions=( - *announcements_to_assert[launcher_id], - *announcements_to_make[launcher_id], - ), - ) - ) - if tx.spend_bundle is not None - ] + async with self.wallet_state_manager.new_action_scope(push=False) as inner_action_scope: + for launcher_id, vc in vcs.items(): + await self.generate_signed_transaction( + launcher_id, + tx_config, + inner_action_scope, + extra_conditions=( + *announcements_to_assert[launcher_id], + *announcements_to_make[launcher_id], + ), ) - ) + + async with action_scope.use() as interface: + interface.side_effects.transactions.extend(inner_action_scope.side_effects.transactions) return Offer.from_spend_bundle( SpendBundle.aggregate( @@ -588,7 +566,11 @@ async def add_vc_authorization( ], offer._bundle.aggregated_signature, ), - *vc_spends, + *[ + tx.spend_bundle + for tx in inner_action_scope.side_effects.transactions + if tx.spend_bundle is not None + ], ] ) ), Solver({"vc_authorizations": coin_args}) diff --git a/chia/wallet/wallet.py b/chia/wallet/wallet.py index c6c803f4f4db..cbfcd9365aad 100644 --- a/chia/wallet/wallet.py +++ b/chia/wallet/wallet.py @@ -404,7 +404,7 @@ async def generate_signed_transaction( puzzle_decorator_override: Optional[List[Dict[str, Any]]] = None, extra_conditions: Tuple[Condition, ...] = tuple(), **kwargs: Unpack[GSTOptionalArgs], - ) -> List[TransactionRecord]: + ) -> None: origin_id: Optional[bytes32] = kwargs.get("origin_id", None) negative_change_allowed: bool = kwargs.get("negative_change_allowed", False) """ @@ -446,27 +446,28 @@ async def generate_signed_transaction( else: assert output_amount == input_amount - return [ - TransactionRecord( - confirmed_at_height=uint32(0), - created_at_time=now, - to_puzzle_hash=puzzle_hash, - amount=uint64(non_change_amount), - fee_amount=uint64(fee), - confirmed=False, - sent=uint32(0), - spend_bundle=spend_bundle, - additions=add_list, - removals=rem_list, - wallet_id=self.id(), - sent_to=[], - trade_id=None, - type=uint32(TransactionType.OUTGOING_TX.value), - name=spend_bundle.name(), - memos=list(compute_memos(spend_bundle).items()), - valid_times=parse_timelock_info(extra_conditions), + async with action_scope.use() as interface: + interface.side_effects.transactions.append( + TransactionRecord( + confirmed_at_height=uint32(0), + created_at_time=now, + to_puzzle_hash=puzzle_hash, + amount=uint64(non_change_amount), + fee_amount=uint64(fee), + confirmed=False, + sent=uint32(0), + spend_bundle=spend_bundle, + additions=add_list, + removals=rem_list, + wallet_id=self.id(), + sent_to=[], + trade_id=None, + type=uint32(TransactionType.OUTGOING_TX.value), + name=spend_bundle.name(), + memos=list(compute_memos(spend_bundle).items()), + valid_times=parse_timelock_info(extra_conditions), + ) ) - ] async def create_tandem_xch_tx( self, @@ -474,9 +475,9 @@ async def create_tandem_xch_tx( tx_config: TXConfig, action_scope: WalletActionScope, extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> TransactionRecord: + ) -> None: chia_coins = await self.select_coins(fee, tx_config.coin_selection_config) - [chia_tx] = await self.generate_signed_transaction( + await self.generate_signed_transaction( uint64(0), (await self.get_puzzle_hash(not tx_config.reuse_puzhash)), tx_config, @@ -485,8 +486,6 @@ async def create_tandem_xch_tx( coins=chia_coins, extra_conditions=extra_conditions, ) - assert chia_tx.spend_bundle is not None - return chia_tx async def get_coins_to_offer( self, diff --git a/chia/wallet/wallet_state_manager.py b/chia/wallet/wallet_state_manager.py index e85957599030..d869da70cf25 100644 --- a/chia/wallet/wallet_state_manager.py +++ b/chia/wallet/wallet_state_manager.py @@ -927,34 +927,34 @@ async def auto_claim_coins(self) -> None: stop=tx_config.coin_selection_config.max_coin_amount, ), ) - all_txs: List[TransactionRecord] = [] - for coin in unspent_coins.records: - try: - metadata: MetadataTypes = coin.parsed_metadata() - assert isinstance(metadata, ClawbackMetadata) - if await metadata.is_recipient(self.puzzle_store): - coin_timestamp = await self.wallet_node.get_timestamp_for_height(coin.confirmed_block_height) - if current_timestamp - coin_timestamp >= metadata.time_lock: - clawback_coins[coin.coin] = metadata - if len(clawback_coins) >= self.config.get("auto_claim", {}).get("batch_size", 50): - async with self.new_action_scope(push=False) as action_scope: - txs = await self.spend_clawback_coins(clawback_coins, tx_fee, tx_config, action_scope) - all_txs.extend(txs) - tx_config = dataclasses.replace( - tx_config, - excluded_coin_ids=[ - *tx_config.excluded_coin_ids, - *(c.name() for tx in txs for c in tx.removals), - ], - ) - clawback_coins = {} - except Exception as e: - self.log.error(f"Failed to claim clawback coin {coin.coin.name().hex()}: %s", e) - if len(clawback_coins) > 0: - async with self.new_action_scope(push=False) as action_scope: - all_txs.extend(await self.spend_clawback_coins(clawback_coins, tx_fee, tx_config, action_scope)) - - await self.add_pending_transactions(all_txs) + async with self.new_action_scope(push=True) as action_scope: + for coin in unspent_coins.records: + try: + metadata: MetadataTypes = coin.parsed_metadata() + assert isinstance(metadata, ClawbackMetadata) + if await metadata.is_recipient(self.puzzle_store): + coin_timestamp = await self.wallet_node.get_timestamp_for_height(coin.confirmed_block_height) + if current_timestamp - coin_timestamp >= metadata.time_lock: + clawback_coins[coin.coin] = metadata + if len(clawback_coins) >= self.config.get("auto_claim", {}).get("batch_size", 50): + await self.spend_clawback_coins(clawback_coins, tx_fee, tx_config, action_scope) + async with action_scope.use() as interface: + tx_config = dataclasses.replace( + tx_config, + excluded_coin_ids=[ + *tx_config.excluded_coin_ids, + *( + c.name() + for tx in interface.side_effects.transactions + for c in tx.removals + ), + ], + ) + clawback_coins = {} + except Exception as e: + self.log.error(f"Failed to claim clawback coin {coin.coin.name().hex()}: %s", e) + if len(clawback_coins) > 0: + await self.spend_clawback_coins(clawback_coins, tx_fee, tx_config, action_scope) async def spend_clawback_coins( self, @@ -964,7 +964,7 @@ async def spend_clawback_coins( action_scope: WalletActionScope, force: bool = False, extra_conditions: Tuple[Condition, ...] = tuple(), - ) -> List[TransactionRecord]: + ) -> None: assert len(clawback_coins) > 0 coin_spends: List[CoinSpend] = [] message: bytes32 = std_hash(b"".join([c.name() for c in clawback_coins.keys()])) @@ -1016,21 +1016,35 @@ async def spend_clawback_coins( except Exception as e: self.log.error(f"Failed to create clawback spend bundle for {coin.name().hex()}: {e}") if len(coin_spends) == 0: - return [] + return spend_bundle: SpendBundle = SpendBundle(coin_spends, G2Element()) - tx_list: List[TransactionRecord] = [] if fee > 0: - chia_tx = await self.main_wallet.create_tandem_xch_tx( - fee, - tx_config, - action_scope, - extra_conditions=( - AssertCoinAnnouncement(asserted_id=coin_spends[0].coin.name(), asserted_msg=message), - ), + async with self.new_action_scope(push=False) as inner_action_scope: + await self.main_wallet.create_tandem_xch_tx( + fee, + tx_config, + inner_action_scope, + extra_conditions=( + AssertCoinAnnouncement(asserted_id=coin_spends[0].coin.name(), asserted_msg=message), + ), + ) + async with action_scope.use() as interface: + # This should not be looked to for best practice. Ideally, the two spend bundles can exist separately on + # each tx record until they are pushed. This is not very supported behavior at the moment so to avoid + # any potential backwards compatibility issues, we're moving the spend bundle from this TX to the main + interface.side_effects.transactions.extend( + [dataclasses.replace(tx, spend_bundle=None) for tx in inner_action_scope.side_effects.transactions] + ) + spend_bundle = SpendBundle.aggregate( + [ + spend_bundle, + *( + tx.spend_bundle + for tx in inner_action_scope.side_effects.transactions + if tx.spend_bundle is not None + ), + ] ) - assert chia_tx.spend_bundle is not None - spend_bundle = SpendBundle.aggregate([spend_bundle, chia_tx.spend_bundle]) - tx_list.append(dataclasses.replace(chia_tx, spend_bundle=None)) assert derivation_record is not None tx_record = TransactionRecord( confirmed_at_height=uint32(0), @@ -1051,8 +1065,8 @@ async def spend_clawback_coins( memos=list(compute_memos(spend_bundle).items()), valid_times=parse_timelock_info(extra_conditions), ) - tx_list.append(tx_record) - return tx_list + async with action_scope.use() as interface: + interface.side_effects.transactions.append(tx_record) async def filter_spam(self, new_coin_state: List[CoinState]) -> List[CoinState]: xch_spam_amount = self.config.get("xch_spam_amount", 1000000)