chia-blockchain 2.5.4rc2__py3-none-any.whl → 2.5.5rc2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (453) hide show
  1. chia/_tests/blockchain/blockchain_test_utils.py +2 -3
  2. chia/_tests/blockchain/test_augmented_chain.py +2 -3
  3. chia/_tests/blockchain/test_blockchain.py +261 -44
  4. chia/_tests/blockchain/test_blockchain_transactions.py +4 -3
  5. chia/_tests/blockchain/test_build_chains.py +197 -1
  6. chia/_tests/blockchain/test_get_block_generator.py +1 -1
  7. chia/_tests/blockchain/test_lookup_fork_chain.py +1 -1
  8. chia/_tests/clvm/benchmark_costs.py +1 -1
  9. chia/_tests/clvm/coin_store.py +3 -4
  10. chia/_tests/clvm/test_message_conditions.py +2 -2
  11. chia/_tests/clvm/test_puzzle_compression.py +2 -3
  12. chia/_tests/clvm/test_puzzles.py +1 -2
  13. chia/_tests/clvm/test_singletons.py +2 -3
  14. chia/_tests/clvm/test_spend_sim.py +7 -7
  15. chia/_tests/cmds/cmd_test_utils.py +30 -25
  16. chia/_tests/cmds/test_dev_gh.py +1 -1
  17. chia/_tests/cmds/test_farm_cmd.py +1 -1
  18. chia/_tests/cmds/test_show.py +1 -2
  19. chia/_tests/cmds/wallet/test_did.py +101 -56
  20. chia/_tests/cmds/wallet/test_nft.py +109 -84
  21. chia/_tests/cmds/wallet/test_notifications.py +1 -1
  22. chia/_tests/cmds/wallet/test_offer.toffer +1 -1
  23. chia/_tests/cmds/wallet/test_vcs.py +8 -8
  24. chia/_tests/cmds/wallet/test_wallet.py +100 -46
  25. chia/_tests/conftest.py +31 -20
  26. chia/_tests/connection_utils.py +1 -1
  27. chia/_tests/core/consensus/stores/__init__.py +0 -0
  28. chia/_tests/core/consensus/stores/test_coin_store_protocol.py +40 -0
  29. chia/_tests/core/consensus/test_block_creation.py +2 -31
  30. chia/_tests/core/consensus/test_pot_iterations.py +38 -3
  31. chia/_tests/core/custom_types/test_proof_of_space.py +154 -26
  32. chia/_tests/core/custom_types/test_spend_bundle.py +2 -3
  33. chia/_tests/core/daemon/test_daemon.py +80 -0
  34. chia/_tests/core/data_layer/test_data_layer.py +1 -1
  35. chia/_tests/core/data_layer/test_data_layer_util.py +1 -1
  36. chia/_tests/core/data_layer/test_data_rpc.py +14 -10
  37. chia/_tests/core/data_layer/test_data_store.py +5 -5
  38. chia/_tests/core/farmer/test_farmer_api.py +2 -2
  39. chia/_tests/core/full_node/full_sync/test_full_sync.py +446 -406
  40. chia/_tests/core/full_node/ram_db.py +3 -1
  41. chia/_tests/core/full_node/stores/test_block_store.py +28 -16
  42. chia/_tests/core/full_node/stores/test_coin_store.py +277 -185
  43. chia/_tests/core/full_node/stores/test_full_node_store.py +11 -4
  44. chia/_tests/core/full_node/stores/test_hint_store.py +2 -2
  45. chia/_tests/core/full_node/test_address_manager.py +200 -27
  46. chia/_tests/core/full_node/test_block_height_map.py +2 -2
  47. chia/_tests/core/full_node/test_conditions.py +7 -6
  48. chia/_tests/core/full_node/test_full_node.py +456 -40
  49. chia/_tests/core/full_node/test_generator_tools.py +32 -2
  50. chia/_tests/core/full_node/test_hint_management.py +1 -1
  51. chia/_tests/core/full_node/test_node_load.py +20 -21
  52. chia/_tests/core/full_node/test_performance.py +3 -4
  53. chia/_tests/core/full_node/test_prev_tx_block.py +43 -0
  54. chia/_tests/core/full_node/test_subscriptions.py +1 -2
  55. chia/_tests/core/full_node/test_transactions.py +9 -5
  56. chia/_tests/core/full_node/test_tx_processing_queue.py +1 -2
  57. chia/_tests/core/large_block.py +1 -2
  58. chia/_tests/core/make_block_generator.py +3 -4
  59. chia/_tests/core/mempool/test_mempool.py +36 -86
  60. chia/_tests/core/mempool/test_mempool_fee_estimator.py +1 -1
  61. chia/_tests/core/mempool/test_mempool_item_queries.py +1 -3
  62. chia/_tests/core/mempool/test_mempool_manager.py +421 -69
  63. chia/_tests/core/mempool/test_mempool_performance.py +3 -2
  64. chia/_tests/core/mempool/test_singleton_fast_forward.py +60 -131
  65. chia/_tests/core/server/flood.py +1 -1
  66. chia/_tests/core/server/test_dos.py +1 -1
  67. chia/_tests/core/server/test_node_discovery.py +41 -27
  68. chia/_tests/core/server/test_rate_limits.py +1 -1
  69. chia/_tests/core/server/test_server.py +1 -1
  70. chia/_tests/core/services/test_services.py +5 -5
  71. chia/_tests/core/ssl/test_ssl.py +1 -1
  72. chia/_tests/core/test_cost_calculation.py +6 -6
  73. chia/_tests/core/test_crawler.py +2 -2
  74. chia/_tests/core/test_crawler_rpc.py +1 -1
  75. chia/_tests/core/test_db_conversion.py +3 -1
  76. chia/_tests/core/test_db_validation.py +5 -3
  77. chia/_tests/core/test_farmer_harvester_rpc.py +15 -15
  78. chia/_tests/core/test_filter.py +4 -1
  79. chia/_tests/core/test_full_node_rpc.py +99 -82
  80. chia/_tests/core/test_program.py +2 -2
  81. chia/_tests/core/util/test_block_cache.py +1 -1
  82. chia/_tests/core/util/test_keychain.py +2 -2
  83. chia/_tests/core/util/test_lockfile.py +1 -1
  84. chia/_tests/core/util/test_log_exceptions.py +5 -5
  85. chia/_tests/core/util/test_streamable.py +81 -22
  86. chia/_tests/db/test_db_wrapper.py +1 -3
  87. chia/_tests/environments/wallet.py +5 -5
  88. chia/_tests/farmer_harvester/test_farmer.py +9 -7
  89. chia/_tests/farmer_harvester/test_farmer_harvester.py +11 -4
  90. chia/_tests/farmer_harvester/test_filter_prefix_bits.py +6 -5
  91. chia/_tests/farmer_harvester/test_third_party_harvesters.py +15 -9
  92. chia/_tests/fee_estimation/test_fee_estimation_integration.py +1 -2
  93. chia/_tests/fee_estimation/test_fee_estimation_rpc.py +7 -5
  94. chia/_tests/fee_estimation/test_fee_estimation_unit_tests.py +1 -1
  95. chia/_tests/generator/test_compression.py +1 -2
  96. chia/_tests/generator/test_rom.py +8 -4
  97. chia/_tests/plot_sync/test_plot_sync.py +3 -3
  98. chia/_tests/plot_sync/test_receiver.py +3 -3
  99. chia/_tests/plot_sync/test_sender.py +1 -1
  100. chia/_tests/plot_sync/test_sync_simulated.py +3 -3
  101. chia/_tests/plot_sync/util.py +2 -2
  102. chia/_tests/pools/test_pool_cmdline.py +48 -21
  103. chia/_tests/pools/test_pool_puzzles_lifecycle.py +2 -3
  104. chia/_tests/pools/test_pool_rpc.py +237 -105
  105. chia/_tests/pools/test_pool_wallet.py +11 -2
  106. chia/_tests/pools/test_wallet_pool_store.py +5 -4
  107. chia/_tests/rpc/test_rpc_client.py +1 -1
  108. chia/_tests/simulation/test_simulation.py +13 -8
  109. chia/_tests/simulation/test_simulator.py +2 -2
  110. chia/_tests/timelord/test_new_peak.py +191 -47
  111. chia/_tests/timelord/test_timelord.py +1 -1
  112. chia/_tests/tools/test_full_sync.py +0 -2
  113. chia/_tests/tools/test_run_block.py +3 -1
  114. chia/_tests/util/benchmark_cost.py +3 -3
  115. chia/_tests/util/benchmarks.py +2 -2
  116. chia/_tests/util/blockchain.py +11 -5
  117. chia/_tests/util/blockchain_mock.py +1 -4
  118. chia/_tests/util/coin_store.py +29 -0
  119. chia/_tests/util/constants.py +2 -18
  120. chia/_tests/util/full_sync.py +3 -3
  121. chia/_tests/util/generator_tools_testing.py +2 -3
  122. chia/_tests/util/key_tool.py +2 -3
  123. chia/_tests/util/misc.py +33 -31
  124. chia/_tests/util/network_protocol_data.py +19 -17
  125. chia/_tests/util/protocol_messages_bytes-v1.0 +0 -0
  126. chia/_tests/util/protocol_messages_json.py +3 -1
  127. chia/_tests/util/run_block.py +2 -2
  128. chia/_tests/util/setup_nodes.py +7 -7
  129. chia/_tests/util/spend_sim.py +47 -55
  130. chia/_tests/util/test_condition_tools.py +5 -4
  131. chia/_tests/util/test_config.py +2 -2
  132. chia/_tests/util/test_dump_keyring.py +1 -1
  133. chia/_tests/util/test_full_block_utils.py +12 -14
  134. chia/_tests/util/test_misc.py +2 -2
  135. chia/_tests/util/test_paginator.py +4 -4
  136. chia/_tests/util/test_priority_mutex.py +2 -2
  137. chia/_tests/util/test_replace_str_to_bytes.py +15 -5
  138. chia/_tests/util/test_ssl_check.py +1 -1
  139. chia/_tests/util/test_testnet_overrides.py +13 -3
  140. chia/_tests/util/time_out_assert.py +4 -2
  141. chia/_tests/wallet/cat_wallet/test_cat_lifecycle.py +1 -1
  142. chia/_tests/wallet/cat_wallet/test_cat_outer_puzzle.py +1 -2
  143. chia/_tests/wallet/cat_wallet/test_cat_wallet.py +352 -432
  144. chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py +3 -6
  145. chia/_tests/wallet/cat_wallet/test_trades.py +53 -77
  146. chia/_tests/wallet/clawback/test_clawback_decorator.py +3 -1
  147. chia/_tests/wallet/clawback/test_clawback_lifecycle.py +3 -3
  148. chia/_tests/wallet/clawback/test_clawback_metadata.py +4 -2
  149. chia/_tests/wallet/conftest.py +11 -12
  150. chia/_tests/wallet/db_wallet/test_db_graftroot.py +11 -4
  151. chia/_tests/wallet/db_wallet/test_dl_offers.py +433 -130
  152. chia/_tests/wallet/db_wallet/test_dl_wallet.py +3 -3
  153. chia/_tests/wallet/did_wallet/test_did.py +2132 -2000
  154. chia/_tests/wallet/nft_wallet/config.py +1 -1
  155. chia/_tests/wallet/nft_wallet/test_nft_1_offers.py +1610 -742
  156. chia/_tests/wallet/nft_wallet/test_nft_bulk_mint.py +486 -907
  157. chia/_tests/wallet/nft_wallet/test_nft_lifecycle.py +4 -4
  158. chia/_tests/wallet/nft_wallet/test_nft_wallet.py +517 -294
  159. chia/_tests/wallet/rpc/test_dl_wallet_rpc.py +133 -62
  160. chia/_tests/wallet/rpc/test_wallet_rpc.py +495 -265
  161. chia/_tests/wallet/simple_sync/test_simple_sync_protocol.py +10 -6
  162. chia/_tests/wallet/sync/test_wallet_sync.py +89 -60
  163. chia/_tests/wallet/test_clvm_casts.py +88 -0
  164. chia/_tests/wallet/test_coin_management.py +1 -1
  165. chia/_tests/wallet/test_coin_selection.py +1 -1
  166. chia/_tests/wallet/test_conditions.py +1 -1
  167. chia/_tests/wallet/test_new_wallet_protocol.py +13 -11
  168. chia/_tests/wallet/test_notifications.py +5 -3
  169. chia/_tests/wallet/test_sign_coin_spends.py +6 -6
  170. chia/_tests/wallet/test_signer_protocol.py +13 -12
  171. chia/_tests/wallet/test_singleton.py +1 -1
  172. chia/_tests/wallet/test_singleton_lifecycle_fast.py +5 -7
  173. chia/_tests/wallet/test_util.py +2 -2
  174. chia/_tests/wallet/test_wallet.py +108 -29
  175. chia/_tests/wallet/test_wallet_action_scope.py +9 -2
  176. chia/_tests/wallet/test_wallet_blockchain.py +2 -3
  177. chia/_tests/wallet/test_wallet_key_val_store.py +1 -2
  178. chia/_tests/wallet/test_wallet_node.py +2 -4
  179. chia/_tests/wallet/test_wallet_retry.py +4 -2
  180. chia/_tests/wallet/test_wallet_state_manager.py +191 -5
  181. chia/_tests/wallet/test_wallet_test_framework.py +1 -1
  182. chia/_tests/wallet/vc_wallet/test_vc_lifecycle.py +8 -8
  183. chia/_tests/wallet/vc_wallet/test_vc_wallet.py +29 -12
  184. chia/_tests/wallet/wallet_block_tools.py +6 -6
  185. chia/_tests/weight_proof/test_weight_proof.py +10 -48
  186. chia/apis.py +1 -1
  187. chia/cmds/beta.py +1 -1
  188. chia/cmds/chia.py +9 -9
  189. chia/cmds/cmd_classes.py +12 -11
  190. chia/cmds/cmd_helpers.py +1 -1
  191. chia/cmds/cmds_util.py +12 -9
  192. chia/cmds/coin_funcs.py +2 -2
  193. chia/cmds/configure.py +2 -2
  194. chia/cmds/data.py +0 -2
  195. chia/cmds/data_funcs.py +1 -1
  196. chia/cmds/db_validate_func.py +1 -2
  197. chia/cmds/dev/__init__.py +0 -0
  198. chia/cmds/dev/data.py +273 -0
  199. chia/cmds/{gh.py → dev/gh.py} +5 -5
  200. chia/cmds/dev/main.py +22 -0
  201. chia/cmds/dev/mempool.py +78 -0
  202. chia/cmds/dev/mempool_funcs.py +63 -0
  203. chia/cmds/farm_funcs.py +5 -4
  204. chia/cmds/init_funcs.py +11 -11
  205. chia/cmds/keys.py +2 -2
  206. chia/cmds/keys_funcs.py +4 -4
  207. chia/cmds/netspace_funcs.py +1 -1
  208. chia/cmds/peer_funcs.py +2 -2
  209. chia/cmds/plotnft_funcs.py +72 -26
  210. chia/cmds/rpc.py +1 -1
  211. chia/cmds/show_funcs.py +5 -5
  212. chia/cmds/signer.py +8 -7
  213. chia/cmds/sim_funcs.py +8 -9
  214. chia/cmds/wallet.py +2 -2
  215. chia/cmds/wallet_funcs.py +165 -131
  216. chia/{util → consensus}/augmented_chain.py +1 -2
  217. chia/consensus/block_body_validation.py +54 -40
  218. chia/consensus/block_creation.py +42 -76
  219. chia/consensus/block_header_validation.py +32 -26
  220. chia/consensus/block_record.py +0 -3
  221. chia/consensus/blockchain.py +23 -32
  222. chia/consensus/blockchain_interface.py +1 -5
  223. chia/consensus/check_time_locks.py +57 -0
  224. chia/consensus/coin_store_protocol.py +151 -0
  225. chia/consensus/coinbase.py +0 -6
  226. chia/consensus/condition_costs.py +4 -0
  227. chia/{util → consensus}/condition_tools.py +4 -5
  228. chia/consensus/cost_calculator.py +1 -1
  229. chia/consensus/default_constants.py +32 -9
  230. chia/consensus/deficit.py +1 -3
  231. chia/consensus/difficulty_adjustment.py +1 -2
  232. chia/consensus/find_fork_point.py +1 -3
  233. chia/consensus/full_block_to_block_record.py +1 -6
  234. chia/{util → consensus}/generator_tools.py +1 -3
  235. chia/consensus/get_block_challenge.py +30 -7
  236. chia/consensus/make_sub_epoch_summary.py +1 -5
  237. chia/consensus/multiprocess_validation.py +21 -20
  238. chia/consensus/pot_iterations.py +74 -13
  239. chia/{util → consensus}/prev_transaction_block.py +1 -1
  240. chia/consensus/vdf_info_computation.py +1 -3
  241. chia/daemon/keychain_proxy.py +5 -5
  242. chia/daemon/server.py +22 -5
  243. chia/data_layer/data_layer.py +92 -51
  244. chia/{rpc → data_layer}/data_layer_rpc_api.py +1 -1
  245. chia/{rpc → data_layer}/data_layer_rpc_util.py +3 -6
  246. chia/data_layer/data_layer_util.py +4 -6
  247. chia/data_layer/data_layer_wallet.py +42 -69
  248. chia/data_layer/dl_wallet_store.py +12 -6
  249. chia/data_layer/download_data.py +3 -3
  250. chia/data_layer/s3_plugin_service.py +0 -1
  251. chia/farmer/farmer.py +3 -4
  252. chia/farmer/farmer_api.py +11 -7
  253. chia/{rpc → farmer}/farmer_rpc_client.py +1 -1
  254. chia/full_node/block_height_map.py +7 -6
  255. chia/full_node/block_store.py +5 -7
  256. chia/full_node/bundle_tools.py +1 -2
  257. chia/full_node/coin_store.py +143 -124
  258. chia/{types → full_node}/eligible_coin_spends.py +39 -70
  259. chia/full_node/fee_estimator.py +1 -1
  260. chia/full_node/fee_estimator_interface.py +0 -8
  261. chia/full_node/fee_tracker.py +25 -25
  262. chia/full_node/full_node.py +70 -53
  263. chia/full_node/full_node_api.py +57 -40
  264. chia/{rpc → full_node}/full_node_rpc_api.py +87 -8
  265. chia/{rpc → full_node}/full_node_rpc_client.py +7 -6
  266. chia/full_node/full_node_store.py +23 -8
  267. chia/full_node/mempool.py +206 -53
  268. chia/full_node/mempool_check_conditions.py +20 -63
  269. chia/full_node/mempool_manager.py +26 -40
  270. chia/full_node/subscriptions.py +1 -3
  271. chia/full_node/tx_processing_queue.py +50 -3
  272. chia/full_node/weight_proof.py +46 -37
  273. chia/harvester/harvester.py +1 -1
  274. chia/harvester/harvester_api.py +22 -7
  275. chia/introducer/introducer.py +1 -1
  276. chia/introducer/introducer_api.py +1 -1
  277. chia/plot_sync/exceptions.py +1 -1
  278. chia/plot_sync/receiver.py +1 -1
  279. chia/plot_sync/sender.py +2 -2
  280. chia/pools/pool_puzzles.py +13 -18
  281. chia/pools/pool_wallet.py +23 -46
  282. chia/protocols/farmer_protocol.py +11 -3
  283. chia/protocols/full_node_protocol.py +1 -4
  284. chia/protocols/harvester_protocol.py +3 -3
  285. chia/protocols/pool_protocol.py +1 -2
  286. chia/protocols/shared_protocol.py +3 -3
  287. chia/protocols/timelord_protocol.py +1 -3
  288. chia/protocols/wallet_protocol.py +3 -3
  289. chia/rpc/rpc_client.py +7 -8
  290. chia/rpc/rpc_server.py +3 -3
  291. chia/rpc/util.py +3 -1
  292. chia/seeder/crawler.py +1 -1
  293. chia/seeder/crawler_api.py +1 -1
  294. chia/seeder/dns_server.py +2 -0
  295. chia/seeder/start_crawler.py +3 -3
  296. chia/server/address_manager.py +286 -38
  297. chia/server/address_manager_store.py +0 -215
  298. chia/{types → server}/aliases.py +7 -7
  299. chia/server/api_protocol.py +1 -1
  300. chia/server/chia_policy.py +1 -1
  301. chia/server/node_discovery.py +76 -113
  302. chia/server/rate_limits.py +1 -1
  303. chia/server/resolve_peer_info.py +43 -0
  304. chia/server/server.py +5 -5
  305. chia/server/start_data_layer.py +4 -4
  306. chia/server/start_farmer.py +5 -4
  307. chia/server/start_full_node.py +5 -4
  308. chia/server/start_harvester.py +7 -5
  309. chia/server/start_introducer.py +2 -2
  310. chia/server/start_service.py +1 -1
  311. chia/server/start_timelord.py +7 -5
  312. chia/server/start_wallet.py +7 -5
  313. chia/server/ws_connection.py +1 -1
  314. chia/simulator/add_blocks_in_batches.py +2 -2
  315. chia/simulator/block_tools.py +245 -201
  316. chia/simulator/full_node_simulator.py +38 -10
  317. chia/simulator/setup_services.py +12 -12
  318. chia/simulator/simulator_full_node_rpc_api.py +2 -2
  319. chia/simulator/simulator_full_node_rpc_client.py +2 -2
  320. chia/simulator/simulator_test_tools.py +2 -2
  321. chia/simulator/start_simulator.py +1 -1
  322. chia/simulator/wallet_tools.py +10 -18
  323. chia/ssl/create_ssl.py +1 -1
  324. chia/timelord/iters_from_block.py +14 -14
  325. chia/timelord/timelord.py +15 -11
  326. chia/timelord/timelord_api.py +14 -2
  327. chia/timelord/timelord_state.py +20 -14
  328. chia/types/blockchain_format/program.py +53 -10
  329. chia/types/blockchain_format/proof_of_space.py +73 -19
  330. chia/types/coin_spend.py +3 -56
  331. chia/types/generator_types.py +28 -0
  332. chia/types/internal_mempool_item.py +1 -2
  333. chia/types/mempool_item.py +12 -7
  334. chia/types/unfinished_header_block.py +1 -2
  335. chia/types/validation_state.py +1 -2
  336. chia/types/weight_proof.py +1 -3
  337. chia/util/action_scope.py +3 -3
  338. chia/util/block_cache.py +1 -2
  339. chia/util/byte_types.py +1 -1
  340. chia/util/casts.py +21 -0
  341. chia/util/config.py +0 -37
  342. chia/util/db_wrapper.py +8 -1
  343. chia/util/errors.py +3 -2
  344. chia/util/initial-config.yaml +21 -5
  345. chia/util/keychain.py +6 -7
  346. chia/util/keyring_wrapper.py +5 -5
  347. chia/util/limited_semaphore.py +1 -1
  348. chia/util/priority_mutex.py +1 -1
  349. chia/util/streamable.py +63 -5
  350. chia/util/task_timing.py +1 -1
  351. chia/util/virtual_project_analysis.py +1 -1
  352. chia/wallet/cat_wallet/cat_info.py +7 -3
  353. chia/wallet/cat_wallet/cat_outer_puzzle.py +9 -5
  354. chia/wallet/cat_wallet/cat_utils.py +1 -1
  355. chia/wallet/cat_wallet/cat_wallet.py +44 -36
  356. chia/wallet/cat_wallet/lineage_store.py +7 -0
  357. chia/wallet/cat_wallet/r_cat_wallet.py +274 -0
  358. chia/wallet/conditions.py +5 -10
  359. chia/wallet/db_wallet/db_wallet_puzzles.py +4 -4
  360. chia/wallet/derivation_record.py +33 -0
  361. chia/wallet/derive_keys.py +3 -3
  362. chia/wallet/did_wallet/did_info.py +12 -3
  363. chia/wallet/did_wallet/did_wallet.py +132 -101
  364. chia/wallet/did_wallet/did_wallet_puzzles.py +9 -9
  365. chia/wallet/driver_protocol.py +3 -1
  366. chia/{types/spend_bundle.py → wallet/estimate_fees.py} +2 -7
  367. chia/wallet/nft_wallet/metadata_outer_puzzle.py +5 -3
  368. chia/wallet/nft_wallet/nft_puzzle_utils.py +1 -1
  369. chia/wallet/nft_wallet/nft_wallet.py +69 -112
  370. chia/wallet/nft_wallet/ownership_outer_puzzle.py +5 -3
  371. chia/wallet/nft_wallet/singleton_outer_puzzle.py +6 -4
  372. chia/wallet/nft_wallet/transfer_program_puzzle.py +4 -2
  373. chia/wallet/nft_wallet/uncurry_nft.py +4 -6
  374. chia/wallet/notification_manager.py +2 -3
  375. chia/wallet/outer_puzzles.py +7 -2
  376. chia/wallet/puzzle_drivers.py +1 -1
  377. chia/wallet/puzzles/clawback/drivers.py +5 -4
  378. chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.py +1 -1
  379. chia/wallet/puzzles/singleton_top_layer.py +2 -1
  380. chia/wallet/puzzles/singleton_top_layer_v1_1.py +2 -1
  381. chia/wallet/puzzles/tails.py +1 -3
  382. chia/wallet/signer_protocol.py +5 -6
  383. chia/wallet/singleton.py +5 -4
  384. chia/wallet/singleton_record.py +1 -1
  385. chia/wallet/trade_manager.py +18 -20
  386. chia/wallet/trade_record.py +3 -6
  387. chia/wallet/trading/offer.py +12 -13
  388. chia/wallet/uncurried_puzzle.py +2 -2
  389. chia/wallet/util/compute_additions.py +58 -0
  390. chia/wallet/util/compute_hints.py +3 -3
  391. chia/wallet/util/compute_memos.py +4 -4
  392. chia/wallet/util/curry_and_treehash.py +2 -1
  393. chia/wallet/util/debug_spend_bundle.py +1 -1
  394. chia/wallet/util/merkle_tree.py +1 -1
  395. chia/wallet/util/peer_request_cache.py +1 -2
  396. chia/wallet/util/tx_config.py +3 -8
  397. chia/wallet/util/wallet_sync_utils.py +10 -5
  398. chia/wallet/util/wallet_types.py +1 -0
  399. chia/wallet/vc_wallet/cr_cat_drivers.py +17 -18
  400. chia/wallet/vc_wallet/cr_cat_wallet.py +30 -28
  401. chia/wallet/vc_wallet/cr_outer_puzzle.py +5 -3
  402. chia/wallet/vc_wallet/vc_drivers.py +50 -8
  403. chia/wallet/vc_wallet/vc_store.py +3 -5
  404. chia/wallet/vc_wallet/vc_wallet.py +15 -22
  405. chia/wallet/wallet.py +36 -46
  406. chia/wallet/wallet_action_scope.py +73 -4
  407. chia/wallet/wallet_blockchain.py +1 -3
  408. chia/wallet/wallet_interested_store.py +1 -1
  409. chia/wallet/wallet_nft_store.py +3 -3
  410. chia/wallet/wallet_node.py +17 -16
  411. chia/wallet/wallet_node_api.py +4 -5
  412. chia/wallet/wallet_pool_store.py +1 -1
  413. chia/wallet/wallet_protocol.py +2 -0
  414. chia/wallet/wallet_puzzle_store.py +1 -1
  415. chia/{rpc → wallet}/wallet_request_types.py +670 -81
  416. chia/{rpc → wallet}/wallet_rpc_api.py +735 -766
  417. chia/{rpc → wallet}/wallet_rpc_client.py +268 -420
  418. chia/wallet/wallet_singleton_store.py +8 -7
  419. chia/wallet/wallet_spend_bundle.py +4 -3
  420. chia/wallet/wallet_state_manager.py +320 -191
  421. chia/wallet/wallet_weight_proof_handler.py +1 -2
  422. chia/wallet/wsm_apis.py +98 -0
  423. {chia_blockchain-2.5.4rc2.dist-info → chia_blockchain-2.5.5rc2.dist-info}/METADATA +7 -7
  424. {chia_blockchain-2.5.4rc2.dist-info → chia_blockchain-2.5.5rc2.dist-info}/RECORD +443 -436
  425. mozilla-ca/cacert.pem +3 -165
  426. chia/_tests/fee_estimation/test_mempoolitem_height_added.py +0 -145
  427. chia/cmds/dev.py +0 -18
  428. chia/types/blockchain_format/slots.py +0 -9
  429. chia/types/blockchain_format/sub_epoch_summary.py +0 -5
  430. chia/types/end_of_slot_bundle.py +0 -5
  431. chia/types/full_block.py +0 -5
  432. chia/types/header_block.py +0 -5
  433. chia/types/spend_bundle_conditions.py +0 -7
  434. chia/types/transaction_queue_entry.py +0 -56
  435. chia/types/unfinished_block.py +0 -5
  436. /chia/cmds/{installers.py → dev/installers.py} +0 -0
  437. /chia/cmds/{sim.py → dev/sim.py} +0 -0
  438. /chia/{util → cmds}/dump_keyring.py +0 -0
  439. /chia/{full_node → consensus}/signage_point.py +0 -0
  440. /chia/{rpc → data_layer}/data_layer_rpc_client.py +0 -0
  441. /chia/{rpc → farmer}/farmer_rpc_api.py +0 -0
  442. /chia/{util → full_node}/full_block_utils.py +0 -0
  443. /chia/{rpc → harvester}/harvester_rpc_api.py +0 -0
  444. /chia/{rpc → harvester}/harvester_rpc_client.py +0 -0
  445. /chia/{full_node → protocols}/fee_estimate.py +0 -0
  446. /chia/{server → protocols}/outbound_message.py +0 -0
  447. /chia/{rpc → seeder}/crawler_rpc_api.py +0 -0
  448. /chia/{util → simulator}/vdf_prover.py +0 -0
  449. /chia/{util → ssl}/ssl_check.py +0 -0
  450. /chia/{rpc → timelord}/timelord_rpc_api.py +0 -0
  451. {chia_blockchain-2.5.4rc2.dist-info → chia_blockchain-2.5.5rc2.dist-info}/LICENSE +0 -0
  452. {chia_blockchain-2.5.4rc2.dist-info → chia_blockchain-2.5.5rc2.dist-info}/WHEEL +0 -0
  453. {chia_blockchain-2.5.4rc2.dist-info → chia_blockchain-2.5.5rc2.dist-info}/entry_points.txt +0 -0
@@ -1,108 +1,87 @@
1
1
  from __future__ import annotations
2
2
 
3
- import asyncio
4
3
  import logging
5
- import random
6
- from collections.abc import Coroutine
7
- from typing import Any, Callable, Optional
4
+ from typing import Any, Optional
8
5
 
9
6
  import pytest
10
7
  from chia_rs.sized_bytes import bytes32
11
- from chia_rs.sized_ints import uint16, uint32, uint64, uint128
8
+ from chia_rs.sized_ints import uint16, uint32, uint64
12
9
 
13
- from chia._tests.util.time_out_assert import time_out_assert, time_out_assert_not_none
14
- from chia.consensus.block_rewards import calculate_base_farmer_reward, calculate_pool_reward
15
- from chia.simulator.full_node_simulator import FullNodeSimulator
16
- from chia.simulator.simulator_protocol import FarmNewBlockProtocol
10
+ from chia._tests.environments.wallet import WalletStateTransition, WalletTestFramework
11
+ from chia._tests.util.time_out_assert import time_out_assert
17
12
  from chia.types.blockchain_format.program import Program
18
- from chia.types.peer_info import PeerInfo
19
13
  from chia.wallet.cat_wallet.cat_wallet import CATWallet
20
14
  from chia.wallet.did_wallet.did_wallet import DIDWallet
21
15
  from chia.wallet.nft_wallet.nft_wallet import NFTWallet
22
16
  from chia.wallet.outer_puzzles import create_asset_id, match_puzzle
23
17
  from chia.wallet.puzzle_drivers import PuzzleInfo
24
- from chia.wallet.trading.offer import Offer
18
+ from chia.wallet.trading.offer import Offer, OfferSummary
25
19
  from chia.wallet.trading.trade_status import TradeStatus
26
20
  from chia.wallet.uncurried_puzzle import uncurry_puzzle
27
- from chia.wallet.util.compute_memos import compute_memos
28
- from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG
29
- from chia.wallet.wallet_node import WalletNode
30
-
31
- # from clvm_tools.binutils import disassemble
32
21
 
33
22
  logging.getLogger("aiosqlite").setLevel(logging.INFO) # Too much logging on debug level
34
23
 
35
24
 
36
- def mempool_not_empty(fnapi: FullNodeSimulator) -> bool:
37
- return fnapi.full_node.mempool_manager.mempool.size() > 0
38
-
39
-
40
- async def farm_blocks_until(
41
- predicate_f: Callable[[], Coroutine[Any, Any, bool]], fnapi: FullNodeSimulator, ph: bytes32
42
- ) -> None:
43
- for i in range(50):
44
- await fnapi.farm_new_transaction_block(FarmNewBlockProtocol(ph))
45
- if await predicate_f():
46
- return None
47
- await asyncio.sleep(0.3)
48
- raise TimeoutError()
49
-
50
-
51
25
  async def get_nft_count(wallet: NFTWallet) -> int:
52
26
  return await wallet.get_nft_count()
53
27
 
54
28
 
55
- def trusted_setup_helper(
56
- trusted: bool, wallet_node_maker: WalletNode, wallet_node_taker: WalletNode, full_node_api: FullNodeSimulator
57
- ) -> None:
58
- if trusted:
59
- wallet_node_maker.config["trusted_peers"] = {
60
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
61
- }
62
- wallet_node_taker.config["trusted_peers"] = {
63
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
64
- }
65
- else:
66
- wallet_node_maker.config["trusted_peers"] = {}
67
- wallet_node_taker.config["trusted_peers"] = {}
68
-
69
-
70
- @pytest.mark.parametrize("trusted", [True, False])
29
+ @pytest.mark.limit_consensus_modes
30
+ @pytest.mark.parametrize("wallet_environments", [{"num_environments": 2, "blocks_needed": [1, 1]}], indirect=True)
71
31
  @pytest.mark.parametrize("zero_royalties", [True, False])
72
32
  @pytest.mark.anyio
73
- async def test_nft_offer_sell_nft(
74
- self_hostname: str, two_wallet_nodes: Any, trusted: Any, zero_royalties: bool, seeded_random: random.Random
75
- ) -> None:
76
- full_nodes, wallets, _ = two_wallet_nodes
77
- full_node_api: FullNodeSimulator = full_nodes[0]
78
- full_node_server = full_node_api.server
79
- wallet_node_maker, server_0 = wallets[0]
80
- wallet_node_taker, server_1 = wallets[1]
81
- wallet_maker = wallet_node_maker.wallet_state_manager.main_wallet
82
- wallet_taker = wallet_node_taker.wallet_state_manager.main_wallet
83
-
84
- ph_maker = await wallet_maker.get_new_puzzlehash()
85
- ph_token = bytes32.random(seeded_random)
86
-
87
- trusted_setup_helper(trusted, wallet_node_maker, wallet_node_taker, full_node_api)
88
-
89
- await server_0.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
90
- await server_1.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
91
-
92
- funds = sum(calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, 2))
93
- await full_node_api.farm_rewards_to_wallet(funds, wallet_maker, timeout=30)
94
- await full_node_api.farm_rewards_to_wallet(funds, wallet_taker, timeout=30)
95
-
96
- async with wallet_maker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
33
+ async def test_nft_offer_sell_nft(wallet_environments: WalletTestFramework, zero_royalties: bool) -> None:
34
+ env_maker = wallet_environments.environments[0]
35
+ env_taker = wallet_environments.environments[1]
36
+ wallet_maker = env_maker.xch_wallet
37
+ wallet_taker = env_taker.xch_wallet
38
+
39
+ env_maker.wallet_aliases = {
40
+ "xch": 1,
41
+ "did": 2,
42
+ "nft": 3,
43
+ }
44
+ env_taker.wallet_aliases = {
45
+ "xch": 1,
46
+ "nft": 2,
47
+ }
48
+
49
+ async with wallet_maker.wallet_state_manager.new_action_scope(
50
+ wallet_environments.tx_config, push=True
51
+ ) as action_scope:
52
+ ph_maker = await action_scope.get_puzzle_hash(wallet_maker.wallet_state_manager)
53
+
54
+ async with wallet_maker.wallet_state_manager.new_action_scope(
55
+ wallet_environments.tx_config, push=True
56
+ ) as action_scope:
97
57
  did_wallet_maker: DIDWallet = await DIDWallet.create_new_did_wallet(
98
- wallet_node_maker.wallet_state_manager, wallet_maker, uint64(1), action_scope
58
+ env_maker.wallet_state_manager, wallet_maker, uint64(1), action_scope
99
59
  )
100
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
101
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker, wallet_node_taker], timeout=20)
102
60
 
103
- await time_out_assert(20, wallet_maker.get_pending_change_balance, 0)
104
- await time_out_assert(20, wallet_maker.get_unconfirmed_balance, funds - 1)
105
- await time_out_assert(20, wallet_maker.get_confirmed_balance, funds - 1)
61
+ await wallet_environments.process_pending_states(
62
+ [
63
+ WalletStateTransition(
64
+ pre_block_balance_updates={
65
+ "xch": {
66
+ "set_remainder": True,
67
+ },
68
+ "did": {
69
+ "init": True,
70
+ "set_remainder": True,
71
+ },
72
+ },
73
+ post_block_balance_updates={
74
+ "xch": {
75
+ "set_remainder": True,
76
+ },
77
+ "did": {
78
+ "set_remainder": True,
79
+ },
80
+ },
81
+ ),
82
+ WalletStateTransition(),
83
+ ]
84
+ )
106
85
 
107
86
  hex_did_id = did_wallet_maker.get_my_DID()
108
87
  did_id = bytes32.fromhex(hex_did_id)
@@ -111,7 +90,7 @@ async def test_nft_offer_sell_nft(
111
90
  royalty_basis_pts = uint16(0 if zero_royalties else 200)
112
91
 
113
92
  nft_wallet_maker = await NFTWallet.create_new_nft_wallet(
114
- wallet_node_maker.wallet_state_manager, wallet_maker, name="NFT WALLET DID 1", did_id=did_id
93
+ env_maker.wallet_state_manager, wallet_maker, name="NFT WALLET DID 1", did_id=did_id
115
94
  )
116
95
  metadata = Program.to(
117
96
  [
@@ -120,7 +99,9 @@ async def test_nft_offer_sell_nft(
120
99
  ]
121
100
  )
122
101
 
123
- async with nft_wallet_maker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
102
+ async with nft_wallet_maker.wallet_state_manager.new_action_scope(
103
+ wallet_environments.tx_config, push=True
104
+ ) as action_scope:
124
105
  await nft_wallet_maker.generate_new_nft(
125
106
  metadata,
126
107
  action_scope,
@@ -129,21 +110,41 @@ async def test_nft_offer_sell_nft(
129
110
  royalty_basis_pts,
130
111
  did_id,
131
112
  )
132
- for tx in action_scope.side_effects.transactions:
133
- if tx.spend_bundle is not None:
134
- assert compute_memos(tx.spend_bundle)
135
- await time_out_assert_not_none(
136
- 20, full_node_api.full_node.mempool_manager.get_spendbundle, tx.spend_bundle.name()
137
- )
138
-
139
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token))
140
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker, wallet_node_taker], timeout=20)
141
113
 
142
- await time_out_assert(20, get_nft_count, 1, nft_wallet_maker)
114
+ await wallet_environments.process_pending_states(
115
+ [
116
+ WalletStateTransition(
117
+ pre_block_balance_updates={
118
+ "xch": {
119
+ "set_remainder": True,
120
+ },
121
+ "did": {
122
+ "set_remainder": True,
123
+ },
124
+ "nft": {
125
+ "init": True,
126
+ "set_remainder": True,
127
+ },
128
+ },
129
+ post_block_balance_updates={
130
+ "xch": {
131
+ "set_remainder": True,
132
+ },
133
+ "did": {
134
+ "set_remainder": True,
135
+ },
136
+ "nft": {
137
+ "set_remainder": True,
138
+ },
139
+ },
140
+ ),
141
+ WalletStateTransition(),
142
+ ]
143
+ )
143
144
 
144
145
  # TAKER SETUP - NO DID
145
146
  nft_wallet_taker = await NFTWallet.create_new_nft_wallet(
146
- wallet_node_taker.wallet_state_manager, wallet_taker, name="NFT WALLET TAKER"
147
+ env_taker.wallet_state_manager, wallet_taker, name="NFT WALLET TAKER"
147
148
  )
148
149
 
149
150
  # maker create offer: NFT for xch
@@ -160,9 +161,11 @@ async def test_nft_offer_sell_nft(
160
161
  xch_requested = 1000
161
162
  maker_fee = uint64(433)
162
163
 
163
- offer_did_nft_for_xch = {nft_to_offer_asset_id: -1, wallet_maker.id(): xch_requested}
164
+ offer_did_nft_for_xch: OfferSummary = {nft_to_offer_asset_id: -1, wallet_maker.id(): xch_requested}
164
165
 
165
- async with trade_manager_maker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=False) as action_scope:
166
+ async with trade_manager_maker.wallet_state_manager.new_action_scope(
167
+ wallet_environments.tx_config, push=False
168
+ ) as action_scope:
166
169
  success, trade_make, error = await trade_manager_maker.create_offer_for_ids(
167
170
  offer_did_nft_for_xch, action_scope, {}, fee=maker_fee
168
171
  )
@@ -171,74 +174,140 @@ async def test_nft_offer_sell_nft(
171
174
  assert trade_make is not None
172
175
 
173
176
  taker_fee = 1
174
- assert not mempool_not_empty(full_node_api)
175
- peer = wallet_node_taker.get_full_node_peer()
177
+ peer = env_taker.node.get_full_node_peer()
176
178
 
177
- [_maker_offer], signing_response = await wallet_node_maker.wallet_state_manager.sign_offers(
179
+ [_maker_offer], signing_response = await env_maker.wallet_state_manager.sign_offers(
178
180
  [Offer.from_bytes(trade_make.offer)]
179
181
  )
180
182
  async with trade_manager_taker.wallet_state_manager.new_action_scope(
181
- DEFAULT_TX_CONFIG, push=True, additional_signing_responses=signing_response
183
+ wallet_environments.tx_config, push=True, additional_signing_responses=signing_response
182
184
  ) as action_scope:
183
185
  trade_take = await trade_manager_taker.respond_to_offer(
184
186
  Offer.from_bytes(trade_make.offer), peer, action_scope, fee=uint64(taker_fee)
185
187
  )
186
188
 
187
- await time_out_assert(20, mempool_not_empty, True, full_node_api)
188
-
189
189
  assert trade_take is not None
190
190
 
191
- async def maker_0_taker_1() -> bool:
192
- return await nft_wallet_maker.get_nft_count() == 0 and await nft_wallet_taker.get_nft_count() == 1
193
-
194
- await farm_blocks_until(maker_0_taker_1, full_node_api, ph_token)
195
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker, wallet_node_taker], timeout=20)
191
+ expected_royalty = uint64(xch_requested * royalty_basis_pts / 10000)
192
+ await wallet_environments.process_pending_states(
193
+ [
194
+ WalletStateTransition(
195
+ pre_block_balance_updates={
196
+ "xch": {
197
+ "<=#spendable_balance": maker_fee,
198
+ "<=#max_send_amount": maker_fee,
199
+ "pending_coin_removal_count": 1,
200
+ },
201
+ "did": {},
202
+ "nft": {
203
+ "pending_coin_removal_count": 1,
204
+ },
205
+ },
206
+ post_block_balance_updates={
207
+ "xch": {
208
+ "confirmed_wallet_balance": (xch_requested + expected_royalty) - maker_fee,
209
+ "unconfirmed_wallet_balance": (xch_requested + expected_royalty) - maker_fee,
210
+ ">=#spendable_balance": 1,
211
+ ">=#max_send_amount": 1,
212
+ "unspent_coin_count": 2 if expected_royalty > 0 else 1,
213
+ "pending_coin_removal_count": -1,
214
+ },
215
+ "did": {},
216
+ "nft": {
217
+ "unspent_coin_count": -1,
218
+ "pending_coin_removal_count": -1,
219
+ },
220
+ },
221
+ ),
222
+ WalletStateTransition(
223
+ pre_block_balance_updates={
224
+ "xch": {
225
+ "unconfirmed_wallet_balance": -(taker_fee + xch_requested + expected_royalty),
226
+ "<=#spendable_balance": -(taker_fee + xch_requested + expected_royalty),
227
+ "<=#max_send_amount": -(taker_fee + xch_requested + expected_royalty),
228
+ ">=#pending_change": 1,
229
+ "pending_coin_removal_count": 1,
230
+ },
231
+ "nft": {
232
+ "init": True,
233
+ },
234
+ },
235
+ post_block_balance_updates={
236
+ "xch": {
237
+ "confirmed_wallet_balance": -(taker_fee + xch_requested + expected_royalty),
238
+ ">=#spendable_balance": 1,
239
+ ">=#max_send_amount": 1,
240
+ "<=#pending_change": -1,
241
+ "pending_coin_removal_count": -1,
242
+ },
243
+ "nft": {
244
+ "unspent_coin_count": 1,
245
+ },
246
+ },
247
+ ),
248
+ ]
249
+ )
196
250
 
197
251
  await time_out_assert(20, get_nft_count, 0, nft_wallet_maker)
198
252
  await time_out_assert(20, get_nft_count, 1, nft_wallet_taker)
199
253
 
200
- # assert payments and royalties
201
- expected_royalty = uint64(xch_requested * royalty_basis_pts / 10000)
202
- expected_maker_balance = funds - 2 - maker_fee + xch_requested + expected_royalty
203
- expected_taker_balance = funds - taker_fee - xch_requested - expected_royalty
204
- await time_out_assert(20, wallet_maker.get_confirmed_balance, expected_maker_balance)
205
- await time_out_assert(20, wallet_taker.get_confirmed_balance, expected_taker_balance)
206
254
 
207
-
208
- @pytest.mark.parametrize("trusted", [True, False])
255
+ @pytest.mark.limit_consensus_modes
256
+ @pytest.mark.parametrize("wallet_environments", [{"num_environments": 2, "blocks_needed": [1, 1]}], indirect=True)
209
257
  @pytest.mark.parametrize("zero_royalties", [True, False])
210
258
  @pytest.mark.anyio
211
- async def test_nft_offer_request_nft(
212
- self_hostname: str, two_wallet_nodes: Any, trusted: Any, zero_royalties: bool, seeded_random: random.Random
213
- ) -> None:
214
- full_nodes, wallets, _ = two_wallet_nodes
215
- full_node_api: FullNodeSimulator = full_nodes[0]
216
- full_node_server = full_node_api.server
217
- wallet_node_maker, server_0 = wallets[0]
218
- wallet_node_taker, server_1 = wallets[1]
219
- wallet_maker = wallet_node_maker.wallet_state_manager.main_wallet
220
- wallet_taker = wallet_node_taker.wallet_state_manager.main_wallet
221
-
222
- ph_taker = await wallet_taker.get_new_puzzlehash()
223
- ph_token = bytes32.random(seeded_random)
224
-
225
- trusted_setup_helper(trusted, wallet_node_maker, wallet_node_taker, full_node_api)
226
-
227
- await server_0.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
228
- await server_1.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
229
-
230
- funds = sum(calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, 2))
231
- await full_node_api.farm_rewards_to_wallet(funds, wallet_maker, timeout=30)
232
- await full_node_api.farm_rewards_to_wallet(funds, wallet_taker, timeout=30)
233
-
234
- async with wallet_taker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
259
+ async def test_nft_offer_request_nft(wallet_environments: WalletTestFramework, zero_royalties: bool) -> None:
260
+ env_maker = wallet_environments.environments[0]
261
+ env_taker = wallet_environments.environments[1]
262
+ wallet_maker = env_maker.xch_wallet
263
+ wallet_taker = env_taker.xch_wallet
264
+
265
+ env_maker.wallet_aliases = {
266
+ "xch": 1,
267
+ "nft": 2,
268
+ }
269
+ env_taker.wallet_aliases = {
270
+ "xch": 1,
271
+ "did": 2,
272
+ "nft": 3,
273
+ }
274
+
275
+ async with wallet_taker.wallet_state_manager.new_action_scope(
276
+ wallet_environments.tx_config, push=True
277
+ ) as action_scope:
278
+ ph_taker = await action_scope.get_puzzle_hash(wallet_taker.wallet_state_manager)
279
+
280
+ async with wallet_taker.wallet_state_manager.new_action_scope(
281
+ wallet_environments.tx_config, push=True
282
+ ) as action_scope:
235
283
  did_wallet_taker: DIDWallet = await DIDWallet.create_new_did_wallet(
236
- wallet_node_taker.wallet_state_manager, wallet_taker, uint64(1), action_scope
284
+ env_taker.wallet_state_manager, wallet_taker, uint64(1), action_scope
237
285
  )
238
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
239
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker, wallet_node_taker], timeout=20)
240
286
 
241
- await time_out_assert(20, wallet_taker.get_pending_change_balance, 0)
287
+ await wallet_environments.process_pending_states(
288
+ [
289
+ WalletStateTransition(),
290
+ WalletStateTransition(
291
+ pre_block_balance_updates={
292
+ "xch": {
293
+ "set_remainder": True,
294
+ },
295
+ "did": {
296
+ "init": True,
297
+ "set_remainder": True,
298
+ },
299
+ },
300
+ post_block_balance_updates={
301
+ "xch": {
302
+ "set_remainder": True,
303
+ },
304
+ "did": {
305
+ "set_remainder": True,
306
+ },
307
+ },
308
+ ),
309
+ ]
310
+ )
242
311
 
243
312
  hex_did_id = did_wallet_taker.get_my_DID()
244
313
  did_id = bytes32.fromhex(hex_did_id)
@@ -247,7 +316,7 @@ async def test_nft_offer_request_nft(
247
316
  royalty_basis_pts = uint16(0 if zero_royalties else 200)
248
317
 
249
318
  nft_wallet_taker = await NFTWallet.create_new_nft_wallet(
250
- wallet_node_taker.wallet_state_manager, wallet_taker, name="NFT WALLET DID TAKER", did_id=did_id
319
+ env_taker.wallet_state_manager, wallet_taker, name="NFT WALLET DID TAKER", did_id=did_id
251
320
  )
252
321
  metadata = Program.to(
253
322
  [
@@ -255,10 +324,10 @@ async def test_nft_offer_request_nft(
255
324
  ("h", "0xD4584AD463139FA8C0D9F68F4B59F185"),
256
325
  ]
257
326
  )
258
- await time_out_assert(20, wallet_taker.get_unconfirmed_balance, funds - 1)
259
- await time_out_assert(20, wallet_taker.get_confirmed_balance, funds - 1)
260
327
 
261
- async with nft_wallet_taker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
328
+ async with nft_wallet_taker.wallet_state_manager.new_action_scope(
329
+ wallet_environments.tx_config, push=True
330
+ ) as action_scope:
262
331
  await nft_wallet_taker.generate_new_nft(
263
332
  metadata,
264
333
  action_scope,
@@ -267,21 +336,43 @@ async def test_nft_offer_request_nft(
267
336
  royalty_basis_pts,
268
337
  did_id,
269
338
  )
270
- for tx in action_scope.side_effects.transactions:
271
- if tx.spend_bundle is not None:
272
- assert compute_memos(tx.spend_bundle)
273
- await time_out_assert_not_none(
274
- 20, full_node_api.full_node.mempool_manager.get_spendbundle, tx.spend_bundle.name()
275
- )
276
339
 
277
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token))
278
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker, wallet_node_taker], timeout=20)
340
+ await wallet_environments.process_pending_states(
341
+ [
342
+ WalletStateTransition(),
343
+ WalletStateTransition(
344
+ pre_block_balance_updates={
345
+ "xch": {
346
+ "set_remainder": True,
347
+ },
348
+ "did": {
349
+ "set_remainder": True,
350
+ },
351
+ "nft": {
352
+ "init": True,
353
+ "set_remainder": True,
354
+ },
355
+ },
356
+ post_block_balance_updates={
357
+ "xch": {
358
+ "set_remainder": True,
359
+ },
360
+ "did": {
361
+ "set_remainder": True,
362
+ },
363
+ "nft": {
364
+ "set_remainder": True,
365
+ },
366
+ },
367
+ ),
368
+ ]
369
+ )
279
370
 
280
371
  await time_out_assert(20, get_nft_count, 1, nft_wallet_taker)
281
372
 
282
373
  # MAKER SETUP - NO DID
283
374
  nft_wallet_maker = await NFTWallet.create_new_nft_wallet(
284
- wallet_node_maker.wallet_state_manager, wallet_maker, name="NFT WALLET MAKER"
375
+ env_maker.wallet_state_manager, wallet_maker, name="NFT WALLET MAKER"
285
376
  )
286
377
 
287
378
  # maker create offer: NFT for xch
@@ -297,13 +388,16 @@ async def test_nft_offer_request_nft(
297
388
 
298
389
  assert isinstance(nft_to_request_info, PuzzleInfo)
299
390
  nft_to_request_asset_id = create_asset_id(nft_to_request_info)
391
+ assert nft_to_request_asset_id is not None
300
392
  xch_offered = 1000
301
- maker_fee = 10
393
+ maker_fee = uint64(10)
302
394
  driver_dict = {nft_to_request_asset_id: nft_to_request_info}
303
395
 
304
- offer_dict = {nft_to_request_asset_id: 1, wallet_maker.id(): -xch_offered}
396
+ offer_dict: OfferSummary = {nft_to_request_asset_id: 1, wallet_maker.id(): -xch_offered}
305
397
 
306
- async with trade_manager_maker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=False) as action_scope:
398
+ async with trade_manager_maker.wallet_state_manager.new_action_scope(
399
+ wallet_environments.tx_config, push=False
400
+ ) as action_scope:
307
401
  success, trade_make, error = await trade_manager_maker.create_offer_for_ids(
308
402
  offer_dict, action_scope, driver_dict, fee=maker_fee
309
403
  )
@@ -313,69 +407,139 @@ async def test_nft_offer_request_nft(
313
407
 
314
408
  taker_fee = 1
315
409
 
316
- peer = wallet_node_taker.get_full_node_peer()
317
- [_maker_offer], signing_response = await wallet_node_maker.wallet_state_manager.sign_offers(
410
+ peer = env_taker.node.get_full_node_peer()
411
+ [_maker_offer], signing_response = await env_maker.wallet_state_manager.sign_offers(
318
412
  [Offer.from_bytes(trade_make.offer)]
319
413
  )
320
414
  async with trade_manager_taker.wallet_state_manager.new_action_scope(
321
- DEFAULT_TX_CONFIG, push=True, additional_signing_responses=signing_response
415
+ wallet_environments.tx_config, push=True, additional_signing_responses=signing_response
322
416
  ) as action_scope:
323
417
  trade_take = await trade_manager_taker.respond_to_offer(
324
418
  Offer.from_bytes(trade_make.offer), peer, action_scope, fee=uint64(taker_fee)
325
419
  )
326
- await time_out_assert(20, mempool_not_empty, True, full_node_api)
327
420
  assert trade_take is not None
328
421
 
329
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
330
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker, wallet_node_taker], timeout=20)
331
-
332
- async def maker_1_taker_0() -> bool:
333
- return await nft_wallet_maker.get_nft_count() == 1 and await nft_wallet_taker.get_nft_count() == 0
334
-
335
- await farm_blocks_until(maker_1_taker_0, full_node_api, ph_token)
336
-
337
- # assert payments and royalties
338
422
  expected_royalty = uint64(xch_offered * royalty_basis_pts / 10000)
339
- expected_maker_balance = funds - maker_fee - xch_offered - expected_royalty
340
- expected_taker_balance = funds - 2 - taker_fee + xch_offered + expected_royalty
341
- await time_out_assert(20, wallet_maker.get_confirmed_balance, expected_maker_balance)
342
- await time_out_assert(20, wallet_taker.get_confirmed_balance, expected_taker_balance)
423
+ await wallet_environments.process_pending_states(
424
+ [
425
+ WalletStateTransition(
426
+ pre_block_balance_updates={
427
+ "xch": {
428
+ "<=#spendable_balance": -(maker_fee + xch_offered + expected_royalty),
429
+ "<=#max_send_amount": -(maker_fee + xch_offered + expected_royalty),
430
+ "pending_coin_removal_count": 1,
431
+ },
432
+ "nft": {
433
+ "init": True,
434
+ },
435
+ },
436
+ post_block_balance_updates={
437
+ "xch": {
438
+ "confirmed_wallet_balance": -(maker_fee + xch_offered + expected_royalty),
439
+ "unconfirmed_wallet_balance": -(maker_fee + xch_offered + expected_royalty),
440
+ ">=#spendable_balance": 1,
441
+ ">=#max_send_amount": 1,
442
+ "pending_coin_removal_count": -1,
443
+ },
444
+ "nft": {
445
+ "unspent_coin_count": 1,
446
+ },
447
+ },
448
+ ),
449
+ WalletStateTransition(
450
+ pre_block_balance_updates={
451
+ "xch": {
452
+ # royalty information doesn't show up in unconfirmed balance
453
+ "unconfirmed_wallet_balance": xch_offered - taker_fee,
454
+ "<=#spendable_balance": -taker_fee,
455
+ "<=#max_send_amount": -taker_fee,
456
+ ">=#pending_change": 1,
457
+ "pending_coin_removal_count": 1,
458
+ },
459
+ "did": {},
460
+ "nft": {
461
+ "pending_coin_removal_count": 1,
462
+ },
463
+ },
464
+ post_block_balance_updates={
465
+ "xch": {
466
+ "confirmed_wallet_balance": xch_offered + expected_royalty - taker_fee,
467
+ "unconfirmed_wallet_balance": expected_royalty,
468
+ ">=#spendable_balance": 1,
469
+ ">=#max_send_amount": 1,
470
+ "<=#pending_change": -1,
471
+ "unspent_coin_count": 2 if expected_royalty > 0 else 1,
472
+ "pending_coin_removal_count": -1,
473
+ },
474
+ "did": {},
475
+ "nft": {
476
+ "unspent_coin_count": -1,
477
+ "pending_coin_removal_count": -1,
478
+ },
479
+ },
480
+ ),
481
+ ]
482
+ )
343
483
 
344
484
 
345
- @pytest.mark.parametrize("trusted", [True, False])
485
+ @pytest.mark.limit_consensus_modes
486
+ @pytest.mark.parametrize("wallet_environments", [{"num_environments": 2, "blocks_needed": [1, 1]}], indirect=True)
346
487
  @pytest.mark.parametrize("zero_royalties", [True, False])
347
488
  @pytest.mark.anyio
348
- async def test_nft_offer_sell_did_to_did(
349
- self_hostname: str, two_wallet_nodes: Any, trusted: Any, zero_royalties: bool, seeded_random: random.Random
350
- ) -> None:
351
- full_nodes, wallets, _ = two_wallet_nodes
352
- full_node_api: FullNodeSimulator = full_nodes[0]
353
- full_node_server = full_node_api.server
354
- wallet_node_maker, server_0 = wallets[0]
355
- wallet_node_taker, server_1 = wallets[1]
356
- wallet_maker = wallet_node_maker.wallet_state_manager.main_wallet
357
- wallet_taker = wallet_node_taker.wallet_state_manager.main_wallet
358
-
359
- ph_maker = await wallet_maker.get_new_puzzlehash()
360
- ph_token = bytes32.random(seeded_random)
361
-
362
- trusted_setup_helper(trusted, wallet_node_maker, wallet_node_taker, full_node_api)
363
-
364
- await server_0.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
365
- await server_1.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
366
-
367
- funds = sum(calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, 2))
368
- await full_node_api.farm_rewards_to_wallet(funds, wallet_maker, timeout=30)
369
- await full_node_api.farm_rewards_to_wallet(funds, wallet_taker, timeout=30)
370
-
371
- async with wallet_maker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
489
+ async def test_nft_offer_sell_did_to_did(wallet_environments: WalletTestFramework, zero_royalties: bool) -> None:
490
+ env_maker = wallet_environments.environments[0]
491
+ env_taker = wallet_environments.environments[1]
492
+ wallet_maker = env_maker.xch_wallet
493
+ wallet_taker = env_taker.xch_wallet
494
+
495
+ env_maker.wallet_aliases = {
496
+ "xch": 1,
497
+ "did": 2,
498
+ "nft": 3,
499
+ }
500
+ env_taker.wallet_aliases = {
501
+ "xch": 1,
502
+ "did": 2,
503
+ "nft1": 3,
504
+ "nft0": 4,
505
+ }
506
+
507
+ async with wallet_maker.wallet_state_manager.new_action_scope(
508
+ wallet_environments.tx_config, push=True
509
+ ) as action_scope:
510
+ ph_maker = await action_scope.get_puzzle_hash(wallet_maker.wallet_state_manager)
511
+
512
+ async with wallet_maker.wallet_state_manager.new_action_scope(
513
+ wallet_environments.tx_config, push=True
514
+ ) as action_scope:
372
515
  did_wallet_maker: DIDWallet = await DIDWallet.create_new_did_wallet(
373
- wallet_node_maker.wallet_state_manager, wallet_maker, uint64(1), action_scope
516
+ env_maker.wallet_state_manager, wallet_maker, uint64(1), action_scope
374
517
  )
375
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
376
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker, wallet_node_taker], timeout=20)
377
518
 
378
- await time_out_assert(20, wallet_maker.get_pending_change_balance, 0)
519
+ await wallet_environments.process_pending_states(
520
+ [
521
+ WalletStateTransition(
522
+ pre_block_balance_updates={
523
+ "xch": {
524
+ "set_remainder": True,
525
+ },
526
+ "did": {
527
+ "init": True,
528
+ "set_remainder": True,
529
+ },
530
+ },
531
+ post_block_balance_updates={
532
+ "xch": {
533
+ "set_remainder": True,
534
+ },
535
+ "did": {
536
+ "set_remainder": True,
537
+ },
538
+ },
539
+ ),
540
+ WalletStateTransition(),
541
+ ]
542
+ )
379
543
 
380
544
  hex_did_id = did_wallet_maker.get_my_DID()
381
545
  did_id = bytes32.fromhex(hex_did_id)
@@ -384,7 +548,7 @@ async def test_nft_offer_sell_did_to_did(
384
548
  royalty_basis_pts = uint16(0 if zero_royalties else 200)
385
549
 
386
550
  nft_wallet_maker = await NFTWallet.create_new_nft_wallet(
387
- wallet_node_maker.wallet_state_manager, wallet_maker, name="NFT WALLET DID 1", did_id=did_id
551
+ env_maker.wallet_state_manager, wallet_maker, name="NFT WALLET DID 1", did_id=did_id
388
552
  )
389
553
  metadata = Program.to(
390
554
  [
@@ -393,10 +557,9 @@ async def test_nft_offer_sell_did_to_did(
393
557
  ]
394
558
  )
395
559
 
396
- await time_out_assert(20, wallet_maker.get_unconfirmed_balance, funds - 1)
397
- await time_out_assert(20, wallet_maker.get_confirmed_balance, funds - 1)
398
-
399
- async with nft_wallet_maker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
560
+ async with nft_wallet_maker.wallet_state_manager.new_action_scope(
561
+ wallet_environments.tx_config, push=True
562
+ ) as action_scope:
400
563
  await nft_wallet_maker.generate_new_nft(
401
564
  metadata,
402
565
  action_scope,
@@ -405,33 +568,107 @@ async def test_nft_offer_sell_did_to_did(
405
568
  royalty_basis_pts,
406
569
  did_id,
407
570
  )
408
- for tx in action_scope.side_effects.transactions:
409
- if tx.spend_bundle is not None:
410
- assert compute_memos(tx.spend_bundle)
411
- await time_out_assert_not_none(
412
- 20, full_node_api.full_node.mempool_manager.get_spendbundle, tx.spend_bundle.name()
413
- )
414
571
 
415
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(bytes32.zeros))
416
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker, wallet_node_taker], timeout=20)
417
-
418
- await time_out_assert(20, get_nft_count, 1, nft_wallet_maker)
572
+ await wallet_environments.process_pending_states(
573
+ [
574
+ WalletStateTransition(
575
+ pre_block_balance_updates={
576
+ "xch": {
577
+ "set_remainder": True,
578
+ },
579
+ "did": {
580
+ "set_remainder": True,
581
+ },
582
+ "nft": {
583
+ "init": True,
584
+ "set_remainder": True,
585
+ },
586
+ },
587
+ post_block_balance_updates={
588
+ "xch": {
589
+ "set_remainder": True,
590
+ },
591
+ "did": {
592
+ "set_remainder": True,
593
+ },
594
+ "nft": {
595
+ "set_remainder": True,
596
+ },
597
+ },
598
+ ),
599
+ WalletStateTransition(),
600
+ ]
601
+ )
419
602
 
420
603
  # TAKER SETUP - WITH DID
421
- async with wallet_taker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
604
+ async with wallet_taker.wallet_state_manager.new_action_scope(
605
+ wallet_environments.tx_config, push=True
606
+ ) as action_scope:
422
607
  did_wallet_taker: DIDWallet = await DIDWallet.create_new_did_wallet(
423
- wallet_node_taker.wallet_state_manager, wallet_taker, uint64(1), action_scope
608
+ env_taker.wallet_state_manager, wallet_taker, uint64(1), action_scope
424
609
  )
425
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
426
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker, wallet_node_taker], timeout=20)
427
610
 
428
- await time_out_assert(20, wallet_taker.get_pending_change_balance, 0)
611
+ await wallet_environments.process_pending_states(
612
+ [
613
+ WalletStateTransition(),
614
+ WalletStateTransition(
615
+ pre_block_balance_updates={
616
+ "xch": {
617
+ "set_remainder": True,
618
+ },
619
+ "did": {
620
+ "init": True,
621
+ "set_remainder": True,
622
+ },
623
+ },
624
+ post_block_balance_updates={
625
+ "xch": {
626
+ "set_remainder": True,
627
+ },
628
+ "did": {
629
+ "set_remainder": True,
630
+ },
631
+ },
632
+ ),
633
+ ]
634
+ )
429
635
 
430
636
  hex_did_id_taker = did_wallet_taker.get_my_DID()
431
637
  did_id_taker = bytes32.fromhex(hex_did_id_taker)
432
638
 
433
639
  nft_wallet_taker = await NFTWallet.create_new_nft_wallet(
434
- wallet_node_taker.wallet_state_manager, wallet_taker, name="NFT WALLET TAKER", did_id=did_id_taker
640
+ env_taker.wallet_state_manager, wallet_taker, name="NFT WALLET TAKER", did_id=did_id_taker
641
+ )
642
+
643
+ await wallet_environments.process_pending_states(
644
+ [
645
+ WalletStateTransition(),
646
+ WalletStateTransition(
647
+ pre_block_balance_updates={
648
+ "xch": {
649
+ "set_remainder": True,
650
+ },
651
+ "did": {
652
+ "set_remainder": True,
653
+ },
654
+ "nft1": {
655
+ "init": True,
656
+ "set_remainder": True,
657
+ },
658
+ },
659
+ post_block_balance_updates={
660
+ "xch": {
661
+ "set_remainder": True,
662
+ },
663
+ "did": {
664
+ "set_remainder": True,
665
+ },
666
+ "nft1": {
667
+ "set_remainder": True,
668
+ },
669
+ },
670
+ ),
671
+ ]
435
672
  )
436
673
 
437
674
  # maker create offer: NFT for xch
@@ -446,9 +683,11 @@ async def test_nft_offer_sell_did_to_did(
446
683
  xch_requested = 1000
447
684
  maker_fee = uint64(433)
448
685
 
449
- offer_did_nft_for_xch = {nft_to_offer_asset_id: -1, wallet_maker.id(): xch_requested}
686
+ offer_did_nft_for_xch: OfferSummary = {nft_to_offer_asset_id: -1, wallet_maker.id(): xch_requested}
450
687
 
451
- async with trade_manager_maker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=False) as action_scope:
688
+ async with trade_manager_maker.wallet_state_manager.new_action_scope(
689
+ wallet_environments.tx_config, push=False
690
+ ) as action_scope:
452
691
  success, trade_make, error = await trade_manager_maker.create_offer_for_ids(
453
692
  offer_did_nft_for_xch, action_scope, {}, fee=maker_fee
454
693
  )
@@ -458,78 +697,141 @@ async def test_nft_offer_sell_did_to_did(
458
697
 
459
698
  taker_fee = 1
460
699
 
461
- peer = wallet_node_taker.get_full_node_peer()
462
- [_maker_offer], signing_response = await wallet_node_maker.wallet_state_manager.sign_offers(
700
+ peer = env_taker.node.get_full_node_peer()
701
+ [_maker_offer], signing_response = await env_maker.wallet_state_manager.sign_offers(
463
702
  [Offer.from_bytes(trade_make.offer)]
464
703
  )
465
704
  async with trade_manager_taker.wallet_state_manager.new_action_scope(
466
- DEFAULT_TX_CONFIG, push=True, additional_signing_responses=signing_response
705
+ wallet_environments.tx_config, push=True, additional_signing_responses=signing_response
467
706
  ) as action_scope:
468
707
  trade_take = await trade_manager_taker.respond_to_offer(
469
708
  Offer.from_bytes(trade_make.offer), peer, action_scope, fee=uint64(taker_fee)
470
709
  )
471
-
472
- await time_out_assert(20, mempool_not_empty, True, full_node_api)
473
710
  assert trade_take is not None
474
711
 
475
- async def maker_0_taker_1() -> bool:
476
- return (
477
- await nft_wallet_maker.get_nft_count() == 0
478
- and len(wallet_taker.wallet_state_manager.wallets) == 4
479
- and await wallet_taker.wallet_state_manager.wallets[4].get_nft_count() == 1
480
- )
481
-
482
- await farm_blocks_until(maker_0_taker_1, full_node_api, ph_token)
712
+ expected_royalty = uint64(xch_requested * royalty_basis_pts / 10000)
713
+ await wallet_environments.process_pending_states(
714
+ [
715
+ WalletStateTransition(
716
+ pre_block_balance_updates={
717
+ "xch": {
718
+ "<=#spendable_balance": maker_fee,
719
+ "<=#max_send_amount": maker_fee,
720
+ "pending_coin_removal_count": 1,
721
+ },
722
+ "did": {},
723
+ "nft": {
724
+ "pending_coin_removal_count": 1,
725
+ },
726
+ },
727
+ post_block_balance_updates={
728
+ "xch": {
729
+ "confirmed_wallet_balance": (xch_requested + expected_royalty) - maker_fee,
730
+ "unconfirmed_wallet_balance": (xch_requested + expected_royalty) - maker_fee,
731
+ ">=#spendable_balance": 1,
732
+ ">=#max_send_amount": 1,
733
+ "unspent_coin_count": 2 if expected_royalty > 0 else 1,
734
+ "pending_coin_removal_count": -1,
735
+ },
736
+ "did": {},
737
+ "nft": {
738
+ "unspent_coin_count": -1,
739
+ "pending_coin_removal_count": -1,
740
+ },
741
+ },
742
+ ),
743
+ WalletStateTransition(
744
+ pre_block_balance_updates={
745
+ "xch": {
746
+ "unconfirmed_wallet_balance": -(taker_fee + xch_requested + expected_royalty),
747
+ "<=#spendable_balance": -(taker_fee + xch_requested + expected_royalty),
748
+ "<=#max_send_amount": -(taker_fee + xch_requested + expected_royalty),
749
+ ">=#pending_change": 1,
750
+ "pending_coin_removal_count": 1,
751
+ },
752
+ },
753
+ post_block_balance_updates={
754
+ "xch": {
755
+ "confirmed_wallet_balance": -(taker_fee + xch_requested + expected_royalty),
756
+ ">=#spendable_balance": 1,
757
+ ">=#max_send_amount": 1,
758
+ "<=#pending_change": -1,
759
+ "pending_coin_removal_count": -1,
760
+ },
761
+ "nft0": {
762
+ "init": True,
763
+ "unspent_coin_count": 1,
764
+ },
765
+ },
766
+ ),
767
+ ]
768
+ )
483
769
 
770
+ nft_0_wallet_taker = env_taker.wallet_state_manager.wallets[uint32(4)]
771
+ assert isinstance(nft_0_wallet_taker, NFTWallet)
484
772
  await time_out_assert(20, get_nft_count, 0, nft_wallet_maker)
485
- # assert nnew nft wallet is created for taker
486
- await time_out_assert(20, len, 4, wallet_taker.wallet_state_manager.wallets)
487
- await time_out_assert(20, get_nft_count, 1, wallet_taker.wallet_state_manager.wallets[4])
488
- assert await wallet_taker.wallet_state_manager.wallets[4].nft_store.get_nft_by_id(nft_to_offer_asset_id) is not None
489
- # assert payments and royalties
490
- expected_royalty = uint64(xch_requested * royalty_basis_pts / 10000)
491
- expected_maker_balance = funds - 2 - maker_fee + xch_requested + expected_royalty
492
- expected_taker_balance = funds - 1 - taker_fee - xch_requested - expected_royalty
493
- await time_out_assert(20, wallet_maker.get_confirmed_balance, expected_maker_balance)
494
- await time_out_assert(20, wallet_taker.get_confirmed_balance, expected_taker_balance)
773
+ await time_out_assert(20, get_nft_count, 1, nft_0_wallet_taker)
774
+ assert await nft_0_wallet_taker.nft_store.get_nft_by_id(nft_to_offer_asset_id) is not None
495
775
 
496
776
 
497
- @pytest.mark.parametrize("trusted", [True, False])
777
+ @pytest.mark.limit_consensus_modes
778
+ @pytest.mark.parametrize("wallet_environments", [{"num_environments": 2, "blocks_needed": [1, 1]}], indirect=True)
498
779
  @pytest.mark.parametrize("zero_royalties", [True, False])
499
780
  @pytest.mark.anyio
500
- async def test_nft_offer_sell_nft_for_cat(
501
- self_hostname: str, two_wallet_nodes: Any, trusted: Any, zero_royalties: bool, seeded_random: random.Random
502
- ) -> None:
503
- full_nodes, wallets, _ = two_wallet_nodes
504
- full_node_api: FullNodeSimulator = full_nodes[0]
505
- full_node_server = full_node_api.server
506
- wallet_node_maker, server_0 = wallets[0]
507
- wallet_node_taker, server_1 = wallets[1]
508
- wallet_maker = wallet_node_maker.wallet_state_manager.main_wallet
509
- wallet_taker = wallet_node_taker.wallet_state_manager.main_wallet
510
-
511
- ph_maker = await wallet_maker.get_new_puzzlehash()
512
- ph_token = bytes32.random(seeded_random)
513
-
514
- trusted_setup_helper(trusted, wallet_node_maker, wallet_node_taker, full_node_api)
515
-
516
- await server_0.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
517
- await server_1.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
518
-
519
- funds = sum(calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, 2))
520
- await full_node_api.farm_rewards_to_wallet(funds, wallet_maker, timeout=30)
521
- await full_node_api.farm_rewards_to_wallet(funds, wallet_taker, timeout=30)
522
-
523
- async with wallet_maker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
781
+ async def test_nft_offer_sell_nft_for_cat(wallet_environments: WalletTestFramework, zero_royalties: bool) -> None:
782
+ env_maker = wallet_environments.environments[0]
783
+ env_taker = wallet_environments.environments[1]
784
+ wallet_maker = env_maker.xch_wallet
785
+ wallet_taker = env_taker.xch_wallet
786
+
787
+ env_maker.wallet_aliases = {
788
+ "xch": 1,
789
+ "did": 2,
790
+ "nft": 3,
791
+ "cat": 4,
792
+ }
793
+ env_taker.wallet_aliases = {
794
+ "xch": 1,
795
+ "nft": 2,
796
+ "cat": 3,
797
+ }
798
+
799
+ async with wallet_maker.wallet_state_manager.new_action_scope(
800
+ wallet_environments.tx_config, push=True
801
+ ) as action_scope:
802
+ ph_maker = await action_scope.get_puzzle_hash(wallet_maker.wallet_state_manager)
803
+
804
+ async with wallet_maker.wallet_state_manager.new_action_scope(
805
+ wallet_environments.tx_config, push=True
806
+ ) as action_scope:
524
807
  did_wallet_maker: DIDWallet = await DIDWallet.create_new_did_wallet(
525
- wallet_node_maker.wallet_state_manager, wallet_maker, uint64(1), action_scope
808
+ env_maker.wallet_state_manager, wallet_maker, uint64(1), action_scope
526
809
  )
527
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
528
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker, wallet_node_taker], timeout=20)
529
810
 
530
- await time_out_assert(20, wallet_maker.get_pending_change_balance, 0)
531
- await time_out_assert(20, wallet_maker.get_unconfirmed_balance, funds - 1)
532
- await time_out_assert(20, wallet_maker.get_confirmed_balance, funds - 1)
811
+ await wallet_environments.process_pending_states(
812
+ [
813
+ WalletStateTransition(
814
+ pre_block_balance_updates={
815
+ "xch": {
816
+ "set_remainder": True,
817
+ },
818
+ "did": {
819
+ "init": True,
820
+ "set_remainder": True,
821
+ },
822
+ },
823
+ post_block_balance_updates={
824
+ "xch": {
825
+ "set_remainder": True,
826
+ },
827
+ "did": {
828
+ "set_remainder": True,
829
+ },
830
+ },
831
+ ),
832
+ WalletStateTransition(),
833
+ ]
834
+ )
533
835
 
534
836
  hex_did_id = did_wallet_maker.get_my_DID()
535
837
  did_id = bytes32.fromhex(hex_did_id)
@@ -538,7 +840,7 @@ async def test_nft_offer_sell_nft_for_cat(
538
840
  royalty_basis_pts = uint16(0 if zero_royalties else 200)
539
841
 
540
842
  nft_wallet_maker = await NFTWallet.create_new_nft_wallet(
541
- wallet_node_maker.wallet_state_manager, wallet_maker, name="NFT WALLET DID 1", did_id=did_id
843
+ env_maker.wallet_state_manager, wallet_maker, name="NFT WALLET DID 1", did_id=did_id
542
844
  )
543
845
  metadata = Program.to(
544
846
  [
@@ -547,7 +849,9 @@ async def test_nft_offer_sell_nft_for_cat(
547
849
  ]
548
850
  )
549
851
 
550
- async with nft_wallet_maker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
852
+ async with nft_wallet_maker.wallet_state_manager.new_action_scope(
853
+ wallet_environments.tx_config, push=True
854
+ ) as action_scope:
551
855
  await nft_wallet_maker.generate_new_nft(
552
856
  metadata,
553
857
  action_scope,
@@ -556,23 +860,45 @@ async def test_nft_offer_sell_nft_for_cat(
556
860
  royalty_basis_pts,
557
861
  did_id,
558
862
  )
559
- for tx in action_scope.side_effects.transactions:
560
- if tx.spend_bundle is not None:
561
- assert compute_memos(tx.spend_bundle)
562
- await time_out_assert_not_none(
563
- 20, full_node_api.full_node.mempool_manager.get_spendbundle, tx.spend_bundle.name()
564
- )
565
863
 
566
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token))
567
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker, wallet_node_taker], timeout=20)
568
-
569
- await time_out_assert(20, get_nft_count, 1, nft_wallet_maker)
864
+ await wallet_environments.process_pending_states(
865
+ [
866
+ WalletStateTransition(
867
+ pre_block_balance_updates={
868
+ "xch": {
869
+ "set_remainder": True,
870
+ },
871
+ "did": {
872
+ "set_remainder": True,
873
+ },
874
+ "nft": {
875
+ "init": True,
876
+ "set_remainder": True,
877
+ },
878
+ },
879
+ post_block_balance_updates={
880
+ "xch": {
881
+ "set_remainder": True,
882
+ },
883
+ "did": {
884
+ "set_remainder": True,
885
+ },
886
+ "nft": {
887
+ "set_remainder": True,
888
+ },
889
+ },
890
+ ),
891
+ WalletStateTransition(),
892
+ ]
893
+ )
570
894
 
571
895
  # TAKER SETUP - NO DID
572
896
  nft_wallet_taker = await NFTWallet.create_new_nft_wallet(
573
- wallet_node_taker.wallet_state_manager, wallet_taker, name="NFT WALLET TAKER"
897
+ env_taker.wallet_state_manager, wallet_taker, name="NFT WALLET TAKER"
574
898
  )
575
899
 
900
+ await env_taker.change_balances({"nft": {"init": True}})
901
+
576
902
  # maker create offer: NFT for xch
577
903
  trade_manager_maker = wallet_maker.wallet_state_manager.trade_manager
578
904
  trade_manager_taker = wallet_taker.wallet_state_manager.trade_manager
@@ -586,38 +912,90 @@ async def test_nft_offer_sell_nft_for_cat(
586
912
  # Trade them between maker and taker to ensure multiple coins for each cat
587
913
  cats_to_mint = 100000
588
914
  cats_to_trade = uint64(10000)
589
- async with wallet_maker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
590
- full_node_api.full_node.log.warning(f"Mempool size: {full_node_api.full_node.mempool_manager.mempool.size()}")
915
+ async with wallet_maker.wallet_state_manager.new_action_scope(
916
+ wallet_environments.tx_config, push=True
917
+ ) as action_scope:
591
918
  cat_wallet_maker = await CATWallet.create_new_cat_wallet(
592
- wallet_node_maker.wallet_state_manager,
919
+ env_maker.wallet_state_manager,
593
920
  wallet_maker,
594
921
  {"identifier": "genesis_by_id"},
595
922
  uint64(cats_to_mint),
596
923
  action_scope,
597
924
  )
598
- await time_out_assert(20, mempool_not_empty, True, full_node_api)
599
925
 
600
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token))
601
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker, wallet_node_taker], timeout=20)
602
-
603
- await time_out_assert(20, cat_wallet_maker.get_confirmed_balance, cats_to_mint)
604
- await time_out_assert(20, cat_wallet_maker.get_unconfirmed_balance, cats_to_mint)
926
+ await wallet_environments.process_pending_states(
927
+ [
928
+ WalletStateTransition(
929
+ pre_block_balance_updates={
930
+ "xch": {
931
+ "set_remainder": True,
932
+ },
933
+ "cat": {
934
+ "init": True,
935
+ "set_remainder": True,
936
+ },
937
+ },
938
+ post_block_balance_updates={
939
+ "xch": {
940
+ "set_remainder": True,
941
+ },
942
+ "cat": {
943
+ "set_remainder": True,
944
+ },
945
+ },
946
+ ),
947
+ WalletStateTransition(),
948
+ ]
949
+ )
605
950
 
606
951
  cat_wallet_taker: CATWallet = await CATWallet.get_or_create_wallet_for_cat(
607
- wallet_node_taker.wallet_state_manager, wallet_taker, cat_wallet_maker.get_asset_id()
952
+ env_taker.wallet_state_manager, wallet_taker, cat_wallet_maker.get_asset_id()
608
953
  )
609
954
 
610
- ph_taker_cat_1 = await wallet_taker.get_new_puzzlehash()
611
- ph_taker_cat_2 = await wallet_taker.get_new_puzzlehash()
612
- async with cat_wallet_maker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
955
+ await env_taker.change_balances({"cat": {"init": True}})
956
+
957
+ with wallet_environments.new_puzzle_hashes_allowed():
958
+ async with wallet_taker.wallet_state_manager.new_action_scope(
959
+ wallet_environments.tx_config, push=True
960
+ ) as action_scope:
961
+ ph_taker_cat_1 = await action_scope.get_puzzle_hash(wallet_taker.wallet_state_manager)
962
+ ph_taker_cat_2 = await action_scope.get_puzzle_hash(
963
+ wallet_taker.wallet_state_manager, override_reuse_puzhash_with=False
964
+ )
965
+ async with cat_wallet_maker.wallet_state_manager.new_action_scope(
966
+ wallet_environments.tx_config, push=True
967
+ ) as action_scope:
613
968
  await cat_wallet_maker.generate_signed_transaction(
614
969
  [cats_to_trade, cats_to_trade],
615
970
  [ph_taker_cat_1, ph_taker_cat_2],
616
971
  action_scope,
617
972
  memos=[[ph_taker_cat_1], [ph_taker_cat_2]],
618
973
  )
619
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
620
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker, wallet_node_taker], timeout=20)
974
+
975
+ await wallet_environments.process_pending_states(
976
+ [
977
+ WalletStateTransition(
978
+ pre_block_balance_updates={
979
+ "cat": {
980
+ "set_remainder": True,
981
+ },
982
+ },
983
+ post_block_balance_updates={
984
+ "cat": {
985
+ "set_remainder": True,
986
+ },
987
+ },
988
+ ),
989
+ WalletStateTransition(
990
+ pre_block_balance_updates={},
991
+ post_block_balance_updates={
992
+ "cat": {
993
+ "set_remainder": True,
994
+ },
995
+ },
996
+ ),
997
+ ]
998
+ )
621
999
 
622
1000
  maker_cat_balance = cats_to_mint - (2 * cats_to_trade)
623
1001
  taker_cat_balance = 2 * cats_to_trade
@@ -629,9 +1007,11 @@ async def test_nft_offer_sell_nft_for_cat(
629
1007
  cats_requested = 1000
630
1008
  maker_fee = uint64(433)
631
1009
 
632
- offer_did_nft_for_xch = {nft_to_offer_asset_id: -1, cat_wallet_maker.id(): cats_requested}
1010
+ offer_did_nft_for_xch: OfferSummary = {nft_to_offer_asset_id: -1, cat_wallet_maker.id(): cats_requested}
633
1011
 
634
- async with trade_manager_maker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=False) as action_scope:
1012
+ async with trade_manager_maker.wallet_state_manager.new_action_scope(
1013
+ wallet_environments.tx_config, push=False
1014
+ ) as action_scope:
635
1015
  success, trade_make, error = await trade_manager_maker.create_offer_for_ids(
636
1016
  offer_did_nft_for_xch, action_scope, {}, fee=maker_fee
637
1017
  )
@@ -642,74 +1022,159 @@ async def test_nft_offer_sell_nft_for_cat(
642
1022
 
643
1023
  taker_fee = 1
644
1024
 
645
- peer = wallet_node_taker.get_full_node_peer()
646
- [_maker_offer], signing_response = await wallet_node_maker.wallet_state_manager.sign_offers(
1025
+ peer = env_taker.node.get_full_node_peer()
1026
+ [_maker_offer], signing_response = await env_maker.wallet_state_manager.sign_offers(
647
1027
  [Offer.from_bytes(trade_make.offer)]
648
1028
  )
649
1029
  async with trade_manager_taker.wallet_state_manager.new_action_scope(
650
- DEFAULT_TX_CONFIG, push=True, additional_signing_responses=signing_response
1030
+ wallet_environments.tx_config, push=True, additional_signing_responses=signing_response
651
1031
  ) as action_scope:
652
1032
  trade_take = await trade_manager_taker.respond_to_offer(
653
1033
  Offer.from_bytes(trade_make.offer), peer, action_scope, fee=uint64(taker_fee)
654
1034
  )
655
- await time_out_assert(20, mempool_not_empty, True, full_node_api)
656
1035
  assert trade_take is not None
657
1036
 
658
- async def maker_0_taker_1() -> bool:
659
- return (
660
- len(await nft_wallet_maker.get_current_nfts()) == 0 and len(await nft_wallet_taker.get_current_nfts()) == 1
661
- )
662
-
663
- await farm_blocks_until(maker_0_taker_1, full_node_api, ph_token)
664
-
665
1037
  # assert payments and royalties
666
1038
  expected_royalty = uint64(cats_requested * royalty_basis_pts / 10000)
667
- expected_maker_balance = funds - 2 - cats_to_mint - maker_fee
668
- expected_taker_balance = funds - taker_fee
669
- expected_maker_cat_balance = maker_cat_balance + cats_requested + expected_royalty
670
- expected_taker_cat_balance = taker_cat_balance - cats_requested - expected_royalty
671
- await time_out_assert(20, wallet_maker.get_confirmed_balance, expected_maker_balance)
672
- await time_out_assert(20, wallet_taker.get_confirmed_balance, expected_taker_balance)
673
- await time_out_assert(20, cat_wallet_maker.get_confirmed_balance, expected_maker_cat_balance)
674
- await time_out_assert(20, cat_wallet_taker.get_confirmed_balance, expected_taker_cat_balance)
1039
+ await wallet_environments.process_pending_states(
1040
+ [
1041
+ WalletStateTransition(
1042
+ pre_block_balance_updates={
1043
+ "xch": {
1044
+ "<=#spendable_balance": -maker_fee,
1045
+ "<=#max_send_amount": -maker_fee,
1046
+ "pending_coin_removal_count": 1,
1047
+ },
1048
+ "cat": {},
1049
+ "did": {},
1050
+ "nft": {
1051
+ "pending_coin_removal_count": 1,
1052
+ },
1053
+ },
1054
+ post_block_balance_updates={
1055
+ "xch": {
1056
+ "confirmed_wallet_balance": -maker_fee,
1057
+ "unconfirmed_wallet_balance": -maker_fee,
1058
+ ">=#spendable_balance": 1,
1059
+ ">=#max_send_amount": 1,
1060
+ "pending_coin_removal_count": -1,
1061
+ },
1062
+ "cat": {
1063
+ "unconfirmed_wallet_balance": cats_requested + expected_royalty,
1064
+ "confirmed_wallet_balance": cats_requested + expected_royalty,
1065
+ "spendable_balance": cats_requested + expected_royalty,
1066
+ "max_send_amount": cats_requested + expected_royalty,
1067
+ "unspent_coin_count": 2 if expected_royalty > 0 else 1,
1068
+ },
1069
+ "did": {},
1070
+ "nft": {
1071
+ "unspent_coin_count": -1,
1072
+ "pending_coin_removal_count": -1,
1073
+ },
1074
+ },
1075
+ ),
1076
+ WalletStateTransition(
1077
+ pre_block_balance_updates={
1078
+ "xch": {
1079
+ "unconfirmed_wallet_balance": -taker_fee,
1080
+ "<=#spendable_balance": -taker_fee,
1081
+ "<=#max_send_amount": -taker_fee,
1082
+ ">=#pending_change": 1,
1083
+ "pending_coin_removal_count": 1,
1084
+ },
1085
+ "cat": {
1086
+ "unconfirmed_wallet_balance": -(cats_requested + expected_royalty),
1087
+ "<=#spendable_balance": -(cats_requested + expected_royalty),
1088
+ "<=#max_send_amount": -(cats_requested + expected_royalty),
1089
+ ">=#pending_change": 1,
1090
+ "pending_coin_removal_count": 1,
1091
+ },
1092
+ "nft": {
1093
+ "init": True,
1094
+ },
1095
+ },
1096
+ post_block_balance_updates={
1097
+ "xch": {
1098
+ "confirmed_wallet_balance": -taker_fee,
1099
+ ">=#spendable_balance": 1,
1100
+ ">=#max_send_amount": 1,
1101
+ "<=#pending_change": -1,
1102
+ "pending_coin_removal_count": -1,
1103
+ },
1104
+ "cat": {
1105
+ "confirmed_wallet_balance": -(cats_requested + expected_royalty),
1106
+ ">=#spendable_balance": 1,
1107
+ ">=#max_send_amount": 1,
1108
+ "<=#pending_change": -1,
1109
+ "pending_coin_removal_count": -1,
1110
+ },
1111
+ "nft": {
1112
+ "unspent_coin_count": 1,
1113
+ },
1114
+ },
1115
+ ),
1116
+ ]
1117
+ )
675
1118
 
676
1119
 
677
- @pytest.mark.parametrize("trusted", [True, False])
1120
+ @pytest.mark.limit_consensus_modes
1121
+ @pytest.mark.parametrize("wallet_environments", [{"num_environments": 2, "blocks_needed": [1, 1]}], indirect=True)
678
1122
  @pytest.mark.parametrize("test_change", [True, False])
679
1123
  @pytest.mark.anyio
680
- async def test_nft_offer_request_nft_for_cat(
681
- self_hostname: str, two_wallet_nodes: Any, trusted: bool, test_change: bool, seeded_random: random.Random
682
- ) -> None:
683
- full_nodes, wallets, _ = two_wallet_nodes
684
- full_node_api: FullNodeSimulator = full_nodes[0]
685
- full_node_server = full_node_api.server
686
- wallet_node_maker, server_0 = wallets[0]
687
- wallet_node_taker, server_1 = wallets[1]
688
- wallet_maker = wallet_node_maker.wallet_state_manager.main_wallet
689
- wallet_taker = wallet_node_taker.wallet_state_manager.main_wallet
690
-
691
- ph_taker = await wallet_taker.get_new_puzzlehash()
692
- ph_token = bytes32.random(seeded_random)
693
-
694
- trusted_setup_helper(trusted, wallet_node_maker, wallet_node_taker, full_node_api)
695
-
696
- await server_0.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
697
- await server_1.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
698
-
699
- funds = sum(calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, 2))
700
- await full_node_api.farm_rewards_to_wallet(funds, wallet_maker, timeout=30)
701
- await full_node_api.farm_rewards_to_wallet(funds, wallet_taker, timeout=30)
702
-
703
- async with wallet_taker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1124
+ async def test_nft_offer_request_nft_for_cat(wallet_environments: WalletTestFramework, test_change: bool) -> None:
1125
+ env_maker = wallet_environments.environments[0]
1126
+ env_taker = wallet_environments.environments[1]
1127
+ wallet_maker = env_maker.xch_wallet
1128
+ wallet_taker = env_taker.xch_wallet
1129
+
1130
+ env_maker.wallet_aliases = {
1131
+ "xch": 1,
1132
+ "nft": 2,
1133
+ "cat": 3,
1134
+ }
1135
+ env_taker.wallet_aliases = {
1136
+ "xch": 1,
1137
+ "did": 2,
1138
+ "nft": 3,
1139
+ "cat": 4,
1140
+ }
1141
+
1142
+ async with wallet_taker.wallet_state_manager.new_action_scope(
1143
+ wallet_environments.tx_config, push=True
1144
+ ) as action_scope:
1145
+ ph_taker = await action_scope.get_puzzle_hash(wallet_taker.wallet_state_manager)
1146
+
1147
+ async with wallet_taker.wallet_state_manager.new_action_scope(
1148
+ wallet_environments.tx_config, push=True
1149
+ ) as action_scope:
704
1150
  did_wallet_taker: DIDWallet = await DIDWallet.create_new_did_wallet(
705
- wallet_node_taker.wallet_state_manager, wallet_taker, uint64(1), action_scope
1151
+ env_taker.wallet_state_manager, wallet_taker, uint64(1), action_scope
706
1152
  )
707
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
708
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker, wallet_node_taker], timeout=20)
709
1153
 
710
- await time_out_assert(20, wallet_taker.get_pending_change_balance, 0)
711
- await time_out_assert(20, wallet_taker.get_unconfirmed_balance, funds - 1)
712
- await time_out_assert(20, wallet_taker.get_confirmed_balance, funds - 1)
1154
+ await wallet_environments.process_pending_states(
1155
+ [
1156
+ WalletStateTransition(),
1157
+ WalletStateTransition(
1158
+ pre_block_balance_updates={
1159
+ "xch": {
1160
+ "set_remainder": True,
1161
+ },
1162
+ "did": {
1163
+ "init": True,
1164
+ "set_remainder": True,
1165
+ },
1166
+ },
1167
+ post_block_balance_updates={
1168
+ "xch": {
1169
+ "set_remainder": True,
1170
+ },
1171
+ "did": {
1172
+ "set_remainder": True,
1173
+ },
1174
+ },
1175
+ ),
1176
+ ]
1177
+ )
713
1178
 
714
1179
  hex_did_id = did_wallet_taker.get_my_DID()
715
1180
  did_id = bytes32.fromhex(hex_did_id)
@@ -718,7 +1183,7 @@ async def test_nft_offer_request_nft_for_cat(
718
1183
  royalty_basis_pts = uint16(5000) # 50%
719
1184
 
720
1185
  nft_wallet_taker = await NFTWallet.create_new_nft_wallet(
721
- wallet_node_taker.wallet_state_manager, wallet_taker, name="NFT WALLET DID TAKER", did_id=did_id
1186
+ env_taker.wallet_state_manager, wallet_taker, name="NFT WALLET DID TAKER", did_id=did_id
722
1187
  )
723
1188
  metadata = Program.to(
724
1189
  [
@@ -727,7 +1192,9 @@ async def test_nft_offer_request_nft_for_cat(
727
1192
  ]
728
1193
  )
729
1194
 
730
- async with nft_wallet_taker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1195
+ async with nft_wallet_taker.wallet_state_manager.new_action_scope(
1196
+ wallet_environments.tx_config, push=True
1197
+ ) as action_scope:
731
1198
  await nft_wallet_taker.generate_new_nft(
732
1199
  metadata,
733
1200
  action_scope,
@@ -736,23 +1203,47 @@ async def test_nft_offer_request_nft_for_cat(
736
1203
  royalty_basis_pts,
737
1204
  did_id,
738
1205
  )
739
- for tx in action_scope.side_effects.transactions:
740
- if tx.spend_bundle is not None:
741
- assert compute_memos(tx.spend_bundle)
742
- await time_out_assert_not_none(
743
- 20, full_node_api.full_node.mempool_manager.get_spendbundle, tx.spend_bundle.name()
744
- )
745
1206
 
746
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token))
747
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker, wallet_node_taker], timeout=20)
1207
+ await wallet_environments.process_pending_states(
1208
+ [
1209
+ WalletStateTransition(),
1210
+ WalletStateTransition(
1211
+ pre_block_balance_updates={
1212
+ "xch": {
1213
+ "set_remainder": True,
1214
+ },
1215
+ "did": {
1216
+ "set_remainder": True,
1217
+ },
1218
+ "nft": {
1219
+ "init": True,
1220
+ "set_remainder": True,
1221
+ },
1222
+ },
1223
+ post_block_balance_updates={
1224
+ "xch": {
1225
+ "set_remainder": True,
1226
+ },
1227
+ "did": {
1228
+ "set_remainder": True,
1229
+ },
1230
+ "nft": {
1231
+ "set_remainder": True,
1232
+ },
1233
+ },
1234
+ ),
1235
+ ]
1236
+ )
748
1237
 
749
1238
  await time_out_assert(20, get_nft_count, 1, nft_wallet_taker)
750
1239
 
751
1240
  # MAKER SETUP - NO DID
752
1241
  nft_wallet_maker = await NFTWallet.create_new_nft_wallet(
753
- wallet_node_maker.wallet_state_manager, wallet_maker, name="NFT WALLET MAKER"
1242
+ env_maker.wallet_state_manager, wallet_maker, name="NFT WALLET MAKER"
754
1243
  )
755
1244
 
1245
+ await env_maker.change_balances({"nft": {"init": True}})
1246
+
756
1247
  # maker create offer: NFT for CAT
757
1248
  trade_manager_maker = wallet_maker.wallet_state_manager.trade_manager
758
1249
  trade_manager_taker = wallet_taker.wallet_state_manager.trade_manager
@@ -766,62 +1257,137 @@ async def test_nft_offer_request_nft_for_cat(
766
1257
  # Trade them between maker and taker to ensure multiple coins for each cat
767
1258
  cats_to_mint = 100000
768
1259
  cats_to_trade = uint64(20000)
769
- async with wallet_maker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1260
+ async with wallet_maker.wallet_state_manager.new_action_scope(
1261
+ wallet_environments.tx_config, push=True
1262
+ ) as action_scope:
770
1263
  cat_wallet_maker = await CATWallet.create_new_cat_wallet(
771
- wallet_node_maker.wallet_state_manager,
1264
+ env_maker.wallet_state_manager,
772
1265
  wallet_maker,
773
1266
  {"identifier": "genesis_by_id"},
774
1267
  uint64(cats_to_mint),
775
1268
  action_scope,
776
1269
  )
777
- await time_out_assert(20, mempool_not_empty, True, full_node_api)
778
-
779
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token))
780
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker, wallet_node_taker], timeout=20)
781
1270
 
782
- await time_out_assert(20, cat_wallet_maker.get_confirmed_balance, cats_to_mint)
783
- await time_out_assert(20, cat_wallet_maker.get_unconfirmed_balance, cats_to_mint)
1271
+ await wallet_environments.process_pending_states(
1272
+ [
1273
+ WalletStateTransition(
1274
+ pre_block_balance_updates={
1275
+ "xch": {
1276
+ "set_remainder": True,
1277
+ },
1278
+ "cat": {
1279
+ "init": True,
1280
+ "set_remainder": True,
1281
+ },
1282
+ },
1283
+ post_block_balance_updates={
1284
+ "xch": {
1285
+ "set_remainder": True,
1286
+ },
1287
+ "cat": {
1288
+ "set_remainder": True,
1289
+ },
1290
+ },
1291
+ ),
1292
+ WalletStateTransition(),
1293
+ ]
1294
+ )
784
1295
 
785
- cat_wallet_taker: CATWallet = await CATWallet.get_or_create_wallet_for_cat(
786
- wallet_node_taker.wallet_state_manager, wallet_taker, cat_wallet_maker.get_asset_id()
1296
+ await CATWallet.get_or_create_wallet_for_cat(
1297
+ env_taker.wallet_state_manager, wallet_taker, cat_wallet_maker.get_asset_id()
787
1298
  )
788
- if test_change:
789
- cat_1 = await wallet_maker.get_new_puzzlehash()
790
- cat_2 = await wallet_maker.get_new_puzzlehash()
791
- else:
792
- cat_1 = await wallet_taker.get_new_puzzlehash()
793
- cat_2 = await wallet_taker.get_new_puzzlehash()
1299
+
1300
+ await env_taker.change_balances({"cat": {"init": True}})
1301
+
1302
+ with wallet_environments.new_puzzle_hashes_allowed():
1303
+ if test_change:
1304
+ async with wallet_maker.wallet_state_manager.new_action_scope(
1305
+ wallet_environments.tx_config, push=True
1306
+ ) as action_scope:
1307
+ cat_1 = await action_scope.get_puzzle_hash(wallet_maker.wallet_state_manager)
1308
+ cat_2 = await action_scope.get_puzzle_hash(
1309
+ wallet_maker.wallet_state_manager, override_reuse_puzhash_with=False
1310
+ )
1311
+ else:
1312
+ async with wallet_taker.wallet_state_manager.new_action_scope(
1313
+ wallet_environments.tx_config, push=True
1314
+ ) as action_scope:
1315
+ cat_1 = await action_scope.get_puzzle_hash(wallet_taker.wallet_state_manager)
1316
+ cat_2 = await action_scope.get_puzzle_hash(
1317
+ wallet_taker.wallet_state_manager, override_reuse_puzhash_with=False
1318
+ )
794
1319
  puzzle_hashes = [cat_1, cat_2]
795
1320
  amounts = [cats_to_trade, cats_to_trade]
796
1321
  if test_change:
797
- ph_taker_cat_1 = await wallet_taker.get_new_puzzlehash()
1322
+ async with wallet_taker.wallet_state_manager.new_action_scope(
1323
+ wallet_environments.tx_config, push=True
1324
+ ) as action_scope:
1325
+ ph_taker_cat_1 = await action_scope.get_puzzle_hash(wallet_taker.wallet_state_manager)
798
1326
  extra_change = cats_to_mint - (2 * cats_to_trade)
799
1327
  amounts.append(uint64(extra_change))
800
1328
  puzzle_hashes.append(ph_taker_cat_1)
801
- async with cat_wallet_maker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1329
+ else:
1330
+ extra_change = 0 # for mypy sake, not useful
1331
+
1332
+ async with cat_wallet_maker.wallet_state_manager.new_action_scope(
1333
+ wallet_environments.tx_config, push=True
1334
+ ) as action_scope:
802
1335
  await cat_wallet_maker.generate_signed_transaction(amounts, puzzle_hashes, action_scope)
803
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
804
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker, wallet_node_taker], timeout=20)
805
1336
 
806
- if test_change:
807
- taker_cat_balance = cats_to_mint - (2 * cats_to_trade)
808
- maker_cat_balance = 2 * cats_to_trade
809
- else:
810
- maker_cat_balance = cats_to_mint - (2 * cats_to_trade)
811
- taker_cat_balance = 2 * cats_to_trade
812
- await time_out_assert(15, cat_wallet_maker.get_confirmed_balance, maker_cat_balance)
813
- await time_out_assert(15, cat_wallet_taker.get_confirmed_balance, taker_cat_balance)
1337
+ taker_diff = extra_change if test_change else 2 * cats_to_trade
1338
+ maker_diff = -taker_diff
1339
+ await wallet_environments.process_pending_states(
1340
+ [
1341
+ WalletStateTransition(
1342
+ pre_block_balance_updates={
1343
+ "cat": {
1344
+ "unconfirmed_wallet_balance": maker_diff,
1345
+ "<=#spendable_balance": maker_diff,
1346
+ "<=#max_send_amount": maker_diff,
1347
+ ">=#pending_change": 1,
1348
+ "pending_coin_removal_count": 1,
1349
+ },
1350
+ },
1351
+ post_block_balance_updates={
1352
+ "cat": {
1353
+ "confirmed_wallet_balance": maker_diff,
1354
+ ">=#spendable_balance": 1,
1355
+ ">=#max_send_amount": 1,
1356
+ "<=#pending_change": 1,
1357
+ "pending_coin_removal_count": -1,
1358
+ "unspent_coin_count": 1 if test_change else 0,
1359
+ },
1360
+ },
1361
+ ),
1362
+ WalletStateTransition(
1363
+ pre_block_balance_updates={},
1364
+ post_block_balance_updates={
1365
+ "cat": {
1366
+ "confirmed_wallet_balance": taker_diff,
1367
+ "unconfirmed_wallet_balance": taker_diff,
1368
+ "spendable_balance": taker_diff,
1369
+ "max_send_amount": taker_diff,
1370
+ "unspent_coin_count": 1 if test_change else 2,
1371
+ },
1372
+ },
1373
+ ),
1374
+ ]
1375
+ )
814
1376
 
815
1377
  nft_to_request = coins_taker[0]
816
- nft_to_request_info: Optional[PuzzleInfo] = match_puzzle(uncurry_puzzle(nft_to_request.full_puzzle))
817
- nft_to_request_asset_id: bytes32 = create_asset_id(nft_to_request_info) # type: ignore
1378
+ nft_to_request_info = match_puzzle(uncurry_puzzle(nft_to_request.full_puzzle))
1379
+ assert nft_to_request_info is not None
1380
+ nft_to_request_asset_id = create_asset_id(nft_to_request_info)
1381
+ assert nft_to_request_asset_id is not None
818
1382
  cats_requested = 10000
819
1383
  maker_fee = uint64(433)
820
1384
  driver_dict = {nft_to_request_asset_id: nft_to_request_info}
821
1385
 
822
- offer_dict = {nft_to_request_asset_id: 1, cat_wallet_maker.id(): -cats_requested}
1386
+ offer_dict: OfferSummary = {nft_to_request_asset_id: 1, cat_wallet_maker.id(): -cats_requested}
823
1387
 
824
- async with trade_manager_maker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=False) as action_scope:
1388
+ async with trade_manager_maker.wallet_state_manager.new_action_scope(
1389
+ wallet_environments.tx_config, push=False
1390
+ ) as action_scope:
825
1391
  success, trade_make, error = await trade_manager_maker.create_offer_for_ids(
826
1392
  offer_dict, action_scope, driver_dict, fee=maker_fee
827
1393
  )
@@ -831,78 +1397,152 @@ async def test_nft_offer_request_nft_for_cat(
831
1397
 
832
1398
  taker_fee = 1
833
1399
 
834
- peer = wallet_node_taker.get_full_node_peer()
835
- [_maker_offer], signing_response = await wallet_node_maker.wallet_state_manager.sign_offers(
1400
+ peer = env_taker.node.get_full_node_peer()
1401
+ [_maker_offer], signing_response = await env_maker.wallet_state_manager.sign_offers(
836
1402
  [Offer.from_bytes(trade_make.offer)]
837
1403
  )
838
1404
  async with trade_manager_taker.wallet_state_manager.new_action_scope(
839
- DEFAULT_TX_CONFIG, push=True, additional_signing_responses=signing_response
1405
+ wallet_environments.tx_config, push=True, additional_signing_responses=signing_response
840
1406
  ) as action_scope:
841
1407
  trade_take = await trade_manager_taker.respond_to_offer(
842
1408
  Offer.from_bytes(trade_make.offer), peer, action_scope, fee=uint64(taker_fee)
843
1409
  )
844
- await time_out_assert(20, mempool_not_empty, True, full_node_api)
845
1410
  assert trade_take is not None
846
1411
 
847
- async def maker_1_taker_0() -> bool:
848
- return (
849
- len(await nft_wallet_maker.get_current_nfts()) == 1 and len(await nft_wallet_taker.get_current_nfts()) == 0
850
- )
851
-
852
- await farm_blocks_until(maker_1_taker_0, full_node_api, ph_token)
853
-
854
- # assert payments and royalties
855
1412
  expected_royalty = uint64(cats_requested * royalty_basis_pts / 10000)
856
- expected_maker_balance = funds - cats_to_mint - maker_fee
857
- expected_taker_balance = funds - 2 - taker_fee
858
- expected_maker_cat_balance = maker_cat_balance - cats_requested - expected_royalty
859
- expected_taker_cat_balance = taker_cat_balance + cats_requested + expected_royalty
860
- await time_out_assert(20, wallet_maker.get_confirmed_balance, expected_maker_balance)
861
- await time_out_assert(20, wallet_taker.get_confirmed_balance, expected_taker_balance)
862
- await time_out_assert(20, cat_wallet_maker.get_confirmed_balance, expected_maker_cat_balance)
863
- await time_out_assert(20, cat_wallet_taker.get_confirmed_balance, expected_taker_cat_balance)
1413
+ await wallet_environments.process_pending_states(
1414
+ [
1415
+ WalletStateTransition(
1416
+ pre_block_balance_updates={
1417
+ "xch": {
1418
+ "<=#spendable_balance": -maker_fee,
1419
+ "<=#max_send_amount": -maker_fee,
1420
+ "pending_coin_removal_count": 1,
1421
+ },
1422
+ "cat": {
1423
+ "<=#spendable_balance": -(cats_requested + expected_royalty),
1424
+ "<=#max_send_amount": -(cats_requested + expected_royalty),
1425
+ "pending_coin_removal_count": 1,
1426
+ },
1427
+ "nft": {
1428
+ "init": True,
1429
+ },
1430
+ },
1431
+ post_block_balance_updates={
1432
+ "xch": {
1433
+ "confirmed_wallet_balance": -maker_fee,
1434
+ "unconfirmed_wallet_balance": -maker_fee,
1435
+ ">=#spendable_balance": 1,
1436
+ ">=#max_send_amount": 1,
1437
+ "pending_coin_removal_count": -1,
1438
+ },
1439
+ "cat": {
1440
+ "confirmed_wallet_balance": -(cats_requested + expected_royalty),
1441
+ "unconfirmed_wallet_balance": -(cats_requested + expected_royalty),
1442
+ ">=#spendable_balance": 1,
1443
+ ">=#max_send_amount": 1,
1444
+ "pending_coin_removal_count": -1,
1445
+ },
1446
+ "nft": {
1447
+ "unspent_coin_count": 1,
1448
+ },
1449
+ },
1450
+ ),
1451
+ WalletStateTransition(
1452
+ pre_block_balance_updates={
1453
+ "xch": {
1454
+ "unconfirmed_wallet_balance": -taker_fee,
1455
+ "<=#spendable_balance": -taker_fee,
1456
+ "<=#max_send_amount": -taker_fee,
1457
+ ">=#pending_change": 1,
1458
+ "pending_coin_removal_count": 1,
1459
+ },
1460
+ "cat": {
1461
+ # Normally taker is not royalty holder so this is an edge case
1462
+ "unconfirmed_wallet_balance": cats_requested # + expected_royalty,
1463
+ },
1464
+ "did": {},
1465
+ "nft": {
1466
+ "pending_coin_removal_count": 1,
1467
+ },
1468
+ },
1469
+ post_block_balance_updates={
1470
+ "xch": {
1471
+ "confirmed_wallet_balance": -taker_fee,
1472
+ ">=#spendable_balance": 1,
1473
+ ">=#max_send_amount": 1,
1474
+ "<=#pending_change": -1,
1475
+ "pending_coin_removal_count": -1,
1476
+ },
1477
+ "cat": {
1478
+ "confirmed_wallet_balance": cats_requested + expected_royalty,
1479
+ "unconfirmed_wallet_balance": expected_royalty, # only find out after sync
1480
+ "spendable_balance": cats_requested + expected_royalty,
1481
+ "max_send_amount": cats_requested + expected_royalty,
1482
+ "unspent_coin_count": 2,
1483
+ },
1484
+ "did": {},
1485
+ "nft": {
1486
+ "unspent_coin_count": -1,
1487
+ "pending_coin_removal_count": -1,
1488
+ },
1489
+ },
1490
+ ),
1491
+ ]
1492
+ )
864
1493
 
1494
+ assert len(await nft_wallet_maker.get_current_nfts()) == 1
1495
+ assert len(await nft_wallet_taker.get_current_nfts()) == 0
865
1496
 
866
- @pytest.mark.parametrize(
867
- "trusted",
868
- [True, False],
869
- )
870
- @pytest.mark.anyio
871
- # @pytest.mark.skip
872
- async def test_nft_offer_sell_cancel(
873
- self_hostname: str, two_wallet_nodes: Any, trusted: Any, seeded_random: random.Random
874
- ) -> None:
875
- full_nodes, wallets, _ = two_wallet_nodes
876
- full_node_api: FullNodeSimulator = full_nodes[0]
877
- full_node_server = full_node_api.server
878
- wallet_node_maker, server_0 = wallets[0]
879
- wallet_maker = wallet_node_maker.wallet_state_manager.main_wallet
880
-
881
- ph_maker = await wallet_maker.get_new_puzzlehash()
882
- ph_token = bytes32.random(seeded_random)
883
-
884
- if trusted:
885
- wallet_node_maker.config["trusted_peers"] = {
886
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
887
- }
888
- else:
889
- wallet_node_maker.config["trusted_peers"] = {}
890
1497
 
891
- await server_0.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
1498
+ @pytest.mark.limit_consensus_modes
1499
+ @pytest.mark.parametrize("wallet_environments", [{"num_environments": 1, "blocks_needed": [2]}], indirect=True)
1500
+ @pytest.mark.anyio
1501
+ async def test_nft_offer_sell_cancel(wallet_environments: WalletTestFramework) -> None:
1502
+ env_maker = wallet_environments.environments[0]
1503
+ wallet_maker = env_maker.xch_wallet
1504
+
1505
+ env_maker.wallet_aliases = {
1506
+ "xch": 1,
1507
+ "did": 2,
1508
+ "nft": 3,
1509
+ }
892
1510
 
893
- funds = sum(calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, 3))
894
- await full_node_api.farm_rewards_to_wallet(funds, wallet_maker, timeout=30)
1511
+ async with wallet_maker.wallet_state_manager.new_action_scope(
1512
+ wallet_environments.tx_config, push=True
1513
+ ) as action_scope:
1514
+ ph_maker = await action_scope.get_puzzle_hash(wallet_maker.wallet_state_manager)
895
1515
 
896
- async with wallet_maker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1516
+ async with wallet_maker.wallet_state_manager.new_action_scope(
1517
+ wallet_environments.tx_config, push=True
1518
+ ) as action_scope:
897
1519
  did_wallet_maker: DIDWallet = await DIDWallet.create_new_did_wallet(
898
- wallet_node_maker.wallet_state_manager, wallet_maker, uint64(1), action_scope
1520
+ env_maker.wallet_state_manager, wallet_maker, uint64(1), action_scope
899
1521
  )
900
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
901
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker], timeout=20)
902
1522
 
903
- await time_out_assert(20, wallet_maker.get_pending_change_balance, 0)
904
- await time_out_assert(20, wallet_maker.get_unconfirmed_balance, funds - 1)
905
- await time_out_assert(20, wallet_maker.get_confirmed_balance, funds - 1)
1523
+ await wallet_environments.process_pending_states(
1524
+ [
1525
+ WalletStateTransition(
1526
+ pre_block_balance_updates={
1527
+ "xch": {
1528
+ "set_remainder": True,
1529
+ },
1530
+ "did": {
1531
+ "init": True,
1532
+ "set_remainder": True,
1533
+ },
1534
+ },
1535
+ post_block_balance_updates={
1536
+ "xch": {
1537
+ "set_remainder": True,
1538
+ },
1539
+ "did": {
1540
+ "set_remainder": True,
1541
+ },
1542
+ },
1543
+ )
1544
+ ]
1545
+ )
906
1546
 
907
1547
  hex_did_id = did_wallet_maker.get_my_DID()
908
1548
  did_id = bytes32.fromhex(hex_did_id)
@@ -911,7 +1551,7 @@ async def test_nft_offer_sell_cancel(
911
1551
  royalty_basis_pts = uint16(200)
912
1552
 
913
1553
  nft_wallet_maker = await NFTWallet.create_new_nft_wallet(
914
- wallet_node_maker.wallet_state_manager, wallet_maker, name="NFT WALLET DID 1", did_id=did_id
1554
+ env_maker.wallet_state_manager, wallet_maker, name="NFT WALLET DID 1", did_id=did_id
915
1555
  )
916
1556
  metadata = Program.to(
917
1557
  [
@@ -920,7 +1560,11 @@ async def test_nft_offer_sell_cancel(
920
1560
  ]
921
1561
  )
922
1562
 
923
- async with nft_wallet_maker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1563
+ await env_maker.change_balances({"nft": {"init": True}})
1564
+
1565
+ async with nft_wallet_maker.wallet_state_manager.new_action_scope(
1566
+ wallet_environments.tx_config, push=True
1567
+ ) as action_scope:
924
1568
  await nft_wallet_maker.generate_new_nft(
925
1569
  metadata,
926
1570
  action_scope,
@@ -929,14 +1573,35 @@ async def test_nft_offer_sell_cancel(
929
1573
  royalty_basis_pts,
930
1574
  did_id,
931
1575
  )
932
- for tx in action_scope.side_effects.transactions:
933
- if tx.spend_bundle is not None:
934
- assert compute_memos(tx.spend_bundle)
935
- await time_out_assert_not_none(
936
- 20, full_node_api.full_node.mempool_manager.get_spendbundle, tx.spend_bundle.name()
1576
+
1577
+ await wallet_environments.process_pending_states(
1578
+ [
1579
+ WalletStateTransition(
1580
+ pre_block_balance_updates={
1581
+ "xch": {
1582
+ "set_remainder": True,
1583
+ },
1584
+ "did": {
1585
+ "set_remainder": True,
1586
+ },
1587
+ "nft": {
1588
+ "set_remainder": True,
1589
+ },
1590
+ },
1591
+ post_block_balance_updates={
1592
+ "xch": {
1593
+ "set_remainder": True,
1594
+ },
1595
+ "did": {
1596
+ "set_remainder": True,
1597
+ },
1598
+ "nft": {
1599
+ "set_remainder": True,
1600
+ },
1601
+ },
937
1602
  )
938
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token))
939
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker], timeout=20)
1603
+ ]
1604
+ )
940
1605
 
941
1606
  await time_out_assert(20, get_nft_count, 1, nft_wallet_maker)
942
1607
 
@@ -947,20 +1612,27 @@ async def test_nft_offer_sell_cancel(
947
1612
  assert len(coins_maker) == 1
948
1613
 
949
1614
  nft_to_offer = coins_maker[0]
950
- nft_to_offer_info: Optional[PuzzleInfo] = match_puzzle(uncurry_puzzle(nft_to_offer.full_puzzle))
951
- nft_to_offer_asset_id: bytes32 = create_asset_id(nft_to_offer_info) # type: ignore
1615
+ nft_to_offer_info = match_puzzle(uncurry_puzzle(nft_to_offer.full_puzzle))
1616
+ assert nft_to_offer_info is not None
1617
+ nft_to_offer_asset_id = create_asset_id(nft_to_offer_info)
1618
+ assert nft_to_offer_asset_id is not None
952
1619
  xch_requested = 1000
953
1620
  maker_fee = uint64(433)
954
1621
 
955
- offer_did_nft_for_xch = {nft_to_offer_asset_id: -1, wallet_maker.id(): xch_requested}
1622
+ offer_did_nft_for_xch: OfferSummary = {nft_to_offer_asset_id: -1, wallet_maker.id(): xch_requested}
956
1623
 
957
- async with trade_manager_maker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=False) as action_scope:
1624
+ async with trade_manager_maker.wallet_state_manager.new_action_scope(
1625
+ wallet_environments.tx_config, push=False
1626
+ ) as action_scope:
958
1627
  _success, trade_make, _error = await trade_manager_maker.create_offer_for_ids(
959
1628
  offer_did_nft_for_xch, action_scope, {}, fee=maker_fee
960
1629
  )
1630
+ assert trade_make is not None
961
1631
 
962
1632
  FEE = uint64(2000000000000)
963
- async with trade_manager_maker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1633
+ async with trade_manager_maker.wallet_state_manager.new_action_scope(
1634
+ wallet_environments.tx_config, push=True
1635
+ ) as action_scope:
964
1636
  await trade_manager_maker.cancel_pending_offers([trade_make.trade_id], action_scope, fee=FEE, secure=True)
965
1637
 
966
1638
  async def get_trade_and_status(trade_manager: Any, trade: Any) -> TradeStatus:
@@ -968,128 +1640,41 @@ async def test_nft_offer_sell_cancel(
968
1640
  return TradeStatus(trade_rec.status)
969
1641
 
970
1642
  await time_out_assert(20, get_trade_and_status, TradeStatus.PENDING_CANCEL, trade_manager_maker, trade_make)
971
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
972
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker], timeout=20)
973
-
974
- await time_out_assert(15, get_trade_and_status, TradeStatus.CANCELLED, trade_manager_maker, trade_make)
975
-
976
-
977
- @pytest.mark.parametrize(
978
- "trusted",
979
- [True],
980
- )
981
- @pytest.mark.anyio
982
- async def test_nft_offer_sell_cancel_in_batch(
983
- self_hostname: str, two_wallet_nodes: Any, trusted: Any, seeded_random: random.Random
984
- ) -> None:
985
- num_blocks = 3
986
- full_nodes, wallets, _ = two_wallet_nodes
987
- full_node_api: FullNodeSimulator = full_nodes[0]
988
- full_node_server = full_node_api.server
989
- wallet_node_maker, server_0 = wallets[0]
990
- wallet_maker = wallet_node_maker.wallet_state_manager.main_wallet
991
-
992
- ph_maker = await wallet_maker.get_new_puzzlehash()
993
- ph_token = bytes32.random(seeded_random)
994
-
995
- if trusted:
996
- wallet_node_maker.config["trusted_peers"] = {
997
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
998
- }
999
- else:
1000
- wallet_node_maker.config["trusted_peers"] = {}
1001
-
1002
- await server_0.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
1003
-
1004
- funds = sum(
1005
- calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, num_blocks)
1006
- )
1007
- await full_node_api.farm_rewards_to_wallet(funds, wallet_maker, timeout=30)
1008
-
1009
- async with wallet_maker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1010
- did_wallet_maker: DIDWallet = await DIDWallet.create_new_did_wallet(
1011
- wallet_node_maker.wallet_state_manager, wallet_maker, uint64(1), action_scope
1012
- )
1013
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
1014
-
1015
- await time_out_assert(15, wallet_maker.get_pending_change_balance, 0)
1016
- await time_out_assert(10, wallet_maker.get_unconfirmed_balance, funds - 1)
1017
- await time_out_assert(10, wallet_maker.get_confirmed_balance, funds - 1)
1018
1643
 
1019
- hex_did_id = did_wallet_maker.get_my_DID()
1020
- did_id = bytes32.fromhex(hex_did_id)
1021
- target_puzhash = ph_maker
1022
- royalty_puzhash = ph_maker
1023
- royalty_basis_pts = uint16(200)
1024
-
1025
- nft_wallet_maker = await NFTWallet.create_new_nft_wallet(
1026
- wallet_node_maker.wallet_state_manager, wallet_maker, name="NFT WALLET DID 1", did_id=did_id
1027
- )
1028
- metadata = Program.to(
1644
+ await wallet_environments.process_pending_states(
1029
1645
  [
1030
- ("u", ["https://www.chia.net/img/branding/chia-logo.svg"]),
1031
- ("h", "0xD4584AD463139FA8C0D9F68F4B59F185"),
1646
+ WalletStateTransition(
1647
+ pre_block_balance_updates={
1648
+ "xch": {
1649
+ "unconfirmed_wallet_balance": -FEE,
1650
+ "<=#spendable_balance": -FEE,
1651
+ "<=#max_send_amount": -FEE,
1652
+ "pending_coin_removal_count": 3,
1653
+ },
1654
+ "nft": {
1655
+ "pending_coin_removal_count": 1,
1656
+ },
1657
+ },
1658
+ post_block_balance_updates={
1659
+ "xch": {
1660
+ "confirmed_wallet_balance": -FEE,
1661
+ ">=#spendable_balance": 1,
1662
+ ">=#max_send_amount": 1,
1663
+ "unspent_coin_count": -2,
1664
+ "pending_coin_removal_count": -3,
1665
+ },
1666
+ "nft": {
1667
+ "pending_coin_removal_count": -1,
1668
+ },
1669
+ },
1670
+ )
1032
1671
  ]
1033
1672
  )
1034
1673
 
1035
- async with nft_wallet_maker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1036
- await nft_wallet_maker.generate_new_nft(
1037
- metadata,
1038
- action_scope,
1039
- target_puzhash,
1040
- royalty_puzhash,
1041
- royalty_basis_pts,
1042
- did_id,
1043
- )
1044
- for tx in action_scope.side_effects.transactions:
1045
- if tx.spend_bundle is not None:
1046
- assert compute_memos(tx.spend_bundle)
1047
- await time_out_assert_not_none(
1048
- 20, full_node_api.full_node.mempool_manager.get_spendbundle, tx.spend_bundle.name()
1049
- )
1050
-
1051
- for i in range(1, num_blocks):
1052
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token))
1053
-
1054
- await time_out_assert(10, get_nft_count, 1, nft_wallet_maker)
1055
-
1056
- # maker create offer: NFT for xch
1057
- trade_manager_maker = wallet_maker.wallet_state_manager.trade_manager
1058
-
1059
- coins_maker = await nft_wallet_maker.get_current_nfts()
1060
- assert len(coins_maker) == 1
1061
-
1062
- nft_to_offer = coins_maker[0]
1063
- nft_to_offer_info: Optional[PuzzleInfo] = match_puzzle(uncurry_puzzle(nft_to_offer.full_puzzle))
1064
- nft_to_offer_asset_id: bytes32 = create_asset_id(nft_to_offer_info) # type: ignore
1065
- xch_requested = 1000
1066
- maker_fee = uint64(433)
1067
-
1068
- offer_did_nft_for_xch = {nft_to_offer_asset_id: -1, wallet_maker.id(): xch_requested}
1069
-
1070
- async with trade_manager_maker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=False) as action_scope:
1071
- _success, trade_make, _error = await trade_manager_maker.create_offer_for_ids(
1072
- offer_did_nft_for_xch, action_scope, {}, fee=maker_fee
1073
- )
1074
-
1075
- FEE = uint64(2000000000000)
1076
- async with trade_manager_maker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1077
- await trade_manager_maker.cancel_pending_offers([trade_make.trade_id], action_scope, fee=FEE, secure=True)
1078
-
1079
- async def get_trade_and_status(trade_manager: Any, trade: Any) -> TradeStatus:
1080
- trade_rec = await trade_manager.get_trade_by_id(trade.trade_id)
1081
- return TradeStatus(trade_rec.status)
1082
-
1083
- await time_out_assert(15, get_trade_and_status, TradeStatus.PENDING_CANCEL, trade_manager_maker, trade_make)
1084
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
1085
-
1086
- for i in range(1, num_blocks):
1087
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(bytes32.zeros))
1088
-
1089
1674
  await time_out_assert(15, get_trade_and_status, TradeStatus.CANCELLED, trade_manager_maker, trade_make)
1090
1675
 
1091
1676
 
1092
- @pytest.mark.parametrize("trusted", [True, False])
1677
+ @pytest.mark.limit_consensus_modes
1093
1678
  @pytest.mark.parametrize(
1094
1679
  "royalty_pts",
1095
1680
  [
@@ -1100,86 +1685,143 @@ async def test_nft_offer_sell_cancel_in_batch(
1100
1685
  (100000, 10001, 10005), # 1000% shouldn't work
1101
1686
  ],
1102
1687
  )
1688
+ @pytest.mark.parametrize(
1689
+ "wallet_environments",
1690
+ [{"num_environments": 2, "blocks_needed": [3, 3], "config_overrides": {"automatically_add_unknown_cats": True}}],
1691
+ indirect=True,
1692
+ )
1103
1693
  @pytest.mark.anyio
1104
- async def test_complex_nft_offer(
1105
- self_hostname: str,
1106
- two_wallet_nodes: Any,
1107
- trusted: Any,
1108
- royalty_pts: tuple[int, int, int],
1109
- seeded_random: random.Random,
1110
- ) -> None:
1694
+ async def test_complex_nft_offer(wallet_environments: WalletTestFramework, royalty_pts: tuple[int, int, int]) -> None:
1111
1695
  """
1112
1696
  This test is going to create an offer where the maker offers 1 NFT and 1 CAT for 2 NFTs, an XCH and a CAT
1113
1697
  """
1114
- full_nodes, wallets, _ = two_wallet_nodes
1115
- full_node_api: FullNodeSimulator = full_nodes[0]
1116
- full_node_server = full_node_api.server
1117
- wallet_node_maker, server_0 = wallets[0]
1118
- wallet_node_taker, server_1 = wallets[1]
1119
- wsm_maker = wallet_node_maker.wallet_state_manager
1120
- wsm_taker = wallet_node_taker.wallet_state_manager
1698
+ env_maker = wallet_environments.environments[0]
1699
+ env_taker = wallet_environments.environments[1]
1700
+ wsm_maker = env_maker.wallet_state_manager
1701
+ wsm_taker = env_taker.wallet_state_manager
1121
1702
  wallet_maker = wsm_maker.main_wallet
1122
1703
  wallet_taker = wsm_taker.main_wallet
1123
1704
 
1124
- ph_maker = await wallet_maker.get_new_puzzlehash()
1125
- ph_taker = await wallet_taker.get_new_puzzlehash()
1126
- ph_token = bytes32.random(seeded_random)
1127
-
1128
- trusted_setup_helper(trusted, wallet_node_maker, wallet_node_taker, full_node_api)
1129
- wallet_node_maker.config["automatically_add_unknown_cats"] = True
1130
- wallet_node_taker.config["automatically_add_unknown_cats"] = True
1131
-
1132
- await server_0.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
1133
- await server_1.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
1134
-
1135
- # Need money for fees and offering
1136
- funds_maker = sum(calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, 3))
1137
- funds_taker = sum(calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, 6))
1705
+ env_maker.wallet_aliases = {
1706
+ "xch": 1,
1707
+ "cat_maker": 2,
1708
+ "nft0": 3,
1709
+ "did": 4,
1710
+ "nft1": 5,
1711
+ "cat_taker": 6,
1712
+ }
1713
+ env_taker.wallet_aliases = {
1714
+ "xch": 1,
1715
+ "cat_taker": 2,
1716
+ "nft0": 3,
1717
+ "did": 4,
1718
+ "nft1": 5,
1719
+ "cat_maker": 6,
1720
+ }
1138
1721
 
1139
- await full_node_api.farm_rewards_to_wallet(amount=funds_maker, wallet=wsm_maker.main_wallet, timeout=60)
1140
- await full_node_api.farm_rewards_to_wallet(amount=funds_taker, wallet=wsm_taker.main_wallet, timeout=60)
1722
+ async with wallet_maker.wallet_state_manager.new_action_scope(
1723
+ wallet_environments.tx_config, push=True
1724
+ ) as action_scope:
1725
+ ph_maker = await action_scope.get_puzzle_hash(wallet_maker.wallet_state_manager)
1726
+ async with wallet_taker.wallet_state_manager.new_action_scope(
1727
+ wallet_environments.tx_config, push=True
1728
+ ) as action_scope:
1729
+ ph_taker = await action_scope.get_puzzle_hash(wallet_taker.wallet_state_manager)
1141
1730
 
1142
1731
  CAT_AMOUNT = uint64(100000000)
1143
- txs = []
1144
- async with wallet_maker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1732
+ async with wallet_maker.wallet_state_manager.new_action_scope(
1733
+ wallet_environments.tx_config, push=True
1734
+ ) as action_scope:
1145
1735
  cat_wallet_maker = await CATWallet.create_new_cat_wallet(
1146
1736
  wsm_maker, wallet_maker, {"identifier": "genesis_by_id"}, CAT_AMOUNT, action_scope
1147
1737
  )
1148
- txs.extend(action_scope.side_effects.transactions)
1149
- async with wallet_taker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1738
+ async with wallet_taker.wallet_state_manager.new_action_scope(
1739
+ wallet_environments.tx_config, push=True
1740
+ ) as action_scope:
1150
1741
  cat_wallet_taker = await CATWallet.create_new_cat_wallet(
1151
1742
  wsm_taker, wallet_taker, {"identifier": "genesis_by_id"}, CAT_AMOUNT, action_scope
1152
1743
  )
1153
- txs.extend(action_scope.side_effects.transactions)
1744
+ await env_maker.change_balances({"cat_maker": {"init": True}})
1745
+ await env_taker.change_balances({"cat_taker": {"init": True}})
1154
1746
 
1155
1747
  # We'll need these later
1156
1748
  basic_nft_wallet_maker = await NFTWallet.create_new_nft_wallet(wsm_maker, wallet_maker, name="NFT WALLET MAKER")
1157
1749
  basic_nft_wallet_taker = await NFTWallet.create_new_nft_wallet(wsm_taker, wallet_taker, name="NFT WALLET TAKER")
1750
+ await env_maker.change_balances({"nft0": {"init": True}})
1751
+ await env_taker.change_balances({"nft0": {"init": True}})
1158
1752
 
1159
- async with wallet_maker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1753
+ async with wallet_maker.wallet_state_manager.new_action_scope(
1754
+ wallet_environments.tx_config, push=True
1755
+ ) as action_scope:
1160
1756
  did_wallet_maker: DIDWallet = await DIDWallet.create_new_did_wallet(
1161
1757
  wsm_maker, wallet_maker, uint64(1), action_scope
1162
1758
  )
1163
- txs.extend(action_scope.side_effects.transactions)
1164
- async with wallet_taker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1759
+ async with wallet_taker.wallet_state_manager.new_action_scope(
1760
+ wallet_environments.tx_config, push=True
1761
+ ) as action_scope:
1165
1762
  did_wallet_taker: DIDWallet = await DIDWallet.create_new_did_wallet(
1166
1763
  wsm_taker, wallet_taker, uint64(1), action_scope
1167
1764
  )
1168
- txs.extend(action_scope.side_effects.transactions)
1765
+ await env_maker.change_balances({"did": {"init": True}})
1766
+ await env_taker.change_balances({"did": {"init": True}})
1169
1767
 
1170
- await full_node_api.process_transaction_records(records=txs)
1171
-
1172
- funds_maker = funds_maker - 1 - CAT_AMOUNT
1173
- funds_taker = funds_taker - 1 - CAT_AMOUNT
1768
+ await wallet_environments.process_pending_states(
1769
+ [
1770
+ WalletStateTransition(
1771
+ pre_block_balance_updates={
1772
+ "xch": {
1773
+ "set_remainder": True,
1774
+ },
1775
+ "cat_maker": {
1776
+ "set_remainder": True,
1777
+ },
1778
+ "nft0": {},
1779
+ "did": {
1780
+ "set_remainder": True,
1781
+ },
1782
+ },
1783
+ post_block_balance_updates={
1784
+ "xch": {
1785
+ "set_remainder": True,
1786
+ },
1787
+ "cat_maker": {
1788
+ "set_remainder": True,
1789
+ },
1790
+ "nft0": {},
1791
+ "did": {
1792
+ "set_remainder": True,
1793
+ },
1794
+ },
1795
+ ),
1796
+ WalletStateTransition(
1797
+ pre_block_balance_updates={
1798
+ "xch": {
1799
+ "set_remainder": True,
1800
+ },
1801
+ "cat_taker": {
1802
+ "set_remainder": True,
1803
+ },
1804
+ "nft0": {},
1805
+ "did": {
1806
+ "set_remainder": True,
1807
+ },
1808
+ },
1809
+ post_block_balance_updates={
1810
+ "xch": {
1811
+ "set_remainder": True,
1812
+ },
1813
+ "cat_taker": {
1814
+ "set_remainder": True,
1815
+ },
1816
+ "nft0": {},
1817
+ "did": {
1818
+ "set_remainder": True,
1819
+ },
1820
+ },
1821
+ ),
1822
+ ]
1823
+ )
1174
1824
 
1175
- await time_out_assert(30, wallet_maker.get_unconfirmed_balance, funds_maker)
1176
- await time_out_assert(30, wallet_maker.get_confirmed_balance, funds_maker)
1177
- await time_out_assert(30, wallet_taker.get_unconfirmed_balance, funds_taker)
1178
- await time_out_assert(30, wallet_taker.get_confirmed_balance, funds_taker)
1179
- await time_out_assert(30, cat_wallet_maker.get_confirmed_balance, CAT_AMOUNT)
1180
- await time_out_assert(30, cat_wallet_maker.get_unconfirmed_balance, CAT_AMOUNT)
1181
- await time_out_assert(30, cat_wallet_taker.get_confirmed_balance, CAT_AMOUNT)
1182
- await time_out_assert(30, cat_wallet_taker.get_unconfirmed_balance, CAT_AMOUNT)
1183
1825
  did_id_maker = bytes32.fromhex(did_wallet_maker.get_my_DID())
1184
1826
  did_id_taker = bytes32.fromhex(did_wallet_taker.get_my_DID())
1185
1827
  target_puzhash_maker = ph_maker
@@ -1193,11 +1835,14 @@ async def test_complex_nft_offer(
1193
1835
  )
1194
1836
 
1195
1837
  nft_wallet_maker = await NFTWallet.create_new_nft_wallet(
1196
- wallet_node_maker.wallet_state_manager, wallet_maker, name="NFT WALLET DID 1", did_id=did_id_maker
1838
+ wsm_maker, wallet_maker, name="NFT WALLET DID 1", did_id=did_id_maker
1197
1839
  )
1198
1840
  nft_wallet_taker = await NFTWallet.create_new_nft_wallet(
1199
- wallet_node_taker.wallet_state_manager, wallet_taker, name="NFT WALLET DID 1", did_id=did_id_taker
1841
+ wsm_taker, wallet_taker, name="NFT WALLET DID 1", did_id=did_id_taker
1200
1842
  )
1843
+ await env_maker.change_balances({"nft1": {"init": True}})
1844
+ await env_taker.change_balances({"nft1": {"init": True}})
1845
+
1201
1846
  metadata = Program.to(
1202
1847
  [
1203
1848
  ("u", ["https://www.chia.net/img/branding/chia-logo.svg"]),
@@ -1207,7 +1852,7 @@ async def test_complex_nft_offer(
1207
1852
  if royalty_basis_pts_maker > 65535:
1208
1853
  with pytest.raises(ValueError):
1209
1854
  async with nft_wallet_maker.wallet_state_manager.new_action_scope(
1210
- DEFAULT_TX_CONFIG, push=False
1855
+ wallet_environments.tx_config, push=False
1211
1856
  ) as action_scope:
1212
1857
  await nft_wallet_maker.generate_new_nft(
1213
1858
  metadata,
@@ -1219,7 +1864,9 @@ async def test_complex_nft_offer(
1219
1864
  )
1220
1865
  return
1221
1866
  else:
1222
- async with nft_wallet_maker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1867
+ async with nft_wallet_maker.wallet_state_manager.new_action_scope(
1868
+ wallet_environments.tx_config, push=True
1869
+ ) as action_scope:
1223
1870
  await nft_wallet_maker.generate_new_nft(
1224
1871
  metadata,
1225
1872
  action_scope,
@@ -1228,13 +1875,10 @@ async def test_complex_nft_offer(
1228
1875
  uint16(royalty_basis_pts_maker),
1229
1876
  did_id_maker,
1230
1877
  )
1231
- for tx in action_scope.side_effects.transactions:
1232
- if tx.spend_bundle is not None:
1233
- await time_out_assert_not_none(
1234
- 20, full_node_api.full_node.mempool_manager.get_spendbundle, tx.spend_bundle.name()
1235
- )
1236
1878
 
1237
- async with nft_wallet_taker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1879
+ async with nft_wallet_taker.wallet_state_manager.new_action_scope(
1880
+ wallet_environments.tx_config, push=True
1881
+ ) as action_scope:
1238
1882
  await nft_wallet_taker.generate_new_nft(
1239
1883
  metadata,
1240
1884
  action_scope,
@@ -1243,25 +1887,67 @@ async def test_complex_nft_offer(
1243
1887
  royalty_basis_pts_taker_1,
1244
1888
  did_id_taker,
1245
1889
  )
1246
- for tx in action_scope.side_effects.transactions:
1247
- if tx.spend_bundle is not None:
1248
- await time_out_assert_not_none(
1249
- 20, full_node_api.full_node.mempool_manager.get_spendbundle, tx.spend_bundle.name()
1250
- )
1251
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token))
1252
1890
 
1253
- funds_maker -= 1
1254
- funds_taker -= 1
1891
+ await wallet_environments.process_pending_states(
1892
+ [
1893
+ WalletStateTransition(
1894
+ pre_block_balance_updates={
1895
+ "xch": {
1896
+ "set_remainder": True,
1897
+ },
1898
+ "did": {
1899
+ "set_remainder": True,
1900
+ },
1901
+ "nft1": {
1902
+ "set_remainder": True,
1903
+ },
1904
+ },
1905
+ post_block_balance_updates={
1906
+ "xch": {
1907
+ "set_remainder": True,
1908
+ },
1909
+ "did": {
1910
+ "set_remainder": True,
1911
+ },
1912
+ "nft1": {
1913
+ "set_remainder": True,
1914
+ },
1915
+ },
1916
+ ),
1917
+ WalletStateTransition(
1918
+ pre_block_balance_updates={
1919
+ "xch": {
1920
+ "set_remainder": True,
1921
+ },
1922
+ "did": {
1923
+ "set_remainder": True,
1924
+ },
1925
+ "nft1": {
1926
+ "set_remainder": True,
1927
+ },
1928
+ },
1929
+ post_block_balance_updates={
1930
+ "xch": {
1931
+ "set_remainder": True,
1932
+ },
1933
+ "did": {
1934
+ "set_remainder": True,
1935
+ },
1936
+ "nft1": {
1937
+ "set_remainder": True,
1938
+ },
1939
+ },
1940
+ ),
1941
+ ]
1942
+ )
1255
1943
 
1256
- await time_out_assert(30, wallet_maker.get_unconfirmed_balance, funds_maker)
1257
- await time_out_assert(30, wallet_maker.get_confirmed_balance, funds_maker)
1258
- await time_out_assert(30, wallet_taker.get_unconfirmed_balance, funds_taker)
1259
- await time_out_assert(30, wallet_taker.get_confirmed_balance, funds_taker)
1260
1944
  await time_out_assert(30, get_nft_count, 1, nft_wallet_maker)
1261
1945
  await time_out_assert(30, get_nft_count, 1, nft_wallet_taker)
1262
1946
 
1263
1947
  # MAke one more NFT for the taker
1264
- async with nft_wallet_taker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1948
+ async with nft_wallet_taker.wallet_state_manager.new_action_scope(
1949
+ wallet_environments.tx_config, push=True
1950
+ ) as action_scope:
1265
1951
  await nft_wallet_taker.generate_new_nft(
1266
1952
  metadata,
1267
1953
  action_scope,
@@ -1270,17 +1956,37 @@ async def test_complex_nft_offer(
1270
1956
  royalty_basis_pts_taker_2,
1271
1957
  did_id_taker,
1272
1958
  )
1273
- for tx in action_scope.side_effects.transactions:
1274
- if tx.spend_bundle is not None:
1275
- await time_out_assert_not_none(
1276
- 20, full_node_api.full_node.mempool_manager.get_spendbundle, tx.spend_bundle.name()
1277
- )
1278
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token))
1279
1959
 
1280
- funds_taker -= 1
1960
+ await wallet_environments.process_pending_states(
1961
+ [
1962
+ WalletStateTransition(),
1963
+ WalletStateTransition(
1964
+ pre_block_balance_updates={
1965
+ "xch": {
1966
+ "set_remainder": True,
1967
+ },
1968
+ "did": {
1969
+ "set_remainder": True,
1970
+ },
1971
+ "nft1": {
1972
+ "set_remainder": True,
1973
+ },
1974
+ },
1975
+ post_block_balance_updates={
1976
+ "xch": {
1977
+ "set_remainder": True,
1978
+ },
1979
+ "did": {
1980
+ "set_remainder": True,
1981
+ },
1982
+ "nft1": {
1983
+ "set_remainder": True,
1984
+ },
1985
+ },
1986
+ ),
1987
+ ]
1988
+ )
1281
1989
 
1282
- await time_out_assert(30, wallet_taker.get_unconfirmed_balance, funds_taker)
1283
- await time_out_assert(30, wallet_taker.get_confirmed_balance, funds_taker)
1284
1990
  await time_out_assert(30, get_nft_count, 2, nft_wallet_taker)
1285
1991
 
1286
1992
  trade_manager_maker = wsm_maker.trade_manager
@@ -1299,7 +2005,7 @@ async def test_complex_nft_offer(
1299
2005
  CAT_REQUESTED = 100000
1300
2006
  FEE = uint64(2000000000000)
1301
2007
 
1302
- complex_nft_offer = {
2008
+ complex_nft_offer: OfferSummary = {
1303
2009
  nft_to_offer_asset_id_maker: -1,
1304
2010
  cat_wallet_maker.id(): CAT_REQUESTED * -1,
1305
2011
  1: XCH_REQUESTED,
@@ -1308,9 +2014,13 @@ async def test_complex_nft_offer(
1308
2014
  bytes32.from_hexstr(cat_wallet_taker.get_asset_id()): CAT_REQUESTED,
1309
2015
  }
1310
2016
 
2017
+ nft_taker_1_info = match_puzzle(uncurry_puzzle(taker_nfts[0].full_puzzle))
2018
+ nft_taker_2_info = match_puzzle(uncurry_puzzle(taker_nfts[1].full_puzzle))
2019
+ assert nft_taker_1_info is not None
2020
+ assert nft_taker_2_info is not None
1311
2021
  driver_dict = {
1312
- nft_to_offer_asset_id_taker_1: match_puzzle(uncurry_puzzle(taker_nfts[0].full_puzzle)),
1313
- nft_to_offer_asset_id_taker_2: match_puzzle(uncurry_puzzle(taker_nfts[1].full_puzzle)),
2022
+ nft_to_offer_asset_id_taker_1: nft_taker_1_info,
2023
+ nft_to_offer_asset_id_taker_2: nft_taker_2_info,
1314
2024
  bytes32.from_hexstr(cat_wallet_taker.get_asset_id()): PuzzleInfo(
1315
2025
  {
1316
2026
  "type": "CAT",
@@ -1319,7 +2029,9 @@ async def test_complex_nft_offer(
1319
2029
  ),
1320
2030
  }
1321
2031
 
1322
- async with trade_manager_maker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=False) as action_scope:
2032
+ async with trade_manager_maker.wallet_state_manager.new_action_scope(
2033
+ wallet_environments.tx_config, push=False
2034
+ ) as action_scope:
1323
2035
  success, trade_make, error = await trade_manager_maker.create_offer_for_ids(
1324
2036
  complex_nft_offer, action_scope, driver_dict=driver_dict, fee=FEE
1325
2037
  )
@@ -1327,17 +2039,15 @@ async def test_complex_nft_offer(
1327
2039
  assert success
1328
2040
  assert trade_make is not None
1329
2041
 
1330
- [maker_offer], signing_response = await wallet_node_maker.wallet_state_manager.sign_offers(
1331
- [Offer.from_bytes(trade_make.offer)]
1332
- )
2042
+ [maker_offer], signing_response = await wsm_maker.sign_offers([Offer.from_bytes(trade_make.offer)])
1333
2043
  if royalty_basis_pts_maker == 10000:
1334
2044
  with pytest.raises(ValueError):
1335
2045
  async with trade_manager_taker.wallet_state_manager.new_action_scope(
1336
- DEFAULT_TX_CONFIG, push=True, additional_signing_responses=signing_response
2046
+ wallet_environments.tx_config, push=True, additional_signing_responses=signing_response
1337
2047
  ) as action_scope:
1338
2048
  trade_take = await trade_manager_taker.respond_to_offer(
1339
2049
  Offer.from_bytes(trade_make.offer),
1340
- wallet_node_taker.get_full_node_peer(),
2050
+ env_taker.node.get_full_node_peer(),
1341
2051
  action_scope,
1342
2052
  fee=FEE,
1343
2053
  )
@@ -1345,19 +2055,16 @@ async def test_complex_nft_offer(
1345
2055
  return
1346
2056
  else:
1347
2057
  async with trade_manager_taker.wallet_state_manager.new_action_scope(
1348
- DEFAULT_TX_CONFIG, push=True, additional_signing_responses=signing_response
2058
+ wallet_environments.tx_config, push=True, additional_signing_responses=signing_response
1349
2059
  ) as action_scope:
1350
2060
  trade_take = await trade_manager_taker.respond_to_offer(
1351
2061
  maker_offer,
1352
- wallet_node_taker.get_full_node_peer(),
2062
+ env_taker.node.get_full_node_peer(),
1353
2063
  action_scope,
1354
2064
  fee=FEE,
1355
2065
  )
1356
2066
  assert trade_take is not None
1357
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
1358
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_maker, wallet_node_taker], timeout=60)
1359
2067
 
1360
- # Now let's make sure the final wallet state is correct
1361
2068
  maker_royalty_summary = NFTWallet.royalty_calculation(
1362
2069
  {
1363
2070
  nft_to_offer_asset_id_maker: (royalty_puzhash_maker, uint16(royalty_basis_pts_maker)),
@@ -1382,37 +2089,124 @@ async def test_complex_nft_offer(
1382
2089
  taker_royalty_summary[nft_to_offer_asset_id_taker_1][0]["amount"]
1383
2090
  + taker_royalty_summary[nft_to_offer_asset_id_taker_2][0]["amount"]
1384
2091
  )
1385
- funds_maker = int(funds_maker - FEE + XCH_REQUESTED + maker_xch_royalties_expected)
1386
- funds_taker = int(funds_taker - FEE - XCH_REQUESTED - maker_xch_royalties_expected)
1387
-
1388
- await time_out_assert(30, wallet_maker.get_unconfirmed_balance, funds_maker)
1389
- await time_out_assert(30, wallet_maker.get_confirmed_balance, funds_maker)
1390
- await time_out_assert(30, wallet_taker.get_unconfirmed_balance, funds_taker)
1391
- await time_out_assert(30, wallet_taker.get_confirmed_balance, funds_taker)
1392
-
1393
- async def get_cat_wallet_and_check_balance(asset_id: str, wsm: Any) -> uint128:
1394
- cat_wallet = await wsm.get_wallet_for_asset_id(asset_id)
1395
- if cat_wallet is None:
1396
- return uint128(0)
1397
- else:
1398
- return uint128(await cat_wallet.get_confirmed_balance())
1399
-
1400
- taker_cat_funds_maker = CAT_REQUESTED + maker_cat_royalties_expected
1401
- maker_cat_funds_taker = CAT_REQUESTED + taker_cat_royalties_expected
1402
- await time_out_assert(
1403
- 30,
1404
- get_cat_wallet_and_check_balance,
1405
- taker_cat_funds_maker,
1406
- cat_wallet_taker.get_asset_id(),
1407
- wsm_maker,
1408
- )
1409
- await time_out_assert(
1410
- 30,
1411
- get_cat_wallet_and_check_balance,
1412
- maker_cat_funds_taker,
1413
- cat_wallet_maker.get_asset_id(),
1414
- wsm_taker,
2092
+
2093
+ xch_coins = int(XCH_REQUESTED / 1_750_000_000_000) + 2
2094
+ fee_coins = int(FEE / 1_750_000_000_000) + 1 if FEE > 1_750_000_000_000 else 1
2095
+ await wallet_environments.process_pending_states(
2096
+ [
2097
+ WalletStateTransition(
2098
+ pre_block_balance_updates={
2099
+ "xch": {
2100
+ "<=#spendable_balance": -FEE,
2101
+ "<=#max_send_amount": -FEE,
2102
+ "pending_coin_removal_count": fee_coins,
2103
+ },
2104
+ "cat_maker": {
2105
+ "<=#spendable_balance": -CAT_REQUESTED - taker_cat_royalties_expected,
2106
+ "<=#max_send_amount": -CAT_REQUESTED - taker_cat_royalties_expected,
2107
+ "pending_coin_removal_count": 1,
2108
+ },
2109
+ "nft1": {
2110
+ "pending_coin_removal_count": 1,
2111
+ },
2112
+ },
2113
+ post_block_balance_updates={
2114
+ "xch": {
2115
+ "unconfirmed_wallet_balance": XCH_REQUESTED + maker_xch_royalties_expected - FEE,
2116
+ "confirmed_wallet_balance": XCH_REQUESTED + maker_xch_royalties_expected - FEE,
2117
+ ">=#spendable_balance": 1,
2118
+ ">=#max_send_amount": 1,
2119
+ "pending_coin_removal_count": -fee_coins,
2120
+ # Parametrizations make unspent_coin_count too complicated
2121
+ "set_remainder": True,
2122
+ },
2123
+ "cat_maker": {
2124
+ "unconfirmed_wallet_balance": -CAT_REQUESTED - taker_cat_royalties_expected,
2125
+ "confirmed_wallet_balance": -CAT_REQUESTED - taker_cat_royalties_expected,
2126
+ ">=#spendable_balance": 1,
2127
+ ">=#max_send_amount": 1,
2128
+ "pending_coin_removal_count": -1,
2129
+ },
2130
+ "cat_taker": {
2131
+ "init": True,
2132
+ "unconfirmed_wallet_balance": CAT_REQUESTED + maker_cat_royalties_expected,
2133
+ "confirmed_wallet_balance": CAT_REQUESTED + maker_cat_royalties_expected,
2134
+ "spendable_balance": CAT_REQUESTED + maker_cat_royalties_expected,
2135
+ "max_send_amount": CAT_REQUESTED + maker_cat_royalties_expected,
2136
+ # Parametrizations make unspent_coin_count too complicated
2137
+ "set_remainder": True,
2138
+ },
2139
+ "nft1": {
2140
+ "pending_coin_removal_count": -1,
2141
+ "unspent_coin_count": -1,
2142
+ },
2143
+ "nft0": {
2144
+ "unspent_coin_count": 2,
2145
+ },
2146
+ },
2147
+ ),
2148
+ WalletStateTransition(
2149
+ pre_block_balance_updates={
2150
+ "xch": {
2151
+ "unconfirmed_wallet_balance": -XCH_REQUESTED - maker_xch_royalties_expected - FEE,
2152
+ "<=#spendable_balance": -XCH_REQUESTED - maker_xch_royalties_expected - FEE,
2153
+ "<=#max_send_amount": -XCH_REQUESTED - maker_xch_royalties_expected - FEE,
2154
+ ">=#pending_change": 1,
2155
+ "pending_coin_removal_count": xch_coins + fee_coins,
2156
+ },
2157
+ "cat_taker": {
2158
+ "unconfirmed_wallet_balance": -CAT_REQUESTED - maker_cat_royalties_expected,
2159
+ "<=#spendable_balance": -CAT_REQUESTED - maker_cat_royalties_expected,
2160
+ "<=#max_send_amount": -CAT_REQUESTED - maker_cat_royalties_expected,
2161
+ ">=#pending_change": 1,
2162
+ "pending_coin_removal_count": 1,
2163
+ },
2164
+ # Royalties don't factor into unconfirmed balance calculations
2165
+ "cat_maker": {
2166
+ "init": True,
2167
+ "unconfirmed_wallet_balance": CAT_REQUESTED,
2168
+ },
2169
+ "nft1": {
2170
+ "pending_coin_removal_count": 2,
2171
+ },
2172
+ },
2173
+ post_block_balance_updates={
2174
+ "xch": {
2175
+ "confirmed_wallet_balance": -XCH_REQUESTED - maker_xch_royalties_expected - FEE,
2176
+ ">=#spendable_balance": 1,
2177
+ ">=#max_send_amount": 1,
2178
+ "<=#pending_change": -1,
2179
+ "pending_coin_removal_count": -fee_coins - xch_coins,
2180
+ # Parametrizations make unspent_coin_count too complicated
2181
+ "set_remainder": True,
2182
+ },
2183
+ "cat_taker": {
2184
+ "confirmed_wallet_balance": -CAT_REQUESTED - maker_cat_royalties_expected,
2185
+ ">=#spendable_balance": 1,
2186
+ ">=#max_send_amount": 1,
2187
+ "<=#pending_change": -1,
2188
+ "pending_coin_removal_count": -1,
2189
+ },
2190
+ "cat_maker": {
2191
+ "confirmed_wallet_balance": CAT_REQUESTED + taker_cat_royalties_expected,
2192
+ "unconfirmed_wallet_balance": taker_cat_royalties_expected,
2193
+ "spendable_balance": CAT_REQUESTED + taker_cat_royalties_expected,
2194
+ "max_send_amount": CAT_REQUESTED + taker_cat_royalties_expected,
2195
+ # Parametrizations make unspent_coin_count too complicated
2196
+ "set_remainder": True,
2197
+ },
2198
+ "nft1": {
2199
+ "unspent_coin_count": -2,
2200
+ "pending_coin_removal_count": -2,
2201
+ },
2202
+ "nft0": {
2203
+ "unspent_coin_count": 1,
2204
+ },
2205
+ },
2206
+ ),
2207
+ ]
1415
2208
  )
2209
+
1416
2210
  maker_nfts = await basic_nft_wallet_maker.get_current_nfts()
1417
2211
  taker_nfts = await basic_nft_wallet_taker.get_current_nfts()
1418
2212
  assert len(maker_nfts) == 2
@@ -1423,15 +2217,18 @@ async def test_complex_nft_offer(
1423
2217
  assert nft_to_offer_asset_id_taker_2 in [nft.nft_id for nft in maker_nfts]
1424
2218
 
1425
2219
  # Try another permutation
2220
+ HALF_XCH_REQUESTED = int(XCH_REQUESTED / 2)
1426
2221
  complex_nft_offer = {
1427
2222
  cat_wallet_maker.id(): CAT_REQUESTED * -1,
1428
- 1: int(XCH_REQUESTED / 2),
2223
+ 1: HALF_XCH_REQUESTED,
1429
2224
  bytes32.from_hexstr(cat_wallet_taker.get_asset_id()): CAT_REQUESTED,
1430
2225
  nft_to_offer_asset_id_maker: 1,
1431
2226
  }
1432
2227
 
2228
+ maker_nft_info = match_puzzle(uncurry_puzzle(taker_nfts[0].full_puzzle))
2229
+ assert maker_nft_info is not None
1433
2230
  driver_dict = {
1434
- nft_to_offer_asset_id_maker: match_puzzle(uncurry_puzzle(taker_nfts[0].full_puzzle)),
2231
+ nft_to_offer_asset_id_maker: maker_nft_info,
1435
2232
  bytes32.from_hexstr(cat_wallet_taker.get_asset_id()): PuzzleInfo(
1436
2233
  {
1437
2234
  "type": "CAT",
@@ -1440,7 +2237,9 @@ async def test_complex_nft_offer(
1440
2237
  ),
1441
2238
  }
1442
2239
 
1443
- async with trade_manager_maker.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=False) as action_scope:
2240
+ async with trade_manager_maker.wallet_state_manager.new_action_scope(
2241
+ wallet_environments.tx_config, push=False
2242
+ ) as action_scope:
1444
2243
  success, trade_make, error = await trade_manager_maker.create_offer_for_ids(
1445
2244
  complex_nft_offer, action_scope, driver_dict=driver_dict, fee=uint64(0)
1446
2245
  )
@@ -1448,46 +2247,115 @@ async def test_complex_nft_offer(
1448
2247
  assert success
1449
2248
  assert trade_make is not None
1450
2249
 
1451
- [maker_offer], signing_response = await wallet_node_maker.wallet_state_manager.sign_offers(
1452
- [Offer.from_bytes(trade_make.offer)]
1453
- )
2250
+ [maker_offer], signing_response = await wsm_maker.sign_offers([Offer.from_bytes(trade_make.offer)])
1454
2251
  async with trade_manager_taker.wallet_state_manager.new_action_scope(
1455
- DEFAULT_TX_CONFIG, push=True, additional_signing_responses=signing_response
2252
+ wallet_environments.tx_config, push=True, additional_signing_responses=signing_response
1456
2253
  ) as action_scope:
1457
2254
  trade_take = await trade_manager_taker.respond_to_offer(
1458
2255
  Offer.from_bytes(trade_make.offer),
1459
- wallet_node_taker.get_full_node_peer(),
2256
+ env_taker.node.get_full_node_peer(),
1460
2257
  action_scope,
1461
2258
  fee=uint64(0),
1462
2259
  )
1463
2260
  assert trade_take is not None
1464
- await time_out_assert(20, mempool_not_empty, True, full_node_api)
1465
2261
 
1466
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_token))
2262
+ await wallet_environments.process_pending_states(
2263
+ [
2264
+ WalletStateTransition(
2265
+ pre_block_balance_updates={
2266
+ "xch": {},
2267
+ "cat_maker": {
2268
+ "<=#spendable_balance": -CAT_REQUESTED,
2269
+ "<=#max_send_amount": -CAT_REQUESTED,
2270
+ "pending_coin_removal_count": 1,
2271
+ },
2272
+ },
2273
+ post_block_balance_updates={
2274
+ "xch": {
2275
+ "confirmed_wallet_balance": HALF_XCH_REQUESTED,
2276
+ "unconfirmed_wallet_balance": HALF_XCH_REQUESTED,
2277
+ "spendable_balance": HALF_XCH_REQUESTED,
2278
+ "max_send_amount": HALF_XCH_REQUESTED,
2279
+ # parametrization makes unspent_coin_count difficult
2280
+ "set_remainder": True,
2281
+ },
2282
+ "cat_maker": {
2283
+ "confirmed_wallet_balance": -CAT_REQUESTED,
2284
+ "unconfirmed_wallet_balance": -CAT_REQUESTED,
2285
+ ">=#spendable_balance": 1,
2286
+ ">=#max_send_amount": 1,
2287
+ "pending_coin_removal_count": -1,
2288
+ # parametrization makes unspent_coin_count difficult
2289
+ "set_remainder": True,
2290
+ },
2291
+ "cat_taker": {
2292
+ "confirmed_wallet_balance": CAT_REQUESTED,
2293
+ "unconfirmed_wallet_balance": CAT_REQUESTED,
2294
+ "spendable_balance": CAT_REQUESTED,
2295
+ "max_send_amount": CAT_REQUESTED,
2296
+ # parametrization makes unspent_coin_count difficult
2297
+ "set_remainder": True,
2298
+ },
2299
+ "nft0": {
2300
+ "unspent_coin_count": 1,
2301
+ },
2302
+ },
2303
+ ),
2304
+ WalletStateTransition(
2305
+ pre_block_balance_updates={
2306
+ "xch": {
2307
+ "unconfirmed_wallet_balance": -HALF_XCH_REQUESTED,
2308
+ "<=#spendable_balance": -HALF_XCH_REQUESTED,
2309
+ "<=#max_send_amount": -HALF_XCH_REQUESTED,
2310
+ ">=#pending_change": 1,
2311
+ "pending_coin_removal_count": 1,
2312
+ },
2313
+ "cat_maker": {
2314
+ "unconfirmed_wallet_balance": CAT_REQUESTED,
2315
+ },
2316
+ "cat_taker": {
2317
+ "unconfirmed_wallet_balance": -CAT_REQUESTED,
2318
+ "<=#spendable_balance": -CAT_REQUESTED,
2319
+ "<=#max_send_amount": -CAT_REQUESTED,
2320
+ ">=#pending_change": 1,
2321
+ "pending_coin_removal_count": 1,
2322
+ },
2323
+ "nft0": {
2324
+ "pending_coin_removal_count": 1,
2325
+ },
2326
+ },
2327
+ post_block_balance_updates={
2328
+ "xch": {
2329
+ "confirmed_wallet_balance": -HALF_XCH_REQUESTED,
2330
+ ">=#spendable_balance": 1,
2331
+ ">=#max_send_amount": 1,
2332
+ "<=#pending_change": -1,
2333
+ "pending_coin_removal_count": -1,
2334
+ },
2335
+ "cat_maker": {
2336
+ "confirmed_wallet_balance": CAT_REQUESTED,
2337
+ "spendable_balance": CAT_REQUESTED,
2338
+ "max_send_amount": CAT_REQUESTED,
2339
+ # parametrization makes unspent_coin_count difficult
2340
+ "set_remainder": True,
2341
+ },
2342
+ "cat_taker": {
2343
+ "confirmed_wallet_balance": -CAT_REQUESTED,
2344
+ ">=#spendable_balance": 1,
2345
+ ">=#max_send_amount": 1,
2346
+ "<=#pending_change": -1,
2347
+ "pending_coin_removal_count": -1,
2348
+ },
2349
+ "nft0": {
2350
+ "unspent_coin_count": -1,
2351
+ "pending_coin_removal_count": -1,
2352
+ },
2353
+ },
2354
+ ),
2355
+ ]
2356
+ )
1467
2357
 
1468
2358
  # Now let's make sure the final wallet state is correct
1469
- funds_maker = int(funds_maker + XCH_REQUESTED / 2)
1470
- funds_taker = int(funds_taker - XCH_REQUESTED / 2)
1471
-
1472
- await time_out_assert(30, wallet_maker.get_unconfirmed_balance, funds_maker)
1473
- await time_out_assert(30, wallet_maker.get_confirmed_balance, funds_maker)
1474
- await time_out_assert(30, wallet_taker.get_unconfirmed_balance, funds_taker)
1475
- await time_out_assert(30, wallet_taker.get_confirmed_balance, funds_taker)
1476
-
1477
- await time_out_assert(
1478
- 30,
1479
- get_cat_wallet_and_check_balance,
1480
- taker_cat_funds_maker + CAT_REQUESTED,
1481
- cat_wallet_taker.get_asset_id(),
1482
- wsm_maker,
1483
- )
1484
- await time_out_assert(
1485
- 30,
1486
- get_cat_wallet_and_check_balance,
1487
- maker_cat_funds_taker + CAT_REQUESTED,
1488
- cat_wallet_maker.get_asset_id(),
1489
- wsm_taker,
1490
- )
1491
2359
  await time_out_assert(20, get_nft_count, 3, basic_nft_wallet_maker)
1492
2360
  await time_out_assert(20, get_nft_count, 0, basic_nft_wallet_taker)
1493
2361
  assert await basic_nft_wallet_maker.nft_store.get_nft_by_id(nft_to_offer_asset_id_maker) is not None