chia-blockchain 2.5.2rc1__py3-none-any.whl → 2.5.3rc1__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 (640) hide show
  1. chia/__init__.py +7 -0
  2. chia/_tests/blockchain/blockchain_test_utils.py +1 -1
  3. chia/_tests/blockchain/test_augmented_chain.py +54 -5
  4. chia/_tests/blockchain/test_blockchain.py +5 -12
  5. chia/_tests/blockchain/test_blockchain_transactions.py +3 -5
  6. chia/_tests/blockchain/test_get_block_generator.py +2 -2
  7. chia/_tests/blockchain/test_lookup_fork_chain.py +2 -2
  8. chia/_tests/clvm/benchmark_costs.py +2 -1
  9. chia/_tests/clvm/coin_store.py +4 -3
  10. chia/_tests/clvm/test_chialisp_deserialization.py +2 -2
  11. chia/_tests/clvm/test_curry_and_treehash.py +1 -1
  12. chia/_tests/clvm/test_puzzle_compression.py +2 -2
  13. chia/_tests/clvm/test_puzzles.py +2 -2
  14. chia/_tests/clvm/test_singletons.py +2 -2
  15. chia/_tests/clvm/test_spend_sim.py +1 -1
  16. chia/_tests/cmds/cmd_test_utils.py +2 -2
  17. chia/_tests/cmds/test_click_types.py +2 -2
  18. chia/_tests/cmds/test_cmd_framework.py +6 -6
  19. chia/_tests/cmds/test_show.py +4 -3
  20. chia/_tests/cmds/test_tx_config_args.py +1 -1
  21. chia/_tests/cmds/testing_classes.py +2 -2
  22. chia/_tests/cmds/wallet/test_consts.py +2 -2
  23. chia/_tests/cmds/wallet/test_did.py +2 -2
  24. chia/_tests/cmds/wallet/test_nft.py +2 -2
  25. chia/_tests/cmds/wallet/test_notifications.py +3 -2
  26. chia/_tests/cmds/wallet/test_vcs.py +2 -2
  27. chia/_tests/cmds/wallet/test_wallet.py +4 -8
  28. chia/_tests/conftest.py +4 -3
  29. chia/_tests/connection_utils.py +2 -2
  30. chia/_tests/core/cmds/test_keys.py +1 -2
  31. chia/_tests/core/cmds/test_wallet.py +2 -2
  32. chia/_tests/core/consensus/test_block_creation.py +2 -2
  33. chia/_tests/core/consensus/test_pot_iterations.py +1 -1
  34. chia/_tests/core/custom_types/test_coin.py +2 -2
  35. chia/_tests/core/custom_types/test_proof_of_space.py +2 -2
  36. chia/_tests/core/custom_types/test_spend_bundle.py +2 -2
  37. chia/_tests/core/data_layer/conftest.py +1 -1
  38. chia/_tests/core/data_layer/test_data_layer.py +1 -1
  39. chia/_tests/core/data_layer/test_data_layer_util.py +1 -1
  40. chia/_tests/core/data_layer/test_data_rpc.py +2 -2
  41. chia/_tests/core/data_layer/test_data_store.py +1 -1
  42. chia/_tests/core/data_layer/test_data_store_schema.py +1 -1
  43. chia/_tests/core/data_layer/util.py +2 -1
  44. chia/_tests/core/farmer/test_farmer_api.py +1 -1
  45. chia/_tests/core/full_node/full_sync/test_full_sync.py +1 -7
  46. chia/_tests/core/full_node/ram_db.py +2 -1
  47. chia/_tests/core/full_node/stores/test_block_store.py +2 -2
  48. chia/_tests/core/full_node/stores/test_coin_store.py +2 -2
  49. chia/_tests/core/full_node/stores/test_full_node_store.py +3 -3
  50. chia/_tests/core/full_node/stores/test_hint_store.py +2 -2
  51. chia/_tests/core/full_node/stores/test_sync_store.py +1 -1
  52. chia/_tests/core/full_node/test_address_manager.py +1 -1
  53. chia/_tests/core/full_node/test_block_height_map.py +2 -2
  54. chia/_tests/core/full_node/test_conditions.py +1 -1
  55. chia/_tests/core/full_node/test_full_node.py +346 -164
  56. chia/_tests/core/full_node/test_generator_tools.py +3 -2
  57. chia/_tests/core/full_node/test_hint_management.py +2 -2
  58. chia/_tests/core/full_node/test_performance.py +2 -15
  59. chia/_tests/core/full_node/test_subscriptions.py +1 -1
  60. chia/_tests/core/full_node/test_transactions.py +186 -185
  61. chia/_tests/core/full_node/test_tx_processing_queue.py +1 -1
  62. chia/_tests/core/make_block_generator.py +2 -2
  63. chia/_tests/core/mempool/test_mempool.py +165 -22
  64. chia/_tests/core/mempool/test_mempool_fee_estimator.py +1 -1
  65. chia/_tests/core/mempool/test_mempool_fee_protocol.py +1 -1
  66. chia/_tests/core/mempool/test_mempool_manager.py +476 -66
  67. chia/_tests/core/mempool/test_mempool_performance.py +2 -2
  68. chia/_tests/core/mempool/test_singleton_fast_forward.py +19 -25
  69. chia/_tests/core/node_height.py +2 -1
  70. chia/_tests/core/server/test_capabilities.py +1 -1
  71. chia/_tests/core/server/test_dos.py +36 -28
  72. chia/_tests/core/server/test_loop.py +3 -3
  73. chia/_tests/core/server/test_rate_limits.py +1 -1
  74. chia/_tests/core/server/test_server.py +2 -2
  75. chia/_tests/core/services/test_services.py +1 -1
  76. chia/_tests/core/ssl/test_ssl.py +1 -1
  77. chia/_tests/core/test_coins.py +2 -1
  78. chia/_tests/core/test_cost_calculation.py +2 -2
  79. chia/_tests/core/test_crawler.py +2 -2
  80. chia/_tests/core/test_db_conversion.py +2 -2
  81. chia/_tests/core/test_db_validation.py +26 -13
  82. chia/_tests/core/test_farmer_harvester_rpc.py +2 -2
  83. chia/_tests/core/test_full_node_rpc.py +2 -2
  84. chia/_tests/core/test_merkle_set.py +2 -2
  85. chia/_tests/core/test_program.py +2 -2
  86. chia/_tests/core/test_rpc_util.py +1 -1
  87. chia/_tests/core/test_seeder.py +1 -1
  88. chia/_tests/core/util/test_block_cache.py +3 -3
  89. chia/_tests/core/util/test_jsonify.py +3 -2
  90. chia/_tests/core/util/test_keychain.py +3 -3
  91. chia/_tests/core/util/test_streamable.py +3 -4
  92. chia/_tests/environments/wallet.py +3 -2
  93. chia/_tests/farmer_harvester/test_farmer.py +3 -4
  94. chia/_tests/farmer_harvester/test_farmer_harvester.py +2 -2
  95. chia/_tests/farmer_harvester/test_filter_prefix_bits.py +2 -2
  96. chia/_tests/farmer_harvester/test_third_party_harvesters.py +3 -4
  97. chia/_tests/fee_estimation/test_fee_estimation_integration.py +1 -1
  98. chia/_tests/fee_estimation/test_fee_estimation_rpc.py +2 -2
  99. chia/_tests/fee_estimation/test_fee_estimation_unit_tests.py +1 -1
  100. chia/_tests/fee_estimation/test_mempoolitem_height_added.py +3 -4
  101. chia/_tests/generator/test_compression.py +20 -10
  102. chia/_tests/generator/test_rom.py +7 -9
  103. chia/_tests/plot_sync/test_delta.py +2 -2
  104. chia/_tests/plot_sync/test_plot_sync.py +2 -2
  105. chia/_tests/plot_sync/test_receiver.py +2 -2
  106. chia/_tests/plot_sync/test_sender.py +2 -2
  107. chia/_tests/plot_sync/test_sync_simulated.py +2 -2
  108. chia/_tests/plot_sync/util.py +3 -2
  109. chia/_tests/plotting/test_plot_manager.py +1 -1
  110. chia/_tests/pools/test_pool_cli_parsing.py +3 -2
  111. chia/_tests/pools/test_pool_cmdline.py +2 -2
  112. chia/_tests/pools/test_pool_puzzles_lifecycle.py +3 -3
  113. chia/_tests/pools/test_pool_rpc.py +4 -5
  114. chia/_tests/pools/test_pool_wallet.py +1 -1
  115. chia/_tests/pools/test_wallet_pool_store.py +2 -2
  116. chia/_tests/rpc/test_rpc_client.py +1 -1
  117. chia/_tests/rpc/test_rpc_server.py +1 -1
  118. chia/_tests/simulation/test_simulation.py +36 -8
  119. chia/_tests/simulation/test_simulator.py +5 -5
  120. chia/_tests/simulation/test_start_simulator.py +2 -2
  121. chia/_tests/timelord/test_new_peak.py +2 -2
  122. chia/_tests/tools/test_run_block.py +3 -2
  123. chia/_tests/util/benchmark_cost.py +2 -2
  124. chia/_tests/util/benchmarks.py +17 -6
  125. chia/_tests/util/blockchain.py +2 -1
  126. chia/_tests/util/blockchain_mock.py +9 -5
  127. chia/_tests/util/build_network_protocol_files.py +2 -1
  128. chia/_tests/util/constants.py +2 -1
  129. chia/_tests/util/full_sync.py +6 -3
  130. chia/_tests/util/gen_ssl_certs.py +2 -2
  131. chia/_tests/util/generator_tools_testing.py +4 -3
  132. chia/_tests/util/get_name_puzzle_conditions.py +2 -2
  133. chia/_tests/util/misc.py +16 -2
  134. chia/_tests/util/network_protocol_data.py +17 -7
  135. chia/_tests/util/run_block.py +6 -8
  136. chia/_tests/util/setup_nodes.py +4 -3
  137. chia/_tests/util/spend_sim.py +9 -5
  138. chia/_tests/util/test_condition_tools.py +2 -2
  139. chia/_tests/util/test_config.py +2 -1
  140. chia/_tests/util/test_errors.py +2 -1
  141. chia/_tests/util/test_full_block_utils.py +17 -7
  142. chia/_tests/util/test_misc.py +1 -1
  143. chia/_tests/util/test_network_protocol_test.py +24 -24
  144. chia/_tests/util/test_replace_str_to_bytes.py +2 -2
  145. chia/_tests/util/test_trusted_peer.py +1 -1
  146. chia/_tests/util/time_out_assert.py +20 -7
  147. chia/_tests/wallet/cat_wallet/test_cat_lifecycle.py +1 -1
  148. chia/_tests/wallet/cat_wallet/test_cat_outer_puzzle.py +2 -2
  149. chia/_tests/wallet/cat_wallet/test_cat_wallet.py +5 -6
  150. chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py +17 -15
  151. chia/_tests/wallet/cat_wallet/test_trades.py +2 -2
  152. chia/_tests/wallet/clawback/test_clawback_lifecycle.py +2 -2
  153. chia/_tests/wallet/clawback/test_clawback_metadata.py +2 -2
  154. chia/_tests/wallet/conftest.py +3 -3
  155. chia/_tests/wallet/db_wallet/test_db_graftroot.py +3 -5
  156. chia/_tests/wallet/db_wallet/test_dl_offers.py +2 -2
  157. chia/_tests/wallet/db_wallet/test_dl_wallet.py +433 -384
  158. chia/_tests/wallet/did_wallet/test_did.py +3 -3
  159. chia/_tests/wallet/nft_wallet/test_nft_1_offers.py +2 -2
  160. chia/_tests/wallet/nft_wallet/test_nft_bulk_mint.py +2 -2
  161. chia/_tests/wallet/nft_wallet/test_nft_lifecycle.py +3 -4
  162. chia/_tests/wallet/nft_wallet/test_nft_offers.py +1293 -703
  163. chia/_tests/wallet/nft_wallet/test_nft_puzzles.py +28 -30
  164. chia/_tests/wallet/nft_wallet/test_nft_wallet.py +2 -2
  165. chia/_tests/wallet/nft_wallet/test_ownership_outer_puzzle.py +2 -2
  166. chia/_tests/wallet/rpc/config.py +1 -1
  167. chia/_tests/wallet/rpc/test_dl_wallet_rpc.py +2 -2
  168. chia/_tests/wallet/rpc/test_wallet_rpc.py +20 -77
  169. chia/_tests/wallet/simple_sync/test_simple_sync_protocol.py +9 -7
  170. chia/_tests/wallet/sync/test_wallet_sync.py +79 -31
  171. chia/_tests/wallet/test_clvm_streamable.py +2 -2
  172. chia/_tests/wallet/test_coin_management.py +7 -7
  173. chia/_tests/wallet/test_coin_selection.py +20 -2
  174. chia/_tests/wallet/test_conditions.py +2 -2
  175. chia/_tests/wallet/test_debug_spend_bundle.py +2 -2
  176. chia/_tests/wallet/test_new_wallet_protocol.py +2 -2
  177. chia/_tests/wallet/test_nft_store.py +2 -2
  178. chia/_tests/wallet/test_notifications.py +2 -2
  179. chia/_tests/wallet/test_puzzle_store.py +2 -2
  180. chia/_tests/wallet/test_sign_coin_spends.py +2 -2
  181. chia/_tests/wallet/test_signer_protocol.py +3 -3
  182. chia/_tests/wallet/test_singleton.py +3 -11
  183. chia/_tests/wallet/test_singleton_lifecycle_fast.py +12 -13
  184. chia/_tests/wallet/test_singleton_store.py +2 -4
  185. chia/_tests/wallet/test_transaction_store.py +2 -2
  186. chia/_tests/wallet/test_util.py +2 -2
  187. chia/_tests/wallet/test_wallet.py +53 -49
  188. chia/_tests/wallet/test_wallet_action_scope.py +24 -6
  189. chia/_tests/wallet/test_wallet_blockchain.py +1 -1
  190. chia/_tests/wallet/test_wallet_coin_store.py +2 -2
  191. chia/_tests/wallet/test_wallet_interested_store.py +2 -2
  192. chia/_tests/wallet/test_wallet_node.py +3 -3
  193. chia/_tests/wallet/test_wallet_retry.py +3 -3
  194. chia/_tests/wallet/test_wallet_state_manager.py +8 -8
  195. chia/_tests/wallet/test_wallet_test_framework.py +1 -1
  196. chia/_tests/wallet/test_wallet_trade_store.py +2 -2
  197. chia/_tests/wallet/test_wallet_utils.py +2 -2
  198. chia/_tests/wallet/vc_wallet/test_cr_outer_puzzle.py +3 -2
  199. chia/_tests/wallet/vc_wallet/test_vc_lifecycle.py +15 -15
  200. chia/_tests/wallet/vc_wallet/test_vc_wallet.py +5 -3
  201. chia/_tests/wallet/wallet_block_tools.py +15 -7
  202. chia/_tests/weight_proof/test_weight_proof.py +3 -3
  203. chia/cmds/chia.py +0 -2
  204. chia/cmds/cmd_classes.py +3 -3
  205. chia/cmds/cmd_helpers.py +4 -4
  206. chia/cmds/cmds_util.py +2 -2
  207. chia/cmds/coin_funcs.py +3 -2
  208. chia/cmds/coins.py +1 -1
  209. chia/cmds/data.py +2 -2
  210. chia/cmds/data_funcs.py +3 -2
  211. chia/cmds/db_upgrade_func.py +2 -2
  212. chia/cmds/db_validate_func.py +15 -8
  213. chia/cmds/farm.py +2 -4
  214. chia/cmds/keys.py +0 -2
  215. chia/cmds/keys_funcs.py +1 -1
  216. chia/cmds/netspace_funcs.py +2 -1
  217. chia/cmds/param_types.py +2 -2
  218. chia/cmds/plotnft.py +2 -2
  219. chia/cmds/plotnft_funcs.py +2 -2
  220. chia/cmds/rpc.py +1 -1
  221. chia/cmds/show.py +1 -2
  222. chia/cmds/show_funcs.py +6 -3
  223. chia/cmds/signer.py +1 -2
  224. chia/cmds/sim.py +1 -2
  225. chia/cmds/sim_funcs.py +2 -2
  226. chia/cmds/wallet.py +2 -2
  227. chia/cmds/wallet_funcs.py +4 -11
  228. chia/consensus/block_body_validation.py +3 -4
  229. chia/consensus/block_creation.py +10 -6
  230. chia/consensus/block_header_validation.py +3 -4
  231. chia/consensus/block_record.py +2 -3
  232. chia/consensus/block_rewards.py +1 -1
  233. chia/consensus/blockchain.py +20 -17
  234. chia/consensus/blockchain_interface.py +5 -4
  235. chia/consensus/coinbase.py +2 -2
  236. chia/consensus/constants.py +1 -1
  237. chia/consensus/cost_calculator.py +2 -1
  238. chia/consensus/default_constants.py +4 -3
  239. chia/consensus/deficit.py +3 -2
  240. chia/consensus/difficulty_adjustment.py +8 -9
  241. chia/consensus/find_fork_point.py +4 -3
  242. chia/consensus/full_block_to_block_record.py +4 -3
  243. chia/consensus/get_block_challenge.py +4 -3
  244. chia/consensus/get_block_generator.py +3 -2
  245. chia/consensus/make_sub_epoch_summary.py +3 -2
  246. chia/consensus/multiprocess_validation.py +9 -4
  247. chia/consensus/pos_quality.py +1 -1
  248. chia/consensus/pot_iterations.py +4 -3
  249. chia/consensus/vdf_info_computation.py +4 -3
  250. chia/daemon/client.py +1 -1
  251. chia/daemon/keychain_server.py +1 -1
  252. chia/daemon/server.py +1 -1
  253. chia/daemon/windows_signal.py +1 -1
  254. chia/data_layer/data_layer.py +4 -3
  255. chia/data_layer/data_layer_errors.py +1 -1
  256. chia/data_layer/data_layer_util.py +2 -2
  257. chia/data_layer/data_layer_wallet.py +47 -69
  258. chia/data_layer/data_store.py +1 -1
  259. chia/data_layer/dl_wallet_store.py +5 -6
  260. chia/data_layer/download_data.py +1 -1
  261. chia/data_layer/s3_plugin_service.py +4 -4
  262. chia/data_layer/singleton_record.py +23 -0
  263. chia/data_layer/util/benchmark.py +2 -1
  264. chia/farmer/farmer.py +4 -6
  265. chia/farmer/farmer_api.py +4 -6
  266. chia/full_node/bitcoin_fee_estimator.py +2 -1
  267. chia/full_node/block_height_map.py +2 -2
  268. chia/full_node/block_store.py +8 -9
  269. chia/{util → full_node}/check_fork_next_block.py +2 -1
  270. chia/full_node/coin_store.py +10 -10
  271. chia/full_node/fee_estimate.py +2 -1
  272. chia/full_node/fee_estimation.py +2 -1
  273. chia/full_node/fee_estimator.py +2 -1
  274. chia/full_node/fee_estimator_interface.py +1 -1
  275. chia/full_node/fee_history.py +2 -1
  276. chia/full_node/fee_tracker.py +2 -1
  277. chia/full_node/full_node.py +25 -15
  278. chia/full_node/full_node_api.py +12 -32
  279. chia/full_node/full_node_store.py +4 -3
  280. chia/full_node/hint_management.py +2 -1
  281. chia/full_node/hint_store.py +3 -3
  282. chia/full_node/mempool.py +79 -12
  283. chia/full_node/mempool_check_conditions.py +6 -7
  284. chia/full_node/mempool_manager.py +168 -21
  285. chia/full_node/pending_tx_cache.py +2 -2
  286. chia/full_node/subscriptions.py +2 -2
  287. chia/full_node/sync_store.py +2 -3
  288. chia/full_node/tx_processing_queue.py +2 -1
  289. chia/full_node/weight_proof.py +5 -8
  290. chia/harvester/harvester.py +5 -3
  291. chia/harvester/harvester_api.py +2 -2
  292. chia/introducer/introducer.py +30 -2
  293. chia/introducer/introducer_api.py +9 -1
  294. chia/legacy/keyring.py +1 -2
  295. chia/plot_sync/exceptions.py +2 -1
  296. chia/plot_sync/receiver.py +2 -2
  297. chia/plot_sync/sender.py +1 -1
  298. chia/plotting/cache.py +2 -2
  299. chia/plotting/check_plots.py +4 -2
  300. chia/plotting/create_plots.py +1 -1
  301. chia/plotting/manager.py +3 -3
  302. chia/plotting/util.py +2 -2
  303. chia/pools/pool_config.py +1 -1
  304. chia/pools/pool_puzzles.py +23 -17
  305. chia/pools/pool_wallet.py +22 -9
  306. chia/pools/pool_wallet_info.py +2 -2
  307. chia/protocols/farmer_protocol.py +3 -6
  308. chia/protocols/full_node_protocol.py +3 -2
  309. chia/protocols/harvester_protocol.py +3 -4
  310. chia/protocols/pool_protocol.py +2 -2
  311. chia/protocols/shared_protocol.py +2 -1
  312. chia/protocols/timelord_protocol.py +4 -4
  313. chia/protocols/wallet_protocol.py +2 -2
  314. chia/rpc/data_layer_rpc_api.py +3 -4
  315. chia/rpc/data_layer_rpc_client.py +3 -2
  316. chia/rpc/farmer_rpc_api.py +2 -2
  317. chia/rpc/farmer_rpc_client.py +2 -1
  318. chia/rpc/full_node_rpc_api.py +3 -2
  319. chia/rpc/full_node_rpc_client.py +3 -2
  320. chia/rpc/harvester_rpc_api.py +2 -1
  321. chia/rpc/rpc_client.py +2 -2
  322. chia/rpc/rpc_server.py +1 -1
  323. chia/rpc/wallet_request_types.py +2 -62
  324. chia/rpc/wallet_rpc_api.py +98 -628
  325. chia/rpc/wallet_rpc_client.py +5 -253
  326. chia/seeder/crawl_store.py +1 -1
  327. chia/seeder/crawler.py +2 -2
  328. chia/seeder/peer_record.py +2 -1
  329. chia/seeder/start_crawler.py +3 -1
  330. chia/server/address_manager.py +2 -1
  331. chia/server/address_manager_store.py +1 -1
  332. chia/server/capabilities.py +2 -1
  333. chia/server/introducer_peers.py +2 -1
  334. chia/server/node_discovery.py +1 -1
  335. chia/server/outbound_message.py +2 -1
  336. chia/server/server.py +2 -2
  337. chia/server/start_data_layer.py +2 -1
  338. chia/server/start_farmer.py +3 -1
  339. chia/server/start_full_node.py +4 -2
  340. chia/server/start_harvester.py +3 -1
  341. chia/server/start_introducer.py +12 -1
  342. chia/server/start_service.py +2 -1
  343. chia/server/start_timelord.py +3 -1
  344. chia/server/start_wallet.py +3 -1
  345. chia/server/upnp.py +1 -2
  346. chia/server/ws_connection.py +3 -4
  347. chia/simulator/add_blocks_in_batches.py +5 -3
  348. chia/simulator/block_tools.py +16 -12
  349. chia/simulator/full_node_simulator.py +9 -14
  350. chia/simulator/setup_services.py +5 -3
  351. chia/simulator/simulator_full_node_rpc_api.py +3 -2
  352. chia/simulator/simulator_full_node_rpc_client.py +3 -2
  353. chia/simulator/simulator_protocol.py +3 -2
  354. chia/simulator/simulator_test_tools.py +2 -2
  355. chia/simulator/start_simulator.py +3 -2
  356. chia/simulator/wallet_tools.py +3 -4
  357. chia/timelord/iters_from_block.py +4 -4
  358. chia/timelord/timelord.py +7 -12
  359. chia/timelord/timelord_api.py +3 -3
  360. chia/timelord/timelord_state.py +4 -3
  361. chia/types/block_protocol.py +2 -2
  362. chia/types/blockchain_format/coin.py +2 -2
  363. chia/types/blockchain_format/program.py +1 -1
  364. chia/types/blockchain_format/proof_of_space.py +3 -4
  365. chia/types/blockchain_format/tree_hash.py +1 -1
  366. chia/types/blockchain_format/vdf.py +3 -4
  367. chia/types/clvm_cost.py +1 -1
  368. chia/types/coin_record.py +4 -3
  369. chia/types/coin_spend.py +1 -1
  370. chia/types/eligible_coin_spends.py +9 -5
  371. chia/types/fee_rate.py +1 -1
  372. chia/types/generator_types.py +3 -3
  373. chia/types/internal_mempool_item.py +3 -2
  374. chia/types/mempool_item.py +10 -3
  375. chia/types/mempool_submission_status.py +2 -1
  376. chia/types/mojos.py +1 -1
  377. chia/types/peer_info.py +2 -1
  378. chia/types/transaction_queue_entry.py +2 -1
  379. chia/types/unfinished_header_block.py +4 -4
  380. chia/types/validation_state.py +2 -1
  381. chia/types/weight_proof.py +1 -9
  382. chia/util/augmented_chain.py +20 -9
  383. chia/util/block_cache.py +8 -4
  384. chia/util/condition_tools.py +2 -2
  385. chia/util/full_block_utils.py +3 -4
  386. chia/util/generator_tools.py +2 -2
  387. chia/util/initial-config.yaml +2 -11
  388. chia/util/network.py +2 -2
  389. chia/util/prev_transaction_block.py +2 -1
  390. chia/util/task_timing.py +1 -1
  391. chia/util/vdf_prover.py +3 -3
  392. chia/util/ws_message.py +1 -1
  393. chia/wallet/cat_wallet/cat_info.py +3 -2
  394. chia/wallet/cat_wallet/cat_outer_puzzle.py +3 -2
  395. chia/wallet/cat_wallet/cat_utils.py +6 -4
  396. chia/wallet/cat_wallet/cat_wallet.py +16 -18
  397. chia/wallet/cat_wallet/lineage_store.py +2 -1
  398. chia/wallet/coin_selection.py +5 -5
  399. chia/wallet/conditions.py +22 -16
  400. chia/wallet/db_wallet/db_wallet_puzzles.py +15 -15
  401. chia/wallet/derivation_record.py +2 -2
  402. chia/wallet/derive_keys.py +2 -2
  403. chia/wallet/did_wallet/did_info.py +3 -2
  404. chia/wallet/did_wallet/did_wallet.py +41 -19
  405. chia/wallet/did_wallet/did_wallet_puzzles.py +18 -12
  406. chia/wallet/driver_protocol.py +1 -1
  407. chia/wallet/lineage_proof.py +3 -2
  408. chia/wallet/nft_wallet/metadata_outer_puzzle.py +6 -7
  409. chia/wallet/nft_wallet/nft_info.py +5 -5
  410. chia/wallet/nft_wallet/nft_puzzle_utils.py +293 -0
  411. chia/wallet/nft_wallet/nft_puzzles.py +21 -298
  412. chia/wallet/nft_wallet/nft_wallet.py +47 -62
  413. chia/wallet/nft_wallet/ownership_outer_puzzle.py +4 -8
  414. chia/wallet/nft_wallet/singleton_outer_puzzle.py +3 -2
  415. chia/wallet/nft_wallet/transfer_program_puzzle.py +6 -10
  416. chia/wallet/nft_wallet/uncurry_nft.py +6 -8
  417. chia/wallet/notification_manager.py +5 -5
  418. chia/wallet/notification_store.py +3 -2
  419. chia/wallet/outer_puzzles.py +2 -1
  420. chia/wallet/puzzles/clawback/drivers.py +21 -8
  421. chia/wallet/puzzles/clawback/metadata.py +3 -2
  422. chia/wallet/puzzles/clawback/puzzle_decorator.py +5 -4
  423. chia/wallet/puzzles/deployed_puzzle_hashes.json +0 -10
  424. chia/wallet/puzzles/p2_conditions.py +3 -2
  425. chia/wallet/puzzles/p2_delegated_conditions.py +3 -2
  426. chia/wallet/puzzles/p2_delegated_puzzle.py +3 -2
  427. chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.py +3 -3
  428. chia/wallet/puzzles/p2_m_of_n_delegate_direct.py +3 -2
  429. chia/wallet/puzzles/p2_puzzle_hash.py +4 -3
  430. chia/wallet/puzzles/puzzle_utils.py +3 -2
  431. chia/wallet/puzzles/singleton_top_layer.py +26 -10
  432. chia/wallet/puzzles/singleton_top_layer_v1_1.py +21 -9
  433. chia/wallet/puzzles/tails.py +21 -129
  434. chia/wallet/signer_protocol.py +3 -2
  435. chia/wallet/singleton.py +12 -6
  436. chia/wallet/singleton_record.py +3 -2
  437. chia/wallet/trade_manager.py +31 -55
  438. chia/wallet/trade_record.py +3 -2
  439. chia/wallet/trading/offer.py +14 -13
  440. chia/wallet/trading/trade_store.py +3 -4
  441. chia/wallet/transaction_record.py +2 -2
  442. chia/wallet/util/blind_signer_tl.py +3 -2
  443. chia/wallet/util/compute_hints.py +3 -2
  444. chia/wallet/util/compute_memos.py +2 -2
  445. chia/wallet/util/curry_and_treehash.py +1 -2
  446. chia/wallet/util/merkle_tree.py +1 -1
  447. chia/wallet/util/merkle_utils.py +1 -1
  448. chia/wallet/util/new_peak_queue.py +2 -1
  449. chia/wallet/util/notifications.py +5 -4
  450. chia/wallet/util/peer_request_cache.py +3 -2
  451. chia/wallet/util/puzzle_compression.py +6 -4
  452. chia/wallet/util/puzzle_decorator.py +6 -4
  453. chia/wallet/util/query_filter.py +3 -2
  454. chia/wallet/util/tx_config.py +3 -3
  455. chia/wallet/util/wallet_sync_utils.py +2 -2
  456. chia/wallet/util/wallet_types.py +2 -3
  457. chia/wallet/vc_wallet/cr_cat_drivers.py +18 -22
  458. chia/wallet/vc_wallet/cr_cat_wallet.py +14 -10
  459. chia/wallet/vc_wallet/cr_outer_puzzle.py +2 -2
  460. chia/wallet/vc_wallet/vc_drivers.py +50 -68
  461. chia/wallet/vc_wallet/vc_store.py +2 -2
  462. chia/wallet/vc_wallet/vc_wallet.py +47 -15
  463. chia/wallet/wallet.py +51 -46
  464. chia/wallet/wallet_action_scope.py +4 -0
  465. chia/wallet/wallet_blockchain.py +12 -7
  466. chia/wallet/wallet_coin_record.py +3 -2
  467. chia/wallet/wallet_coin_store.py +3 -2
  468. chia/wallet/wallet_info.py +2 -1
  469. chia/wallet/wallet_interested_store.py +3 -2
  470. chia/wallet/wallet_nft_store.py +4 -4
  471. chia/wallet/wallet_node.py +3 -4
  472. chia/wallet/wallet_pool_store.py +3 -4
  473. chia/wallet/wallet_protocol.py +19 -5
  474. chia/wallet/wallet_puzzle_store.py +2 -2
  475. chia/wallet/wallet_retry_store.py +3 -6
  476. chia/wallet/wallet_singleton_store.py +2 -2
  477. chia/wallet/wallet_state_manager.py +20 -197
  478. chia/wallet/wallet_transaction_store.py +2 -2
  479. chia/wallet/wallet_user_store.py +2 -1
  480. chia/wallet/wallet_weight_proof_handler.py +3 -2
  481. {chia_blockchain-2.5.2rc1.dist-info → chia_blockchain-2.5.3rc1.dist-info}/METADATA +3 -2
  482. chia_blockchain-2.5.3rc1.dist-info/RECORD +891 -0
  483. mozilla-ca/cacert.pem +64 -33
  484. chia/_tests/clvm/test_condition_codes.py +0 -13
  485. chia/_tests/cmds/wallet/test_dao.py +0 -565
  486. chia/_tests/wallet/dao_wallet/__init__.py +0 -0
  487. chia/_tests/wallet/dao_wallet/config.py +0 -3
  488. chia/_tests/wallet/dao_wallet/test_dao_clvm.py +0 -1330
  489. chia/_tests/wallet/dao_wallet/test_dao_wallets.py +0 -3488
  490. chia/cmds/dao.py +0 -1064
  491. chia/cmds/dao_funcs.py +0 -598
  492. chia/consensus/puzzles/__init__.py +0 -0
  493. chia/consensus/puzzles/chialisp_deserialisation.clsp +0 -69
  494. chia/consensus/puzzles/chialisp_deserialisation.clsp.hex +0 -1
  495. chia/consensus/puzzles/rom_bootstrap_generator.clsp +0 -37
  496. chia/consensus/puzzles/rom_bootstrap_generator.clsp.hex +0 -1
  497. chia/full_node/puzzles/__init__.py +0 -0
  498. chia/full_node/puzzles/block_program_zero.clsp +0 -14
  499. chia/full_node/puzzles/block_program_zero.clsp.hex +0 -1
  500. chia/full_node/puzzles/decompress_coin_spend_entry.clsp +0 -5
  501. chia/full_node/puzzles/decompress_coin_spend_entry.clsp.hex +0 -1
  502. chia/full_node/puzzles/decompress_coin_spend_entry_with_prefix.clsp +0 -7
  503. chia/full_node/puzzles/decompress_coin_spend_entry_with_prefix.clsp.hex +0 -1
  504. chia/full_node/puzzles/decompress_puzzle.clsp +0 -6
  505. chia/full_node/puzzles/decompress_puzzle.clsp.hex +0 -1
  506. chia/pools/puzzles/__init__.py +0 -0
  507. chia/pools/puzzles/pool_member_innerpuz.clsp +0 -70
  508. chia/pools/puzzles/pool_member_innerpuz.clsp.hex +0 -1
  509. chia/pools/puzzles/pool_waitingroom_innerpuz.clsp +0 -69
  510. chia/pools/puzzles/pool_waitingroom_innerpuz.clsp.hex +0 -1
  511. chia/simulator/simulator_constants.py +0 -13
  512. chia/types/blockchain_format/foliage.py +0 -8
  513. chia/types/blockchain_format/pool_target.py +0 -5
  514. chia/types/blockchain_format/reward_chain_block.py +0 -6
  515. chia/types/blockchain_format/sized_bytes.py +0 -11
  516. chia/util/ints.py +0 -19
  517. chia/wallet/cat_wallet/dao_cat_info.py +0 -28
  518. chia/wallet/cat_wallet/dao_cat_wallet.py +0 -669
  519. chia/wallet/cat_wallet/puzzles/__init__.py +0 -0
  520. chia/wallet/cat_wallet/puzzles/cat_truths.clib +0 -31
  521. chia/wallet/cat_wallet/puzzles/cat_v2.clsp +0 -397
  522. chia/wallet/cat_wallet/puzzles/cat_v2.clsp.hex +0 -1
  523. chia/wallet/cat_wallet/puzzles/delegated_tail.clsp +0 -25
  524. chia/wallet/cat_wallet/puzzles/delegated_tail.clsp.hex +0 -1
  525. chia/wallet/cat_wallet/puzzles/everything_with_signature.clsp +0 -15
  526. chia/wallet/cat_wallet/puzzles/everything_with_signature.clsp.hex +0 -1
  527. chia/wallet/cat_wallet/puzzles/genesis_by_coin_id.clsp +0 -26
  528. chia/wallet/cat_wallet/puzzles/genesis_by_coin_id.clsp.hex +0 -1
  529. chia/wallet/cat_wallet/puzzles/genesis_by_coin_id_or_singleton.clsp +0 -42
  530. chia/wallet/cat_wallet/puzzles/genesis_by_coin_id_or_singleton.clsp.hex +0 -1
  531. chia/wallet/cat_wallet/puzzles/genesis_by_puzzle_hash.clsp +0 -24
  532. chia/wallet/cat_wallet/puzzles/genesis_by_puzzle_hash.clsp.hex +0 -1
  533. chia/wallet/dao_wallet/__init__.py +0 -0
  534. chia/wallet/dao_wallet/dao_info.py +0 -61
  535. chia/wallet/dao_wallet/dao_utils.py +0 -811
  536. chia/wallet/dao_wallet/dao_wallet.py +0 -2119
  537. chia/wallet/did_wallet/puzzles/__init__.py +0 -0
  538. chia/wallet/did_wallet/puzzles/did_innerpuz.clsp +0 -135
  539. chia/wallet/did_wallet/puzzles/did_innerpuz.clsp.hex +0 -1
  540. chia/wallet/payment.py +0 -33
  541. chia/wallet/puzzles/augmented_condition.clsp +0 -13
  542. chia/wallet/puzzles/augmented_condition.clsp.hex +0 -1
  543. chia/wallet/puzzles/condition_codes.clib +0 -77
  544. chia/wallet/puzzles/curry-and-treehash.clib +0 -102
  545. chia/wallet/puzzles/curry.clib +0 -135
  546. chia/wallet/puzzles/curry_by_index.clib +0 -16
  547. chia/wallet/puzzles/dao_cat_eve.clsp +0 -17
  548. chia/wallet/puzzles/dao_cat_eve.clsp.hex +0 -1
  549. chia/wallet/puzzles/dao_cat_launcher.clsp +0 -36
  550. chia/wallet/puzzles/dao_cat_launcher.clsp.hex +0 -1
  551. chia/wallet/puzzles/dao_finished_state.clsp +0 -35
  552. chia/wallet/puzzles/dao_finished_state.clsp.hex +0 -1
  553. chia/wallet/puzzles/dao_finished_state.clsp.hex.sha256tree +0 -1
  554. chia/wallet/puzzles/dao_lockup.clsp +0 -288
  555. chia/wallet/puzzles/dao_lockup.clsp.hex +0 -1
  556. chia/wallet/puzzles/dao_lockup.clsp.hex.sha256tree +0 -1
  557. chia/wallet/puzzles/dao_proposal.clsp +0 -377
  558. chia/wallet/puzzles/dao_proposal.clsp.hex +0 -1
  559. chia/wallet/puzzles/dao_proposal.clsp.hex.sha256tree +0 -1
  560. chia/wallet/puzzles/dao_proposal_timer.clsp +0 -78
  561. chia/wallet/puzzles/dao_proposal_timer.clsp.hex +0 -1
  562. chia/wallet/puzzles/dao_proposal_timer.clsp.hex.sha256tree +0 -1
  563. chia/wallet/puzzles/dao_proposal_validator.clsp +0 -87
  564. chia/wallet/puzzles/dao_proposal_validator.clsp.hex +0 -1
  565. chia/wallet/puzzles/dao_proposal_validator.clsp.hex.sha256tree +0 -1
  566. chia/wallet/puzzles/dao_spend_p2_singleton_v2.clsp +0 -240
  567. chia/wallet/puzzles/dao_spend_p2_singleton_v2.clsp.hex +0 -1
  568. chia/wallet/puzzles/dao_spend_p2_singleton_v2.clsp.hex.sha256tree +0 -1
  569. chia/wallet/puzzles/dao_treasury.clsp +0 -115
  570. chia/wallet/puzzles/dao_treasury.clsp.hex +0 -1
  571. chia/wallet/puzzles/dao_update_proposal.clsp +0 -44
  572. chia/wallet/puzzles/dao_update_proposal.clsp.hex +0 -1
  573. chia/wallet/puzzles/json.clib +0 -25
  574. chia/wallet/puzzles/merkle_utils.clib +0 -18
  575. chia/wallet/puzzles/notification.clsp +0 -7
  576. chia/wallet/puzzles/notification.clsp.hex +0 -1
  577. chia/wallet/puzzles/p2_1_of_n.clsp +0 -22
  578. chia/wallet/puzzles/p2_1_of_n.clsp.hex +0 -1
  579. chia/wallet/puzzles/p2_conditions.clsp +0 -3
  580. chia/wallet/puzzles/p2_conditions.clsp.hex +0 -1
  581. chia/wallet/puzzles/p2_delegated_conditions.clsp +0 -18
  582. chia/wallet/puzzles/p2_delegated_conditions.clsp.hex +0 -1
  583. chia/wallet/puzzles/p2_delegated_puzzle.clsp +0 -19
  584. chia/wallet/puzzles/p2_delegated_puzzle.clsp.hex +0 -1
  585. chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.clsp +0 -91
  586. chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.clsp.hex +0 -1
  587. chia/wallet/puzzles/p2_m_of_n_delegate_direct.clsp +0 -108
  588. chia/wallet/puzzles/p2_m_of_n_delegate_direct.clsp.hex +0 -1
  589. chia/wallet/puzzles/p2_parent.clsp +0 -19
  590. chia/wallet/puzzles/p2_parent.clsp.hex +0 -1
  591. chia/wallet/puzzles/p2_puzzle_hash.clsp +0 -18
  592. chia/wallet/puzzles/p2_puzzle_hash.clsp.hex +0 -1
  593. chia/wallet/puzzles/p2_singleton.clsp +0 -30
  594. chia/wallet/puzzles/p2_singleton.clsp.hex +0 -1
  595. chia/wallet/puzzles/p2_singleton_aggregator.clsp +0 -81
  596. chia/wallet/puzzles/p2_singleton_aggregator.clsp.hex +0 -1
  597. chia/wallet/puzzles/p2_singleton_or_delayed_puzhash.clsp +0 -50
  598. chia/wallet/puzzles/p2_singleton_or_delayed_puzhash.clsp.hex +0 -1
  599. chia/wallet/puzzles/p2_singleton_via_delegated_puzzle.clsp +0 -47
  600. chia/wallet/puzzles/p2_singleton_via_delegated_puzzle.clsp.hex +0 -1
  601. chia/wallet/puzzles/settlement_payments.clsp +0 -49
  602. chia/wallet/puzzles/settlement_payments.clsp.hex +0 -1
  603. chia/wallet/puzzles/sha256tree.clib +0 -11
  604. chia/wallet/puzzles/singleton_launcher.clsp +0 -16
  605. chia/wallet/puzzles/singleton_launcher.clsp.hex +0 -1
  606. chia/wallet/puzzles/singleton_top_layer.clsp +0 -177
  607. chia/wallet/puzzles/singleton_top_layer.clsp.hex +0 -1
  608. chia/wallet/puzzles/singleton_top_layer_v1_1.clsp +0 -107
  609. chia/wallet/puzzles/singleton_top_layer_v1_1.clsp.hex +0 -1
  610. chia/wallet/puzzles/singleton_truths.clib +0 -21
  611. chia/wallet/vc_wallet/cr_puzzles/__init__.py +0 -0
  612. chia/wallet/vc_wallet/cr_puzzles/conditions_w_fee_announce.clsp +0 -3
  613. chia/wallet/vc_wallet/cr_puzzles/conditions_w_fee_announce.clsp.hex +0 -1
  614. chia/wallet/vc_wallet/cr_puzzles/credential_restriction.clsp +0 -304
  615. chia/wallet/vc_wallet/cr_puzzles/credential_restriction.clsp.hex +0 -1
  616. chia/wallet/vc_wallet/cr_puzzles/flag_proofs_checker.clsp +0 -45
  617. chia/wallet/vc_wallet/cr_puzzles/flag_proofs_checker.clsp.hex +0 -1
  618. chia/wallet/vc_wallet/vc_puzzles/__init__.py +0 -0
  619. chia/wallet/vc_wallet/vc_puzzles/covenant_layer.clsp +0 -30
  620. chia/wallet/vc_wallet/vc_puzzles/covenant_layer.clsp.hex +0 -1
  621. chia/wallet/vc_wallet/vc_puzzles/eml_covenant_morpher.clsp +0 -75
  622. chia/wallet/vc_wallet/vc_puzzles/eml_covenant_morpher.clsp.hex +0 -1
  623. chia/wallet/vc_wallet/vc_puzzles/eml_transfer_program_covenant_adapter.clsp +0 -32
  624. chia/wallet/vc_wallet/vc_puzzles/eml_transfer_program_covenant_adapter.clsp.hex +0 -1
  625. chia/wallet/vc_wallet/vc_puzzles/eml_update_metadata_with_DID.clsp +0 -80
  626. chia/wallet/vc_wallet/vc_puzzles/eml_update_metadata_with_DID.clsp.hex +0 -1
  627. chia/wallet/vc_wallet/vc_puzzles/exigent_metadata_layer.clsp +0 -163
  628. chia/wallet/vc_wallet/vc_puzzles/exigent_metadata_layer.clsp.hex +0 -1
  629. chia/wallet/vc_wallet/vc_puzzles/p2_announced_delegated_puzzle.clsp +0 -16
  630. chia/wallet/vc_wallet/vc_puzzles/p2_announced_delegated_puzzle.clsp.hex +0 -1
  631. chia/wallet/vc_wallet/vc_puzzles/standard_vc_backdoor_puzzle.clsp +0 -74
  632. chia/wallet/vc_wallet/vc_puzzles/standard_vc_backdoor_puzzle.clsp.hex +0 -1
  633. chia/wallet/vc_wallet/vc_puzzles/std_parent_morpher.clsp +0 -23
  634. chia/wallet/vc_wallet/vc_puzzles/std_parent_morpher.clsp.hex +0 -1
  635. chia/wallet/vc_wallet/vc_puzzles/viral_backdoor.clsp +0 -64
  636. chia/wallet/vc_wallet/vc_puzzles/viral_backdoor.clsp.hex +0 -1
  637. chia_blockchain-2.5.2rc1.dist-info/RECORD +0 -1042
  638. {chia_blockchain-2.5.2rc1.dist-info → chia_blockchain-2.5.3rc1.dist-info}/LICENSE +0 -0
  639. {chia_blockchain-2.5.2rc1.dist-info → chia_blockchain-2.5.3rc1.dist-info}/WHEEL +0 -0
  640. {chia_blockchain-2.5.2rc1.dist-info → chia_blockchain-2.5.3rc1.dist-info}/entry_points.txt +0 -0
@@ -1,3488 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import asyncio
4
- import contextlib
5
- import time
6
- from typing import Any, Callable, Optional, Union
7
-
8
- import pytest
9
-
10
- from chia._tests.util.rpc import validate_get_routes
11
- from chia._tests.util.setup_nodes import OldSimulatorsAndWallets, SimulatorsAndWalletsServices
12
- from chia._tests.util.time_out_assert import time_out_assert, time_out_assert_not_none
13
- from chia.consensus.block_rewards import calculate_base_farmer_reward, calculate_pool_reward
14
- from chia.rpc.wallet_rpc_api import WalletRpcApi
15
- from chia.rpc.wallet_rpc_client import WalletRpcClient
16
- from chia.simulator.simulator_protocol import FarmNewBlockProtocol, ReorgProtocol
17
- from chia.types.blockchain_format.program import Program
18
- from chia.types.blockchain_format.sized_bytes import bytes32
19
- from chia.types.peer_info import PeerInfo
20
- from chia.util.bech32m import encode_puzzle_hash
21
- from chia.util.ints import uint32, uint64, uint128
22
- from chia.util.timing import adjusted_timeout
23
- from chia.wallet.cat_wallet.cat_wallet import CATWallet
24
- from chia.wallet.cat_wallet.dao_cat_wallet import DAOCATWallet
25
- from chia.wallet.dao_wallet.dao_info import DAORules
26
- from chia.wallet.dao_wallet.dao_utils import (
27
- generate_mint_proposal_innerpuz,
28
- generate_simple_proposal_innerpuz,
29
- generate_update_proposal_innerpuz,
30
- )
31
- from chia.wallet.dao_wallet.dao_wallet import DAOWallet
32
- from chia.wallet.transaction_record import TransactionRecord
33
- from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG
34
-
35
-
36
- async def get_proposal_state(wallet: DAOWallet, index: int) -> tuple[Optional[bool], Optional[bool]]:
37
- return wallet.dao_info.proposals_list[index].passed, wallet.dao_info.proposals_list[index].closed
38
-
39
-
40
- async def rpc_state(
41
- timeout: float,
42
- async_function: Callable[[Any], Any],
43
- params: list[Union[int, dict[str, Any]]],
44
- condition_func: Callable[[dict[str, Any]], Any],
45
- result: Optional[Any] = None,
46
- ) -> Union[bool, dict[str, Any]]: # pragma: no cover
47
- __tracebackhide__ = True
48
-
49
- timeout = adjusted_timeout(timeout=timeout)
50
-
51
- start = time.monotonic()
52
-
53
- while True:
54
- resp = await async_function(*params)
55
- assert isinstance(resp, dict)
56
- try:
57
- if result:
58
- if condition_func(resp) == result:
59
- return True
60
- else:
61
- if condition_func(resp):
62
- return resp
63
- except IndexError:
64
- continue
65
-
66
- now = time.monotonic()
67
- elapsed = now - start
68
- if elapsed >= timeout:
69
- raise asyncio.TimeoutError(
70
- f"timed out while waiting for {async_function.__name__}(): {elapsed} >= {timeout}",
71
- )
72
-
73
- await asyncio.sleep(0.3)
74
-
75
-
76
- puzzle_hash_0 = bytes32(32 * b"0")
77
-
78
-
79
- @pytest.mark.limit_consensus_modes(reason="does not depend on consensus rules")
80
- @pytest.mark.parametrize(
81
- "trusted",
82
- [True, False],
83
- )
84
- @pytest.mark.anyio
85
- async def test_dao_creation(self_hostname: str, two_wallet_nodes: OldSimulatorsAndWallets, trusted: bool) -> None:
86
- full_nodes, wallets, _ = two_wallet_nodes
87
- full_node_api = full_nodes[0]
88
- full_node_server = full_node_api.server
89
- wallet_node_0, server_0 = wallets[0]
90
- wallet_node_1, server_1 = wallets[1]
91
- wallet_0 = wallet_node_0.wallet_state_manager.main_wallet
92
- wallet_1 = wallet_node_1.wallet_state_manager.main_wallet
93
- ph = await wallet_0.get_new_puzzlehash()
94
- ph_1 = await wallet_1.get_new_puzzlehash()
95
-
96
- if trusted:
97
- wallet_node_0.config["trusted_peers"] = {
98
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
99
- }
100
- wallet_node_1.config["trusted_peers"] = {
101
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
102
- }
103
- else:
104
- wallet_node_0.config["trusted_peers"] = {}
105
- wallet_node_1.config["trusted_peers"] = {}
106
-
107
- await server_0.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
108
- await server_1.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
109
-
110
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
111
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_1))
112
-
113
- funds = calculate_pool_reward(uint32(1)) + calculate_base_farmer_reward(uint32(1))
114
-
115
- await time_out_assert(20, wallet_0.get_confirmed_balance, funds)
116
- await time_out_assert(20, full_node_api.wallet_is_synced, True, wallet_node_0)
117
-
118
- cat_amt = 2000
119
- dao_rules = DAORules(
120
- proposal_timelock=uint64(10),
121
- soft_close_length=uint64(5),
122
- attendance_required=uint64(1000), # 10%
123
- pass_percentage=uint64(5100), # 51%
124
- self_destruct_length=uint64(20),
125
- oracle_spend_delay=uint64(10),
126
- proposal_minimum_amount=uint64(1),
127
- )
128
-
129
- fee = uint64(10)
130
- fee_for_cat = uint64(20)
131
-
132
- # Try to create a DAO with more CATs than xch balance
133
- with pytest.raises(ValueError) as e_info:
134
- async with wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=False) as action_scope:
135
- await DAOWallet.create_new_dao_and_wallet(
136
- wallet_node_0.wallet_state_manager,
137
- wallet_0,
138
- uint64(funds + 1),
139
- dao_rules,
140
- action_scope,
141
- fee=fee,
142
- fee_for_cat=fee_for_cat,
143
- )
144
- assert e_info.value.args[0] == f"Your balance of {funds} mojos is not enough to create {funds + 1} CATs"
145
-
146
- async with wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
147
- dao_wallet_0 = await DAOWallet.create_new_dao_and_wallet(
148
- wallet_node_0.wallet_state_manager,
149
- wallet_0,
150
- uint64(cat_amt * 2),
151
- dao_rules,
152
- action_scope,
153
- fee=fee,
154
- fee_for_cat=fee_for_cat,
155
- )
156
-
157
- await full_node_api.wait_transaction_records_entered_mempool(
158
- records=action_scope.side_effects.transactions, timeout=60
159
- )
160
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
161
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
162
-
163
- # Check the spend was successful
164
- treasury_id = dao_wallet_0.dao_info.treasury_id
165
-
166
- # check the dao wallet balances
167
- await time_out_assert(20, dao_wallet_0.get_confirmed_balance, uint128(1))
168
- await time_out_assert(20, dao_wallet_0.get_unconfirmed_balance, uint128(1))
169
- await time_out_assert(20, dao_wallet_0.get_pending_change_balance, uint64(0))
170
-
171
- # check select coins
172
- async with wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=False) as action_scope:
173
- no_coins = await dao_wallet_0.select_coins(uint64(2), action_scope)
174
- assert no_coins == set()
175
- selected_coins = await dao_wallet_0.select_coins(uint64(1), action_scope)
176
- assert len(selected_coins) == 1
177
-
178
- # get the cat wallets
179
- cat_wallet_0 = dao_wallet_0.wallet_state_manager.wallets[dao_wallet_0.dao_info.cat_wallet_id]
180
- dao_cat_wallet_0 = dao_wallet_0.wallet_state_manager.wallets[dao_wallet_0.dao_info.dao_cat_wallet_id]
181
- # Some dao_cat_wallet checks for coverage
182
- assert dao_cat_wallet_0.get_name() == f"CAT {cat_wallet_0.cat_info.limitations_program_hash.hex()[:16]}..."
183
- async with wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=False) as action_scope:
184
- assert (await dao_cat_wallet_0.select_coins(uint64(1), action_scope)) == set()
185
- dao_cat_puzhash = await dao_cat_wallet_0.get_new_puzzlehash()
186
- assert dao_cat_puzhash == bytes32.from_hexstr("09f905ba3e9db3644ac4537495565bf268c6f030266aa412863c5efced6b1800")
187
- await dao_cat_wallet_0.get_new_inner_puzzle(DEFAULT_TX_CONFIG)
188
- dao_cat_inner_hash = await dao_cat_wallet_0.get_new_inner_hash(DEFAULT_TX_CONFIG)
189
- assert dao_cat_inner_hash == bytes32.from_hexstr("8a66292fde9ef08198d996eae0ea21677eb478afeabed8030b1bf42c728f7dcc")
190
-
191
- cat_wallet_0_bal = await cat_wallet_0.get_confirmed_balance()
192
- assert cat_wallet_0_bal == cat_amt * 2
193
-
194
- # Create the other user's wallet from the treasury id
195
- dao_wallet_1 = await DAOWallet.create_new_dao_wallet_for_existing_dao(
196
- wallet_node_1.wallet_state_manager, wallet_1, treasury_id
197
- )
198
- assert dao_wallet_0.dao_info.treasury_id == dao_wallet_1.dao_info.treasury_id
199
-
200
- # Get the cat wallets for wallet_1
201
- cat_wallet_1 = dao_wallet_1.wallet_state_manager.wallets[dao_wallet_1.dao_info.cat_wallet_id]
202
- assert cat_wallet_1
203
-
204
- # Send some cats to the dao_cat lockup
205
- dao_cat_amt = uint64(100)
206
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
207
- await dao_wallet_0.enter_dao_cat_voting_mode(dao_cat_amt, action_scope)
208
-
209
- await full_node_api.wait_transaction_records_entered_mempool(
210
- records=action_scope.side_effects.transactions, timeout=60
211
- )
212
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
213
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30)
214
-
215
- # Test that we can get spendable coins from both cat and dao_cat wallet
216
- fake_proposal_id = Program.to("proposal_id").get_tree_hash()
217
- spendable_coins = await dao_cat_wallet_0.wallet_state_manager.get_spendable_coins_for_wallet(
218
- dao_cat_wallet_0.id(), None
219
- )
220
-
221
- assert len(spendable_coins) > 0
222
- coins = await dao_cat_wallet_0.advanced_select_coins(1, fake_proposal_id)
223
- assert len(coins) > 0
224
- # check that we have selected the coin from dao_cat_wallet
225
- assert coins[0].coin.amount == dao_cat_amt
226
-
227
- # send some cats from wallet_0 to wallet_1 so we can test voting
228
- async with cat_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
229
- await cat_wallet_0.generate_signed_transaction([cat_amt], [ph_1], action_scope)
230
-
231
- await full_node_api.wait_transaction_records_entered_mempool(
232
- records=action_scope.side_effects.transactions, timeout=60
233
- )
234
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
235
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30)
236
-
237
- await time_out_assert(10, cat_wallet_1.get_confirmed_balance, cat_amt)
238
-
239
- # Smaller tests of dao_wallet funcs for coverage
240
- await dao_wallet_0.adjust_filter_level(uint64(10))
241
- assert dao_wallet_0.dao_info.filter_below_vote_amount == uint64(10)
242
-
243
- await dao_wallet_0.set_name("Renamed Wallet")
244
- assert dao_wallet_0.get_name() == "Renamed Wallet"
245
-
246
- new_inner_puzhash = await dao_wallet_0.get_new_p2_inner_hash()
247
- assert isinstance(new_inner_puzhash, bytes32)
248
-
249
- # run DAOCATwallet.create for coverage
250
- create_dao_cat_from_info = await DAOCATWallet.create(
251
- wallet_0.wallet_state_manager, wallet_0, dao_cat_wallet_0.wallet_info
252
- )
253
- assert create_dao_cat_from_info
254
- create_dao_wallet_from_info = await DAOWallet.create(
255
- wallet_0.wallet_state_manager, wallet_0, dao_wallet_0.wallet_info
256
- )
257
- assert create_dao_wallet_from_info
258
-
259
-
260
- @pytest.mark.limit_consensus_modes(reason="does not depend on consensus rules")
261
- @pytest.mark.parametrize(
262
- "trusted",
263
- [True, False],
264
- )
265
- @pytest.mark.anyio
266
- async def test_dao_funding(self_hostname: str, three_wallet_nodes: OldSimulatorsAndWallets, trusted: bool) -> None:
267
- full_nodes, wallets, _ = three_wallet_nodes
268
- full_node_api = full_nodes[0]
269
- full_node_server = full_node_api.server
270
- wallet_node_0, server_0 = wallets[0]
271
- wallet_node_1, server_1 = wallets[1]
272
- wallet_node_2, server_2 = wallets[2]
273
- wallet_0 = wallet_node_0.wallet_state_manager.main_wallet
274
- wallet_1 = wallet_node_1.wallet_state_manager.main_wallet
275
- wallet_2 = wallet_node_1.wallet_state_manager.main_wallet
276
- ph = await wallet_0.get_new_puzzlehash()
277
- ph_1 = await wallet_1.get_new_puzzlehash()
278
- ph_2 = await wallet_2.get_new_puzzlehash()
279
-
280
- if trusted:
281
- wallet_node_0.config["trusted_peers"] = {
282
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
283
- }
284
- wallet_node_1.config["trusted_peers"] = {
285
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
286
- }
287
- wallet_node_2.config["trusted_peers"] = {
288
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
289
- }
290
- else:
291
- wallet_node_0.config["trusted_peers"] = {}
292
- wallet_node_1.config["trusted_peers"] = {}
293
- wallet_node_2.config["trusted_peers"] = {}
294
-
295
- await server_0.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
296
- await server_1.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
297
- await server_2.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
298
-
299
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
300
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_1))
301
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_2))
302
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30)
303
-
304
- funds = calculate_pool_reward(uint32(1)) + calculate_base_farmer_reward(uint32(1))
305
-
306
- await time_out_assert(20, wallet_0.get_confirmed_balance, funds)
307
- await time_out_assert(20, full_node_api.wallet_is_synced, True, wallet_node_0)
308
-
309
- cat_amt = 300000
310
- dao_rules = DAORules(
311
- proposal_timelock=uint64(5),
312
- soft_close_length=uint64(5),
313
- attendance_required=uint64(1000), # 10%
314
- pass_percentage=uint64(5100), # 51%
315
- self_destruct_length=uint64(20),
316
- oracle_spend_delay=uint64(10),
317
- proposal_minimum_amount=uint64(1),
318
- )
319
-
320
- async with wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
321
- dao_wallet_0 = await DAOWallet.create_new_dao_and_wallet(
322
- wallet_node_0.wallet_state_manager, wallet_0, uint64(cat_amt), dao_rules, action_scope
323
- )
324
-
325
- treasury_id = dao_wallet_0.dao_info.treasury_id
326
-
327
- # Get the full node sim to process the wallet creation spend
328
- await full_node_api.wait_transaction_records_entered_mempool(
329
- records=action_scope.side_effects.transactions, timeout=60
330
- )
331
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
332
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
333
-
334
- # get the cat wallets
335
- cat_wallet_0 = dao_wallet_0.wallet_state_manager.wallets[dao_wallet_0.dao_info.cat_wallet_id]
336
- await time_out_assert(20, cat_wallet_0.get_confirmed_balance, cat_amt)
337
-
338
- # Create funding spends for xch and cat
339
- xch_funds = uint64(500000)
340
- cat_funds = uint64(100000)
341
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
342
- await dao_wallet_0.create_add_funds_to_treasury_spend(xch_funds, action_scope)
343
- await full_node_api.wait_transaction_records_entered_mempool(
344
- records=action_scope.side_effects.transactions, timeout=60
345
- )
346
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
347
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30)
348
-
349
- # Check that the funding spend is found
350
- await time_out_assert(20, dao_wallet_0.get_balance_by_asset_type, xch_funds)
351
-
352
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
353
- await dao_wallet_0.create_add_funds_to_treasury_spend(
354
- cat_funds, action_scope, funding_wallet_id=cat_wallet_0.id()
355
- )
356
- await full_node_api.wait_transaction_records_entered_mempool(
357
- records=action_scope.side_effects.transactions, timeout=60
358
- )
359
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
360
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30)
361
-
362
- await time_out_assert(20, cat_wallet_0.get_confirmed_balance, cat_amt - cat_funds)
363
-
364
- # Check that the funding spend is found
365
- cat_id = bytes32.from_hexstr(cat_wallet_0.get_asset_id())
366
- await time_out_assert(20, dao_wallet_0.get_balance_by_asset_type, cat_funds, cat_id)
367
-
368
- # Create and close a proposal
369
- cat_wallet_0 = dao_wallet_0.wallet_state_manager.wallets[dao_wallet_0.dao_info.cat_wallet_id]
370
- dao_cat_wallet_0 = dao_wallet_0.wallet_state_manager.wallets[dao_wallet_0.dao_info.dao_cat_wallet_id]
371
- dao_cat_0_bal = await dao_cat_wallet_0.get_votable_balance()
372
- async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
373
- await dao_cat_wallet_0.enter_dao_cat_voting_mode(dao_cat_0_bal, action_scope)
374
- await full_node_api.wait_transaction_records_entered_mempool(
375
- records=action_scope.side_effects.transactions, timeout=60
376
- )
377
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
378
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30)
379
-
380
- recipient_puzzle_hash = await wallet_2.get_new_puzzlehash()
381
- proposal_amount_1 = uint64(10000)
382
- xch_proposal_inner = generate_simple_proposal_innerpuz(
383
- treasury_id,
384
- [recipient_puzzle_hash],
385
- [proposal_amount_1],
386
- [None],
387
- )
388
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
389
- await dao_wallet_0.generate_new_proposal(xch_proposal_inner, action_scope, dao_cat_0_bal)
390
- await full_node_api.wait_transaction_records_entered_mempool(
391
- records=action_scope.side_effects.transactions, timeout=60
392
- )
393
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
394
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
395
-
396
- # farm blocks to pass proposal
397
- for _ in range(5):
398
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
399
-
400
- prop_0 = dao_wallet_0.dao_info.proposals_list[0]
401
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
402
- await dao_wallet_0.create_proposal_close_spend(prop_0.proposal_id, action_scope)
403
- await full_node_api.wait_transaction_records_entered_mempool(
404
- records=action_scope.side_effects.transactions, timeout=60
405
- )
406
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
407
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
408
-
409
- # Create the other user's wallet from the treasury id
410
- dao_wallet_1 = await DAOWallet.create_new_dao_wallet_for_existing_dao(
411
- wallet_node_1.wallet_state_manager, wallet_1, treasury_id
412
- )
413
- assert dao_wallet_1.dao_info.treasury_id == dao_wallet_1.dao_info.treasury_id
414
-
415
- # Get the cat wallets for wallet_1
416
- cat_wallet_1 = dao_wallet_1.wallet_state_manager.wallets[dao_wallet_1.dao_info.cat_wallet_id]
417
- assert cat_wallet_1
418
- assert cat_wallet_1.cat_info.limitations_program_hash == cat_id
419
-
420
- await time_out_assert(30, dao_wallet_0.get_balance_by_asset_type, xch_funds - 10000)
421
- await time_out_assert(30, dao_wallet_0.get_balance_by_asset_type, cat_funds, cat_id)
422
- await time_out_assert(30, dao_wallet_1.get_balance_by_asset_type, xch_funds - 10000)
423
- await time_out_assert(30, dao_wallet_1.get_balance_by_asset_type, cat_funds, cat_id)
424
-
425
-
426
- @pytest.mark.limit_consensus_modes(reason="does not depend on consensus rules")
427
- @pytest.mark.parametrize(
428
- "trusted",
429
- [True, False],
430
- )
431
- @pytest.mark.anyio
432
- async def test_dao_proposals(self_hostname: str, three_wallet_nodes: OldSimulatorsAndWallets, trusted: bool) -> None:
433
- """
434
- Test a set of proposals covering:
435
- - the spend, update, and mint types.
436
- - passing and failing
437
- - force closing broken proposals
438
-
439
- total cats issued: 300k
440
- each wallet holds: 100k
441
-
442
- The proposal types and amounts voted are:
443
- P0 Spend => Pass
444
- P1 Mint => Pass
445
- P2 Update => Pass
446
- P3 Spend => Fail
447
- P4 Bad Spend => Force Close
448
-
449
- """
450
- full_nodes, wallets, _ = three_wallet_nodes
451
- full_node_api = full_nodes[0]
452
- full_node_server = full_node_api.server
453
- wallet_node_0, server_0 = wallets[0]
454
- wallet_node_1, server_1 = wallets[1]
455
- wallet_node_2, server_2 = wallets[2]
456
- wallet_0 = wallet_node_0.wallet_state_manager.main_wallet
457
- wallet_1 = wallet_node_1.wallet_state_manager.main_wallet
458
- wallet_2 = wallet_node_2.wallet_state_manager.main_wallet
459
- ph_0 = await wallet_0.get_new_puzzlehash()
460
- ph_1 = await wallet_1.get_new_puzzlehash()
461
- ph_2 = await wallet_2.get_new_puzzlehash()
462
-
463
- if trusted:
464
- wallet_node_0.config["trusted_peers"] = {
465
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
466
- }
467
- wallet_node_1.config["trusted_peers"] = {
468
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
469
- }
470
- wallet_node_2.config["trusted_peers"] = {
471
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
472
- }
473
- else:
474
- wallet_node_0.config["trusted_peers"] = {}
475
- wallet_node_1.config["trusted_peers"] = {}
476
- wallet_node_2.config["trusted_peers"] = {}
477
-
478
- await server_0.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
479
- await server_1.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
480
- await server_2.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
481
-
482
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_0))
483
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_1))
484
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_2))
485
-
486
- funds = calculate_pool_reward(uint32(1)) + calculate_base_farmer_reward(uint32(1))
487
-
488
- await time_out_assert(20, wallet_0.get_confirmed_balance, funds)
489
- await time_out_assert(20, full_node_api.wallet_is_synced, True, wallet_node_0)
490
-
491
- # set a standard fee amount to use in all txns
492
- base_fee = uint64(100)
493
-
494
- # set the cat issuance and DAO rules
495
- cat_issuance = 300000
496
- proposal_min_amt = uint64(101)
497
- dao_rules = DAORules(
498
- proposal_timelock=uint64(10),
499
- soft_close_length=uint64(5),
500
- attendance_required=uint64(190000),
501
- pass_percentage=uint64(5100), # 51%
502
- self_destruct_length=uint64(20),
503
- oracle_spend_delay=uint64(10),
504
- proposal_minimum_amount=proposal_min_amt,
505
- )
506
-
507
- # Create the DAO.
508
- # This takes two steps: create the treasury singleton, wait for oracle_spend_delay and
509
- # then complete the eve spend
510
- async with wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
511
- dao_wallet_0 = await DAOWallet.create_new_dao_and_wallet(
512
- wallet_node_0.wallet_state_manager,
513
- wallet_0,
514
- uint64(cat_issuance),
515
- dao_rules,
516
- action_scope,
517
- )
518
-
519
- await full_node_api.wait_transaction_records_entered_mempool(
520
- records=action_scope.side_effects.transactions, timeout=60
521
- )
522
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
523
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
524
-
525
- cat_wallet_0 = dao_wallet_0.wallet_state_manager.wallets[dao_wallet_0.dao_info.cat_wallet_id]
526
- dao_cat_wallet_0 = dao_wallet_0.wallet_state_manager.wallets[dao_wallet_0.dao_info.dao_cat_wallet_id]
527
- await time_out_assert(10, cat_wallet_0.get_confirmed_balance, cat_issuance)
528
- assert dao_cat_wallet_0
529
-
530
- treasury_id = dao_wallet_0.dao_info.treasury_id
531
-
532
- # Create dao_wallet_1 from the treasury id
533
- dao_wallet_1 = await DAOWallet.create_new_dao_wallet_for_existing_dao(
534
- wallet_node_1.wallet_state_manager, wallet_1, treasury_id
535
- )
536
- assert dao_wallet_1.dao_info.treasury_id == treasury_id
537
- cat_wallet_1 = dao_wallet_1.wallet_state_manager.wallets[dao_wallet_1.dao_info.cat_wallet_id]
538
- dao_cat_wallet_1 = dao_wallet_1.wallet_state_manager.wallets[dao_wallet_1.dao_info.dao_cat_wallet_id]
539
- assert cat_wallet_1
540
- assert dao_cat_wallet_1
541
-
542
- # Create dao_wallet_2 from the treasury id
543
- dao_wallet_2 = await DAOWallet.create_new_dao_wallet_for_existing_dao(
544
- wallet_node_2.wallet_state_manager, wallet_2, treasury_id
545
- )
546
- assert dao_wallet_2.dao_info.treasury_id == treasury_id
547
- cat_wallet_2 = dao_wallet_2.wallet_state_manager.wallets[dao_wallet_2.dao_info.cat_wallet_id]
548
- dao_cat_wallet_2 = dao_wallet_2.wallet_state_manager.wallets[dao_wallet_2.dao_info.dao_cat_wallet_id]
549
- assert cat_wallet_2
550
- assert dao_cat_wallet_2
551
-
552
- # Send 100k cats to wallet_1 and wallet_2
553
- cat_amt = uint64(100000)
554
- async with cat_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
555
- await cat_wallet_0.generate_signed_transaction([cat_amt, cat_amt], [ph_1, ph_2], action_scope, fee=base_fee)
556
- await full_node_api.wait_transaction_records_entered_mempool(
557
- records=action_scope.side_effects.transactions, timeout=60
558
- )
559
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
560
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30)
561
-
562
- # Lockup voting cats for all wallets
563
- dao_cat_0_bal = await dao_cat_wallet_0.get_votable_balance()
564
- async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
565
- await dao_cat_wallet_0.enter_dao_cat_voting_mode(dao_cat_0_bal, action_scope, fee=base_fee)
566
- await full_node_api.wait_transaction_records_entered_mempool(
567
- records=action_scope.side_effects.transactions, timeout=60
568
- )
569
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
570
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30)
571
-
572
- dao_cat_1_bal = await dao_cat_wallet_1.get_votable_balance()
573
- async with dao_cat_wallet_1.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
574
- await dao_cat_wallet_1.enter_dao_cat_voting_mode(dao_cat_1_bal, action_scope)
575
- await full_node_api.wait_transaction_records_entered_mempool(
576
- records=action_scope.side_effects.transactions, timeout=60
577
- )
578
- await full_node_api.process_all_wallet_transactions(wallet_1, timeout=60)
579
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30)
580
-
581
- dao_cat_2_bal = await dao_cat_wallet_2.get_votable_balance()
582
- async with dao_cat_wallet_2.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
583
- await dao_cat_wallet_2.enter_dao_cat_voting_mode(dao_cat_2_bal, action_scope)
584
- await full_node_api.wait_transaction_records_entered_mempool(
585
- records=action_scope.side_effects.transactions, timeout=60
586
- )
587
- await full_node_api.process_all_wallet_transactions(wallet_2, timeout=60)
588
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30)
589
-
590
- await time_out_assert(10, dao_cat_wallet_0.get_confirmed_balance, cat_amt)
591
- await time_out_assert(10, dao_cat_wallet_1.get_confirmed_balance, cat_amt)
592
- await time_out_assert(10, dao_cat_wallet_2.get_confirmed_balance, cat_amt)
593
-
594
- # Create funding spend so the treasury holds some XCH
595
- xch_funds = uint64(500000)
596
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
597
- await dao_wallet_0.create_add_funds_to_treasury_spend(xch_funds, action_scope)
598
- await full_node_api.wait_transaction_records_entered_mempool(
599
- records=action_scope.side_effects.transactions, timeout=60
600
- )
601
- await full_node_api.process_all_wallet_transactions(wallet_1, timeout=60)
602
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30)
603
-
604
- # Check that the funding spend is recognized by all wallets
605
- await time_out_assert(10, dao_wallet_0.get_balance_by_asset_type, xch_funds)
606
- await time_out_assert(10, dao_wallet_1.get_balance_by_asset_type, xch_funds)
607
- await time_out_assert(10, dao_wallet_2.get_balance_by_asset_type, xch_funds)
608
-
609
- # Create Proposals
610
-
611
- # Proposal 0: Spend xch to wallet_2.
612
- recipient_puzzle_hash = await wallet_2.get_new_puzzlehash()
613
- proposal_amount_1 = uint64(9998)
614
- xch_proposal_inner = generate_simple_proposal_innerpuz(
615
- treasury_id,
616
- [recipient_puzzle_hash],
617
- [proposal_amount_1],
618
- [None],
619
- )
620
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
621
- await dao_wallet_0.generate_new_proposal(xch_proposal_inner, action_scope, dao_cat_0_bal, fee=base_fee)
622
- await full_node_api.wait_transaction_records_entered_mempool(
623
- records=action_scope.side_effects.transactions, timeout=60
624
- )
625
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
626
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30)
627
-
628
- assert len(dao_wallet_0.dao_info.proposals_list) == 1
629
- assert dao_wallet_0.dao_info.proposals_list[0].amount_voted == dao_cat_0_bal
630
- assert dao_wallet_0.dao_info.proposals_list[0].timer_coin is not None
631
- prop_0 = dao_wallet_0.dao_info.proposals_list[0]
632
-
633
- # Proposal 1: Mint new CATs
634
- new_mint_amount = uint64(1000)
635
- mint_proposal_inner = await generate_mint_proposal_innerpuz(
636
- treasury_id,
637
- cat_wallet_0.cat_info.limitations_program_hash,
638
- new_mint_amount,
639
- recipient_puzzle_hash,
640
- )
641
-
642
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
643
- await dao_wallet_0.generate_new_proposal(
644
- mint_proposal_inner, action_scope, vote_amount=dao_cat_0_bal, fee=base_fee
645
- )
646
- await full_node_api.wait_transaction_records_entered_mempool(
647
- records=action_scope.side_effects.transactions, timeout=60
648
- )
649
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
650
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30)
651
-
652
- assert len(dao_wallet_0.dao_info.proposals_list) == 2
653
- prop_1 = dao_wallet_0.dao_info.proposals_list[1]
654
-
655
- # Proposal 2: Update DAO Rules.
656
- new_dao_rules = DAORules(
657
- proposal_timelock=uint64(8),
658
- soft_close_length=uint64(4),
659
- attendance_required=uint64(150000),
660
- pass_percentage=uint64(7500),
661
- self_destruct_length=uint64(12),
662
- oracle_spend_delay=uint64(5),
663
- proposal_minimum_amount=uint64(1),
664
- )
665
- current_innerpuz = dao_wallet_0.dao_info.current_treasury_innerpuz
666
- assert current_innerpuz is not None
667
- update_inner = await generate_update_proposal_innerpuz(current_innerpuz, new_dao_rules)
668
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
669
- await dao_wallet_0.generate_new_proposal(update_inner, action_scope, dao_cat_0_bal, fee=base_fee)
670
- await full_node_api.wait_transaction_records_entered_mempool(
671
- records=action_scope.side_effects.transactions, timeout=60
672
- )
673
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
674
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30)
675
-
676
- assert len(dao_wallet_0.dao_info.proposals_list) == 3
677
- prop_2 = dao_wallet_0.dao_info.proposals_list[2]
678
-
679
- # Proposal 3: Spend xch to wallet_2 (this prop will close as failed)
680
- proposal_amount_2 = uint64(500)
681
- xch_proposal_inner = generate_simple_proposal_innerpuz(
682
- treasury_id, [recipient_puzzle_hash], [proposal_amount_2], [None]
683
- )
684
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
685
- await dao_wallet_0.generate_new_proposal(xch_proposal_inner, action_scope, dao_cat_0_bal, fee=base_fee)
686
- await full_node_api.wait_transaction_records_entered_mempool(
687
- records=action_scope.side_effects.transactions, timeout=60
688
- )
689
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
690
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30)
691
-
692
- assert len(dao_wallet_0.dao_info.proposals_list) == 4
693
- prop_3 = dao_wallet_0.dao_info.proposals_list[3]
694
-
695
- # Proposal 4: Create a 'bad' proposal (can't be executed, must be force-closed)
696
- xch_proposal_inner = Program.to(["x"])
697
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
698
- await dao_wallet_0.generate_new_proposal(xch_proposal_inner, action_scope, dao_cat_0_bal, fee=base_fee)
699
- await full_node_api.wait_transaction_records_entered_mempool(
700
- records=action_scope.side_effects.transactions, timeout=60
701
- )
702
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
703
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30)
704
-
705
- assert len(dao_wallet_0.dao_info.proposals_list) == 5
706
- assert len(dao_wallet_1.dao_info.proposals_list) == 5
707
- assert len(dao_wallet_1.dao_info.proposals_list) == 5
708
- prop_4 = dao_wallet_0.dao_info.proposals_list[4]
709
-
710
- # Proposal 0 Voting: wallet 1 votes yes, wallet 2 votes no. Proposal Passes
711
- async with dao_wallet_1.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
712
- await dao_wallet_1.generate_proposal_vote_spend(prop_0.proposal_id, dao_cat_1_bal, True, action_scope)
713
- await full_node_api.wait_transaction_records_entered_mempool(
714
- records=action_scope.side_effects.transactions, timeout=60
715
- )
716
- await full_node_api.process_all_wallet_transactions(wallet_1, timeout=60)
717
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30)
718
-
719
- async with dao_wallet_2.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
720
- await dao_wallet_2.generate_proposal_vote_spend(prop_0.proposal_id, dao_cat_2_bal, False, action_scope)
721
- await full_node_api.wait_transaction_records_entered_mempool(
722
- records=action_scope.side_effects.transactions, timeout=60
723
- )
724
- await full_node_api.process_all_wallet_transactions(wallet_1, timeout=60)
725
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30)
726
-
727
- total_votes = dao_cat_0_bal + dao_cat_1_bal + dao_cat_2_bal
728
- assert dao_wallet_0.dao_info.proposals_list[0].amount_voted == total_votes
729
- assert dao_wallet_0.dao_info.proposals_list[0].yes_votes == total_votes - dao_cat_2_bal
730
- assert dao_wallet_1.dao_info.proposals_list[0].amount_voted == total_votes
731
- assert dao_wallet_1.dao_info.proposals_list[0].yes_votes == total_votes - dao_cat_2_bal
732
- assert dao_wallet_2.dao_info.proposals_list[0].amount_voted == total_votes
733
- assert dao_wallet_2.dao_info.proposals_list[0].yes_votes == total_votes - dao_cat_2_bal
734
-
735
- prop_0_state = await dao_wallet_0.get_proposal_state(prop_0.proposal_id)
736
- assert prop_0_state["passed"]
737
- assert prop_0_state["closable"]
738
-
739
- # Proposal 0 is closable, but soft_close_length has not passed.
740
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
741
- await dao_wallet_0.create_proposal_close_spend(prop_0.proposal_id, action_scope)
742
- with pytest.raises(AssertionError, match="Timed assertion timed out"):
743
- assert action_scope.side_effects.transactions[0].spend_bundle is not None
744
- await time_out_assert_not_none(
745
- 5,
746
- full_node_api.full_node.mempool_manager.get_spendbundle,
747
- action_scope.side_effects.transactions[0].spend_bundle.name(),
748
- )
749
-
750
- for _ in range(5):
751
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
752
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30)
753
-
754
- # Proposal 0: Close
755
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
756
- await dao_wallet_0.create_proposal_close_spend(prop_0.proposal_id, action_scope)
757
- close_sb_0 = action_scope.side_effects.transactions[0].spend_bundle
758
- assert close_sb_0 is not None
759
- await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, close_sb_0.name())
760
- await full_node_api.process_spend_bundles(bundles=[close_sb_0])
761
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
762
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30)
763
- await time_out_assert(20, wallet_2.get_confirmed_balance, funds + proposal_amount_1)
764
- await time_out_assert(
765
- 20, dao_wallet_0.get_balance_by_asset_type, xch_funds - proposal_amount_1 + proposal_min_amt - 1
766
- )
767
-
768
- await time_out_assert(20, get_proposal_state, (True, True), *[dao_wallet_0, 0])
769
- await time_out_assert(20, get_proposal_state, (True, True), *[dao_wallet_1, 0])
770
- await time_out_assert(20, get_proposal_state, (True, True), *[dao_wallet_2, 0])
771
-
772
- # Proposal 1 vote and close
773
- async with dao_wallet_1.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
774
- await dao_wallet_1.generate_proposal_vote_spend(prop_1.proposal_id, dao_cat_1_bal, True, action_scope)
775
- await full_node_api.wait_transaction_records_entered_mempool(
776
- records=action_scope.side_effects.transactions, timeout=60
777
- )
778
- await full_node_api.process_all_wallet_transactions(wallet_1, timeout=60)
779
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30)
780
-
781
- for _ in range(10):
782
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
783
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30)
784
-
785
- prop_1_state = await dao_wallet_0.get_proposal_state(prop_1.proposal_id)
786
- assert prop_1_state["passed"]
787
- assert prop_1_state["closable"]
788
-
789
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
790
- await dao_wallet_0.create_proposal_close_spend(prop_1.proposal_id, action_scope)
791
- await full_node_api.wait_transaction_records_entered_mempool(
792
- records=action_scope.side_effects.transactions, timeout=60
793
- )
794
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
795
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30)
796
-
797
- await time_out_assert(20, cat_wallet_2.get_confirmed_balance, new_mint_amount)
798
-
799
- # Proposal 2 vote and close
800
- async with dao_wallet_1.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
801
- await dao_wallet_1.generate_proposal_vote_spend(prop_2.proposal_id, dao_cat_1_bal, True, action_scope)
802
- await full_node_api.wait_transaction_records_entered_mempool(
803
- records=action_scope.side_effects.transactions, timeout=60
804
- )
805
- await full_node_api.process_all_wallet_transactions(wallet_1, timeout=60)
806
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30)
807
-
808
- for _ in range(10):
809
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
810
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30)
811
-
812
- prop_2_state = await dao_wallet_0.get_proposal_state(prop_2.proposal_id)
813
- assert prop_2_state["passed"]
814
- assert prop_2_state["closable"]
815
-
816
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
817
- await dao_wallet_0.create_proposal_close_spend(prop_2.proposal_id, action_scope)
818
- await full_node_api.wait_transaction_records_entered_mempool(
819
- records=action_scope.side_effects.transactions, timeout=60
820
- )
821
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
822
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30)
823
-
824
- assert dao_wallet_0.dao_rules == new_dao_rules
825
- assert dao_wallet_1.dao_rules == new_dao_rules
826
- assert dao_wallet_2.dao_rules == new_dao_rules
827
-
828
- # Proposal 3 - Close as FAILED
829
- async with dao_wallet_1.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
830
- await dao_wallet_1.generate_proposal_vote_spend(prop_3.proposal_id, dao_cat_1_bal, False, action_scope)
831
- await full_node_api.wait_transaction_records_entered_mempool(
832
- records=action_scope.side_effects.transactions, timeout=60
833
- )
834
- await full_node_api.process_all_wallet_transactions(wallet_1, timeout=60)
835
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30)
836
-
837
- for _ in range(10):
838
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
839
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30)
840
-
841
- prop_3_state = await dao_wallet_1.get_proposal_state(prop_3.proposal_id)
842
- assert not prop_3_state["passed"]
843
- assert prop_3_state["closable"]
844
-
845
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
846
- await dao_wallet_0.create_proposal_close_spend(prop_3.proposal_id, action_scope)
847
- await full_node_api.wait_transaction_records_entered_mempool(
848
- records=action_scope.side_effects.transactions, timeout=60
849
- )
850
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
851
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30)
852
-
853
- await time_out_assert(20, wallet_2.get_confirmed_balance, funds + proposal_amount_1)
854
- expected_balance = xch_funds - proposal_amount_1 + (3 * proposal_min_amt) - 3 - new_mint_amount
855
- await time_out_assert(20, dao_wallet_0.get_balance_by_asset_type, expected_balance)
856
-
857
- await time_out_assert(20, get_proposal_state, (False, True), *[dao_wallet_0, 3])
858
- await time_out_assert(20, get_proposal_state, (False, True), *[dao_wallet_1, 3])
859
- await time_out_assert(20, get_proposal_state, (False, True), *[dao_wallet_2, 3])
860
-
861
- # Proposal 4 - Self Destruct a broken proposal
862
- async with dao_wallet_1.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
863
- await dao_wallet_1.generate_proposal_vote_spend(prop_4.proposal_id, dao_cat_1_bal, True, action_scope)
864
- await full_node_api.wait_transaction_records_entered_mempool(
865
- records=action_scope.side_effects.transactions, timeout=60
866
- )
867
- await full_node_api.process_all_wallet_transactions(wallet_1, timeout=60)
868
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30)
869
-
870
- for _ in range(10):
871
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
872
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30)
873
-
874
- prop_4_state = await dao_wallet_1.get_proposal_state(prop_4.proposal_id)
875
- assert prop_4_state["passed"]
876
- assert prop_4_state["closable"]
877
-
878
- with pytest.raises(Exception, match="Unrecognised proposal type"):
879
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
880
- await dao_wallet_0.create_proposal_close_spend(prop_4.proposal_id, action_scope)
881
-
882
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
883
- await dao_wallet_0.create_proposal_close_spend(prop_4.proposal_id, action_scope, self_destruct=True)
884
- await full_node_api.wait_transaction_records_entered_mempool(
885
- records=action_scope.side_effects.transactions, timeout=60
886
- )
887
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
888
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30)
889
-
890
- # expected balance is unchanged because broken props can't release their amount
891
- await time_out_assert(20, dao_wallet_0.get_balance_by_asset_type, expected_balance)
892
- await time_out_assert(20, get_proposal_state, (True, True), *[dao_wallet_0, 4])
893
- await time_out_assert(20, get_proposal_state, (True, True), *[dao_wallet_1, 4])
894
- await time_out_assert(20, get_proposal_state, (True, True), *[dao_wallet_2, 4])
895
-
896
- # Remove Proposals from Memory and Free up locked coins
897
- await time_out_assert(20, len, 5, dao_wallet_0.dao_info.proposals_list)
898
- await dao_wallet_0.clear_finished_proposals_from_memory()
899
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
900
- await dao_wallet_0.free_coins_from_finished_proposals(action_scope, fee=uint64(100))
901
- await full_node_api.wait_transaction_records_entered_mempool(
902
- records=action_scope.side_effects.transactions, timeout=60
903
- )
904
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
905
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30)
906
-
907
- await dao_wallet_0.clear_finished_proposals_from_memory()
908
- await time_out_assert(20, len, 0, dao_wallet_0.dao_info.proposals_list)
909
-
910
-
911
- @pytest.mark.limit_consensus_modes(reason="does not depend on consensus rules")
912
- @pytest.mark.parametrize(
913
- "trusted",
914
- [True, False],
915
- )
916
- @pytest.mark.anyio
917
- async def test_dao_proposal_partial_vote(
918
- self_hostname: str, two_wallet_nodes: OldSimulatorsAndWallets, trusted: bool
919
- ) -> None:
920
- full_nodes, wallets, _ = two_wallet_nodes
921
- full_node_api = full_nodes[0]
922
- full_node_server = full_node_api.server
923
- wallet_node_0, server_0 = wallets[0]
924
- wallet_node_1, server_1 = wallets[1]
925
- wallet_0 = wallet_node_0.wallet_state_manager.main_wallet
926
- wallet_1 = wallet_node_1.wallet_state_manager.main_wallet
927
- ph = await wallet_0.get_new_puzzlehash()
928
- ph_1 = await wallet_1.get_new_puzzlehash()
929
-
930
- if trusted:
931
- wallet_node_0.config["trusted_peers"] = {
932
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
933
- }
934
- wallet_node_1.config["trusted_peers"] = {
935
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
936
- }
937
- else:
938
- wallet_node_0.config["trusted_peers"] = {}
939
- wallet_node_1.config["trusted_peers"] = {}
940
-
941
- await server_0.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
942
- await server_1.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
943
-
944
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
945
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_1))
946
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
947
-
948
- funds = calculate_pool_reward(uint32(1)) + calculate_base_farmer_reward(uint32(1))
949
-
950
- await time_out_assert(20, wallet_0.get_confirmed_balance, funds)
951
- await time_out_assert(20, full_node_api.wallet_is_synced, True, wallet_node_0)
952
-
953
- cat_amt = 300000
954
- dao_rules = DAORules(
955
- proposal_timelock=uint64(10),
956
- soft_close_length=uint64(5),
957
- attendance_required=uint64(1000), # 10%
958
- pass_percentage=uint64(5100), # 51%
959
- self_destruct_length=uint64(20),
960
- oracle_spend_delay=uint64(10),
961
- proposal_minimum_amount=uint64(1),
962
- )
963
-
964
- async with wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
965
- dao_wallet_0 = await DAOWallet.create_new_dao_and_wallet(
966
- wallet_node_0.wallet_state_manager, wallet_0, uint64(cat_amt), dao_rules, action_scope
967
- )
968
-
969
- # Get the full node sim to process the wallet creation spend
970
- await full_node_api.wait_transaction_records_entered_mempool(
971
- records=action_scope.side_effects.transactions, timeout=60
972
- )
973
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
974
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
975
-
976
- # get the cat wallets
977
- cat_wallet_0 = dao_wallet_0.wallet_state_manager.wallets[dao_wallet_0.dao_info.cat_wallet_id]
978
- await time_out_assert(10, cat_wallet_0.get_confirmed_balance, cat_amt)
979
-
980
- # get the dao_cat wallet
981
- dao_cat_wallet_0 = dao_wallet_0.wallet_state_manager.wallets[dao_wallet_0.dao_info.dao_cat_wallet_id]
982
-
983
- treasury_id = dao_wallet_0.dao_info.treasury_id
984
-
985
- # make sure the next wallet node can find the treasury
986
- assert dao_wallet_0.dao_info.current_treasury_coin is not None
987
- treasury_parent = dao_wallet_0.dao_info.current_treasury_coin.parent_coin_info
988
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
989
- await time_out_assert_not_none(
990
- 60, wallet_node_1.fetch_children, treasury_parent, wallet_node_1.get_full_node_peer()
991
- )
992
- # Create the other user's wallet from the treasury id
993
- dao_wallet_1 = await DAOWallet.create_new_dao_wallet_for_existing_dao(
994
- wallet_node_1.wallet_state_manager, wallet_1, treasury_id
995
- )
996
- assert dao_wallet_1.dao_info.treasury_id == treasury_id
997
-
998
- # Create funding spends for xch
999
- xch_funds = uint64(500000)
1000
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1001
- await dao_wallet_0.create_add_funds_to_treasury_spend(
1002
- xch_funds,
1003
- action_scope,
1004
- )
1005
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
1006
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
1007
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30)
1008
-
1009
- # Check that the funding spend is recognized by both dao wallets
1010
- await time_out_assert(10, dao_wallet_0.get_balance_by_asset_type, xch_funds)
1011
-
1012
- # Send some dao_cats to wallet_1
1013
- # Get the cat wallets for wallet_1
1014
- cat_wallet_1 = dao_wallet_1.wallet_state_manager.wallets[dao_wallet_1.dao_info.cat_wallet_id]
1015
- dao_cat_wallet_1 = dao_wallet_1.wallet_state_manager.wallets[dao_wallet_1.dao_info.dao_cat_wallet_id]
1016
- assert cat_wallet_1
1017
- assert dao_cat_wallet_1
1018
-
1019
- async with cat_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1020
- await cat_wallet_0.generate_signed_transaction([100000], [ph_1], action_scope)
1021
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
1022
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
1023
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30)
1024
- await time_out_assert(10, cat_wallet_1.get_spendable_balance, 100000)
1025
-
1026
- # Create dao cats for voting
1027
- dao_cat_0_bal = await dao_cat_wallet_0.get_votable_balance()
1028
- async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1029
- await dao_cat_wallet_0.enter_dao_cat_voting_mode(dao_cat_0_bal, action_scope)
1030
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
1031
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
1032
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1033
-
1034
- # Create a mint proposal
1035
- recipient_puzzle_hash = await cat_wallet_1.standard_wallet.get_puzzle_hash(new=False)
1036
- new_mint_amount = uint64(500)
1037
- mint_proposal_inner = await generate_mint_proposal_innerpuz(
1038
- treasury_id,
1039
- cat_wallet_0.cat_info.limitations_program_hash,
1040
- new_mint_amount,
1041
- recipient_puzzle_hash,
1042
- )
1043
-
1044
- vote_amount = dao_cat_0_bal - 10
1045
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1046
- await dao_wallet_0.generate_new_proposal(
1047
- mint_proposal_inner, action_scope, vote_amount=vote_amount, fee=uint64(1000)
1048
- )
1049
- await full_node_api.wait_transaction_records_entered_mempool(records=action_scope.side_effects.transactions)
1050
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
1051
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1052
-
1053
- # Check the proposal is saved
1054
- assert len(dao_wallet_0.dao_info.proposals_list) == 1
1055
- assert dao_wallet_0.dao_info.proposals_list[0].amount_voted == vote_amount
1056
- assert dao_wallet_0.dao_info.proposals_list[0].timer_coin is not None
1057
-
1058
- # Check that wallet_1 also finds and saved the proposal
1059
- assert len(dao_wallet_1.dao_info.proposals_list) == 1
1060
- prop = dao_wallet_1.dao_info.proposals_list[0]
1061
-
1062
- # Create votable dao cats and add a new vote
1063
- dao_cat_1_bal = await dao_cat_wallet_1.get_votable_balance()
1064
- async with dao_cat_wallet_1.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1065
- await dao_cat_wallet_1.enter_dao_cat_voting_mode(dao_cat_1_bal, action_scope)
1066
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
1067
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
1068
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1069
-
1070
- async with dao_wallet_1.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1071
- await dao_wallet_1.generate_proposal_vote_spend(prop.proposal_id, dao_cat_1_bal // 2, True, action_scope)
1072
- [vote_tx] = action_scope.side_effects.transactions
1073
- vote_sb = vote_tx.spend_bundle
1074
- assert vote_sb is not None
1075
- await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, vote_sb.name())
1076
- await full_node_api.process_spend_bundles(bundles=[vote_sb])
1077
-
1078
- for i in range(1, dao_rules.proposal_timelock + 1):
1079
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
1080
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1081
-
1082
- total_votes = vote_amount + dao_cat_1_bal // 2
1083
-
1084
- assert dao_wallet_0.dao_info.proposals_list[0].amount_voted == total_votes
1085
- assert dao_wallet_0.dao_info.proposals_list[0].yes_votes == total_votes
1086
- assert dao_wallet_1.dao_info.proposals_list[0].amount_voted == total_votes
1087
- assert dao_wallet_1.dao_info.proposals_list[0].yes_votes == total_votes
1088
-
1089
- try:
1090
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1091
- await dao_wallet_0.create_proposal_close_spend(prop.proposal_id, action_scope, fee=uint64(100))
1092
- except Exception as e: # pragma: no cover
1093
- print(e)
1094
-
1095
- await full_node_api.process_transaction_records(action_scope.side_effects.transactions)
1096
- balance = await cat_wallet_1.get_spendable_balance()
1097
-
1098
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
1099
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1100
-
1101
- await time_out_assert(20, get_proposal_state, (True, True), dao_wallet_0, 0)
1102
- await time_out_assert(20, get_proposal_state, (True, True), dao_wallet_1, 0)
1103
-
1104
- await time_out_assert(20, cat_wallet_1.get_spendable_balance, balance + new_mint_amount)
1105
- # Can we spend the newly minted CATs?
1106
- old_balance = await cat_wallet_0.get_spendable_balance()
1107
- ph_0 = await cat_wallet_0.standard_wallet.get_puzzle_hash(new=False)
1108
- async with cat_wallet_1.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1109
- await cat_wallet_1.generate_signed_transaction([balance + new_mint_amount], [ph_0], action_scope)
1110
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
1111
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
1112
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1113
-
1114
- await time_out_assert(20, cat_wallet_1.get_spendable_balance, 0)
1115
- await time_out_assert(20, cat_wallet_0.get_spendable_balance, old_balance + balance + new_mint_amount)
1116
- # release coins
1117
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1118
- await dao_wallet_0.free_coins_from_finished_proposals(action_scope)
1119
-
1120
-
1121
- @pytest.mark.limit_consensus_modes(reason="does not depend on consensus rules")
1122
- @pytest.mark.parametrize(
1123
- "trusted",
1124
- [True, False],
1125
- )
1126
- @pytest.mark.anyio
1127
- async def test_dao_rpc_api(self_hostname: str, two_wallet_nodes: Any, trusted: Any) -> None:
1128
- full_nodes, wallets, _ = two_wallet_nodes
1129
- full_node_api = full_nodes[0]
1130
- full_node_server = full_node_api.server
1131
- wallet_node_0, server_0 = wallets[0]
1132
- wallet_node_1, server_1 = wallets[1]
1133
- wallet_0 = wallet_node_0.wallet_state_manager.main_wallet
1134
- wallet_1 = wallet_node_1.wallet_state_manager.main_wallet
1135
-
1136
- ph_0 = await wallet_0.get_new_puzzlehash()
1137
- ph_1 = await wallet_1.get_new_puzzlehash()
1138
-
1139
- if trusted:
1140
- wallet_node_0.config["trusted_peers"] = {
1141
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
1142
- }
1143
- wallet_node_1.config["trusted_peers"] = {
1144
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
1145
- }
1146
- else:
1147
- wallet_node_0.config["trusted_peers"] = {}
1148
- wallet_node_1.config["trusted_peers"] = {}
1149
-
1150
- await server_0.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
1151
- await server_1.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
1152
-
1153
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_0))
1154
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
1155
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30)
1156
-
1157
- funds = calculate_pool_reward(uint32(1)) + calculate_base_farmer_reward(uint32(1))
1158
-
1159
- await time_out_assert(30, wallet_0.get_unconfirmed_balance, funds)
1160
- await time_out_assert(30, wallet_0.get_confirmed_balance, funds)
1161
-
1162
- api_0 = WalletRpcApi(wallet_node_0)
1163
- api_1 = WalletRpcApi(wallet_node_1)
1164
-
1165
- cat_amt = 300000
1166
- fee = 10000
1167
- dao_rules = DAORules(
1168
- proposal_timelock=uint64(10),
1169
- soft_close_length=uint64(5),
1170
- attendance_required=uint64(1000), # 10%
1171
- pass_percentage=uint64(5100), # 51%
1172
- self_destruct_length=uint64(20),
1173
- oracle_spend_delay=uint64(10),
1174
- proposal_minimum_amount=uint64(1),
1175
- )
1176
-
1177
- # Try to create a DAO without rules
1178
- with pytest.raises(ValueError) as e_info:
1179
- dao_wallet_0 = await api_0.create_new_wallet(
1180
- dict(
1181
- wallet_type="dao_wallet",
1182
- name="DAO WALLET 1",
1183
- mode="new",
1184
- amount_of_cats=cat_amt,
1185
- filter_amount=1,
1186
- fee=fee,
1187
- )
1188
- )
1189
- assert e_info.value.args[0] == "DAO rules must be specified for wallet creation"
1190
-
1191
- dao_wallet_0 = await api_0.create_new_wallet(
1192
- dict(
1193
- wallet_type="dao_wallet",
1194
- name="DAO WALLET 1",
1195
- mode="new",
1196
- dao_rules=dao_rules,
1197
- amount_of_cats=cat_amt,
1198
- filter_amount=1,
1199
- fee=fee,
1200
- )
1201
- )
1202
- assert isinstance(dao_wallet_0, dict)
1203
- assert dao_wallet_0.get("success")
1204
- dao_wallet_0_id = dao_wallet_0["wallet_id"]
1205
- dao_cat_wallet_0_id = dao_wallet_0["cat_wallet_id"]
1206
- treasury_id = bytes32(dao_wallet_0["treasury_id"])
1207
- txs = await wallet_0.wallet_state_manager.tx_store.get_all_unconfirmed()
1208
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
1209
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
1210
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30)
1211
-
1212
- await time_out_assert(30, wallet_0.get_pending_change_balance, 0)
1213
- expected_xch = funds - 1 - cat_amt - fee
1214
- await time_out_assert(30, wallet_0.get_confirmed_balance, expected_xch)
1215
-
1216
- dao_wallet_1 = await api_1.create_new_wallet(
1217
- dict(
1218
- wallet_type="dao_wallet",
1219
- name="DAO WALLET 2",
1220
- mode="existing",
1221
- treasury_id=treasury_id.hex(),
1222
- filter_amount=1,
1223
- )
1224
- )
1225
- assert isinstance(dao_wallet_1, dict)
1226
- assert dao_wallet_1.get("success")
1227
- dao_wallet_1_id = dao_wallet_1["wallet_id"]
1228
- # Create a cat wallet and add funds to treasury
1229
- new_cat_amt = 1000000000000
1230
- cat_wallet_0 = await api_0.create_new_wallet(
1231
- dict(
1232
- wallet_type="cat_wallet",
1233
- name="CAT WALLET 1",
1234
- test=True,
1235
- mode="new",
1236
- amount=new_cat_amt,
1237
- )
1238
- )
1239
- txs = await wallet_0.wallet_state_manager.tx_store.get_all_unconfirmed()
1240
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
1241
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
1242
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30)
1243
-
1244
- cat_wallet_0_id = cat_wallet_0["wallet_id"]
1245
- cat_id = bytes32.from_hexstr(cat_wallet_0["asset_id"])
1246
-
1247
- await rpc_state(
1248
- 20,
1249
- api_0.get_wallet_balance,
1250
- [{"wallet_id": cat_wallet_0_id}],
1251
- lambda x: x["wallet_balance"]["confirmed_wallet_balance"],
1252
- new_cat_amt,
1253
- )
1254
-
1255
- cat_funding_amt = 500000
1256
- cat_tx = await api_0.dao_add_funds_to_treasury(
1257
- dict(
1258
- wallet_id=dao_wallet_0_id,
1259
- amount=cat_funding_amt,
1260
- funding_wallet_id=cat_wallet_0_id,
1261
- )
1262
- )
1263
-
1264
- xch_funding_amt = 200000
1265
- xch_tx = await api_0.dao_add_funds_to_treasury(
1266
- dict(
1267
- wallet_id=dao_wallet_0_id,
1268
- amount=xch_funding_amt,
1269
- funding_wallet_id=1,
1270
- )
1271
- )
1272
- txs = [TransactionRecord.from_json_dict(cat_tx["tx"]), TransactionRecord.from_json_dict(xch_tx["tx"])]
1273
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
1274
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
1275
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30)
1276
-
1277
- expected_xch -= xch_funding_amt + new_cat_amt
1278
- await time_out_assert(30, wallet_0.get_confirmed_balance, expected_xch)
1279
-
1280
- await rpc_state(
1281
- 20,
1282
- api_0.get_wallet_balance,
1283
- [{"wallet_id": cat_wallet_0_id}],
1284
- lambda x: x["wallet_balance"]["confirmed_wallet_balance"],
1285
- new_cat_amt - cat_funding_amt,
1286
- )
1287
-
1288
- await rpc_state(
1289
- 20, api_0.dao_get_treasury_balance, [{"wallet_id": dao_wallet_0_id}], lambda x: x["balances"]["xch"]
1290
- )
1291
- balances = await api_0.dao_get_treasury_balance({"wallet_id": dao_wallet_0_id})
1292
- assert balances["balances"]["xch"] == xch_funding_amt
1293
- assert balances["balances"][cat_id.hex()] == cat_funding_amt
1294
-
1295
- # Send some cats to wallet_1
1296
- await api_0.cat_spend(
1297
- {
1298
- "wallet_id": dao_cat_wallet_0_id,
1299
- "amount": cat_amt // 2,
1300
- "inner_address": encode_puzzle_hash(ph_1, "xch"),
1301
- "fee": fee,
1302
- }
1303
- )
1304
- txs = await wallet_0.wallet_state_manager.tx_store.get_all_unconfirmed()
1305
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
1306
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
1307
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30)
1308
-
1309
- await rpc_state(
1310
- 20,
1311
- api_0.get_wallet_balance,
1312
- [{"wallet_id": dao_cat_wallet_0_id}],
1313
- lambda x: x["wallet_balance"]["confirmed_wallet_balance"],
1314
- cat_amt // 2,
1315
- )
1316
-
1317
- # send cats to lockup
1318
- await api_0.dao_send_to_lockup({"wallet_id": dao_wallet_0_id, "amount": cat_amt // 2})
1319
- tx_queue = await wallet_node_0.wallet_state_manager.tx_store.get_not_sent()
1320
- await full_node_api.process_transaction_records(records=[tx for tx in tx_queue])
1321
- await api_1.dao_send_to_lockup({"wallet_id": dao_wallet_1_id, "amount": cat_amt // 2})
1322
- tx_queue = await wallet_node_1.wallet_state_manager.tx_store.get_not_sent()
1323
- await full_node_api.process_transaction_records(records=[tx for tx in tx_queue])
1324
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30)
1325
-
1326
- # create a spend proposal
1327
- additions = [
1328
- {"puzzle_hash": ph_1.hex(), "amount": 1000},
1329
- ]
1330
- create_proposal = await api_0.dao_create_proposal(
1331
- {
1332
- "wallet_id": dao_wallet_0_id,
1333
- "proposal_type": "spend",
1334
- "additions": additions,
1335
- "vote_amount": cat_amt // 2,
1336
- "fee": fee,
1337
- }
1338
- )
1339
- txs = [TransactionRecord.from_json_dict(create_proposal["tx"])]
1340
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
1341
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
1342
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1343
-
1344
- await rpc_state(20, api_0.dao_get_proposals, [{"wallet_id": dao_wallet_0_id}], lambda x: len(x["proposals"]), 1)
1345
-
1346
- await rpc_state(20, api_1.dao_get_proposals, [{"wallet_id": dao_wallet_1_id}], lambda x: len(x["proposals"]), 1)
1347
-
1348
- props_0 = await api_0.dao_get_proposals({"wallet_id": dao_wallet_0_id})
1349
- prop = props_0["proposals"][0]
1350
- assert prop.amount_voted == cat_amt // 2
1351
- assert prop.yes_votes == cat_amt // 2
1352
-
1353
- # Add votes
1354
- vote_tx = await api_1.dao_vote_on_proposal(
1355
- {
1356
- "wallet_id": dao_wallet_1_id,
1357
- "vote_amount": cat_amt // 2,
1358
- "proposal_id": prop.proposal_id.hex(),
1359
- "is_yes_vote": True,
1360
- }
1361
- )
1362
- txs = [TransactionRecord.from_json_dict(vote_tx["tx"])]
1363
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
1364
- await full_node_api.process_all_wallet_transactions(wallet_1, timeout=60)
1365
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1366
-
1367
- await rpc_state(
1368
- 20, api_0.dao_get_proposals, [{"wallet_id": dao_wallet_0_id}], lambda x: x["proposals"][0].amount_voted, cat_amt
1369
- )
1370
-
1371
- # farm blocks until we can close proposal
1372
- state = await api_0.dao_get_proposal_state({"wallet_id": dao_wallet_0_id, "proposal_id": prop.proposal_id.hex()})
1373
- for _ in range(state["state"]["blocks_needed"] + 1):
1374
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
1375
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1376
-
1377
- await rpc_state(
1378
- 20,
1379
- api_0.dao_get_proposal_state,
1380
- [{"wallet_id": dao_wallet_0_id, "proposal_id": prop.proposal_id.hex()}],
1381
- lambda x: x["state"]["closable"],
1382
- True,
1383
- )
1384
-
1385
- proposal_tx = await api_0.dao_close_proposal({"wallet_id": dao_wallet_0_id, "proposal_id": prop.proposal_id.hex()})
1386
- txs = [TransactionRecord.from_json_dict(proposal_tx["tx"])]
1387
- try:
1388
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
1389
- except TimeoutError: # pragma: no cover
1390
- # try again
1391
- await api_0.push_tx({"spend_bundle": txs[0].spend_bundle.stream_to_bytes().hex()})
1392
- await full_node_api.wait_transaction_records_marked_as_in_mempool([txs[0].name], wallet_node_0, 60)
1393
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
1394
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1395
-
1396
- await rpc_state(
1397
- 20, api_0.dao_get_proposals, [{"wallet_id": dao_wallet_0_id}], lambda x: x["proposals"][0].closed, True
1398
- )
1399
-
1400
- # check that the proposal state has changed for everyone
1401
- await rpc_state(
1402
- 20,
1403
- api_0.dao_get_proposal_state,
1404
- [{"wallet_id": dao_wallet_0_id, "proposal_id": prop.proposal_id.hex()}],
1405
- lambda x: x["state"]["closed"],
1406
- True,
1407
- )
1408
-
1409
- await rpc_state(
1410
- 20,
1411
- api_1.dao_get_proposal_state,
1412
- [{"wallet_id": dao_wallet_1_id, "proposal_id": prop.proposal_id.hex()}],
1413
- lambda x: x["state"]["closed"],
1414
- True,
1415
- )
1416
-
1417
- # create a mint proposal
1418
- mint_proposal = await api_0.dao_create_proposal(
1419
- {
1420
- "wallet_id": dao_wallet_0_id,
1421
- "proposal_type": "mint",
1422
- "amount": uint64(10000),
1423
- "cat_target_address": encode_puzzle_hash(ph_0, "xch"),
1424
- "vote_amount": cat_amt // 2,
1425
- "fee": fee,
1426
- }
1427
- )
1428
- txs = [TransactionRecord.from_json_dict(mint_proposal["tx"])]
1429
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
1430
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
1431
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1432
-
1433
- await rpc_state(20, api_0.dao_get_proposals, [{"wallet_id": dao_wallet_0_id}], lambda x: len(x["proposals"]), 2)
1434
-
1435
- await rpc_state(20, api_1.dao_get_proposals, [{"wallet_id": dao_wallet_1_id}], lambda x: len(x["proposals"]), 2)
1436
-
1437
- props = await api_0.dao_get_proposals({"wallet_id": dao_wallet_0_id})
1438
- prop = props["proposals"][1]
1439
- assert prop.amount_voted == cat_amt // 2
1440
- assert prop.yes_votes == cat_amt // 2
1441
-
1442
- # Add votes
1443
- vote_tx = await api_1.dao_vote_on_proposal(
1444
- {
1445
- "wallet_id": dao_wallet_1_id,
1446
- "vote_amount": cat_amt // 2,
1447
- "proposal_id": prop.proposal_id.hex(),
1448
- "is_yes_vote": True,
1449
- }
1450
- )
1451
- txs = [TransactionRecord.from_json_dict(vote_tx["tx"])]
1452
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
1453
- await full_node_api.process_all_wallet_transactions(wallet_1, timeout=60)
1454
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1455
-
1456
- await rpc_state(
1457
- 20, api_0.dao_get_proposals, [{"wallet_id": dao_wallet_0_id}], lambda x: x["proposals"][1].amount_voted, cat_amt
1458
- )
1459
-
1460
- # farm blocks until we can close proposal
1461
- state = await api_0.dao_get_proposal_state({"wallet_id": dao_wallet_0_id, "proposal_id": prop.proposal_id.hex()})
1462
- for _ in range(state["state"]["blocks_needed"] + 1):
1463
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
1464
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1465
-
1466
- await rpc_state(
1467
- 20,
1468
- api_0.dao_get_proposal_state,
1469
- [{"wallet_id": dao_wallet_0_id, "proposal_id": prop.proposal_id.hex()}],
1470
- lambda x: x["state"]["closable"],
1471
- True,
1472
- )
1473
-
1474
- proposal_tx = await api_0.dao_close_proposal({"wallet_id": dao_wallet_0_id, "proposal_id": prop.proposal_id.hex()})
1475
- txs = [TransactionRecord.from_json_dict(proposal_tx["tx"])]
1476
- try:
1477
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
1478
- except TimeoutError: # pragma: no cover
1479
- # try again
1480
- await api_0.push_tx({"spend_bundle": txs[0].spend_bundle.stream_to_bytes().hex()})
1481
- await full_node_api.wait_transaction_records_marked_as_in_mempool([txs[0].name], wallet_node_0, 60)
1482
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
1483
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1484
-
1485
- await rpc_state(
1486
- 20, api_0.dao_get_proposals, [{"wallet_id": dao_wallet_0_id}], lambda x: x["proposals"][1].closed, True
1487
- )
1488
-
1489
- # check that the proposal state has changed for everyone
1490
- await rpc_state(
1491
- 20,
1492
- api_0.dao_get_proposal_state,
1493
- [{"wallet_id": dao_wallet_0_id, "proposal_id": prop.proposal_id.hex()}],
1494
- lambda x: x["state"]["closed"],
1495
- True,
1496
- )
1497
-
1498
- await rpc_state(
1499
- 20,
1500
- api_1.dao_get_proposal_state,
1501
- [{"wallet_id": dao_wallet_1_id, "proposal_id": prop.proposal_id.hex()}],
1502
- lambda x: x["state"]["closed"],
1503
- True,
1504
- )
1505
-
1506
- # Check the minted cats are received
1507
- await rpc_state(
1508
- 20,
1509
- api_0.get_wallet_balance,
1510
- [{"wallet_id": dao_cat_wallet_0_id}],
1511
- lambda x: x["wallet_balance"]["confirmed_wallet_balance"],
1512
- 10000,
1513
- )
1514
-
1515
- # create an update proposal
1516
- new_dao_rules = {"pass_percentage": 10000}
1517
- update_proposal = await api_0.dao_create_proposal(
1518
- {
1519
- "wallet_id": dao_wallet_0_id,
1520
- "proposal_type": "update",
1521
- "new_dao_rules": new_dao_rules,
1522
- "vote_amount": cat_amt // 2,
1523
- "fee": fee,
1524
- }
1525
- )
1526
- txs = [TransactionRecord.from_json_dict(update_proposal["tx"])]
1527
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
1528
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
1529
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1530
-
1531
- await rpc_state(20, api_0.dao_get_proposals, [{"wallet_id": dao_wallet_0_id}], lambda x: len(x["proposals"]), 3)
1532
-
1533
- await rpc_state(20, api_1.dao_get_proposals, [{"wallet_id": dao_wallet_1_id}], lambda x: len(x["proposals"]), 3)
1534
-
1535
- props = await api_0.dao_get_proposals({"wallet_id": dao_wallet_0_id})
1536
- prop = props["proposals"][2]
1537
- assert prop.amount_voted == cat_amt // 2
1538
- assert prop.yes_votes == cat_amt // 2
1539
-
1540
- # Add votes
1541
- vote_tx = await api_1.dao_vote_on_proposal(
1542
- {
1543
- "wallet_id": dao_wallet_1_id,
1544
- "vote_amount": cat_amt // 2,
1545
- "proposal_id": prop.proposal_id.hex(),
1546
- "is_yes_vote": True,
1547
- }
1548
- )
1549
- txs = [TransactionRecord.from_json_dict(vote_tx["tx"])]
1550
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
1551
- await full_node_api.process_all_wallet_transactions(wallet_1, timeout=60)
1552
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1553
-
1554
- await rpc_state(
1555
- 20, api_0.dao_get_proposals, [{"wallet_id": dao_wallet_0_id}], lambda x: x["proposals"][2].amount_voted, cat_amt
1556
- )
1557
-
1558
- # farm blocks until we can close proposal
1559
- state = await api_0.dao_get_proposal_state({"wallet_id": dao_wallet_0_id, "proposal_id": prop.proposal_id.hex()})
1560
- for _ in range(state["state"]["blocks_needed"] + 1):
1561
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
1562
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1563
-
1564
- await rpc_state(
1565
- 20,
1566
- api_0.dao_get_proposal_state,
1567
- [{"wallet_id": dao_wallet_0_id, "proposal_id": prop.proposal_id.hex()}],
1568
- lambda x: x["state"]["closable"],
1569
- True,
1570
- )
1571
-
1572
- open_props = await api_0.dao_get_proposals({"wallet_id": dao_wallet_0_id, "include_closed": False})
1573
- assert len(open_props["proposals"]) == 1
1574
-
1575
- close_tx = await api_0.dao_close_proposal({"wallet_id": dao_wallet_0_id, "proposal_id": prop.proposal_id.hex()})
1576
- txs = [TransactionRecord.from_json_dict(close_tx["tx"])]
1577
- try:
1578
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
1579
- except TimeoutError: # pragma: no cover
1580
- # try again
1581
- await api_0.push_tx({"spend_bundle": txs[0].spend_bundle.stream_to_bytes().hex()})
1582
- await full_node_api.wait_transaction_records_marked_as_in_mempool([txs[0].name], wallet_node_0, 60)
1583
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
1584
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1585
-
1586
- await rpc_state(
1587
- 20, api_0.dao_get_proposals, [{"wallet_id": dao_wallet_0_id}], lambda x: x["proposals"][1].closed, True
1588
- )
1589
-
1590
- # check that the proposal state has changed for everyone
1591
- await rpc_state(
1592
- 20,
1593
- api_0.dao_get_proposal_state,
1594
- [{"wallet_id": dao_wallet_0_id, "proposal_id": prop.proposal_id.hex()}],
1595
- lambda x: x["state"]["closed"],
1596
- True,
1597
- )
1598
-
1599
- await rpc_state(
1600
- 20,
1601
- api_1.dao_get_proposal_state,
1602
- [{"wallet_id": dao_wallet_1_id, "proposal_id": prop.proposal_id.hex()}],
1603
- lambda x: x["state"]["closed"],
1604
- True,
1605
- )
1606
-
1607
- # Check the rules have updated
1608
- dao_wallet = wallet_node_0.wallet_state_manager.wallets[dao_wallet_0_id]
1609
- assert dao_wallet.dao_rules.pass_percentage == 10000
1610
-
1611
- # Test adjust filter level
1612
- resp = await api_0.dao_adjust_filter_level({"wallet_id": dao_wallet_1_id, "filter_level": 101})
1613
- assert resp["success"]
1614
- assert resp["dao_info"].filter_below_vote_amount == 101
1615
-
1616
- # Test get_treasury_id
1617
- resp = await api_0.dao_get_treasury_id({"wallet_id": dao_wallet_0_id})
1618
- assert resp["treasury_id"] == treasury_id
1619
-
1620
-
1621
- @pytest.mark.limit_consensus_modes(reason="does not depend on consensus rules")
1622
- @pytest.mark.parametrize(
1623
- "trusted",
1624
- [True, False],
1625
- )
1626
- @pytest.mark.anyio
1627
- async def test_dao_rpc_client(
1628
- two_wallet_nodes_services: SimulatorsAndWalletsServices, trusted: bool, self_hostname: str
1629
- ) -> None:
1630
- [full_node_service], wallet_services, _bt = two_wallet_nodes_services
1631
- full_node_api = full_node_service._api
1632
- full_node_server = full_node_api.full_node.server
1633
- wallet_node_0 = wallet_services[0]._node
1634
- server_0 = wallet_node_0.server
1635
- wallet_node_1 = wallet_services[1]._node
1636
- server_1 = wallet_node_1.server
1637
- wallet_0 = wallet_node_0.wallet_state_manager.main_wallet
1638
- wallet_1 = wallet_node_1.wallet_state_manager.main_wallet
1639
- ph_0 = await wallet_0.get_new_puzzlehash()
1640
- ph_1 = await wallet_1.get_new_puzzlehash()
1641
-
1642
- if trusted:
1643
- wallet_node_0.config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()}
1644
- wallet_node_1.config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()}
1645
- else:
1646
- wallet_node_0.config["trusted_peers"] = {}
1647
- wallet_node_1.config["trusted_peers"] = {}
1648
-
1649
- await server_0.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
1650
- await server_1.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
1651
-
1652
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_0))
1653
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_1))
1654
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
1655
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1656
-
1657
- initial_funds = calculate_pool_reward(uint32(1)) + calculate_base_farmer_reward(uint32(1))
1658
-
1659
- await time_out_assert(15, wallet_0.get_confirmed_balance, initial_funds)
1660
- await time_out_assert(15, wallet_0.get_unconfirmed_balance, initial_funds)
1661
-
1662
- assert wallet_services[0].rpc_server is not None
1663
- assert wallet_services[1].rpc_server is not None
1664
-
1665
- async with contextlib.AsyncExitStack() as exit_stack:
1666
- client_0 = await exit_stack.enter_async_context(
1667
- WalletRpcClient.create_as_context(
1668
- self_hostname,
1669
- wallet_services[0].rpc_server.listen_port,
1670
- wallet_services[0].root_path,
1671
- wallet_services[0].config,
1672
- )
1673
- )
1674
- await validate_get_routes(client_0, wallet_services[0].rpc_server.rpc_api)
1675
- client_1 = await exit_stack.enter_async_context(
1676
- WalletRpcClient.create_as_context(
1677
- self_hostname,
1678
- wallet_services[1].rpc_server.listen_port,
1679
- wallet_services[1].root_path,
1680
- wallet_services[1].config,
1681
- )
1682
- )
1683
- await validate_get_routes(client_1, wallet_services[1].rpc_server.rpc_api)
1684
-
1685
- cat_amt = uint64(150000)
1686
- amount_of_cats = uint64(cat_amt * 2)
1687
- dao_rules = DAORules(
1688
- proposal_timelock=uint64(8),
1689
- soft_close_length=uint64(4),
1690
- attendance_required=uint64(1000), # 10%
1691
- pass_percentage=uint64(4900), # 49%
1692
- self_destruct_length=uint64(20),
1693
- oracle_spend_delay=uint64(10),
1694
- proposal_minimum_amount=uint64(1),
1695
- )
1696
- filter_amount = uint64(1)
1697
- fee = uint64(10000)
1698
-
1699
- # create new dao
1700
- dao_wallet_res_0 = await client_0.create_new_dao_wallet(
1701
- mode="new",
1702
- tx_config=DEFAULT_TX_CONFIG,
1703
- dao_rules=dao_rules.to_json_dict(),
1704
- amount_of_cats=amount_of_cats,
1705
- filter_amount=filter_amount,
1706
- name="DAO WALLET 0",
1707
- )
1708
- dao_id_0 = dao_wallet_res_0.wallet_id
1709
- cat_wallet_0 = wallet_node_0.wallet_state_manager.wallets[dao_wallet_res_0.cat_wallet_id]
1710
-
1711
- txs = await wallet_0.wallet_state_manager.tx_store.get_all_unconfirmed()
1712
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
1713
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
1714
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1715
-
1716
- await time_out_assert(20, cat_wallet_0.get_confirmed_balance, amount_of_cats)
1717
-
1718
- # Create a new standard cat for treasury funds
1719
- new_cat_amt = uint64(100000)
1720
- new_cat_res = await client_0.create_new_cat_and_wallet(new_cat_amt, test=True)
1721
- new_cat_wallet_id = new_cat_res["wallet_id"]
1722
- new_cat_wallet = wallet_node_0.wallet_state_manager.wallets[new_cat_wallet_id]
1723
-
1724
- txs = await wallet_0.wallet_state_manager.tx_store.get_all_unconfirmed()
1725
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
1726
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
1727
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1728
-
1729
- # join dao
1730
- dao_wallet_res_1 = await client_1.create_new_dao_wallet(
1731
- mode="existing",
1732
- tx_config=DEFAULT_TX_CONFIG,
1733
- treasury_id=dao_wallet_res_0.treasury_id,
1734
- filter_amount=filter_amount,
1735
- name="DAO WALLET 1",
1736
- )
1737
- dao_id_1 = dao_wallet_res_1.wallet_id
1738
- cat_wallet_1 = wallet_node_1.wallet_state_manager.wallets[dao_wallet_res_1.cat_wallet_id]
1739
-
1740
- # fund treasury
1741
- xch_funds = uint64(10000000000)
1742
- await client_0.dao_add_funds_to_treasury(dao_id_0, 1, xch_funds, DEFAULT_TX_CONFIG)
1743
- await client_0.dao_add_funds_to_treasury(dao_id_0, new_cat_wallet_id, new_cat_amt, DEFAULT_TX_CONFIG)
1744
- txs = await wallet_0.wallet_state_manager.tx_store.get_all_unconfirmed()
1745
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
1746
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
1747
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1748
-
1749
- await rpc_state(20, client_0.dao_get_treasury_balance, [dao_id_0], lambda x: x["balances"]["xch"], xch_funds)
1750
- assert isinstance(new_cat_wallet, CATWallet)
1751
- new_cat_asset_id = new_cat_wallet.cat_info.limitations_program_hash
1752
- await rpc_state(
1753
- 20,
1754
- client_0.dao_get_treasury_balance,
1755
- [dao_id_0],
1756
- lambda x: x["balances"][new_cat_asset_id.hex()],
1757
- new_cat_amt,
1758
- )
1759
- await rpc_state(
1760
- 20,
1761
- client_0.dao_get_treasury_balance,
1762
- [dao_id_0],
1763
- lambda x: x["balances"]["xch"],
1764
- xch_funds,
1765
- )
1766
-
1767
- # send cats to wallet 1
1768
- await client_0.cat_spend(
1769
- wallet_id=dao_wallet_res_0.cat_wallet_id,
1770
- tx_config=DEFAULT_TX_CONFIG,
1771
- amount=cat_amt,
1772
- inner_address=encode_puzzle_hash(ph_1, "xch"),
1773
- fee=fee,
1774
- )
1775
-
1776
- txs = await wallet_0.wallet_state_manager.tx_store.get_all_unconfirmed()
1777
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
1778
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
1779
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1780
-
1781
- await time_out_assert(20, cat_wallet_0.get_confirmed_balance, cat_amt)
1782
- await time_out_assert(20, cat_wallet_1.get_confirmed_balance, cat_amt)
1783
-
1784
- # send cats to lockup
1785
- await client_0.dao_send_to_lockup(dao_id_0, cat_amt, DEFAULT_TX_CONFIG)
1786
- await client_1.dao_send_to_lockup(dao_id_1, cat_amt, DEFAULT_TX_CONFIG)
1787
-
1788
- txs_0 = await wallet_0.wallet_state_manager.tx_store.get_all_unconfirmed()
1789
- txs_1 = await wallet_1.wallet_state_manager.tx_store.get_all_unconfirmed()
1790
- await full_node_api.wait_transaction_records_entered_mempool(records=txs_0 + txs_1, timeout=60)
1791
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
1792
- await full_node_api.process_all_wallet_transactions(wallet_1, timeout=60)
1793
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1794
-
1795
- # create a spend proposal
1796
- additions = [
1797
- {"puzzle_hash": ph_0.hex(), "amount": 1000},
1798
- {"puzzle_hash": ph_0.hex(), "amount": 10000, "asset_id": new_cat_asset_id.hex()},
1799
- ]
1800
- await client_0.dao_create_proposal(
1801
- wallet_id=dao_id_0,
1802
- proposal_type="spend",
1803
- tx_config=DEFAULT_TX_CONFIG,
1804
- additions=additions,
1805
- vote_amount=cat_amt,
1806
- fee=fee,
1807
- )
1808
- txs = await wallet_0.wallet_state_manager.tx_store.get_all_unconfirmed()
1809
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
1810
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
1811
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1812
-
1813
- # check proposal is found by wallet 1
1814
- await rpc_state(20, client_1.dao_get_proposals, [dao_id_1], lambda x: x["proposals"][0]["yes_votes"], cat_amt)
1815
- props = await client_1.dao_get_proposals(dao_id_1)
1816
- proposal_id_hex = props["proposals"][0]["proposal_id"]
1817
-
1818
- # create an update proposal
1819
- await client_1.dao_create_proposal(
1820
- wallet_id=dao_id_1,
1821
- proposal_type="update",
1822
- tx_config=DEFAULT_TX_CONFIG,
1823
- vote_amount=cat_amt,
1824
- new_dao_rules={"proposal_timelock": uint64(10)},
1825
- fee=fee,
1826
- )
1827
- txs = await wallet_1.wallet_state_manager.tx_store.get_all_unconfirmed()
1828
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
1829
- await full_node_api.process_all_wallet_transactions(wallet_1, timeout=60)
1830
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1831
-
1832
- # create a mint proposal
1833
- mint_addr = await client_1.get_next_address(wallet_id=wallet_1.id(), new_address=False)
1834
- await client_1.dao_create_proposal(
1835
- wallet_id=dao_id_1,
1836
- proposal_type="mint",
1837
- tx_config=DEFAULT_TX_CONFIG,
1838
- vote_amount=cat_amt,
1839
- amount=uint64(100),
1840
- cat_target_address=mint_addr,
1841
- fee=fee,
1842
- )
1843
- txs = await wallet_1.wallet_state_manager.tx_store.get_all_unconfirmed()
1844
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
1845
- await full_node_api.process_all_wallet_transactions(wallet_1, timeout=60)
1846
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1847
-
1848
- # vote spend
1849
- await client_1.dao_vote_on_proposal(
1850
- wallet_id=dao_id_1,
1851
- proposal_id=proposal_id_hex,
1852
- vote_amount=cat_amt,
1853
- tx_config=DEFAULT_TX_CONFIG,
1854
- is_yes_vote=True,
1855
- fee=fee,
1856
- )
1857
- txs = await wallet_1.wallet_state_manager.tx_store.get_all_unconfirmed()
1858
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
1859
- await full_node_api.process_all_wallet_transactions(wallet_1, timeout=60)
1860
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1861
-
1862
- # check updated proposal is found by wallet 0
1863
- await rpc_state(
1864
- 20, client_0.dao_get_proposals, [dao_id_0], lambda x: x["proposals"][0]["yes_votes"], cat_amt * 2
1865
- )
1866
-
1867
- # check proposal state and farm enough blocks to pass
1868
- state = await client_0.dao_get_proposal_state(wallet_id=dao_id_0, proposal_id=proposal_id_hex)
1869
- assert state["success"]
1870
- assert state["state"]["passed"]
1871
-
1872
- for _ in range(0, state["state"]["blocks_needed"]):
1873
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
1874
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1875
-
1876
- state = await client_0.dao_get_proposal_state(wallet_id=dao_id_0, proposal_id=proposal_id_hex)
1877
- assert state["success"]
1878
- assert state["state"]["closable"]
1879
-
1880
- # check proposal parsing
1881
- props = await client_0.dao_get_proposals(dao_id_0)
1882
- proposal_2_hex = props["proposals"][1]["proposal_id"]
1883
- proposal_3_hex = props["proposals"][2]["proposal_id"]
1884
- parsed_1 = await client_0.dao_parse_proposal(wallet_id=dao_id_0, proposal_id=proposal_id_hex)
1885
- assert parsed_1["success"]
1886
- parsed_2 = await client_0.dao_parse_proposal(wallet_id=dao_id_0, proposal_id=proposal_2_hex)
1887
- assert parsed_2["success"]
1888
- parsed_3 = await client_0.dao_parse_proposal(wallet_id=dao_id_0, proposal_id=proposal_3_hex)
1889
- assert parsed_3["success"]
1890
-
1891
- # farm blocks so proposal can close
1892
- for i in range(1, 10):
1893
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
1894
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1895
-
1896
- # close the proposal
1897
- close = await client_0.dao_close_proposal(
1898
- wallet_id=dao_id_0, proposal_id=proposal_id_hex, tx_config=DEFAULT_TX_CONFIG, self_destruct=False, fee=fee
1899
- )
1900
- tx = close.tx
1901
- await full_node_api.wait_transaction_records_entered_mempool(records=[tx], timeout=60)
1902
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
1903
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1904
-
1905
- # check proposal is closed
1906
- await rpc_state(20, client_0.dao_get_proposals, [dao_id_0], lambda x: x["proposals"][0]["closed"], True)
1907
- await rpc_state(20, client_1.dao_get_proposals, [dao_id_1], lambda x: x["proposals"][0]["closed"], True)
1908
- # check treasury balances
1909
- await rpc_state(
1910
- 20,
1911
- client_0.dao_get_treasury_balance,
1912
- [dao_id_0],
1913
- lambda x: x["balances"][new_cat_asset_id.hex()],
1914
- new_cat_amt - 10000,
1915
- )
1916
- await rpc_state(
1917
- 20, client_0.dao_get_treasury_balance, [dao_id_0], lambda x: x["balances"]["xch"], xch_funds - 1000
1918
- )
1919
-
1920
- # check wallet balances
1921
- await rpc_state(
1922
- 20, client_0.get_wallet_balance, [new_cat_wallet_id], lambda x: x["confirmed_wallet_balance"], 10000
1923
- )
1924
- expected_xch = initial_funds - amount_of_cats - new_cat_amt - xch_funds - (2 * fee) - 2 - 9000
1925
- await rpc_state(
1926
- 20, client_0.get_wallet_balance, [wallet_0.id()], lambda x: x["confirmed_wallet_balance"], expected_xch
1927
- )
1928
-
1929
- # close the mint proposal
1930
- props = await client_0.dao_get_proposals(dao_id_0)
1931
- proposal_id_hex = props["proposals"][2]["proposal_id"]
1932
- close = await client_0.dao_close_proposal(
1933
- wallet_id=dao_id_0, proposal_id=proposal_id_hex, tx_config=DEFAULT_TX_CONFIG, self_destruct=False, fee=fee
1934
- )
1935
- tx = close.tx
1936
- await full_node_api.wait_transaction_records_entered_mempool(records=[tx], timeout=60)
1937
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
1938
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1939
-
1940
- # check proposal is closed
1941
- await rpc_state(20, client_0.dao_get_proposals, [dao_id_0], lambda x: x["proposals"][2]["closed"], True)
1942
- await rpc_state(20, client_1.dao_get_proposals, [dao_id_1], lambda x: x["proposals"][2]["closed"], True)
1943
-
1944
- # check minted cats are received
1945
- await rpc_state(
1946
- 20,
1947
- client_1.get_wallet_balance,
1948
- [dao_wallet_res_1.cat_wallet_id],
1949
- lambda x: x["confirmed_wallet_balance"],
1950
- 100,
1951
- )
1952
-
1953
- open_props = await client_0.dao_get_proposals(dao_id_0, False)
1954
- assert len(open_props["proposals"]) == 1
1955
-
1956
- # close the update proposal
1957
- proposal_id_hex = props["proposals"][1]["proposal_id"]
1958
- close = await client_0.dao_close_proposal(
1959
- wallet_id=dao_id_0, proposal_id=proposal_id_hex, tx_config=DEFAULT_TX_CONFIG, self_destruct=False, fee=fee
1960
- )
1961
- tx = close.tx
1962
- await full_node_api.wait_transaction_records_entered_mempool(records=[tx], timeout=60)
1963
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
1964
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1965
-
1966
- # check proposal is closed
1967
- await rpc_state(20, client_0.dao_get_proposals, [dao_id_0], lambda x: x["proposals"][1]["closed"], True)
1968
- await rpc_state(20, client_1.dao_get_proposals, [dao_id_1], lambda x: x["proposals"][1]["closed"], True)
1969
-
1970
- # check dao rules are updated
1971
- new_rules = await client_0.dao_get_rules(dao_id_0)
1972
- assert new_rules["rules"]["proposal_timelock"] == 10
1973
- new_rules_1 = await client_0.dao_get_rules(dao_id_1)
1974
- assert new_rules_1["rules"]["proposal_timelock"] == 10
1975
-
1976
- # free locked cats from finished proposal
1977
- free_coins_res = await client_0.dao_free_coins_from_finished_proposals(
1978
- wallet_id=dao_id_0, tx_config=DEFAULT_TX_CONFIG
1979
- )
1980
- free_coins_tx = free_coins_res.tx
1981
- await full_node_api.wait_transaction_records_entered_mempool(records=[free_coins_tx], timeout=60)
1982
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
1983
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1984
-
1985
- bal = await client_0.get_wallet_balance(dao_wallet_res_0.dao_cat_wallet_id)
1986
- assert bal["confirmed_wallet_balance"] == cat_amt
1987
-
1988
- exit = await client_0.dao_exit_lockup(dao_id_0, tx_config=DEFAULT_TX_CONFIG)
1989
- exit_tx = exit.tx
1990
- await full_node_api.wait_transaction_records_entered_mempool(records=[exit_tx], timeout=60)
1991
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
1992
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
1993
-
1994
- await rpc_state(
1995
- 20,
1996
- client_0.get_wallet_balance,
1997
- [dao_wallet_res_0.cat_wallet_id],
1998
- lambda x: x["confirmed_wallet_balance"],
1999
- cat_amt,
2000
- )
2001
-
2002
- # coverage tests for filter amount and get treasury id
2003
- treasury_id_resp = await client_0.dao_get_treasury_id(wallet_id=dao_id_0)
2004
- assert treasury_id_resp["treasury_id"] == "0x" + dao_wallet_res_0.treasury_id.hex()
2005
- filter_amount_resp = await client_0.dao_adjust_filter_level(wallet_id=dao_id_0, filter_level=30)
2006
- assert filter_amount_resp["dao_info"]["filter_below_vote_amount"] == 30
2007
-
2008
-
2009
- @pytest.mark.limit_consensus_modes(reason="does not depend on consensus rules")
2010
- @pytest.mark.parametrize(
2011
- "trusted",
2012
- [True, False],
2013
- )
2014
- @pytest.mark.anyio
2015
- async def test_dao_complex_spends(
2016
- two_wallet_nodes_services: SimulatorsAndWalletsServices, trusted: bool, self_hostname: str
2017
- ) -> None:
2018
- [full_node_service], wallet_services, _bt = two_wallet_nodes_services
2019
- full_node_api = full_node_service._api
2020
- full_node_server = full_node_api.full_node.server
2021
- wallet_node_0 = wallet_services[0]._node
2022
- server_0 = wallet_node_0.server
2023
- wallet_node_1 = wallet_services[1]._node
2024
- server_1 = wallet_node_1.server
2025
- wallet_0 = wallet_node_0.wallet_state_manager.main_wallet
2026
- wallet_1 = wallet_node_1.wallet_state_manager.main_wallet
2027
- ph_0 = await wallet_0.get_new_puzzlehash()
2028
- ph_1 = await wallet_1.get_new_puzzlehash()
2029
-
2030
- if trusted:
2031
- wallet_node_0.config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()}
2032
- wallet_node_1.config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()}
2033
- else:
2034
- wallet_node_0.config["trusted_peers"] = {}
2035
- wallet_node_1.config["trusted_peers"] = {}
2036
-
2037
- await server_0.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
2038
- await server_1.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
2039
-
2040
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_0))
2041
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_1))
2042
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
2043
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2044
-
2045
- initial_funds = calculate_pool_reward(uint32(1)) + calculate_base_farmer_reward(uint32(1))
2046
-
2047
- await time_out_assert(15, wallet_0.get_confirmed_balance, initial_funds)
2048
- await time_out_assert(15, wallet_0.get_unconfirmed_balance, initial_funds)
2049
-
2050
- assert wallet_services[0].rpc_server is not None
2051
- assert wallet_services[1].rpc_server is not None
2052
-
2053
- async with contextlib.AsyncExitStack() as exit_stack:
2054
- client_0 = await exit_stack.enter_async_context(
2055
- WalletRpcClient.create_as_context(
2056
- self_hostname,
2057
- wallet_services[0].rpc_server.listen_port,
2058
- wallet_services[0].root_path,
2059
- wallet_services[0].config,
2060
- )
2061
- )
2062
- await validate_get_routes(client_0, wallet_services[0].rpc_server.rpc_api)
2063
- client_1 = await exit_stack.enter_async_context(
2064
- WalletRpcClient.create_as_context(
2065
- self_hostname,
2066
- wallet_services[1].rpc_server.listen_port,
2067
- wallet_services[1].root_path,
2068
- wallet_services[1].config,
2069
- )
2070
- )
2071
- await validate_get_routes(client_1, wallet_services[1].rpc_server.rpc_api)
2072
-
2073
- cat_amt = uint64(300000)
2074
- dao_rules = DAORules(
2075
- proposal_timelock=uint64(2),
2076
- soft_close_length=uint64(2),
2077
- attendance_required=uint64(1000), # 10%
2078
- pass_percentage=uint64(5100), # 51%
2079
- self_destruct_length=uint64(5),
2080
- oracle_spend_delay=uint64(2),
2081
- proposal_minimum_amount=uint64(1),
2082
- )
2083
- filter_amount = uint64(1)
2084
-
2085
- # create new dao
2086
- dao_wallet_res_0 = await client_0.create_new_dao_wallet(
2087
- mode="new",
2088
- tx_config=DEFAULT_TX_CONFIG,
2089
- dao_rules=dao_rules.to_json_dict(),
2090
- amount_of_cats=cat_amt,
2091
- filter_amount=filter_amount,
2092
- name="DAO WALLET 0",
2093
- )
2094
- dao_id_0 = dao_wallet_res_0.wallet_id
2095
- treasury_id = dao_wallet_res_0.treasury_id
2096
- cat_wallet_0 = wallet_node_0.wallet_state_manager.wallets[dao_wallet_res_0.cat_wallet_id]
2097
-
2098
- txs = await wallet_0.wallet_state_manager.tx_store.get_all_unconfirmed()
2099
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
2100
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
2101
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2102
-
2103
- await time_out_assert(20, cat_wallet_0.get_confirmed_balance, cat_amt)
2104
-
2105
- # Create a new standard cat for treasury funds
2106
- new_cat_amt = uint64(1000000)
2107
- new_cat_wallet_dict = await client_0.create_new_cat_and_wallet(new_cat_amt, test=True)
2108
- new_cat_wallet_id = new_cat_wallet_dict["wallet_id"]
2109
- new_cat_wallet = wallet_node_0.wallet_state_manager.wallets[new_cat_wallet_id]
2110
-
2111
- txs = await wallet_0.wallet_state_manager.tx_store.get_all_unconfirmed()
2112
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
2113
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
2114
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2115
-
2116
- # Create a new standard cat for treasury funds
2117
- new_cat_wallet_dict_2 = await client_0.create_new_cat_and_wallet(new_cat_amt, test=True)
2118
- new_cat_wallet_id_2 = new_cat_wallet_dict_2["wallet_id"]
2119
- new_cat_wallet_2 = wallet_node_0.wallet_state_manager.wallets[new_cat_wallet_id_2]
2120
-
2121
- txs = await wallet_0.wallet_state_manager.tx_store.get_all_unconfirmed()
2122
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
2123
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
2124
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2125
-
2126
- # join dao
2127
- dao_wallet_res_1 = await client_1.create_new_dao_wallet(
2128
- mode="existing",
2129
- tx_config=DEFAULT_TX_CONFIG,
2130
- treasury_id=treasury_id,
2131
- filter_amount=filter_amount,
2132
- name="DAO WALLET 1",
2133
- )
2134
- dao_id_1 = dao_wallet_res_1.wallet_id
2135
-
2136
- # fund treasury so there are multiple coins for each asset
2137
- xch_funds = uint64(10000000000)
2138
- for _ in range(4):
2139
- await client_0.dao_add_funds_to_treasury(dao_id_0, 1, uint64(xch_funds / 4), DEFAULT_TX_CONFIG)
2140
- await client_0.dao_add_funds_to_treasury(
2141
- dao_id_0, new_cat_wallet_id, uint64(new_cat_amt / 4), DEFAULT_TX_CONFIG
2142
- )
2143
- await client_0.dao_add_funds_to_treasury(
2144
- dao_id_0, new_cat_wallet_id_2, uint64(new_cat_amt / 4), DEFAULT_TX_CONFIG
2145
- )
2146
- txs = await wallet_0.wallet_state_manager.tx_store.get_all_unconfirmed()
2147
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
2148
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
2149
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2150
-
2151
- await rpc_state(20, client_0.dao_get_treasury_balance, [dao_id_0], lambda x: x["balances"]["xch"], xch_funds)
2152
- assert isinstance(new_cat_wallet, CATWallet)
2153
- new_cat_asset_id = new_cat_wallet.cat_info.limitations_program_hash
2154
- assert isinstance(new_cat_wallet_2, CATWallet)
2155
- new_cat_asset_id_2 = new_cat_wallet_2.cat_info.limitations_program_hash
2156
- await rpc_state(
2157
- 20,
2158
- client_0.dao_get_treasury_balance,
2159
- [dao_id_0],
2160
- lambda x: x["balances"][new_cat_asset_id.hex()],
2161
- new_cat_amt,
2162
- )
2163
- await rpc_state(
2164
- 20,
2165
- client_0.dao_get_treasury_balance,
2166
- [dao_id_0],
2167
- lambda x: x["balances"][new_cat_asset_id_2.hex()],
2168
- new_cat_amt,
2169
- )
2170
-
2171
- # add the new cat wallets to wallet_1
2172
- await client_1.create_wallet_for_existing_cat(new_cat_asset_id)
2173
- await client_1.create_wallet_for_existing_cat(new_cat_asset_id_2)
2174
-
2175
- # send cats to lockup
2176
- await client_0.dao_send_to_lockup(dao_id_0, cat_amt, DEFAULT_TX_CONFIG)
2177
-
2178
- txs = await wallet_0.wallet_state_manager.tx_store.get_all_unconfirmed()
2179
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
2180
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
2181
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2182
-
2183
- # Test spend proposal types
2184
-
2185
- # Test proposal with multiple conditions and xch coins
2186
- additions = [
2187
- {"puzzle_hash": ph_0.hex(), "amount": xch_funds / 4},
2188
- {"puzzle_hash": ph_1.hex(), "amount": xch_funds / 4},
2189
- ]
2190
- await client_0.dao_create_proposal(
2191
- wallet_id=dao_id_0,
2192
- proposal_type="spend",
2193
- tx_config=DEFAULT_TX_CONFIG,
2194
- additions=additions,
2195
- vote_amount=cat_amt,
2196
- )
2197
- txs = await wallet_0.wallet_state_manager.tx_store.get_all_unconfirmed()
2198
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
2199
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
2200
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2201
-
2202
- props = await client_1.dao_get_proposals(dao_id_1)
2203
- proposal_id_hex = props["proposals"][-1]["proposal_id"]
2204
-
2205
- await client_0.dao_close_proposal(
2206
- wallet_id=dao_id_0, proposal_id=proposal_id_hex, tx_config=DEFAULT_TX_CONFIG, self_destruct=False
2207
- )
2208
- txs = await wallet_0.wallet_state_manager.tx_store.get_all_unconfirmed()
2209
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
2210
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
2211
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2212
-
2213
- # check proposal is closed
2214
- await rpc_state(20, client_0.dao_get_proposals, [dao_id_0], lambda x: x["proposals"][-1]["closed"], True)
2215
- await rpc_state(20, client_1.dao_get_proposals, [dao_id_1], lambda x: x["proposals"][-1]["closed"], True)
2216
- # check the xch is received and removed from treasury
2217
- await rpc_state(
2218
- 20,
2219
- client_1.get_wallet_balance,
2220
- [wallet_1.id()],
2221
- lambda x: x["confirmed_wallet_balance"],
2222
- initial_funds + (xch_funds / 4),
2223
- )
2224
- await rpc_state(
2225
- 20,
2226
- client_0.dao_get_treasury_balance,
2227
- [dao_id_0],
2228
- lambda x: x["balances"]["xch"],
2229
- xch_funds / 2,
2230
- )
2231
-
2232
- # Test proposal with multiple cats and multiple coins
2233
- cat_spend_amt = 510000
2234
- additions = [
2235
- {"puzzle_hash": ph_0.hex(), "amount": cat_spend_amt, "asset_id": new_cat_asset_id.hex()},
2236
- {"puzzle_hash": ph_0.hex(), "amount": cat_spend_amt, "asset_id": new_cat_asset_id_2.hex()},
2237
- ]
2238
- await client_0.dao_create_proposal(
2239
- wallet_id=dao_id_0,
2240
- proposal_type="spend",
2241
- tx_config=DEFAULT_TX_CONFIG,
2242
- additions=additions,
2243
- vote_amount=cat_amt,
2244
- )
2245
- txs = await wallet_0.wallet_state_manager.tx_store.get_all_unconfirmed()
2246
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
2247
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
2248
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2249
-
2250
- props = await client_1.dao_get_proposals(dao_id_1)
2251
- proposal_id_hex = props["proposals"][-1]["proposal_id"]
2252
-
2253
- await client_0.dao_close_proposal(
2254
- wallet_id=dao_id_0, proposal_id=proposal_id_hex, tx_config=DEFAULT_TX_CONFIG, self_destruct=False
2255
- )
2256
- txs = await wallet_0.wallet_state_manager.tx_store.get_all_unconfirmed()
2257
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
2258
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
2259
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2260
-
2261
- # check proposal is closed
2262
- await rpc_state(20, client_0.dao_get_proposals, [dao_id_0], lambda x: x["proposals"][-1]["closed"], True)
2263
- await rpc_state(20, client_1.dao_get_proposals, [dao_id_1], lambda x: x["proposals"][-1]["closed"], True)
2264
-
2265
- # check cat balances
2266
- await rpc_state(
2267
- 20,
2268
- client_0.dao_get_treasury_balance,
2269
- [dao_id_0],
2270
- lambda x: x["balances"][new_cat_asset_id.hex()],
2271
- new_cat_amt - cat_spend_amt,
2272
- )
2273
- await rpc_state(
2274
- 20,
2275
- client_0.dao_get_treasury_balance,
2276
- [dao_id_0],
2277
- lambda x: x["balances"][new_cat_asset_id_2.hex()],
2278
- new_cat_amt - cat_spend_amt,
2279
- )
2280
-
2281
- await rpc_state(
2282
- 20, client_0.get_wallet_balance, [new_cat_wallet_id], lambda x: x["confirmed_wallet_balance"], cat_spend_amt
2283
- )
2284
- await rpc_state(
2285
- 20,
2286
- client_0.get_wallet_balance,
2287
- [new_cat_wallet_id_2],
2288
- lambda x: x["confirmed_wallet_balance"],
2289
- cat_spend_amt,
2290
- )
2291
-
2292
- # Spend remaining balances with multiple outputs
2293
-
2294
- additions = [
2295
- {"puzzle_hash": ph_0.hex(), "amount": 400000, "asset_id": new_cat_asset_id.hex()},
2296
- {"puzzle_hash": ph_1.hex(), "amount": 90000, "asset_id": new_cat_asset_id.hex()},
2297
- {"puzzle_hash": ph_0.hex(), "amount": 400000, "asset_id": new_cat_asset_id_2.hex()},
2298
- {"puzzle_hash": ph_1.hex(), "amount": 90000, "asset_id": new_cat_asset_id_2.hex()},
2299
- {"puzzle_hash": ph_0.hex(), "amount": xch_funds / 4},
2300
- {"puzzle_hash": ph_1.hex(), "amount": xch_funds / 4},
2301
- ]
2302
- await client_0.dao_create_proposal(
2303
- wallet_id=dao_id_0,
2304
- proposal_type="spend",
2305
- tx_config=DEFAULT_TX_CONFIG,
2306
- additions=additions,
2307
- vote_amount=cat_amt,
2308
- )
2309
- txs = await wallet_0.wallet_state_manager.tx_store.get_all_unconfirmed()
2310
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
2311
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
2312
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2313
-
2314
- props = await client_0.dao_get_proposals(dao_id_0)
2315
- proposal_id_hex = props["proposals"][-1]["proposal_id"]
2316
-
2317
- await client_0.dao_close_proposal(
2318
- wallet_id=dao_id_0,
2319
- proposal_id=proposal_id_hex,
2320
- tx_config=DEFAULT_TX_CONFIG,
2321
- self_destruct=False,
2322
- )
2323
- txs = await wallet_0.wallet_state_manager.tx_store.get_all_unconfirmed()
2324
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
2325
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
2326
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2327
-
2328
- # check proposal is closed
2329
- await rpc_state(20, client_0.dao_get_proposals, [dao_id_0], lambda x: x["proposals"][-1]["closed"], True)
2330
- await rpc_state(20, client_1.dao_get_proposals, [dao_id_1], lambda x: x["proposals"][-1]["closed"], True)
2331
-
2332
- # check cat balances
2333
- await rpc_state(
2334
- 20,
2335
- client_0.get_wallet_balance,
2336
- [new_cat_wallet_id],
2337
- lambda x: x["confirmed_wallet_balance"],
2338
- cat_spend_amt + 400000,
2339
- )
2340
- await rpc_state(
2341
- 20,
2342
- client_0.get_wallet_balance,
2343
- [new_cat_wallet_id_2],
2344
- lambda x: x["confirmed_wallet_balance"],
2345
- cat_spend_amt + 400000,
2346
- )
2347
- await rpc_state(
2348
- 20, client_1.get_wallet_balance, [new_cat_wallet_id], lambda x: x["confirmed_wallet_balance"], 90000
2349
- )
2350
- await rpc_state(
2351
- 20, client_1.get_wallet_balance, [new_cat_wallet_id_2], lambda x: x["confirmed_wallet_balance"], 90000
2352
- )
2353
-
2354
- # check xch
2355
- await rpc_state(
2356
- 20,
2357
- client_1.get_wallet_balance,
2358
- [wallet_1.id()],
2359
- lambda x: x["confirmed_wallet_balance"],
2360
- initial_funds + (xch_funds / 2),
2361
- )
2362
-
2363
- # check treasury balances are 0
2364
- await rpc_state(
2365
- 20,
2366
- client_1.dao_get_treasury_balance,
2367
- [dao_id_0],
2368
- lambda x: x["balances"]["xch"] + 1, # add 1 so result isn't 0
2369
- 1,
2370
- )
2371
- await rpc_state(
2372
- 20,
2373
- client_1.dao_get_treasury_balance,
2374
- [dao_id_0],
2375
- lambda x: x["balances"][new_cat_asset_id.hex()] + 1, # add 1 so result isn't 0
2376
- 1,
2377
- )
2378
- await rpc_state(
2379
- 20,
2380
- client_0.dao_get_treasury_balance,
2381
- [dao_id_0],
2382
- lambda x: x["balances"][new_cat_asset_id_2.hex()] + 1, # add 1 so result isn't 0
2383
- 1,
2384
- )
2385
-
2386
-
2387
- @pytest.mark.limit_consensus_modes(reason="does not depend on consensus rules")
2388
- @pytest.mark.parametrize(
2389
- "trusted",
2390
- [True, False],
2391
- )
2392
- @pytest.mark.anyio
2393
- async def test_dao_concurrency(self_hostname: str, three_wallet_nodes: OldSimulatorsAndWallets, trusted: bool) -> None:
2394
- full_nodes, wallets, _ = three_wallet_nodes
2395
- full_node_api = full_nodes[0]
2396
- full_node_server = full_node_api.server
2397
- wallet_node_0, server_0 = wallets[0]
2398
- wallet_node_1, server_1 = wallets[1]
2399
- wallet_node_2, server_2 = wallets[2]
2400
- wallet_0 = wallet_node_0.wallet_state_manager.main_wallet
2401
- wallet_1 = wallet_node_1.wallet_state_manager.main_wallet
2402
- wallet_2 = wallet_node_2.wallet_state_manager.main_wallet
2403
- ph = await wallet_0.get_new_puzzlehash()
2404
- ph_1 = await wallet_1.get_new_puzzlehash()
2405
- ph_2 = await wallet_2.get_new_puzzlehash()
2406
-
2407
- if trusted:
2408
- wallet_node_0.config["trusted_peers"] = {
2409
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
2410
- }
2411
- wallet_node_1.config["trusted_peers"] = {
2412
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
2413
- }
2414
- wallet_node_2.config["trusted_peers"] = {
2415
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
2416
- }
2417
- else:
2418
- wallet_node_0.config["trusted_peers"] = {}
2419
- wallet_node_1.config["trusted_peers"] = {}
2420
- wallet_node_2.config["trusted_peers"] = {}
2421
-
2422
- await server_0.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
2423
- await server_1.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
2424
- await server_2.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
2425
-
2426
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
2427
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_1))
2428
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_2))
2429
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
2430
-
2431
- funds = calculate_pool_reward(uint32(1)) + calculate_base_farmer_reward(uint32(1))
2432
-
2433
- await time_out_assert(20, wallet_0.get_confirmed_balance, funds)
2434
- await time_out_assert(20, full_node_api.wallet_is_synced, True, wallet_node_0)
2435
-
2436
- cat_amt = 300000
2437
- dao_rules = DAORules(
2438
- proposal_timelock=uint64(10),
2439
- soft_close_length=uint64(5),
2440
- attendance_required=uint64(1000), # 10%
2441
- pass_percentage=uint64(5100), # 51%
2442
- self_destruct_length=uint64(20),
2443
- oracle_spend_delay=uint64(10),
2444
- proposal_minimum_amount=uint64(101),
2445
- )
2446
-
2447
- async with wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
2448
- dao_wallet_0 = await DAOWallet.create_new_dao_and_wallet(
2449
- wallet_node_0.wallet_state_manager, wallet_0, uint64(cat_amt), dao_rules, action_scope
2450
- )
2451
-
2452
- # Get the full node sim to process the wallet creation spend
2453
- await full_node_api.wait_transaction_records_entered_mempool(
2454
- records=action_scope.side_effects.transactions, timeout=60
2455
- )
2456
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
2457
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2458
-
2459
- # get the cat wallets
2460
- cat_wallet_0 = dao_wallet_0.wallet_state_manager.wallets[dao_wallet_0.dao_info.cat_wallet_id]
2461
- await time_out_assert(10, cat_wallet_0.get_confirmed_balance, cat_amt)
2462
-
2463
- # get the dao_cat wallet
2464
- dao_cat_wallet_0 = dao_wallet_0.wallet_state_manager.wallets[dao_wallet_0.dao_info.dao_cat_wallet_id]
2465
-
2466
- treasury_id = dao_wallet_0.dao_info.treasury_id
2467
-
2468
- # Create the other user's wallet from the treasury id
2469
- dao_wallet_1 = await DAOWallet.create_new_dao_wallet_for_existing_dao(
2470
- wallet_node_1.wallet_state_manager, wallet_1, treasury_id
2471
- )
2472
- assert dao_wallet_1.dao_info.treasury_id == treasury_id
2473
-
2474
- # Create funding spends for xch
2475
- xch_funds = uint64(500000)
2476
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
2477
- await dao_wallet_0.create_add_funds_to_treasury_spend(xch_funds, action_scope)
2478
- await full_node_api.wait_transaction_records_entered_mempool(
2479
- records=action_scope.side_effects.transactions, timeout=60
2480
- )
2481
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
2482
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2483
-
2484
- # Check that the funding spend is recognized by both dao wallets
2485
- await time_out_assert(10, dao_wallet_0.get_balance_by_asset_type, xch_funds)
2486
-
2487
- # Send some dao_cats to wallet_1
2488
- # Get the cat wallets for wallet_1
2489
- cat_wallet_1 = dao_wallet_1.wallet_state_manager.wallets[dao_wallet_1.dao_info.cat_wallet_id]
2490
- dao_cat_wallet_1 = dao_wallet_1.wallet_state_manager.wallets[dao_wallet_1.dao_info.dao_cat_wallet_id]
2491
- assert cat_wallet_1
2492
- assert dao_cat_wallet_1
2493
-
2494
- # Add a third wallet and check they can find proposal with accurate vote counts
2495
- dao_wallet_2 = await DAOWallet.create_new_dao_wallet_for_existing_dao(
2496
- wallet_node_2.wallet_state_manager, wallet_2, treasury_id
2497
- )
2498
- assert dao_wallet_2.dao_info.treasury_id == treasury_id
2499
-
2500
- dao_cat_wallet_2 = dao_wallet_2.wallet_state_manager.wallets[dao_wallet_2.dao_info.dao_cat_wallet_id]
2501
- assert dao_cat_wallet_2
2502
-
2503
- async with cat_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
2504
- await cat_wallet_0.generate_signed_transaction([100000, 100000], [ph_1, ph_2], action_scope)
2505
- await full_node_api.wait_transaction_records_entered_mempool(
2506
- records=action_scope.side_effects.transactions, timeout=60
2507
- )
2508
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
2509
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2510
-
2511
- cat_wallet_1 = dao_wallet_1.wallet_state_manager.wallets[dao_wallet_1.dao_info.cat_wallet_id]
2512
- await time_out_assert(10, cat_wallet_1.get_confirmed_balance, 100000)
2513
- cat_wallet_2 = dao_wallet_2.wallet_state_manager.wallets[dao_wallet_2.dao_info.cat_wallet_id]
2514
- await time_out_assert(10, cat_wallet_2.get_confirmed_balance, 100000)
2515
- await time_out_assert(10, cat_wallet_0.get_confirmed_balance, 100000)
2516
-
2517
- # Create dao cats for voting
2518
- dao_cat_0_bal = await dao_cat_wallet_0.get_votable_balance()
2519
- assert dao_cat_0_bal == 100000
2520
- async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
2521
- await dao_cat_wallet_0.enter_dao_cat_voting_mode(dao_cat_0_bal, action_scope)
2522
- await full_node_api.wait_transaction_records_entered_mempool(
2523
- records=action_scope.side_effects.transactions, timeout=60
2524
- )
2525
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
2526
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2527
-
2528
- # Create a proposal for xch spend
2529
- recipient_puzzle_hash = await wallet_2.get_new_puzzlehash()
2530
- proposal_amount = uint64(10000)
2531
- xch_proposal_inner = generate_simple_proposal_innerpuz(
2532
- treasury_id,
2533
- [recipient_puzzle_hash],
2534
- [proposal_amount],
2535
- [None],
2536
- )
2537
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
2538
- await dao_wallet_0.generate_new_proposal(xch_proposal_inner, action_scope, dao_cat_0_bal, uint64(1000))
2539
- await full_node_api.wait_transaction_records_entered_mempool(
2540
- records=action_scope.side_effects.transactions, timeout=60
2541
- )
2542
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
2543
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2544
-
2545
- # Check the proposal is saved
2546
- assert len(dao_wallet_0.dao_info.proposals_list) == 1
2547
- assert dao_wallet_0.dao_info.proposals_list[0].amount_voted == dao_cat_0_bal
2548
- assert dao_wallet_0.dao_info.proposals_list[0].timer_coin is not None
2549
-
2550
- # Check that wallet_1 also finds and saved the proposal
2551
- assert len(dao_wallet_1.dao_info.proposals_list) == 1
2552
- prop = dao_wallet_1.dao_info.proposals_list[0]
2553
-
2554
- total_votes = dao_cat_0_bal
2555
-
2556
- assert dao_wallet_0.dao_info.proposals_list[0].amount_voted == total_votes
2557
- assert dao_wallet_0.dao_info.proposals_list[0].yes_votes == total_votes
2558
- assert dao_wallet_1.dao_info.proposals_list[0].amount_voted == total_votes
2559
- assert dao_wallet_1.dao_info.proposals_list[0].yes_votes == total_votes
2560
-
2561
- # Create votable dao cats and add a new vote
2562
- dao_cat_1_bal = await dao_cat_wallet_1.get_votable_balance()
2563
- async with dao_cat_wallet_1.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
2564
- await dao_cat_wallet_1.enter_dao_cat_voting_mode(dao_cat_1_bal, action_scope)
2565
- await full_node_api.wait_transaction_records_entered_mempool(
2566
- records=action_scope.side_effects.transactions, timeout=60
2567
- )
2568
- await full_node_api.process_all_wallet_transactions(wallet_1, timeout=60)
2569
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30)
2570
-
2571
- async with dao_cat_wallet_2.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
2572
- await dao_cat_wallet_2.enter_dao_cat_voting_mode(dao_cat_1_bal, action_scope)
2573
- await full_node_api.wait_transaction_records_entered_mempool(
2574
- records=action_scope.side_effects.transactions, timeout=60
2575
- )
2576
- await full_node_api.process_all_wallet_transactions(wallet_2, timeout=60)
2577
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30)
2578
-
2579
- async with dao_wallet_1.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
2580
- await dao_wallet_1.generate_proposal_vote_spend(prop.proposal_id, dao_cat_1_bal, True, action_scope)
2581
- [vote_tx] = action_scope.side_effects.transactions
2582
- vote_sb = vote_tx.spend_bundle
2583
- assert vote_sb is not None
2584
- async with dao_wallet_2.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
2585
- await dao_wallet_2.generate_proposal_vote_spend(prop.proposal_id, dao_cat_1_bal, True, action_scope)
2586
- [vote_tx_2] = action_scope.side_effects.transactions
2587
- vote_2 = vote_tx_2.spend_bundle
2588
- assert vote_2 is not None
2589
- await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, vote_sb.name())
2590
- await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, vote_2.name())
2591
-
2592
- await time_out_assert(20, len, 1, dao_wallet_2.dao_info.proposals_list)
2593
- await time_out_assert(20, int, total_votes, dao_wallet_1.dao_info.proposals_list[0].amount_voted)
2594
- await time_out_assert(20, int, total_votes, dao_wallet_2.dao_info.proposals_list[0].amount_voted)
2595
-
2596
- await full_node_api.process_all_wallet_transactions(wallet_1, timeout=60)
2597
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1, wallet_node_2], timeout=30)
2598
-
2599
- await time_out_assert(20, int, total_votes * 2, dao_wallet_1.dao_info.proposals_list[0].amount_voted)
2600
- await time_out_assert(20, int, total_votes * 2, dao_wallet_2.dao_info.proposals_list[0].amount_voted)
2601
- dao_cat_1_bal = await dao_cat_wallet_1.get_votable_balance(prop.proposal_id)
2602
- dao_cat_2_bal = await dao_cat_wallet_2.get_votable_balance(prop.proposal_id)
2603
-
2604
- assert (dao_cat_1_bal == 100000 and dao_cat_2_bal == 0) or (dao_cat_1_bal == 0 and dao_cat_2_bal == 100000)
2605
-
2606
-
2607
- @pytest.mark.limit_consensus_modes(reason="does not depend on consensus rules")
2608
- @pytest.mark.parametrize(
2609
- "trusted",
2610
- [True, False],
2611
- )
2612
- @pytest.mark.anyio
2613
- @pytest.mark.standard_block_tools
2614
- async def test_dao_cat_exits(
2615
- two_wallet_nodes_services: SimulatorsAndWalletsServices, trusted: bool, self_hostname: str
2616
- ) -> None:
2617
- [full_node_service], wallet_services, _bt = two_wallet_nodes_services
2618
- full_node_api = full_node_service._api
2619
- full_node_server = full_node_api.full_node.server
2620
- wallet_node_0 = wallet_services[0]._node
2621
- server_0 = wallet_node_0.server
2622
- wallet_node_1 = wallet_services[1]._node
2623
- server_1 = wallet_node_1.server
2624
- wallet_0 = wallet_node_0.wallet_state_manager.main_wallet
2625
- wallet_1 = wallet_node_1.wallet_state_manager.main_wallet
2626
- ph_0 = await wallet_0.get_new_puzzlehash()
2627
- ph_1 = await wallet_1.get_new_puzzlehash()
2628
-
2629
- if trusted:
2630
- wallet_node_0.config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()}
2631
- wallet_node_1.config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()}
2632
- else:
2633
- wallet_node_0.config["trusted_peers"] = {}
2634
- wallet_node_1.config["trusted_peers"] = {}
2635
-
2636
- await server_0.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
2637
- await server_1.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
2638
-
2639
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_0))
2640
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_1))
2641
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
2642
-
2643
- initial_funds = calculate_pool_reward(uint32(1)) + calculate_base_farmer_reward(uint32(1))
2644
-
2645
- await time_out_assert(15, wallet_0.get_confirmed_balance, initial_funds)
2646
- await time_out_assert(15, wallet_0.get_unconfirmed_balance, initial_funds)
2647
-
2648
- assert wallet_services[0].rpc_server is not None
2649
- assert wallet_services[1].rpc_server is not None
2650
-
2651
- async with contextlib.AsyncExitStack() as exit_stack:
2652
- client_0 = await exit_stack.enter_async_context(
2653
- WalletRpcClient.create_as_context(
2654
- self_hostname,
2655
- wallet_services[0].rpc_server.listen_port,
2656
- wallet_services[0].root_path,
2657
- wallet_services[0].config,
2658
- )
2659
- )
2660
- await validate_get_routes(client_0, wallet_services[0].rpc_server.rpc_api)
2661
- client_1 = await exit_stack.enter_async_context(
2662
- WalletRpcClient.create_as_context(
2663
- self_hostname,
2664
- wallet_services[1].rpc_server.listen_port,
2665
- wallet_services[1].root_path,
2666
- wallet_services[1].config,
2667
- )
2668
- )
2669
- await validate_get_routes(client_1, wallet_services[1].rpc_server.rpc_api)
2670
-
2671
- cat_amt = uint64(150000)
2672
- dao_rules = DAORules(
2673
- proposal_timelock=uint64(8),
2674
- soft_close_length=uint64(4),
2675
- attendance_required=uint64(1000), # 10%
2676
- pass_percentage=uint64(5100), # 51%
2677
- self_destruct_length=uint64(20),
2678
- oracle_spend_delay=uint64(10),
2679
- proposal_minimum_amount=uint64(1),
2680
- )
2681
- filter_amount = uint64(1)
2682
- fee = uint64(10000)
2683
-
2684
- # create new dao
2685
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2686
- dao_wallet_res_0 = await client_0.create_new_dao_wallet(
2687
- mode="new",
2688
- tx_config=DEFAULT_TX_CONFIG,
2689
- dao_rules=dao_rules.to_json_dict(),
2690
- amount_of_cats=cat_amt,
2691
- filter_amount=filter_amount,
2692
- name="DAO WALLET 0",
2693
- )
2694
- dao_id_0 = dao_wallet_res_0.wallet_id
2695
- cat_wallet_0 = wallet_node_0.wallet_state_manager.wallets[dao_wallet_res_0.cat_wallet_id]
2696
- dao_cat_wallet_0 = wallet_node_0.wallet_state_manager.wallets[dao_wallet_res_0.dao_cat_wallet_id]
2697
- ltxs = await wallet_0.wallet_state_manager.tx_store.get_all_unconfirmed()
2698
- txs: list[TransactionRecord] = []
2699
- for ltx in ltxs:
2700
- tx = await wallet_0.wallet_state_manager.tx_store.get_transaction_record(ltx.name)
2701
- assert tx is not None
2702
- txs.append(tx)
2703
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
2704
- await full_node_api.process_transaction_records(records=txs, timeout=60)
2705
- await full_node_api.process_all_wallet_transactions(wallet_0, 60)
2706
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2707
- await full_node_api.check_transactions_confirmed(wallet_node_0.wallet_state_manager, txs, 60)
2708
- await time_out_assert(60, cat_wallet_0.get_confirmed_balance, cat_amt)
2709
-
2710
- # fund treasury
2711
- xch_funds = uint64(10000000000)
2712
- funding_tx = await client_0.dao_add_funds_to_treasury(dao_id_0, 1, xch_funds, DEFAULT_TX_CONFIG)
2713
- tx = funding_tx.tx
2714
- await full_node_api.wait_transaction_records_entered_mempool(records=[tx], timeout=60)
2715
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
2716
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2717
-
2718
- await rpc_state(20, client_0.dao_get_treasury_balance, [dao_id_0], lambda x: x["balances"]["xch"], xch_funds)
2719
-
2720
- # send cats to lockup
2721
- lockup_0 = await client_0.dao_send_to_lockup(dao_id_0, cat_amt, DEFAULT_TX_CONFIG)
2722
- txs = lockup_0.txs
2723
- await full_node_api.wait_transaction_records_entered_mempool(records=txs, timeout=60)
2724
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
2725
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2726
-
2727
- assert isinstance(dao_cat_wallet_0, DAOCATWallet)
2728
- await time_out_assert(60, dao_cat_wallet_0.get_confirmed_balance, cat_amt)
2729
-
2730
- # create a spend proposal
2731
- additions = [
2732
- {"puzzle_hash": ph_1.hex(), "amount": 1000},
2733
- ]
2734
- proposal = await client_0.dao_create_proposal(
2735
- wallet_id=dao_id_0,
2736
- proposal_type="spend",
2737
- tx_config=DEFAULT_TX_CONFIG,
2738
- additions=additions,
2739
- vote_amount=cat_amt,
2740
- fee=fee,
2741
- )
2742
- tx = proposal.tx
2743
- await full_node_api.wait_transaction_records_entered_mempool(records=[tx], timeout=60)
2744
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
2745
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2746
-
2747
- await time_out_assert_not_none(20, client_0.dao_get_proposals, dao_id_0)
2748
- props = await client_0.dao_get_proposals(dao_id_0)
2749
- proposal_id_hex = props["proposals"][0]["proposal_id"]
2750
-
2751
- # check proposal state and farm enough blocks to pass
2752
- state = await client_0.dao_get_proposal_state(wallet_id=dao_id_0, proposal_id=proposal_id_hex)
2753
- assert state["success"]
2754
- assert state["state"]["passed"]
2755
-
2756
- for _ in range(state["state"]["blocks_needed"] + 1):
2757
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
2758
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2759
-
2760
- state = await client_0.dao_get_proposal_state(wallet_id=dao_id_0, proposal_id=proposal_id_hex)
2761
- assert state["success"]
2762
- assert state["state"]["closable"]
2763
-
2764
- # close the proposal
2765
- close = await client_0.dao_close_proposal(
2766
- wallet_id=dao_id_0, proposal_id=proposal_id_hex, tx_config=DEFAULT_TX_CONFIG, self_destruct=False, fee=fee
2767
- )
2768
- tx = close.tx
2769
- await full_node_api.wait_transaction_records_entered_mempool(records=[tx], timeout=60)
2770
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
2771
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2772
-
2773
- # check proposal is closed
2774
- await rpc_state(20, client_0.dao_get_proposals, [dao_id_0], lambda x: x["proposals"][0]["closed"], True)
2775
-
2776
- # free locked cats from finished proposal
2777
- res = await client_0.dao_free_coins_from_finished_proposals(wallet_id=dao_id_0, tx_config=DEFAULT_TX_CONFIG)
2778
- tx = res.tx
2779
- await full_node_api.wait_transaction_records_entered_mempool(records=[tx], timeout=60)
2780
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
2781
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2782
-
2783
- assert isinstance(dao_cat_wallet_0, DAOCATWallet)
2784
- assert dao_cat_wallet_0.dao_cat_info.locked_coins[0].active_votes == []
2785
-
2786
- exit = await client_0.dao_exit_lockup(dao_id_0, DEFAULT_TX_CONFIG)
2787
- exit_tx = exit.tx
2788
- await full_node_api.wait_transaction_records_entered_mempool(records=[exit_tx], timeout=60)
2789
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
2790
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2791
-
2792
- await time_out_assert(20, dao_cat_wallet_0.get_confirmed_balance, 0)
2793
- await time_out_assert(20, cat_wallet_0.get_confirmed_balance, cat_amt)
2794
-
2795
-
2796
- @pytest.mark.limit_consensus_modes(reason="does not depend on consensus rules")
2797
- @pytest.mark.parametrize(
2798
- "trusted",
2799
- [True, False],
2800
- )
2801
- @pytest.mark.anyio
2802
- async def test_dao_reorgs(self_hostname: str, two_wallet_nodes: OldSimulatorsAndWallets, trusted: bool) -> None:
2803
- full_nodes, wallets, _ = two_wallet_nodes
2804
- full_node_api = full_nodes[0]
2805
- full_node_server = full_node_api.server
2806
- wallet_node_0, server_0 = wallets[0]
2807
- wallet_node_1, server_1 = wallets[1]
2808
- wallet_0 = wallet_node_0.wallet_state_manager.main_wallet
2809
- wallet_1 = wallet_node_1.wallet_state_manager.main_wallet
2810
- ph = await wallet_0.get_new_puzzlehash()
2811
- ph_1 = await wallet_1.get_new_puzzlehash()
2812
-
2813
- if trusted:
2814
- wallet_node_0.config["trusted_peers"] = {
2815
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
2816
- }
2817
- wallet_node_1.config["trusted_peers"] = {
2818
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
2819
- }
2820
- else:
2821
- wallet_node_0.config["trusted_peers"] = {}
2822
- wallet_node_1.config["trusted_peers"] = {}
2823
-
2824
- await server_0.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
2825
- await server_1.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
2826
-
2827
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
2828
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_1))
2829
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
2830
-
2831
- funds = calculate_pool_reward(uint32(1)) + calculate_base_farmer_reward(uint32(1))
2832
-
2833
- await time_out_assert(20, wallet_0.get_confirmed_balance, funds)
2834
- await time_out_assert(20, full_node_api.wallet_is_synced, True, wallet_node_0)
2835
-
2836
- cat_amt = 300000
2837
- dao_rules = DAORules(
2838
- proposal_timelock=uint64(5),
2839
- soft_close_length=uint64(2),
2840
- attendance_required=uint64(1000), # 10%
2841
- pass_percentage=uint64(5100), # 51%
2842
- self_destruct_length=uint64(5),
2843
- oracle_spend_delay=uint64(2),
2844
- proposal_minimum_amount=uint64(101),
2845
- )
2846
-
2847
- async with wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
2848
- dao_wallet_0 = await DAOWallet.create_new_dao_and_wallet(
2849
- wallet_node_0.wallet_state_manager, wallet_0, uint64(cat_amt), dao_rules, action_scope
2850
- )
2851
-
2852
- # Get the full node sim to process the wallet creation spend
2853
- await full_node_api.wait_transaction_records_entered_mempool(
2854
- records=action_scope.side_effects.transactions, timeout=60
2855
- )
2856
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
2857
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2858
-
2859
- await time_out_assert(60, dao_wallet_0.get_confirmed_balance, uint128(1))
2860
-
2861
- # Test Reorg on creation
2862
- height = full_node_api.full_node.blockchain.get_peak_height()
2863
- assert height is not None
2864
- await full_node_api.reorg_from_index_to_new_index(
2865
- ReorgProtocol(uint32(height - 2), uint32(height + 1), puzzle_hash_0, None)
2866
- )
2867
-
2868
- assert dao_wallet_0.dao_info.current_treasury_coin
2869
- await time_out_assert(60, dao_wallet_0.get_confirmed_balance, uint128(1))
2870
-
2871
- # get the cat wallets
2872
- cat_wallet_0 = dao_wallet_0.wallet_state_manager.wallets[dao_wallet_0.dao_info.cat_wallet_id]
2873
- await time_out_assert(10, cat_wallet_0.get_confirmed_balance, cat_amt)
2874
-
2875
- # get the dao_cat wallet
2876
- dao_cat_wallet_0 = dao_wallet_0.wallet_state_manager.wallets[dao_wallet_0.dao_info.dao_cat_wallet_id]
2877
-
2878
- treasury_id = dao_wallet_0.dao_info.treasury_id
2879
-
2880
- # Create the other user's wallet from the treasury id
2881
- dao_wallet_1 = await DAOWallet.create_new_dao_wallet_for_existing_dao(
2882
- wallet_node_1.wallet_state_manager, wallet_1, treasury_id
2883
- )
2884
- assert dao_wallet_1.dao_info.treasury_id == treasury_id
2885
-
2886
- # Create funding spends for xch
2887
- xch_funds = uint64(500000)
2888
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
2889
- await dao_wallet_0.create_add_funds_to_treasury_spend(
2890
- xch_funds,
2891
- action_scope,
2892
- )
2893
- await full_node_api.wait_transaction_records_entered_mempool(
2894
- records=action_scope.side_effects.transactions, timeout=60
2895
- )
2896
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
2897
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2898
-
2899
- # Check that the funding spend is recognized by both dao wallets
2900
- await time_out_assert(20, dao_wallet_0.get_balance_by_asset_type, xch_funds)
2901
- await time_out_assert(20, dao_wallet_1.get_balance_by_asset_type, xch_funds)
2902
-
2903
- # Reorg funding spend
2904
- height = full_node_api.full_node.blockchain.get_peak_height()
2905
- assert height is not None
2906
- await full_node_api.reorg_from_index_to_new_index(
2907
- ReorgProtocol(uint32(height - 1), uint32(height + 1), puzzle_hash_0, None)
2908
- )
2909
- await time_out_assert(20, dao_wallet_0.get_balance_by_asset_type, xch_funds)
2910
- await time_out_assert(20, dao_wallet_1.get_balance_by_asset_type, xch_funds)
2911
-
2912
- # Send some dao_cats to wallet_1
2913
- # Get the cat wallets for wallet_1
2914
- cat_wallet_1 = dao_wallet_1.wallet_state_manager.wallets[dao_wallet_1.dao_info.cat_wallet_id]
2915
- dao_cat_wallet_1 = dao_wallet_1.wallet_state_manager.wallets[dao_wallet_1.dao_info.dao_cat_wallet_id]
2916
- assert cat_wallet_1
2917
- assert dao_cat_wallet_1
2918
-
2919
- async with cat_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
2920
- await cat_wallet_0.generate_signed_transaction(
2921
- [100000],
2922
- [ph_1],
2923
- action_scope,
2924
- )
2925
- await full_node_api.wait_transaction_records_entered_mempool(
2926
- records=action_scope.side_effects.transactions, timeout=60
2927
- )
2928
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
2929
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2930
-
2931
- cat_wallet_1 = dao_wallet_1.wallet_state_manager.wallets[dao_wallet_1.dao_info.cat_wallet_id]
2932
- await time_out_assert(20, cat_wallet_1.get_confirmed_balance, 100000)
2933
-
2934
- # Create dao cats for voting
2935
- dao_cat_0_bal = await dao_cat_wallet_0.get_votable_balance()
2936
- assert dao_cat_0_bal == 200000
2937
- async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
2938
- await dao_cat_wallet_0.enter_dao_cat_voting_mode(dao_cat_0_bal, action_scope)
2939
- await full_node_api.wait_transaction_records_entered_mempool(
2940
- records=action_scope.side_effects.transactions, timeout=60
2941
- )
2942
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
2943
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2944
-
2945
- # Create a proposal for xch spend
2946
- recipient_puzzle_hash = await wallet_0.get_new_puzzlehash()
2947
- proposal_amount = uint64(10000)
2948
- xch_proposal_inner = generate_simple_proposal_innerpuz(
2949
- treasury_id,
2950
- [recipient_puzzle_hash],
2951
- [proposal_amount],
2952
- [None],
2953
- )
2954
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
2955
- await dao_wallet_0.generate_new_proposal(xch_proposal_inner, action_scope, dao_cat_0_bal, uint64(1000))
2956
- await full_node_api.wait_transaction_records_entered_mempool(
2957
- records=action_scope.side_effects.transactions, timeout=60
2958
- )
2959
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
2960
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2961
-
2962
- # Check the proposal is saved
2963
- assert len(dao_wallet_0.dao_info.proposals_list) == 1
2964
- assert dao_wallet_0.dao_info.proposals_list[0].amount_voted == dao_cat_0_bal
2965
- assert dao_wallet_0.dao_info.proposals_list[0].timer_coin is not None
2966
-
2967
- # Reorg proposal creation
2968
- height = full_node_api.full_node.blockchain.get_peak_height()
2969
- assert height is not None
2970
- await full_node_api.reorg_from_index_to_new_index(
2971
- ReorgProtocol(uint32(height - 1), uint32(height + 1), puzzle_hash_0, None)
2972
- )
2973
- assert len(dao_wallet_0.dao_info.proposals_list) == 1
2974
- assert dao_wallet_0.dao_info.proposals_list[0].amount_voted == dao_cat_0_bal
2975
- assert dao_wallet_0.dao_info.proposals_list[0].timer_coin is not None
2976
-
2977
- # Check that wallet_1 also finds and saved the proposal
2978
- assert len(dao_wallet_1.dao_info.proposals_list) == 1
2979
- prop = dao_wallet_1.dao_info.proposals_list[0]
2980
-
2981
- total_votes = dao_cat_0_bal
2982
-
2983
- assert dao_wallet_0.dao_info.proposals_list[0].amount_voted == total_votes
2984
- assert dao_wallet_0.dao_info.proposals_list[0].yes_votes == total_votes
2985
- assert dao_wallet_1.dao_info.proposals_list[0].amount_voted == total_votes
2986
- assert dao_wallet_1.dao_info.proposals_list[0].yes_votes == total_votes
2987
-
2988
- # Create votable dao cats and add a new vote
2989
- dao_cat_1_bal = await dao_cat_wallet_1.get_votable_balance()
2990
- async with dao_cat_wallet_1.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
2991
- await dao_cat_wallet_1.enter_dao_cat_voting_mode(dao_cat_1_bal, action_scope)
2992
- await full_node_api.wait_transaction_records_entered_mempool(
2993
- records=action_scope.side_effects.transactions, timeout=60
2994
- )
2995
- await full_node_api.process_all_wallet_transactions(wallet_1, timeout=60)
2996
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
2997
-
2998
- async with dao_cat_wallet_1.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
2999
- await dao_wallet_1.generate_proposal_vote_spend(prop.proposal_id, dao_cat_1_bal, True, action_scope)
3000
- await full_node_api.wait_transaction_records_entered_mempool(
3001
- records=action_scope.side_effects.transactions, timeout=60
3002
- )
3003
- await full_node_api.process_all_wallet_transactions(wallet_1, timeout=60)
3004
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
3005
-
3006
- assert dao_wallet_0.dao_info.proposals_list[0].amount_voted == dao_cat_0_bal + dao_cat_1_bal
3007
- assert dao_wallet_0.dao_info.proposals_list[0].yes_votes == dao_cat_0_bal + dao_cat_1_bal
3008
- assert dao_wallet_1.dao_info.proposals_list[0].amount_voted == dao_cat_0_bal + dao_cat_1_bal
3009
- assert dao_wallet_1.dao_info.proposals_list[0].yes_votes == dao_cat_0_bal + dao_cat_1_bal
3010
-
3011
- # Reorg on vote spend
3012
- height = full_node_api.full_node.blockchain.get_peak_height()
3013
- assert height is not None
3014
- await full_node_api.reorg_from_index_to_new_index(
3015
- ReorgProtocol(uint32(height - 1), uint32(height + 1), puzzle_hash_0, None)
3016
- )
3017
- assert dao_wallet_0.dao_info.proposals_list[0].amount_voted == dao_cat_0_bal + dao_cat_1_bal
3018
- assert dao_wallet_0.dao_info.proposals_list[0].yes_votes == dao_cat_0_bal + dao_cat_1_bal
3019
- assert dao_wallet_1.dao_info.proposals_list[0].amount_voted == dao_cat_0_bal + dao_cat_1_bal
3020
- assert dao_wallet_1.dao_info.proposals_list[0].yes_votes == dao_cat_0_bal + dao_cat_1_bal
3021
-
3022
- # Close proposal
3023
- for i in range(5):
3024
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
3025
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
3026
-
3027
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
3028
- await dao_wallet_0.create_proposal_close_spend(prop.proposal_id, action_scope, fee=uint64(100))
3029
- await full_node_api.wait_transaction_records_entered_mempool(
3030
- records=action_scope.side_effects.transactions, timeout=60
3031
- )
3032
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
3033
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
3034
-
3035
- await time_out_assert(20, get_proposal_state, (True, True), *[dao_wallet_0, 0])
3036
- await time_out_assert(20, get_proposal_state, (True, True), *[dao_wallet_1, 0])
3037
-
3038
- # Reorg closed proposal
3039
- height = full_node_api.full_node.blockchain.get_peak_height()
3040
- assert height is not None
3041
- await full_node_api.reorg_from_index_to_new_index(
3042
- ReorgProtocol(uint32(height - 1), uint32(height + 1), puzzle_hash_0, None)
3043
- )
3044
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
3045
- await time_out_assert(20, get_proposal_state, (True, True), *[dao_wallet_0, 0])
3046
- await time_out_assert(20, get_proposal_state, (True, True), *[dao_wallet_1, 0])
3047
-
3048
-
3049
- @pytest.mark.limit_consensus_modes(reason="does not depend on consensus rules")
3050
- @pytest.mark.parametrize(
3051
- "trusted",
3052
- [True, False],
3053
- )
3054
- @pytest.mark.anyio
3055
- async def test_dao_votes(self_hostname: str, three_wallet_nodes: OldSimulatorsAndWallets, trusted: bool) -> None:
3056
- full_nodes, wallets, _ = three_wallet_nodes
3057
- full_node_api = full_nodes[0]
3058
- full_node_server = full_node_api.server
3059
- wallet_node_0, server_0 = wallets[0]
3060
- wallet_node_1, server_1 = wallets[1]
3061
- wallet_node_2, server_2 = wallets[2]
3062
- wallet_0 = wallet_node_0.wallet_state_manager.main_wallet
3063
- wallet_1 = wallet_node_1.wallet_state_manager.main_wallet
3064
- wallet_2 = wallet_node_2.wallet_state_manager.main_wallet
3065
- ph_0 = await wallet_0.get_new_puzzlehash()
3066
- ph_1 = await wallet_1.get_new_puzzlehash()
3067
- ph_2 = await wallet_2.get_new_puzzlehash()
3068
-
3069
- if trusted:
3070
- wallet_node_0.config["trusted_peers"] = {
3071
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
3072
- }
3073
- wallet_node_1.config["trusted_peers"] = {
3074
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
3075
- }
3076
- wallet_node_2.config["trusted_peers"] = {
3077
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
3078
- }
3079
- else:
3080
- wallet_node_0.config["trusted_peers"] = {}
3081
- wallet_node_1.config["trusted_peers"] = {}
3082
- wallet_node_2.config["trusted_peers"] = {}
3083
-
3084
- await server_0.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
3085
- await server_1.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
3086
- await server_2.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
3087
-
3088
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_0))
3089
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_1))
3090
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_2))
3091
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
3092
-
3093
- funds = calculate_pool_reward(uint32(1)) + calculate_base_farmer_reward(uint32(1))
3094
-
3095
- await time_out_assert(20, wallet_0.get_confirmed_balance, funds)
3096
- await time_out_assert(20, full_node_api.wallet_is_synced, True, wallet_node_0)
3097
-
3098
- # set a standard fee amount to use in all txns
3099
- base_fee = uint64(100)
3100
-
3101
- # set the cat issuance and DAO rules
3102
- cat_issuance = 300000
3103
- proposal_min_amt = uint64(101)
3104
- dao_rules = DAORules(
3105
- proposal_timelock=uint64(10),
3106
- soft_close_length=uint64(5),
3107
- attendance_required=uint64(190000),
3108
- pass_percentage=uint64(5100), # 51%
3109
- self_destruct_length=uint64(20),
3110
- oracle_spend_delay=uint64(10),
3111
- proposal_minimum_amount=proposal_min_amt,
3112
- )
3113
-
3114
- async with wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
3115
- dao_wallet_0 = await DAOWallet.create_new_dao_and_wallet(
3116
- wallet_node_0.wallet_state_manager,
3117
- wallet_0,
3118
- uint64(cat_issuance),
3119
- dao_rules,
3120
- action_scope,
3121
- )
3122
-
3123
- await full_node_api.wait_transaction_records_entered_mempool(
3124
- records=action_scope.side_effects.transactions, timeout=60
3125
- )
3126
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
3127
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
3128
-
3129
- cat_wallet_0 = dao_wallet_0.wallet_state_manager.wallets[dao_wallet_0.dao_info.cat_wallet_id]
3130
- dao_cat_wallet_0 = dao_wallet_0.wallet_state_manager.wallets[dao_wallet_0.dao_info.dao_cat_wallet_id]
3131
- await time_out_assert(10, cat_wallet_0.get_confirmed_balance, cat_issuance)
3132
- assert dao_cat_wallet_0
3133
-
3134
- treasury_id = dao_wallet_0.dao_info.treasury_id
3135
-
3136
- dc_1 = uint64(100000)
3137
- dc_2 = uint64(50000)
3138
- dc_3 = uint64(30000)
3139
- dc_4 = uint64(20000)
3140
- dc_5 = uint64(10000)
3141
-
3142
- # Lockup voting cats for all wallets
3143
- async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
3144
- await dao_cat_wallet_0.enter_dao_cat_voting_mode(dc_1, action_scope, fee=base_fee)
3145
- await full_node_api.wait_transaction_records_entered_mempool(
3146
- records=action_scope.side_effects.transactions, timeout=60
3147
- )
3148
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
3149
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30)
3150
-
3151
- async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
3152
- await dao_cat_wallet_0.enter_dao_cat_voting_mode(dc_2, action_scope, fee=base_fee)
3153
- await full_node_api.wait_transaction_records_entered_mempool(
3154
- records=action_scope.side_effects.transactions, timeout=60
3155
- )
3156
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
3157
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30)
3158
-
3159
- async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
3160
- await dao_cat_wallet_0.enter_dao_cat_voting_mode(dc_3, action_scope, fee=base_fee)
3161
- await full_node_api.wait_transaction_records_entered_mempool(
3162
- records=action_scope.side_effects.transactions, timeout=60
3163
- )
3164
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
3165
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30)
3166
-
3167
- async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
3168
- await dao_cat_wallet_0.enter_dao_cat_voting_mode(dc_4, action_scope, fee=base_fee)
3169
- await full_node_api.wait_transaction_records_entered_mempool(
3170
- records=action_scope.side_effects.transactions, timeout=60
3171
- )
3172
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
3173
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30)
3174
-
3175
- async with dao_cat_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
3176
- await dao_cat_wallet_0.enter_dao_cat_voting_mode(dc_5, action_scope, fee=base_fee)
3177
- await full_node_api.wait_transaction_records_entered_mempool(
3178
- records=action_scope.side_effects.transactions, timeout=60
3179
- )
3180
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
3181
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30)
3182
-
3183
- await time_out_assert(10, dao_cat_wallet_0.get_confirmed_balance, dc_1 + dc_2 + dc_3 + dc_4 + dc_5)
3184
-
3185
- # Create funding spend so the treasury holds some XCH
3186
- xch_funds = uint64(500000)
3187
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
3188
- await dao_wallet_0.create_add_funds_to_treasury_spend(xch_funds, action_scope)
3189
- await full_node_api.wait_transaction_records_entered_mempool(
3190
- records=action_scope.side_effects.transactions, timeout=60
3191
- )
3192
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
3193
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30)
3194
-
3195
- # Check that the funding spend is recognized by all wallets
3196
- await time_out_assert(10, dao_wallet_0.get_balance_by_asset_type, xch_funds)
3197
-
3198
- # Create Proposals
3199
- recipient_puzzle_hash = await wallet_2.get_new_puzzlehash()
3200
- proposal_amount_1 = uint64(9998)
3201
- xch_proposal_inner = generate_simple_proposal_innerpuz(
3202
- treasury_id,
3203
- [recipient_puzzle_hash],
3204
- [proposal_amount_1],
3205
- [None],
3206
- )
3207
-
3208
- vote_1 = uint64(120000)
3209
- vote_2 = uint64(150000)
3210
-
3211
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
3212
- await dao_wallet_0.generate_new_proposal(xch_proposal_inner, action_scope, vote_1, fee=base_fee)
3213
- await full_node_api.wait_transaction_records_entered_mempool(
3214
- records=action_scope.side_effects.transactions, timeout=60
3215
- )
3216
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
3217
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30)
3218
-
3219
- assert len(dao_wallet_0.dao_info.proposals_list) == 1
3220
- assert dao_wallet_0.dao_info.proposals_list[0].amount_voted == vote_1
3221
- assert dao_wallet_0.dao_info.proposals_list[0].timer_coin is not None
3222
- prop_0 = dao_wallet_0.dao_info.proposals_list[0]
3223
-
3224
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
3225
- await dao_wallet_0.generate_new_proposal(xch_proposal_inner, action_scope, vote_2, fee=base_fee)
3226
- await full_node_api.wait_transaction_records_entered_mempool(
3227
- records=action_scope.side_effects.transactions, timeout=60
3228
- )
3229
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
3230
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30)
3231
-
3232
- assert len(dao_wallet_0.dao_info.proposals_list) == 2
3233
- assert dao_wallet_0.dao_info.proposals_list[1].amount_voted == vote_2
3234
-
3235
- vote_3 = uint64(30000)
3236
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
3237
- await dao_wallet_0.generate_proposal_vote_spend(prop_0.proposal_id, vote_3, True, action_scope)
3238
- await full_node_api.wait_transaction_records_entered_mempool(
3239
- records=action_scope.side_effects.transactions, timeout=60
3240
- )
3241
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
3242
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30)
3243
-
3244
- assert dao_wallet_0.dao_info.proposals_list[0].amount_voted == vote_1 + vote_3
3245
-
3246
- vote_4 = uint64(60000)
3247
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
3248
- await dao_wallet_0.generate_proposal_vote_spend(prop_0.proposal_id, vote_4, True, action_scope)
3249
- await full_node_api.wait_transaction_records_entered_mempool(
3250
- records=action_scope.side_effects.transactions, timeout=60
3251
- )
3252
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
3253
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30)
3254
-
3255
- assert dao_wallet_0.dao_info.proposals_list[0].amount_voted == vote_1 + vote_3 + vote_4
3256
-
3257
- vote_5 = uint64(1)
3258
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
3259
- await dao_wallet_0.generate_new_proposal(xch_proposal_inner, action_scope, vote_5, fee=base_fee)
3260
- await full_node_api.wait_transaction_records_entered_mempool(
3261
- records=action_scope.side_effects.transactions, timeout=60
3262
- )
3263
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
3264
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30)
3265
-
3266
- assert len(dao_wallet_0.dao_info.proposals_list) == 3
3267
- assert dao_wallet_0.dao_info.proposals_list[2].amount_voted == vote_5
3268
- prop_2 = dao_wallet_0.dao_info.proposals_list[2]
3269
-
3270
- vote_6 = uint64(20000)
3271
- for i in range(10):
3272
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
3273
- await dao_wallet_0.generate_proposal_vote_spend(prop_2.proposal_id, vote_6, True, action_scope)
3274
- await full_node_api.wait_transaction_records_entered_mempool(
3275
- records=action_scope.side_effects.transactions, timeout=60
3276
- )
3277
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
3278
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30)
3279
-
3280
- assert dao_wallet_0.dao_info.proposals_list[2].amount_voted == 200001
3281
-
3282
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
3283
- await dao_wallet_0.create_proposal_close_spend(prop_0.proposal_id, action_scope)
3284
- await full_node_api.wait_transaction_records_entered_mempool(
3285
- records=action_scope.side_effects.transactions, timeout=60
3286
- )
3287
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
3288
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30)
3289
-
3290
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
3291
- await dao_wallet_0.generate_new_proposal(xch_proposal_inner, action_scope, fee=base_fee)
3292
- await full_node_api.wait_transaction_records_entered_mempool(
3293
- records=action_scope.side_effects.transactions, timeout=60
3294
- )
3295
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
3296
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30)
3297
-
3298
- assert dao_wallet_0.dao_info.proposals_list[3].amount_voted == 210000
3299
-
3300
-
3301
- @pytest.mark.limit_consensus_modes(reason="does not depend on consensus rules")
3302
- @pytest.mark.parametrize(
3303
- "trusted",
3304
- [True, False],
3305
- )
3306
- @pytest.mark.anyio
3307
- async def test_dao_resync(self_hostname: str, two_wallet_nodes: OldSimulatorsAndWallets, trusted: bool) -> None:
3308
- full_nodes, wallets, _ = two_wallet_nodes
3309
- full_node_api = full_nodes[0]
3310
- full_node_server = full_node_api.server
3311
- wallet_node_0, server_0 = wallets[0]
3312
- wallet_node_1, server_1 = wallets[1]
3313
- wallet_api_0 = WalletRpcApi(wallet_node_0)
3314
- wallet_api_1 = WalletRpcApi(wallet_node_1)
3315
- wallet_0 = wallet_node_0.wallet_state_manager.main_wallet
3316
- wallet_1 = wallet_node_1.wallet_state_manager.main_wallet
3317
- ph = await wallet_0.get_new_puzzlehash()
3318
- ph_1 = await wallet_1.get_new_puzzlehash()
3319
-
3320
- if trusted:
3321
- wallet_node_0.config["trusted_peers"] = {
3322
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
3323
- }
3324
- wallet_node_1.config["trusted_peers"] = {
3325
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
3326
- }
3327
- else:
3328
- wallet_node_0.config["trusted_peers"] = {}
3329
- wallet_node_1.config["trusted_peers"] = {}
3330
-
3331
- await server_0.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
3332
- await server_1.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
3333
-
3334
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
3335
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph_1))
3336
-
3337
- funds = calculate_pool_reward(uint32(1)) + calculate_base_farmer_reward(uint32(1))
3338
-
3339
- await time_out_assert(20, wallet_0.get_confirmed_balance, funds)
3340
- await time_out_assert(20, full_node_api.wallet_is_synced, True, wallet_node_0)
3341
-
3342
- cat_amt = 2000
3343
- dao_rules = DAORules(
3344
- proposal_timelock=uint64(10),
3345
- soft_close_length=uint64(5),
3346
- attendance_required=uint64(1000), # 10%
3347
- pass_percentage=uint64(5100), # 51%
3348
- self_destruct_length=uint64(20),
3349
- oracle_spend_delay=uint64(10),
3350
- proposal_minimum_amount=uint64(1),
3351
- )
3352
-
3353
- fee = uint64(10)
3354
- fee_for_cat = uint64(20)
3355
- async with wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
3356
- dao_wallet_0 = await DAOWallet.create_new_dao_and_wallet(
3357
- wallet_node_0.wallet_state_manager,
3358
- wallet_0,
3359
- uint64(cat_amt * 2),
3360
- dao_rules,
3361
- action_scope=action_scope,
3362
- fee=fee,
3363
- fee_for_cat=fee_for_cat,
3364
- )
3365
-
3366
- await full_node_api.wait_transaction_records_entered_mempool(
3367
- records=action_scope.side_effects.transactions, timeout=60
3368
- )
3369
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
3370
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
3371
-
3372
- treasury_id = dao_wallet_0.dao_info.treasury_id
3373
-
3374
- # get the cat wallets
3375
- cat_wallet_0 = dao_wallet_0.wallet_state_manager.wallets[dao_wallet_0.dao_info.cat_wallet_id]
3376
- # dao_cat_wallet_0 = dao_wallet_0.wallet_state_manager.wallets[dao_wallet_0.dao_info.dao_cat_wallet_id]
3377
-
3378
- # Create the other user's wallet from the treasury id
3379
- dao_wallet_1 = await DAOWallet.create_new_dao_wallet_for_existing_dao(
3380
- wallet_node_1.wallet_state_manager, wallet_1, treasury_id
3381
- )
3382
- assert dao_wallet_0.dao_info.treasury_id == dao_wallet_1.dao_info.treasury_id
3383
-
3384
- # Get the cat wallets for wallet_1
3385
- cat_wallet_1 = dao_wallet_1.wallet_state_manager.wallets[dao_wallet_1.dao_info.cat_wallet_id]
3386
-
3387
- # Send some cats to the dao_cat lockup
3388
- dao_cat_amt = uint64(100)
3389
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
3390
- await dao_wallet_0.enter_dao_cat_voting_mode(dao_cat_amt, action_scope)
3391
-
3392
- await full_node_api.wait_transaction_records_entered_mempool(
3393
- records=action_scope.side_effects.transactions, timeout=60
3394
- )
3395
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
3396
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30)
3397
-
3398
- # send some cats from wallet_0 to wallet_1 so we can test voting
3399
- async with cat_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
3400
- await cat_wallet_0.generate_signed_transaction([cat_amt], [ph_1], action_scope)
3401
-
3402
- await full_node_api.wait_transaction_records_entered_mempool(
3403
- records=action_scope.side_effects.transactions, timeout=60
3404
- )
3405
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
3406
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=30)
3407
-
3408
- await time_out_assert(10, cat_wallet_1.get_confirmed_balance, cat_amt)
3409
-
3410
- recipient_puzzle_hash = await wallet_1.get_new_puzzlehash()
3411
- proposal_amount_1 = uint64(9998)
3412
- xch_proposal_inner = generate_simple_proposal_innerpuz(
3413
- treasury_id,
3414
- [recipient_puzzle_hash],
3415
- [proposal_amount_1],
3416
- [None],
3417
- )
3418
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
3419
- await dao_wallet_0.generate_new_proposal(xch_proposal_inner, action_scope, uint64(10))
3420
- await full_node_api.wait_transaction_records_entered_mempool(
3421
- records=action_scope.side_effects.transactions, timeout=60
3422
- )
3423
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
3424
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
3425
-
3426
- # make another proposal spending all the dao_cats
3427
- xch_proposal_inner = generate_simple_proposal_innerpuz(
3428
- treasury_id,
3429
- [recipient_puzzle_hash],
3430
- [proposal_amount_1],
3431
- [None],
3432
- )
3433
- async with dao_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
3434
- await dao_wallet_0.generate_new_proposal(xch_proposal_inner, action_scope)
3435
- await full_node_api.wait_transaction_records_entered_mempool(
3436
- records=action_scope.side_effects.transactions, timeout=60
3437
- )
3438
- await full_node_api.process_all_wallet_transactions(wallet_0, timeout=60)
3439
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1], timeout=30)
3440
-
3441
- # set flag to reset wallet sync data on start
3442
- await wallet_api_0.set_wallet_resync_on_startup({"enable": True})
3443
- fingerprint_0 = wallet_node_0.logged_in_fingerprint
3444
- await wallet_api_1.set_wallet_resync_on_startup({"enable": True})
3445
- fingerprint_1 = wallet_node_1.logged_in_fingerprint
3446
- # Delete tx records
3447
- await wallet_node_0.wallet_state_manager.tx_store.rollback_to_block(0)
3448
- wallet_node_0._close()
3449
- await wallet_node_0._await_closed()
3450
- wallet_node_1._close()
3451
- await wallet_node_1._await_closed()
3452
- wallet_node_0.config["database_path"] = "wallet/db/blockchain_wallet_v2_test_1_CHALLENGE_KEY.sqlite"
3453
- wallet_node_1.config["database_path"] = "wallet/db/blockchain_wallet_v2_test_2_CHALLENGE_KEY.sqlite"
3454
- # Start resync
3455
- await wallet_node_0._start_with_fingerprint(fingerprint_0)
3456
- await wallet_node_1._start_with_fingerprint(fingerprint_1)
3457
- await server_0.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
3458
- await server_1.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
3459
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
3460
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=20)
3461
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_1, timeout=20)
3462
- wallet_0 = wallet_node_0.wallet_state_manager.main_wallet
3463
-
3464
- assert len(await wallet_node_0.wallet_state_manager.get_all_wallet_info_entries()) == 1
3465
-
3466
- new_dao_wallet = await DAOWallet.create_new_dao_wallet_for_existing_dao(
3467
- wallet_node_0.wallet_state_manager,
3468
- wallet_0,
3469
- treasury_id,
3470
- )
3471
-
3472
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
3473
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=20)
3474
- assert len(await wallet_node_0.wallet_state_manager.get_all_wallet_info_entries()) == 4
3475
- new_cat_wallet = new_dao_wallet.wallet_state_manager.wallets[new_dao_wallet.dao_info.cat_wallet_id]
3476
- new_dao_cat_wallet = new_dao_wallet.wallet_state_manager.wallets[new_dao_wallet.dao_info.dao_cat_wallet_id]
3477
-
3478
- await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(puzzle_hash_0))
3479
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_0, timeout=20)
3480
-
3481
- # Check the new wallets have the right balances
3482
- await time_out_assert(20, new_cat_wallet.get_confirmed_balance, cat_amt - dao_cat_amt)
3483
- await time_out_assert(20, new_dao_cat_wallet.get_confirmed_balance, dao_cat_amt)
3484
-
3485
- # Check the proposals are found and accurate
3486
- assert len(new_dao_wallet.dao_info.proposals_list) == 2
3487
- assert new_dao_wallet.dao_info.proposals_list[0].yes_votes == 10
3488
- assert new_dao_wallet.dao_info.proposals_list[1].yes_votes == 100