chia-blockchain 2.4.4__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 (1028) hide show
  1. chia/__init__.py +10 -0
  2. chia/__main__.py +5 -0
  3. chia/_tests/README.md +53 -0
  4. chia/_tests/__init__.py +0 -0
  5. chia/_tests/blockchain/__init__.py +0 -0
  6. chia/_tests/blockchain/blockchain_test_utils.py +197 -0
  7. chia/_tests/blockchain/config.py +4 -0
  8. chia/_tests/blockchain/test_augmented_chain.py +147 -0
  9. chia/_tests/blockchain/test_blockchain.py +4100 -0
  10. chia/_tests/blockchain/test_blockchain_transactions.py +1050 -0
  11. chia/_tests/blockchain/test_build_chains.py +61 -0
  12. chia/_tests/blockchain/test_get_block_generator.py +72 -0
  13. chia/_tests/blockchain/test_lookup_fork_chain.py +195 -0
  14. chia/_tests/build-init-files.py +93 -0
  15. chia/_tests/build-job-matrix.py +204 -0
  16. chia/_tests/check_pytest_monitor_output.py +34 -0
  17. chia/_tests/check_sql_statements.py +73 -0
  18. chia/_tests/chia-start-sim +42 -0
  19. chia/_tests/clvm/__init__.py +0 -0
  20. chia/_tests/clvm/benchmark_costs.py +23 -0
  21. chia/_tests/clvm/coin_store.py +147 -0
  22. chia/_tests/clvm/test_chialisp_deserialization.py +101 -0
  23. chia/_tests/clvm/test_clvm_step.py +37 -0
  24. chia/_tests/clvm/test_condition_codes.py +13 -0
  25. chia/_tests/clvm/test_curry_and_treehash.py +57 -0
  26. chia/_tests/clvm/test_program.py +150 -0
  27. chia/_tests/clvm/test_puzzle_compression.py +144 -0
  28. chia/_tests/clvm/test_puzzle_drivers.py +45 -0
  29. chia/_tests/clvm/test_puzzles.py +247 -0
  30. chia/_tests/clvm/test_singletons.py +540 -0
  31. chia/_tests/clvm/test_spend_sim.py +181 -0
  32. chia/_tests/cmds/__init__.py +0 -0
  33. chia/_tests/cmds/cmd_test_utils.py +472 -0
  34. chia/_tests/cmds/config.py +3 -0
  35. chia/_tests/cmds/conftest.py +23 -0
  36. chia/_tests/cmds/test_click_types.py +195 -0
  37. chia/_tests/cmds/test_cmd_framework.py +400 -0
  38. chia/_tests/cmds/test_cmds_util.py +97 -0
  39. chia/_tests/cmds/test_daemon.py +92 -0
  40. chia/_tests/cmds/test_farm_cmd.py +67 -0
  41. chia/_tests/cmds/test_show.py +116 -0
  42. chia/_tests/cmds/test_sim.py +207 -0
  43. chia/_tests/cmds/test_timelock_args.py +75 -0
  44. chia/_tests/cmds/test_tx_config_args.py +153 -0
  45. chia/_tests/cmds/testing_classes.py +59 -0
  46. chia/_tests/cmds/wallet/__init__.py +0 -0
  47. chia/_tests/cmds/wallet/test_coins.py +195 -0
  48. chia/_tests/cmds/wallet/test_consts.py +47 -0
  49. chia/_tests/cmds/wallet/test_dao.py +565 -0
  50. chia/_tests/cmds/wallet/test_did.py +403 -0
  51. chia/_tests/cmds/wallet/test_nft.py +470 -0
  52. chia/_tests/cmds/wallet/test_notifications.py +124 -0
  53. chia/_tests/cmds/wallet/test_offer.toffer +1 -0
  54. chia/_tests/cmds/wallet/test_tx_decorators.py +27 -0
  55. chia/_tests/cmds/wallet/test_vcs.py +376 -0
  56. chia/_tests/cmds/wallet/test_wallet.py +1126 -0
  57. chia/_tests/cmds/wallet/test_wallet_check.py +111 -0
  58. chia/_tests/conftest.py +1304 -0
  59. chia/_tests/connection_utils.py +124 -0
  60. chia/_tests/core/__init__.py +0 -0
  61. chia/_tests/core/cmds/__init__.py +0 -0
  62. chia/_tests/core/cmds/test_beta.py +382 -0
  63. chia/_tests/core/cmds/test_keys.py +1734 -0
  64. chia/_tests/core/cmds/test_wallet.py +126 -0
  65. chia/_tests/core/config.py +3 -0
  66. chia/_tests/core/consensus/__init__.py +0 -0
  67. chia/_tests/core/consensus/test_block_creation.py +56 -0
  68. chia/_tests/core/consensus/test_pot_iterations.py +117 -0
  69. chia/_tests/core/custom_types/__init__.py +0 -0
  70. chia/_tests/core/custom_types/test_coin.py +109 -0
  71. chia/_tests/core/custom_types/test_proof_of_space.py +144 -0
  72. chia/_tests/core/custom_types/test_spend_bundle.py +71 -0
  73. chia/_tests/core/daemon/__init__.py +0 -0
  74. chia/_tests/core/daemon/config.py +4 -0
  75. chia/_tests/core/daemon/test_daemon.py +2128 -0
  76. chia/_tests/core/daemon/test_daemon_register.py +109 -0
  77. chia/_tests/core/daemon/test_keychain_proxy.py +100 -0
  78. chia/_tests/core/data_layer/__init__.py +0 -0
  79. chia/_tests/core/data_layer/config.py +5 -0
  80. chia/_tests/core/data_layer/conftest.py +105 -0
  81. chia/_tests/core/data_layer/test_data_cli.py +57 -0
  82. chia/_tests/core/data_layer/test_data_layer.py +83 -0
  83. chia/_tests/core/data_layer/test_data_layer_util.py +219 -0
  84. chia/_tests/core/data_layer/test_data_rpc.py +3865 -0
  85. chia/_tests/core/data_layer/test_data_store.py +2423 -0
  86. chia/_tests/core/data_layer/test_data_store_schema.py +381 -0
  87. chia/_tests/core/data_layer/test_plugin.py +91 -0
  88. chia/_tests/core/data_layer/util.py +232 -0
  89. chia/_tests/core/farmer/__init__.py +0 -0
  90. chia/_tests/core/farmer/config.py +3 -0
  91. chia/_tests/core/farmer/test_farmer_api.py +101 -0
  92. chia/_tests/core/full_node/__init__.py +0 -0
  93. chia/_tests/core/full_node/config.py +4 -0
  94. chia/_tests/core/full_node/dos/__init__.py +0 -0
  95. chia/_tests/core/full_node/dos/config.py +3 -0
  96. chia/_tests/core/full_node/full_sync/__init__.py +0 -0
  97. chia/_tests/core/full_node/full_sync/config.py +4 -0
  98. chia/_tests/core/full_node/full_sync/test_full_sync.py +448 -0
  99. chia/_tests/core/full_node/ram_db.py +27 -0
  100. chia/_tests/core/full_node/stores/__init__.py +0 -0
  101. chia/_tests/core/full_node/stores/config.py +4 -0
  102. chia/_tests/core/full_node/stores/test_block_store.py +488 -0
  103. chia/_tests/core/full_node/stores/test_coin_store.py +888 -0
  104. chia/_tests/core/full_node/stores/test_full_node_store.py +1215 -0
  105. chia/_tests/core/full_node/stores/test_hint_store.py +230 -0
  106. chia/_tests/core/full_node/stores/test_sync_store.py +135 -0
  107. chia/_tests/core/full_node/test_address_manager.py +588 -0
  108. chia/_tests/core/full_node/test_block_height_map.py +556 -0
  109. chia/_tests/core/full_node/test_conditions.py +558 -0
  110. chia/_tests/core/full_node/test_full_node.py +2445 -0
  111. chia/_tests/core/full_node/test_generator_tools.py +82 -0
  112. chia/_tests/core/full_node/test_hint_management.py +104 -0
  113. chia/_tests/core/full_node/test_node_load.py +34 -0
  114. chia/_tests/core/full_node/test_performance.py +182 -0
  115. chia/_tests/core/full_node/test_subscriptions.py +492 -0
  116. chia/_tests/core/full_node/test_transactions.py +203 -0
  117. chia/_tests/core/full_node/test_tx_processing_queue.py +154 -0
  118. chia/_tests/core/large_block.py +2388 -0
  119. chia/_tests/core/make_block_generator.py +72 -0
  120. chia/_tests/core/mempool/__init__.py +0 -0
  121. chia/_tests/core/mempool/config.py +4 -0
  122. chia/_tests/core/mempool/test_mempool.py +3180 -0
  123. chia/_tests/core/mempool/test_mempool_fee_estimator.py +104 -0
  124. chia/_tests/core/mempool/test_mempool_fee_protocol.py +55 -0
  125. chia/_tests/core/mempool/test_mempool_item_queries.py +192 -0
  126. chia/_tests/core/mempool/test_mempool_manager.py +2054 -0
  127. chia/_tests/core/mempool/test_mempool_performance.py +65 -0
  128. chia/_tests/core/mempool/test_singleton_fast_forward.py +567 -0
  129. chia/_tests/core/node_height.py +28 -0
  130. chia/_tests/core/server/__init__.py +0 -0
  131. chia/_tests/core/server/config.py +3 -0
  132. chia/_tests/core/server/flood.py +82 -0
  133. chia/_tests/core/server/serve.py +132 -0
  134. chia/_tests/core/server/test_capabilities.py +68 -0
  135. chia/_tests/core/server/test_dos.py +320 -0
  136. chia/_tests/core/server/test_event_loop.py +109 -0
  137. chia/_tests/core/server/test_loop.py +290 -0
  138. chia/_tests/core/server/test_node_discovery.py +74 -0
  139. chia/_tests/core/server/test_rate_limits.py +370 -0
  140. chia/_tests/core/server/test_server.py +225 -0
  141. chia/_tests/core/server/test_upnp.py +8 -0
  142. chia/_tests/core/services/__init__.py +0 -0
  143. chia/_tests/core/services/config.py +3 -0
  144. chia/_tests/core/services/test_services.py +166 -0
  145. chia/_tests/core/ssl/__init__.py +0 -0
  146. chia/_tests/core/ssl/config.py +3 -0
  147. chia/_tests/core/ssl/test_ssl.py +198 -0
  148. chia/_tests/core/test_coins.py +33 -0
  149. chia/_tests/core/test_cost_calculation.py +314 -0
  150. chia/_tests/core/test_crawler.py +175 -0
  151. chia/_tests/core/test_crawler_rpc.py +53 -0
  152. chia/_tests/core/test_daemon_rpc.py +24 -0
  153. chia/_tests/core/test_db_conversion.py +129 -0
  154. chia/_tests/core/test_db_validation.py +161 -0
  155. chia/_tests/core/test_farmer_harvester_rpc.py +504 -0
  156. chia/_tests/core/test_filter.py +37 -0
  157. chia/_tests/core/test_full_node_rpc.py +794 -0
  158. chia/_tests/core/test_merkle_set.py +343 -0
  159. chia/_tests/core/test_program.py +49 -0
  160. chia/_tests/core/test_rpc_util.py +87 -0
  161. chia/_tests/core/test_seeder.py +308 -0
  162. chia/_tests/core/test_setproctitle.py +13 -0
  163. chia/_tests/core/util/__init__.py +0 -0
  164. chia/_tests/core/util/config.py +4 -0
  165. chia/_tests/core/util/test_block_cache.py +44 -0
  166. chia/_tests/core/util/test_cached_bls.py +57 -0
  167. chia/_tests/core/util/test_config.py +337 -0
  168. chia/_tests/core/util/test_file_keyring_synchronization.py +105 -0
  169. chia/_tests/core/util/test_files.py +391 -0
  170. chia/_tests/core/util/test_jsonify.py +146 -0
  171. chia/_tests/core/util/test_keychain.py +514 -0
  172. chia/_tests/core/util/test_keyring_wrapper.py +490 -0
  173. chia/_tests/core/util/test_lockfile.py +380 -0
  174. chia/_tests/core/util/test_log_exceptions.py +187 -0
  175. chia/_tests/core/util/test_lru_cache.py +56 -0
  176. chia/_tests/core/util/test_significant_bits.py +40 -0
  177. chia/_tests/core/util/test_streamable.py +883 -0
  178. chia/_tests/db/__init__.py +0 -0
  179. chia/_tests/db/test_db_wrapper.py +565 -0
  180. chia/_tests/environments/__init__.py +0 -0
  181. chia/_tests/environments/common.py +35 -0
  182. chia/_tests/environments/full_node.py +47 -0
  183. chia/_tests/environments/wallet.py +368 -0
  184. chia/_tests/ether.py +19 -0
  185. chia/_tests/farmer_harvester/__init__.py +0 -0
  186. chia/_tests/farmer_harvester/config.py +3 -0
  187. chia/_tests/farmer_harvester/test_farmer.py +1264 -0
  188. chia/_tests/farmer_harvester/test_farmer_harvester.py +292 -0
  189. chia/_tests/farmer_harvester/test_filter_prefix_bits.py +130 -0
  190. chia/_tests/farmer_harvester/test_third_party_harvesters.py +501 -0
  191. chia/_tests/farmer_harvester/test_third_party_harvesters_data.json +29 -0
  192. chia/_tests/fee_estimation/__init__.py +0 -0
  193. chia/_tests/fee_estimation/config.py +3 -0
  194. chia/_tests/fee_estimation/test_fee_estimation_integration.py +262 -0
  195. chia/_tests/fee_estimation/test_fee_estimation_rpc.py +287 -0
  196. chia/_tests/fee_estimation/test_fee_estimation_unit_tests.py +145 -0
  197. chia/_tests/fee_estimation/test_mempoolitem_height_added.py +146 -0
  198. chia/_tests/generator/__init__.py +0 -0
  199. chia/_tests/generator/puzzles/__init__.py +0 -0
  200. chia/_tests/generator/puzzles/test_generator_deserialize.clsp +3 -0
  201. chia/_tests/generator/puzzles/test_generator_deserialize.clsp.hex +1 -0
  202. chia/_tests/generator/puzzles/test_multiple_generator_input_arguments.clsp +19 -0
  203. chia/_tests/generator/puzzles/test_multiple_generator_input_arguments.clsp.hex +1 -0
  204. chia/_tests/generator/test_compression.py +218 -0
  205. chia/_tests/generator/test_generator_types.py +44 -0
  206. chia/_tests/generator/test_rom.py +182 -0
  207. chia/_tests/plot_sync/__init__.py +0 -0
  208. chia/_tests/plot_sync/config.py +3 -0
  209. chia/_tests/plot_sync/test_delta.py +102 -0
  210. chia/_tests/plot_sync/test_plot_sync.py +617 -0
  211. chia/_tests/plot_sync/test_receiver.py +451 -0
  212. chia/_tests/plot_sync/test_sender.py +116 -0
  213. chia/_tests/plot_sync/test_sync_simulated.py +450 -0
  214. chia/_tests/plot_sync/util.py +67 -0
  215. chia/_tests/plotting/__init__.py +0 -0
  216. chia/_tests/plotting/config.py +3 -0
  217. chia/_tests/plotting/test_plot_manager.py +738 -0
  218. chia/_tests/plotting/util.py +13 -0
  219. chia/_tests/pools/__init__.py +0 -0
  220. chia/_tests/pools/config.py +5 -0
  221. chia/_tests/pools/test_pool_cmdline.py +23 -0
  222. chia/_tests/pools/test_pool_config.py +44 -0
  223. chia/_tests/pools/test_pool_puzzles_lifecycle.py +398 -0
  224. chia/_tests/pools/test_pool_rpc.py +1010 -0
  225. chia/_tests/pools/test_pool_wallet.py +201 -0
  226. chia/_tests/pools/test_wallet_pool_store.py +161 -0
  227. chia/_tests/process_junit.py +349 -0
  228. chia/_tests/rpc/__init__.py +0 -0
  229. chia/_tests/rpc/test_rpc_client.py +81 -0
  230. chia/_tests/simulation/__init__.py +0 -0
  231. chia/_tests/simulation/config.py +6 -0
  232. chia/_tests/simulation/test_simulation.py +501 -0
  233. chia/_tests/simulation/test_simulator.py +234 -0
  234. chia/_tests/simulation/test_start_simulator.py +106 -0
  235. chia/_tests/testconfig.py +13 -0
  236. chia/_tests/timelord/__init__.py +0 -0
  237. chia/_tests/timelord/config.py +3 -0
  238. chia/_tests/timelord/test_new_peak.py +437 -0
  239. chia/_tests/timelord/test_timelord.py +11 -0
  240. chia/_tests/tools/1315537.json +170 -0
  241. chia/_tests/tools/1315544.json +160 -0
  242. chia/_tests/tools/1315630.json +150 -0
  243. chia/_tests/tools/300000.json +105 -0
  244. chia/_tests/tools/442734.json +140 -0
  245. chia/_tests/tools/466212.json +130 -0
  246. chia/_tests/tools/__init__.py +0 -0
  247. chia/_tests/tools/config.py +5 -0
  248. chia/_tests/tools/test-blockchain-db.sqlite +0 -0
  249. chia/_tests/tools/test_full_sync.py +30 -0
  250. chia/_tests/tools/test_legacy_keyring.py +82 -0
  251. chia/_tests/tools/test_run_block.py +129 -0
  252. chia/_tests/util/__init__.py +0 -0
  253. chia/_tests/util/benchmark_cost.py +170 -0
  254. chia/_tests/util/benchmarks.py +154 -0
  255. chia/_tests/util/bip39_test_vectors.json +148 -0
  256. chia/_tests/util/blockchain.py +133 -0
  257. chia/_tests/util/blockchain_mock.py +132 -0
  258. chia/_tests/util/build_network_protocol_files.py +302 -0
  259. chia/_tests/util/clvm_generator.bin +0 -0
  260. chia/_tests/util/config.py +3 -0
  261. chia/_tests/util/constants.py +20 -0
  262. chia/_tests/util/db_connection.py +36 -0
  263. chia/_tests/util/full_sync.py +245 -0
  264. chia/_tests/util/gen_ssl_certs.py +115 -0
  265. chia/_tests/util/generator_tools_testing.py +47 -0
  266. chia/_tests/util/key_tool.py +37 -0
  267. chia/_tests/util/misc.py +722 -0
  268. chia/_tests/util/network_protocol_data.py +1074 -0
  269. chia/_tests/util/protocol_messages_bytes-v1.0 +0 -0
  270. chia/_tests/util/protocol_messages_json.py +2700 -0
  271. chia/_tests/util/rpc.py +23 -0
  272. chia/_tests/util/run_block.py +163 -0
  273. chia/_tests/util/setup_nodes.py +479 -0
  274. chia/_tests/util/split_managers.py +99 -0
  275. chia/_tests/util/temp_file.py +14 -0
  276. chia/_tests/util/test_action_scope.py +143 -0
  277. chia/_tests/util/test_async_pool.py +366 -0
  278. chia/_tests/util/test_build_job_matrix.py +43 -0
  279. chia/_tests/util/test_build_network_protocol_files.py +7 -0
  280. chia/_tests/util/test_chia_version.py +50 -0
  281. chia/_tests/util/test_collection.py +11 -0
  282. chia/_tests/util/test_condition_tools.py +231 -0
  283. chia/_tests/util/test_config.py +426 -0
  284. chia/_tests/util/test_dump_keyring.py +60 -0
  285. chia/_tests/util/test_errors.py +10 -0
  286. chia/_tests/util/test_full_block_utils.py +271 -0
  287. chia/_tests/util/test_installed.py +20 -0
  288. chia/_tests/util/test_limited_semaphore.py +52 -0
  289. chia/_tests/util/test_logging_filter.py +43 -0
  290. chia/_tests/util/test_misc.py +444 -0
  291. chia/_tests/util/test_network.py +74 -0
  292. chia/_tests/util/test_network_protocol_files.py +579 -0
  293. chia/_tests/util/test_network_protocol_json.py +266 -0
  294. chia/_tests/util/test_network_protocol_test.py +257 -0
  295. chia/_tests/util/test_paginator.py +72 -0
  296. chia/_tests/util/test_pprint.py +17 -0
  297. chia/_tests/util/test_priority_mutex.py +487 -0
  298. chia/_tests/util/test_recursive_replace.py +116 -0
  299. chia/_tests/util/test_replace_str_to_bytes.py +137 -0
  300. chia/_tests/util/test_service_groups.py +15 -0
  301. chia/_tests/util/test_ssl_check.py +31 -0
  302. chia/_tests/util/test_testnet_overrides.py +19 -0
  303. chia/_tests/util/test_tests_misc.py +38 -0
  304. chia/_tests/util/test_timing.py +37 -0
  305. chia/_tests/util/test_trusted_peer.py +51 -0
  306. chia/_tests/util/time_out_assert.py +154 -0
  307. chia/_tests/wallet/__init__.py +0 -0
  308. chia/_tests/wallet/cat_wallet/__init__.py +0 -0
  309. chia/_tests/wallet/cat_wallet/config.py +4 -0
  310. chia/_tests/wallet/cat_wallet/test_cat_lifecycle.py +468 -0
  311. chia/_tests/wallet/cat_wallet/test_cat_outer_puzzle.py +69 -0
  312. chia/_tests/wallet/cat_wallet/test_cat_wallet.py +1738 -0
  313. chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py +291 -0
  314. chia/_tests/wallet/cat_wallet/test_trades.py +2578 -0
  315. chia/_tests/wallet/clawback/__init__.py +0 -0
  316. chia/_tests/wallet/clawback/config.py +3 -0
  317. chia/_tests/wallet/clawback/test_clawback_decorator.py +80 -0
  318. chia/_tests/wallet/clawback/test_clawback_lifecycle.py +292 -0
  319. chia/_tests/wallet/clawback/test_clawback_metadata.py +51 -0
  320. chia/_tests/wallet/config.py +4 -0
  321. chia/_tests/wallet/conftest.py +217 -0
  322. chia/_tests/wallet/dao_wallet/__init__.py +0 -0
  323. chia/_tests/wallet/dao_wallet/config.py +3 -0
  324. chia/_tests/wallet/dao_wallet/test_dao_clvm.py +1322 -0
  325. chia/_tests/wallet/dao_wallet/test_dao_wallets.py +3488 -0
  326. chia/_tests/wallet/db_wallet/__init__.py +0 -0
  327. chia/_tests/wallet/db_wallet/config.py +3 -0
  328. chia/_tests/wallet/db_wallet/test_db_graftroot.py +143 -0
  329. chia/_tests/wallet/db_wallet/test_dl_offers.py +491 -0
  330. chia/_tests/wallet/db_wallet/test_dl_wallet.py +823 -0
  331. chia/_tests/wallet/did_wallet/__init__.py +0 -0
  332. chia/_tests/wallet/did_wallet/config.py +4 -0
  333. chia/_tests/wallet/did_wallet/test_did.py +1481 -0
  334. chia/_tests/wallet/nft_wallet/__init__.py +0 -0
  335. chia/_tests/wallet/nft_wallet/config.py +4 -0
  336. chia/_tests/wallet/nft_wallet/test_nft_1_offers.py +1492 -0
  337. chia/_tests/wallet/nft_wallet/test_nft_bulk_mint.py +1014 -0
  338. chia/_tests/wallet/nft_wallet/test_nft_lifecycle.py +376 -0
  339. chia/_tests/wallet/nft_wallet/test_nft_offers.py +1209 -0
  340. chia/_tests/wallet/nft_wallet/test_nft_puzzles.py +172 -0
  341. chia/_tests/wallet/nft_wallet/test_nft_wallet.py +2558 -0
  342. chia/_tests/wallet/nft_wallet/test_ownership_outer_puzzle.py +70 -0
  343. chia/_tests/wallet/rpc/__init__.py +0 -0
  344. chia/_tests/wallet/rpc/config.py +4 -0
  345. chia/_tests/wallet/rpc/test_dl_wallet_rpc.py +287 -0
  346. chia/_tests/wallet/rpc/test_wallet_rpc.py +3106 -0
  347. chia/_tests/wallet/simple_sync/__init__.py +0 -0
  348. chia/_tests/wallet/simple_sync/config.py +3 -0
  349. chia/_tests/wallet/simple_sync/test_simple_sync_protocol.py +719 -0
  350. chia/_tests/wallet/sync/__init__.py +0 -0
  351. chia/_tests/wallet/sync/config.py +4 -0
  352. chia/_tests/wallet/sync/test_wallet_sync.py +1529 -0
  353. chia/_tests/wallet/test_address_type.py +189 -0
  354. chia/_tests/wallet/test_bech32m.py +45 -0
  355. chia/_tests/wallet/test_clvm_streamable.py +244 -0
  356. chia/_tests/wallet/test_coin_selection.py +589 -0
  357. chia/_tests/wallet/test_conditions.py +388 -0
  358. chia/_tests/wallet/test_debug_spend_bundle.py +76 -0
  359. chia/_tests/wallet/test_new_wallet_protocol.py +1176 -0
  360. chia/_tests/wallet/test_nft_store.py +193 -0
  361. chia/_tests/wallet/test_notifications.py +196 -0
  362. chia/_tests/wallet/test_offer_parsing_performance.py +48 -0
  363. chia/_tests/wallet/test_puzzle_store.py +133 -0
  364. chia/_tests/wallet/test_sign_coin_spends.py +159 -0
  365. chia/_tests/wallet/test_signer_protocol.py +948 -0
  366. chia/_tests/wallet/test_singleton.py +122 -0
  367. chia/_tests/wallet/test_singleton_lifecycle_fast.py +772 -0
  368. chia/_tests/wallet/test_singleton_store.py +152 -0
  369. chia/_tests/wallet/test_taproot.py +19 -0
  370. chia/_tests/wallet/test_transaction_store.py +941 -0
  371. chia/_tests/wallet/test_util.py +181 -0
  372. chia/_tests/wallet/test_wallet.py +2139 -0
  373. chia/_tests/wallet/test_wallet_action_scope.py +85 -0
  374. chia/_tests/wallet/test_wallet_blockchain.py +113 -0
  375. chia/_tests/wallet/test_wallet_coin_store.py +1002 -0
  376. chia/_tests/wallet/test_wallet_interested_store.py +43 -0
  377. chia/_tests/wallet/test_wallet_key_val_store.py +40 -0
  378. chia/_tests/wallet/test_wallet_node.py +783 -0
  379. chia/_tests/wallet/test_wallet_retry.py +95 -0
  380. chia/_tests/wallet/test_wallet_state_manager.py +252 -0
  381. chia/_tests/wallet/test_wallet_test_framework.py +275 -0
  382. chia/_tests/wallet/test_wallet_trade_store.py +218 -0
  383. chia/_tests/wallet/test_wallet_user_store.py +34 -0
  384. chia/_tests/wallet/test_wallet_utils.py +155 -0
  385. chia/_tests/wallet/vc_wallet/__init__.py +0 -0
  386. chia/_tests/wallet/vc_wallet/config.py +3 -0
  387. chia/_tests/wallet/vc_wallet/test_cr_outer_puzzle.py +70 -0
  388. chia/_tests/wallet/vc_wallet/test_vc_lifecycle.py +883 -0
  389. chia/_tests/wallet/vc_wallet/test_vc_wallet.py +801 -0
  390. chia/_tests/wallet/wallet_block_tools.py +327 -0
  391. chia/_tests/weight_proof/__init__.py +0 -0
  392. chia/_tests/weight_proof/config.py +3 -0
  393. chia/_tests/weight_proof/test_weight_proof.py +528 -0
  394. chia/clvm/__init__.py +0 -0
  395. chia/clvm/spend_sim.py +488 -0
  396. chia/cmds/__init__.py +0 -0
  397. chia/cmds/beta.py +183 -0
  398. chia/cmds/beta_funcs.py +133 -0
  399. chia/cmds/check_wallet_db.py +418 -0
  400. chia/cmds/chia.py +143 -0
  401. chia/cmds/cmd_classes.py +315 -0
  402. chia/cmds/cmds_util.py +498 -0
  403. chia/cmds/coin_funcs.py +260 -0
  404. chia/cmds/coins.py +220 -0
  405. chia/cmds/completion.py +49 -0
  406. chia/cmds/configure.py +331 -0
  407. chia/cmds/dao.py +1008 -0
  408. chia/cmds/dao_funcs.py +576 -0
  409. chia/cmds/data.py +707 -0
  410. chia/cmds/data_funcs.py +380 -0
  411. chia/cmds/db.py +86 -0
  412. chia/cmds/db_backup_func.py +77 -0
  413. chia/cmds/db_upgrade_func.py +452 -0
  414. chia/cmds/db_validate_func.py +184 -0
  415. chia/cmds/dev.py +16 -0
  416. chia/cmds/farm.py +87 -0
  417. chia/cmds/farm_funcs.py +207 -0
  418. chia/cmds/init.py +70 -0
  419. chia/cmds/init_funcs.py +367 -0
  420. chia/cmds/installers.py +129 -0
  421. chia/cmds/keys.py +510 -0
  422. chia/cmds/keys_funcs.py +864 -0
  423. chia/cmds/netspace.py +47 -0
  424. chia/cmds/netspace_funcs.py +53 -0
  425. chia/cmds/options.py +32 -0
  426. chia/cmds/param_types.py +228 -0
  427. chia/cmds/passphrase.py +130 -0
  428. chia/cmds/passphrase_funcs.py +346 -0
  429. chia/cmds/peer.py +50 -0
  430. chia/cmds/peer_funcs.py +129 -0
  431. chia/cmds/plotnft.py +206 -0
  432. chia/cmds/plotnft_funcs.py +374 -0
  433. chia/cmds/plots.py +222 -0
  434. chia/cmds/plotters.py +17 -0
  435. chia/cmds/rpc.py +188 -0
  436. chia/cmds/show.py +71 -0
  437. chia/cmds/show_funcs.py +214 -0
  438. chia/cmds/signer.py +304 -0
  439. chia/cmds/sim.py +217 -0
  440. chia/cmds/sim_funcs.py +509 -0
  441. chia/cmds/start.py +24 -0
  442. chia/cmds/start_funcs.py +112 -0
  443. chia/cmds/stop.py +61 -0
  444. chia/cmds/units.py +11 -0
  445. chia/cmds/wallet.py +1745 -0
  446. chia/cmds/wallet_funcs.py +1800 -0
  447. chia/consensus/__init__.py +0 -0
  448. chia/consensus/block_body_validation.py +515 -0
  449. chia/consensus/block_creation.py +525 -0
  450. chia/consensus/block_header_validation.py +1064 -0
  451. chia/consensus/block_record.py +32 -0
  452. chia/consensus/block_rewards.py +53 -0
  453. chia/consensus/block_root_validation.py +46 -0
  454. chia/consensus/blockchain.py +1100 -0
  455. chia/consensus/blockchain_interface.py +56 -0
  456. chia/consensus/coinbase.py +30 -0
  457. chia/consensus/condition_costs.py +9 -0
  458. chia/consensus/constants.py +49 -0
  459. chia/consensus/cost_calculator.py +15 -0
  460. chia/consensus/default_constants.py +90 -0
  461. chia/consensus/deficit.py +55 -0
  462. chia/consensus/difficulty_adjustment.py +412 -0
  463. chia/consensus/find_fork_point.py +111 -0
  464. chia/consensus/full_block_to_block_record.py +167 -0
  465. chia/consensus/get_block_challenge.py +106 -0
  466. chia/consensus/get_block_generator.py +26 -0
  467. chia/consensus/make_sub_epoch_summary.py +210 -0
  468. chia/consensus/multiprocess_validation.py +365 -0
  469. chia/consensus/pos_quality.py +19 -0
  470. chia/consensus/pot_iterations.py +67 -0
  471. chia/consensus/puzzles/__init__.py +0 -0
  472. chia/consensus/puzzles/chialisp_deserialisation.clsp +69 -0
  473. chia/consensus/puzzles/chialisp_deserialisation.clsp.hex +1 -0
  474. chia/consensus/puzzles/rom_bootstrap_generator.clsp +37 -0
  475. chia/consensus/puzzles/rom_bootstrap_generator.clsp.hex +1 -0
  476. chia/consensus/vdf_info_computation.py +156 -0
  477. chia/daemon/__init__.py +0 -0
  478. chia/daemon/client.py +233 -0
  479. chia/daemon/keychain_proxy.py +501 -0
  480. chia/daemon/keychain_server.py +365 -0
  481. chia/daemon/server.py +1616 -0
  482. chia/daemon/windows_signal.py +56 -0
  483. chia/data_layer/__init__.py +0 -0
  484. chia/data_layer/data_layer.py +1303 -0
  485. chia/data_layer/data_layer_api.py +25 -0
  486. chia/data_layer/data_layer_errors.py +50 -0
  487. chia/data_layer/data_layer_server.py +170 -0
  488. chia/data_layer/data_layer_util.py +985 -0
  489. chia/data_layer/data_layer_wallet.py +1315 -0
  490. chia/data_layer/data_store.py +2267 -0
  491. chia/data_layer/dl_wallet_store.py +407 -0
  492. chia/data_layer/download_data.py +389 -0
  493. chia/data_layer/puzzles/__init__.py +0 -0
  494. chia/data_layer/puzzles/graftroot_dl_offers.clsp +100 -0
  495. chia/data_layer/puzzles/graftroot_dl_offers.clsp.hex +1 -0
  496. chia/data_layer/s3_plugin_config.yml +33 -0
  497. chia/data_layer/s3_plugin_service.py +468 -0
  498. chia/data_layer/util/__init__.py +0 -0
  499. chia/data_layer/util/benchmark.py +108 -0
  500. chia/data_layer/util/plugin.py +41 -0
  501. chia/farmer/__init__.py +0 -0
  502. chia/farmer/farmer.py +920 -0
  503. chia/farmer/farmer_api.py +814 -0
  504. chia/full_node/__init__.py +0 -0
  505. chia/full_node/bitcoin_fee_estimator.py +85 -0
  506. chia/full_node/block_height_map.py +271 -0
  507. chia/full_node/block_store.py +570 -0
  508. chia/full_node/bundle_tools.py +19 -0
  509. chia/full_node/coin_store.py +646 -0
  510. chia/full_node/fee_estimate.py +54 -0
  511. chia/full_node/fee_estimate_store.py +24 -0
  512. chia/full_node/fee_estimation.py +93 -0
  513. chia/full_node/fee_estimator.py +90 -0
  514. chia/full_node/fee_estimator_constants.py +38 -0
  515. chia/full_node/fee_estimator_interface.py +42 -0
  516. chia/full_node/fee_history.py +26 -0
  517. chia/full_node/fee_tracker.py +564 -0
  518. chia/full_node/full_node.py +3052 -0
  519. chia/full_node/full_node_api.py +1974 -0
  520. chia/full_node/full_node_store.py +1033 -0
  521. chia/full_node/hint_management.py +56 -0
  522. chia/full_node/hint_store.py +94 -0
  523. chia/full_node/mempool.py +583 -0
  524. chia/full_node/mempool_check_conditions.py +177 -0
  525. chia/full_node/mempool_manager.py +858 -0
  526. chia/full_node/pending_tx_cache.py +112 -0
  527. chia/full_node/puzzles/__init__.py +0 -0
  528. chia/full_node/puzzles/block_program_zero.clsp +14 -0
  529. chia/full_node/puzzles/block_program_zero.clsp.hex +1 -0
  530. chia/full_node/puzzles/decompress_coin_spend_entry.clsp +5 -0
  531. chia/full_node/puzzles/decompress_coin_spend_entry.clsp.hex +1 -0
  532. chia/full_node/puzzles/decompress_coin_spend_entry_with_prefix.clsp +7 -0
  533. chia/full_node/puzzles/decompress_coin_spend_entry_with_prefix.clsp.hex +1 -0
  534. chia/full_node/puzzles/decompress_puzzle.clsp +6 -0
  535. chia/full_node/puzzles/decompress_puzzle.clsp.hex +1 -0
  536. chia/full_node/signage_point.py +16 -0
  537. chia/full_node/subscriptions.py +248 -0
  538. chia/full_node/sync_store.py +145 -0
  539. chia/full_node/tx_processing_queue.py +78 -0
  540. chia/full_node/weight_proof.py +1719 -0
  541. chia/harvester/__init__.py +0 -0
  542. chia/harvester/harvester.py +271 -0
  543. chia/harvester/harvester_api.py +374 -0
  544. chia/introducer/__init__.py +0 -0
  545. chia/introducer/introducer.py +120 -0
  546. chia/introducer/introducer_api.py +64 -0
  547. chia/legacy/__init__.py +0 -0
  548. chia/legacy/keyring.py +154 -0
  549. chia/plot_sync/__init__.py +0 -0
  550. chia/plot_sync/delta.py +61 -0
  551. chia/plot_sync/exceptions.py +56 -0
  552. chia/plot_sync/receiver.py +385 -0
  553. chia/plot_sync/sender.py +337 -0
  554. chia/plot_sync/util.py +43 -0
  555. chia/plotters/__init__.py +0 -0
  556. chia/plotters/bladebit.py +388 -0
  557. chia/plotters/chiapos.py +63 -0
  558. chia/plotters/madmax.py +224 -0
  559. chia/plotters/plotters.py +577 -0
  560. chia/plotters/plotters_util.py +131 -0
  561. chia/plotting/__init__.py +0 -0
  562. chia/plotting/cache.py +212 -0
  563. chia/plotting/check_plots.py +283 -0
  564. chia/plotting/create_plots.py +278 -0
  565. chia/plotting/manager.py +436 -0
  566. chia/plotting/util.py +324 -0
  567. chia/pools/__init__.py +0 -0
  568. chia/pools/pool_config.py +110 -0
  569. chia/pools/pool_puzzles.py +459 -0
  570. chia/pools/pool_wallet.py +926 -0
  571. chia/pools/pool_wallet_info.py +118 -0
  572. chia/pools/puzzles/__init__.py +0 -0
  573. chia/pools/puzzles/pool_member_innerpuz.clsp +70 -0
  574. chia/pools/puzzles/pool_member_innerpuz.clsp.hex +1 -0
  575. chia/pools/puzzles/pool_waitingroom_innerpuz.clsp +69 -0
  576. chia/pools/puzzles/pool_waitingroom_innerpuz.clsp.hex +1 -0
  577. chia/protocols/__init__.py +0 -0
  578. chia/protocols/farmer_protocol.py +102 -0
  579. chia/protocols/full_node_protocol.py +219 -0
  580. chia/protocols/harvester_protocol.py +216 -0
  581. chia/protocols/introducer_protocol.py +26 -0
  582. chia/protocols/pool_protocol.py +177 -0
  583. chia/protocols/protocol_message_types.py +139 -0
  584. chia/protocols/protocol_state_machine.py +87 -0
  585. chia/protocols/protocol_timing.py +7 -0
  586. chia/protocols/shared_protocol.py +86 -0
  587. chia/protocols/timelord_protocol.py +93 -0
  588. chia/protocols/wallet_protocol.py +401 -0
  589. chia/py.typed +0 -0
  590. chia/rpc/__init__.py +0 -0
  591. chia/rpc/crawler_rpc_api.py +75 -0
  592. chia/rpc/data_layer_rpc_api.py +639 -0
  593. chia/rpc/data_layer_rpc_client.py +188 -0
  594. chia/rpc/data_layer_rpc_util.py +62 -0
  595. chia/rpc/farmer_rpc_api.py +360 -0
  596. chia/rpc/farmer_rpc_client.py +86 -0
  597. chia/rpc/full_node_rpc_api.py +954 -0
  598. chia/rpc/full_node_rpc_client.py +292 -0
  599. chia/rpc/harvester_rpc_api.py +136 -0
  600. chia/rpc/harvester_rpc_client.py +54 -0
  601. chia/rpc/rpc_client.py +144 -0
  602. chia/rpc/rpc_server.py +447 -0
  603. chia/rpc/timelord_rpc_api.py +27 -0
  604. chia/rpc/util.py +293 -0
  605. chia/rpc/wallet_request_types.py +688 -0
  606. chia/rpc/wallet_rpc_api.py +4779 -0
  607. chia/rpc/wallet_rpc_client.py +1844 -0
  608. chia/seeder/__init__.py +0 -0
  609. chia/seeder/crawl_store.py +427 -0
  610. chia/seeder/crawler.py +423 -0
  611. chia/seeder/crawler_api.py +129 -0
  612. chia/seeder/dns_server.py +544 -0
  613. chia/seeder/peer_record.py +146 -0
  614. chia/seeder/start_crawler.py +88 -0
  615. chia/server/__init__.py +0 -0
  616. chia/server/address_manager.py +658 -0
  617. chia/server/address_manager_store.py +237 -0
  618. chia/server/api_protocol.py +11 -0
  619. chia/server/capabilities.py +24 -0
  620. chia/server/chia_policy.py +345 -0
  621. chia/server/introducer_peers.py +76 -0
  622. chia/server/node_discovery.py +718 -0
  623. chia/server/outbound_message.py +33 -0
  624. chia/server/rate_limit_numbers.py +204 -0
  625. chia/server/rate_limits.py +113 -0
  626. chia/server/server.py +720 -0
  627. chia/server/signal_handlers.py +117 -0
  628. chia/server/ssl_context.py +32 -0
  629. chia/server/start_data_layer.py +137 -0
  630. chia/server/start_farmer.py +86 -0
  631. chia/server/start_full_node.py +106 -0
  632. chia/server/start_harvester.py +80 -0
  633. chia/server/start_introducer.py +69 -0
  634. chia/server/start_service.py +328 -0
  635. chia/server/start_timelord.py +82 -0
  636. chia/server/start_wallet.py +109 -0
  637. chia/server/upnp.py +117 -0
  638. chia/server/ws_connection.py +752 -0
  639. chia/simulator/__init__.py +0 -0
  640. chia/simulator/block_tools.py +2053 -0
  641. chia/simulator/full_node_simulator.py +802 -0
  642. chia/simulator/keyring.py +128 -0
  643. chia/simulator/setup_services.py +505 -0
  644. chia/simulator/simulator_constants.py +13 -0
  645. chia/simulator/simulator_full_node_rpc_api.py +101 -0
  646. chia/simulator/simulator_full_node_rpc_client.py +62 -0
  647. chia/simulator/simulator_protocol.py +29 -0
  648. chia/simulator/simulator_test_tools.py +163 -0
  649. chia/simulator/socket.py +27 -0
  650. chia/simulator/ssl_certs.py +114 -0
  651. chia/simulator/ssl_certs_1.py +699 -0
  652. chia/simulator/ssl_certs_10.py +699 -0
  653. chia/simulator/ssl_certs_2.py +699 -0
  654. chia/simulator/ssl_certs_3.py +699 -0
  655. chia/simulator/ssl_certs_4.py +699 -0
  656. chia/simulator/ssl_certs_5.py +699 -0
  657. chia/simulator/ssl_certs_6.py +699 -0
  658. chia/simulator/ssl_certs_7.py +699 -0
  659. chia/simulator/ssl_certs_8.py +699 -0
  660. chia/simulator/ssl_certs_9.py +699 -0
  661. chia/simulator/start_simulator.py +135 -0
  662. chia/simulator/wallet_tools.py +245 -0
  663. chia/ssl/__init__.py +0 -0
  664. chia/ssl/chia_ca.crt +19 -0
  665. chia/ssl/chia_ca.key +28 -0
  666. chia/ssl/create_ssl.py +249 -0
  667. chia/ssl/dst_root_ca.pem +20 -0
  668. chia/timelord/__init__.py +0 -0
  669. chia/timelord/iters_from_block.py +50 -0
  670. chia/timelord/timelord.py +1202 -0
  671. chia/timelord/timelord_api.py +132 -0
  672. chia/timelord/timelord_launcher.py +188 -0
  673. chia/timelord/timelord_state.py +244 -0
  674. chia/timelord/types.py +22 -0
  675. chia/types/__init__.py +0 -0
  676. chia/types/aliases.py +35 -0
  677. chia/types/block_protocol.py +20 -0
  678. chia/types/blockchain_format/__init__.py +0 -0
  679. chia/types/blockchain_format/classgroup.py +5 -0
  680. chia/types/blockchain_format/coin.py +28 -0
  681. chia/types/blockchain_format/foliage.py +8 -0
  682. chia/types/blockchain_format/pool_target.py +5 -0
  683. chia/types/blockchain_format/program.py +270 -0
  684. chia/types/blockchain_format/proof_of_space.py +135 -0
  685. chia/types/blockchain_format/reward_chain_block.py +6 -0
  686. chia/types/blockchain_format/serialized_program.py +5 -0
  687. chia/types/blockchain_format/sized_bytes.py +11 -0
  688. chia/types/blockchain_format/slots.py +9 -0
  689. chia/types/blockchain_format/sub_epoch_summary.py +5 -0
  690. chia/types/blockchain_format/tree_hash.py +72 -0
  691. chia/types/blockchain_format/vdf.py +86 -0
  692. chia/types/clvm_cost.py +13 -0
  693. chia/types/coin_record.py +43 -0
  694. chia/types/coin_spend.py +115 -0
  695. chia/types/condition_opcodes.py +73 -0
  696. chia/types/condition_with_args.py +17 -0
  697. chia/types/eligible_coin_spends.py +364 -0
  698. chia/types/end_of_slot_bundle.py +5 -0
  699. chia/types/fee_rate.py +38 -0
  700. chia/types/full_block.py +5 -0
  701. chia/types/generator_types.py +14 -0
  702. chia/types/header_block.py +5 -0
  703. chia/types/internal_mempool_item.py +19 -0
  704. chia/types/mempool_inclusion_status.py +9 -0
  705. chia/types/mempool_item.py +85 -0
  706. chia/types/mempool_submission_status.py +30 -0
  707. chia/types/mojos.py +7 -0
  708. chia/types/peer_info.py +64 -0
  709. chia/types/signing_mode.py +29 -0
  710. chia/types/spend_bundle.py +31 -0
  711. chia/types/spend_bundle_conditions.py +7 -0
  712. chia/types/transaction_queue_entry.py +55 -0
  713. chia/types/unfinished_block.py +5 -0
  714. chia/types/unfinished_header_block.py +37 -0
  715. chia/types/weight_proof.py +50 -0
  716. chia/util/__init__.py +0 -0
  717. chia/util/action_scope.py +168 -0
  718. chia/util/api_decorators.py +89 -0
  719. chia/util/async_pool.py +224 -0
  720. chia/util/augmented_chain.py +130 -0
  721. chia/util/batches.py +39 -0
  722. chia/util/bech32m.py +123 -0
  723. chia/util/beta_metrics.py +118 -0
  724. chia/util/block_cache.py +56 -0
  725. chia/util/byte_types.py +10 -0
  726. chia/util/check_fork_next_block.py +32 -0
  727. chia/util/chia_logging.py +124 -0
  728. chia/util/chia_version.py +33 -0
  729. chia/util/collection.py +17 -0
  730. chia/util/condition_tools.py +201 -0
  731. chia/util/config.py +366 -0
  732. chia/util/cpu.py +20 -0
  733. chia/util/db_synchronous.py +21 -0
  734. chia/util/db_version.py +30 -0
  735. chia/util/db_wrapper.py +427 -0
  736. chia/util/default_root.py +10 -0
  737. chia/util/dump_keyring.py +93 -0
  738. chia/util/english.txt +2048 -0
  739. chia/util/errors.py +351 -0
  740. chia/util/file_keyring.py +480 -0
  741. chia/util/files.py +95 -0
  742. chia/util/full_block_utils.py +321 -0
  743. chia/util/generator_tools.py +62 -0
  744. chia/util/hash.py +29 -0
  745. chia/util/initial-config.yaml +675 -0
  746. chia/util/inline_executor.py +24 -0
  747. chia/util/ints.py +19 -0
  748. chia/util/json_util.py +41 -0
  749. chia/util/keychain.py +673 -0
  750. chia/util/keyring_wrapper.py +266 -0
  751. chia/util/limited_semaphore.py +39 -0
  752. chia/util/lock.py +47 -0
  753. chia/util/log_exceptions.py +29 -0
  754. chia/util/logging.py +34 -0
  755. chia/util/lru_cache.py +29 -0
  756. chia/util/math.py +20 -0
  757. chia/util/network.py +240 -0
  758. chia/util/paginator.py +46 -0
  759. chia/util/path.py +29 -0
  760. chia/util/permissions.py +19 -0
  761. chia/util/pprint.py +40 -0
  762. chia/util/prev_transaction_block.py +23 -0
  763. chia/util/priority_mutex.py +92 -0
  764. chia/util/profiler.py +194 -0
  765. chia/util/recursive_replace.py +22 -0
  766. chia/util/safe_cancel_task.py +14 -0
  767. chia/util/service_groups.py +47 -0
  768. chia/util/setproctitle.py +20 -0
  769. chia/util/significant_bits.py +30 -0
  770. chia/util/ssl_check.py +213 -0
  771. chia/util/streamable.py +654 -0
  772. chia/util/task_timing.py +378 -0
  773. chia/util/timing.py +64 -0
  774. chia/util/vdf_prover.py +31 -0
  775. chia/util/ws_message.py +66 -0
  776. chia/wallet/__init__.py +0 -0
  777. chia/wallet/cat_wallet/__init__.py +0 -0
  778. chia/wallet/cat_wallet/cat_constants.py +75 -0
  779. chia/wallet/cat_wallet/cat_info.py +47 -0
  780. chia/wallet/cat_wallet/cat_outer_puzzle.py +120 -0
  781. chia/wallet/cat_wallet/cat_utils.py +163 -0
  782. chia/wallet/cat_wallet/cat_wallet.py +869 -0
  783. chia/wallet/cat_wallet/dao_cat_info.py +28 -0
  784. chia/wallet/cat_wallet/dao_cat_wallet.py +669 -0
  785. chia/wallet/cat_wallet/lineage_store.py +74 -0
  786. chia/wallet/cat_wallet/puzzles/__init__.py +0 -0
  787. chia/wallet/cat_wallet/puzzles/cat_truths.clib +31 -0
  788. chia/wallet/cat_wallet/puzzles/cat_v2.clsp +397 -0
  789. chia/wallet/cat_wallet/puzzles/cat_v2.clsp.hex +1 -0
  790. chia/wallet/cat_wallet/puzzles/delegated_tail.clsp +25 -0
  791. chia/wallet/cat_wallet/puzzles/delegated_tail.clsp.hex +1 -0
  792. chia/wallet/cat_wallet/puzzles/everything_with_signature.clsp +15 -0
  793. chia/wallet/cat_wallet/puzzles/everything_with_signature.clsp.hex +1 -0
  794. chia/wallet/cat_wallet/puzzles/genesis_by_coin_id.clsp +26 -0
  795. chia/wallet/cat_wallet/puzzles/genesis_by_coin_id.clsp.hex +1 -0
  796. chia/wallet/cat_wallet/puzzles/genesis_by_coin_id_or_singleton.clsp +42 -0
  797. chia/wallet/cat_wallet/puzzles/genesis_by_coin_id_or_singleton.clsp.hex +1 -0
  798. chia/wallet/cat_wallet/puzzles/genesis_by_puzzle_hash.clsp +24 -0
  799. chia/wallet/cat_wallet/puzzles/genesis_by_puzzle_hash.clsp.hex +1 -0
  800. chia/wallet/coin_selection.py +188 -0
  801. chia/wallet/conditions.py +1326 -0
  802. chia/wallet/dao_wallet/__init__.py +0 -0
  803. chia/wallet/dao_wallet/dao_info.py +61 -0
  804. chia/wallet/dao_wallet/dao_utils.py +810 -0
  805. chia/wallet/dao_wallet/dao_wallet.py +2121 -0
  806. chia/wallet/db_wallet/__init__.py +0 -0
  807. chia/wallet/db_wallet/db_wallet_puzzles.py +107 -0
  808. chia/wallet/derivation_record.py +30 -0
  809. chia/wallet/derive_keys.py +146 -0
  810. chia/wallet/did_wallet/__init__.py +0 -0
  811. chia/wallet/did_wallet/did_info.py +39 -0
  812. chia/wallet/did_wallet/did_wallet.py +1485 -0
  813. chia/wallet/did_wallet/did_wallet_puzzles.py +220 -0
  814. chia/wallet/did_wallet/puzzles/__init__.py +0 -0
  815. chia/wallet/did_wallet/puzzles/did_innerpuz.clsp +135 -0
  816. chia/wallet/did_wallet/puzzles/did_innerpuz.clsp.hex +1 -0
  817. chia/wallet/driver_protocol.py +26 -0
  818. chia/wallet/key_val_store.py +55 -0
  819. chia/wallet/lineage_proof.py +58 -0
  820. chia/wallet/nft_wallet/__init__.py +0 -0
  821. chia/wallet/nft_wallet/metadata_outer_puzzle.py +92 -0
  822. chia/wallet/nft_wallet/nft_info.py +120 -0
  823. chia/wallet/nft_wallet/nft_puzzles.py +305 -0
  824. chia/wallet/nft_wallet/nft_wallet.py +1686 -0
  825. chia/wallet/nft_wallet/ownership_outer_puzzle.py +101 -0
  826. chia/wallet/nft_wallet/puzzles/__init__.py +0 -0
  827. chia/wallet/nft_wallet/puzzles/create_nft_launcher_from_did.clsp +6 -0
  828. chia/wallet/nft_wallet/puzzles/create_nft_launcher_from_did.clsp.hex +1 -0
  829. chia/wallet/nft_wallet/puzzles/nft_intermediate_launcher.clsp +6 -0
  830. chia/wallet/nft_wallet/puzzles/nft_intermediate_launcher.clsp.hex +1 -0
  831. chia/wallet/nft_wallet/puzzles/nft_metadata_updater_default.clsp +30 -0
  832. chia/wallet/nft_wallet/puzzles/nft_metadata_updater_default.clsp.hex +1 -0
  833. chia/wallet/nft_wallet/puzzles/nft_metadata_updater_updateable.clsp +28 -0
  834. chia/wallet/nft_wallet/puzzles/nft_metadata_updater_updateable.clsp.hex +1 -0
  835. chia/wallet/nft_wallet/puzzles/nft_ownership_layer.clsp +100 -0
  836. chia/wallet/nft_wallet/puzzles/nft_ownership_layer.clsp.hex +1 -0
  837. chia/wallet/nft_wallet/puzzles/nft_ownership_transfer_program_one_way_claim_with_royalties.clsp +78 -0
  838. chia/wallet/nft_wallet/puzzles/nft_ownership_transfer_program_one_way_claim_with_royalties.clsp.hex +1 -0
  839. chia/wallet/nft_wallet/puzzles/nft_state_layer.clsp +74 -0
  840. chia/wallet/nft_wallet/puzzles/nft_state_layer.clsp.hex +1 -0
  841. chia/wallet/nft_wallet/singleton_outer_puzzle.py +101 -0
  842. chia/wallet/nft_wallet/transfer_program_puzzle.py +82 -0
  843. chia/wallet/nft_wallet/uncurry_nft.py +217 -0
  844. chia/wallet/notification_manager.py +117 -0
  845. chia/wallet/notification_store.py +178 -0
  846. chia/wallet/outer_puzzles.py +84 -0
  847. chia/wallet/payment.py +34 -0
  848. chia/wallet/puzzle_drivers.py +118 -0
  849. chia/wallet/puzzles/__init__.py +0 -0
  850. chia/wallet/puzzles/augmented_condition.clsp +13 -0
  851. chia/wallet/puzzles/augmented_condition.clsp.hex +1 -0
  852. chia/wallet/puzzles/clawback/__init__.py +0 -0
  853. chia/wallet/puzzles/clawback/drivers.py +188 -0
  854. chia/wallet/puzzles/clawback/metadata.py +38 -0
  855. chia/wallet/puzzles/clawback/puzzle_decorator.py +67 -0
  856. chia/wallet/puzzles/condition_codes.clib +77 -0
  857. chia/wallet/puzzles/curry-and-treehash.clib +102 -0
  858. chia/wallet/puzzles/curry.clib +135 -0
  859. chia/wallet/puzzles/curry_by_index.clib +16 -0
  860. chia/wallet/puzzles/dao_cat_eve.clsp +17 -0
  861. chia/wallet/puzzles/dao_cat_eve.clsp.hex +1 -0
  862. chia/wallet/puzzles/dao_cat_launcher.clsp +36 -0
  863. chia/wallet/puzzles/dao_cat_launcher.clsp.hex +1 -0
  864. chia/wallet/puzzles/dao_finished_state.clsp +35 -0
  865. chia/wallet/puzzles/dao_finished_state.clsp.hex +1 -0
  866. chia/wallet/puzzles/dao_finished_state.clsp.hex.sha256tree +1 -0
  867. chia/wallet/puzzles/dao_lockup.clsp +288 -0
  868. chia/wallet/puzzles/dao_lockup.clsp.hex +1 -0
  869. chia/wallet/puzzles/dao_lockup.clsp.hex.sha256tree +1 -0
  870. chia/wallet/puzzles/dao_proposal.clsp +377 -0
  871. chia/wallet/puzzles/dao_proposal.clsp.hex +1 -0
  872. chia/wallet/puzzles/dao_proposal.clsp.hex.sha256tree +1 -0
  873. chia/wallet/puzzles/dao_proposal_timer.clsp +78 -0
  874. chia/wallet/puzzles/dao_proposal_timer.clsp.hex +1 -0
  875. chia/wallet/puzzles/dao_proposal_timer.clsp.hex.sha256tree +1 -0
  876. chia/wallet/puzzles/dao_proposal_validator.clsp +87 -0
  877. chia/wallet/puzzles/dao_proposal_validator.clsp.hex +1 -0
  878. chia/wallet/puzzles/dao_proposal_validator.clsp.hex.sha256tree +1 -0
  879. chia/wallet/puzzles/dao_spend_p2_singleton_v2.clsp +240 -0
  880. chia/wallet/puzzles/dao_spend_p2_singleton_v2.clsp.hex +1 -0
  881. chia/wallet/puzzles/dao_spend_p2_singleton_v2.clsp.hex.sha256tree +1 -0
  882. chia/wallet/puzzles/dao_treasury.clsp +115 -0
  883. chia/wallet/puzzles/dao_treasury.clsp.hex +1 -0
  884. chia/wallet/puzzles/dao_update_proposal.clsp +44 -0
  885. chia/wallet/puzzles/dao_update_proposal.clsp.hex +1 -0
  886. chia/wallet/puzzles/deployed_puzzle_hashes.json +67 -0
  887. chia/wallet/puzzles/json.clib +25 -0
  888. chia/wallet/puzzles/load_clvm.py +162 -0
  889. chia/wallet/puzzles/merkle_utils.clib +18 -0
  890. chia/wallet/puzzles/notification.clsp +7 -0
  891. chia/wallet/puzzles/notification.clsp.hex +1 -0
  892. chia/wallet/puzzles/p2_1_of_n.clsp +22 -0
  893. chia/wallet/puzzles/p2_1_of_n.clsp.hex +1 -0
  894. chia/wallet/puzzles/p2_conditions.clsp +3 -0
  895. chia/wallet/puzzles/p2_conditions.clsp.hex +1 -0
  896. chia/wallet/puzzles/p2_conditions.py +27 -0
  897. chia/wallet/puzzles/p2_delegated_conditions.clsp +18 -0
  898. chia/wallet/puzzles/p2_delegated_conditions.clsp.hex +1 -0
  899. chia/wallet/puzzles/p2_delegated_conditions.py +22 -0
  900. chia/wallet/puzzles/p2_delegated_puzzle.clsp +19 -0
  901. chia/wallet/puzzles/p2_delegated_puzzle.clsp.hex +1 -0
  902. chia/wallet/puzzles/p2_delegated_puzzle.py +35 -0
  903. chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.clsp +91 -0
  904. chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.clsp.hex +1 -0
  905. chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.py +161 -0
  906. chia/wallet/puzzles/p2_m_of_n_delegate_direct.clsp +108 -0
  907. chia/wallet/puzzles/p2_m_of_n_delegate_direct.clsp.hex +1 -0
  908. chia/wallet/puzzles/p2_m_of_n_delegate_direct.py +22 -0
  909. chia/wallet/puzzles/p2_parent.clsp +19 -0
  910. chia/wallet/puzzles/p2_parent.clsp.hex +1 -0
  911. chia/wallet/puzzles/p2_puzzle_hash.clsp +18 -0
  912. chia/wallet/puzzles/p2_puzzle_hash.clsp.hex +1 -0
  913. chia/wallet/puzzles/p2_puzzle_hash.py +28 -0
  914. chia/wallet/puzzles/p2_singleton.clsp +30 -0
  915. chia/wallet/puzzles/p2_singleton.clsp.hex +1 -0
  916. chia/wallet/puzzles/p2_singleton_aggregator.clsp +81 -0
  917. chia/wallet/puzzles/p2_singleton_aggregator.clsp.hex +1 -0
  918. chia/wallet/puzzles/p2_singleton_or_delayed_puzhash.clsp +50 -0
  919. chia/wallet/puzzles/p2_singleton_or_delayed_puzhash.clsp.hex +1 -0
  920. chia/wallet/puzzles/p2_singleton_via_delegated_puzzle.clsp +47 -0
  921. chia/wallet/puzzles/p2_singleton_via_delegated_puzzle.clsp.hex +1 -0
  922. chia/wallet/puzzles/puzzle_utils.py +34 -0
  923. chia/wallet/puzzles/settlement_payments.clsp +49 -0
  924. chia/wallet/puzzles/settlement_payments.clsp.hex +1 -0
  925. chia/wallet/puzzles/sha256tree.clib +11 -0
  926. chia/wallet/puzzles/singleton_launcher.clsp +16 -0
  927. chia/wallet/puzzles/singleton_launcher.clsp.hex +1 -0
  928. chia/wallet/puzzles/singleton_top_layer.clsp +177 -0
  929. chia/wallet/puzzles/singleton_top_layer.clsp.hex +1 -0
  930. chia/wallet/puzzles/singleton_top_layer.py +295 -0
  931. chia/wallet/puzzles/singleton_top_layer_v1_1.clsp +107 -0
  932. chia/wallet/puzzles/singleton_top_layer_v1_1.clsp.hex +1 -0
  933. chia/wallet/puzzles/singleton_top_layer_v1_1.py +344 -0
  934. chia/wallet/puzzles/singleton_truths.clib +21 -0
  935. chia/wallet/puzzles/tails.py +344 -0
  936. chia/wallet/puzzles/utility_macros.clib +48 -0
  937. chia/wallet/signer_protocol.py +126 -0
  938. chia/wallet/singleton.py +106 -0
  939. chia/wallet/singleton_record.py +30 -0
  940. chia/wallet/trade_manager.py +1088 -0
  941. chia/wallet/trade_record.py +67 -0
  942. chia/wallet/trading/__init__.py +0 -0
  943. chia/wallet/trading/offer.py +703 -0
  944. chia/wallet/trading/trade_status.py +13 -0
  945. chia/wallet/trading/trade_store.py +526 -0
  946. chia/wallet/transaction_record.py +143 -0
  947. chia/wallet/transaction_sorting.py +14 -0
  948. chia/wallet/uncurried_puzzle.py +17 -0
  949. chia/wallet/util/__init__.py +0 -0
  950. chia/wallet/util/address_type.py +55 -0
  951. chia/wallet/util/blind_signer_tl.py +168 -0
  952. chia/wallet/util/clvm_streamable.py +203 -0
  953. chia/wallet/util/compute_hints.py +66 -0
  954. chia/wallet/util/compute_memos.py +45 -0
  955. chia/wallet/util/curry_and_treehash.py +90 -0
  956. chia/wallet/util/debug_spend_bundle.py +234 -0
  957. chia/wallet/util/merkle_tree.py +100 -0
  958. chia/wallet/util/merkle_utils.py +102 -0
  959. chia/wallet/util/new_peak_queue.py +82 -0
  960. chia/wallet/util/notifications.py +12 -0
  961. chia/wallet/util/peer_request_cache.py +174 -0
  962. chia/wallet/util/puzzle_compression.py +96 -0
  963. chia/wallet/util/puzzle_decorator.py +100 -0
  964. chia/wallet/util/puzzle_decorator_type.py +7 -0
  965. chia/wallet/util/query_filter.py +60 -0
  966. chia/wallet/util/transaction_type.py +23 -0
  967. chia/wallet/util/tx_config.py +158 -0
  968. chia/wallet/util/wallet_sync_utils.py +348 -0
  969. chia/wallet/util/wallet_types.py +65 -0
  970. chia/wallet/vc_wallet/__init__.py +0 -0
  971. chia/wallet/vc_wallet/cr_cat_drivers.py +663 -0
  972. chia/wallet/vc_wallet/cr_cat_wallet.py +875 -0
  973. chia/wallet/vc_wallet/cr_outer_puzzle.py +102 -0
  974. chia/wallet/vc_wallet/cr_puzzles/__init__.py +0 -0
  975. chia/wallet/vc_wallet/cr_puzzles/conditions_w_fee_announce.clsp +3 -0
  976. chia/wallet/vc_wallet/cr_puzzles/conditions_w_fee_announce.clsp.hex +1 -0
  977. chia/wallet/vc_wallet/cr_puzzles/credential_restriction.clsp +304 -0
  978. chia/wallet/vc_wallet/cr_puzzles/credential_restriction.clsp.hex +1 -0
  979. chia/wallet/vc_wallet/cr_puzzles/flag_proofs_checker.clsp +45 -0
  980. chia/wallet/vc_wallet/cr_puzzles/flag_proofs_checker.clsp.hex +1 -0
  981. chia/wallet/vc_wallet/vc_drivers.py +838 -0
  982. chia/wallet/vc_wallet/vc_puzzles/__init__.py +0 -0
  983. chia/wallet/vc_wallet/vc_puzzles/covenant_layer.clsp +30 -0
  984. chia/wallet/vc_wallet/vc_puzzles/covenant_layer.clsp.hex +1 -0
  985. chia/wallet/vc_wallet/vc_puzzles/eml_covenant_morpher.clsp +75 -0
  986. chia/wallet/vc_wallet/vc_puzzles/eml_covenant_morpher.clsp.hex +1 -0
  987. chia/wallet/vc_wallet/vc_puzzles/eml_transfer_program_covenant_adapter.clsp +32 -0
  988. chia/wallet/vc_wallet/vc_puzzles/eml_transfer_program_covenant_adapter.clsp.hex +1 -0
  989. chia/wallet/vc_wallet/vc_puzzles/eml_update_metadata_with_DID.clsp +80 -0
  990. chia/wallet/vc_wallet/vc_puzzles/eml_update_metadata_with_DID.clsp.hex +1 -0
  991. chia/wallet/vc_wallet/vc_puzzles/exigent_metadata_layer.clsp +163 -0
  992. chia/wallet/vc_wallet/vc_puzzles/exigent_metadata_layer.clsp.hex +1 -0
  993. chia/wallet/vc_wallet/vc_puzzles/p2_announced_delegated_puzzle.clsp +16 -0
  994. chia/wallet/vc_wallet/vc_puzzles/p2_announced_delegated_puzzle.clsp.hex +1 -0
  995. chia/wallet/vc_wallet/vc_puzzles/standard_vc_backdoor_puzzle.clsp +74 -0
  996. chia/wallet/vc_wallet/vc_puzzles/standard_vc_backdoor_puzzle.clsp.hex +1 -0
  997. chia/wallet/vc_wallet/vc_puzzles/std_parent_morpher.clsp +23 -0
  998. chia/wallet/vc_wallet/vc_puzzles/std_parent_morpher.clsp.hex +1 -0
  999. chia/wallet/vc_wallet/vc_puzzles/viral_backdoor.clsp +64 -0
  1000. chia/wallet/vc_wallet/vc_puzzles/viral_backdoor.clsp.hex +1 -0
  1001. chia/wallet/vc_wallet/vc_store.py +263 -0
  1002. chia/wallet/vc_wallet/vc_wallet.py +638 -0
  1003. chia/wallet/wallet.py +698 -0
  1004. chia/wallet/wallet_action_scope.py +95 -0
  1005. chia/wallet/wallet_blockchain.py +244 -0
  1006. chia/wallet/wallet_coin_record.py +72 -0
  1007. chia/wallet/wallet_coin_store.py +351 -0
  1008. chia/wallet/wallet_info.py +36 -0
  1009. chia/wallet/wallet_interested_store.py +188 -0
  1010. chia/wallet/wallet_nft_store.py +279 -0
  1011. chia/wallet/wallet_node.py +1769 -0
  1012. chia/wallet/wallet_node_api.py +201 -0
  1013. chia/wallet/wallet_pool_store.py +120 -0
  1014. chia/wallet/wallet_protocol.py +90 -0
  1015. chia/wallet/wallet_puzzle_store.py +365 -0
  1016. chia/wallet/wallet_retry_store.py +70 -0
  1017. chia/wallet/wallet_singleton_store.py +258 -0
  1018. chia/wallet/wallet_spend_bundle.py +41 -0
  1019. chia/wallet/wallet_state_manager.py +2820 -0
  1020. chia/wallet/wallet_transaction_store.py +470 -0
  1021. chia/wallet/wallet_user_store.py +110 -0
  1022. chia/wallet/wallet_weight_proof_handler.py +126 -0
  1023. chia_blockchain-2.4.4.dist-info/LICENSE +201 -0
  1024. chia_blockchain-2.4.4.dist-info/METADATA +161 -0
  1025. chia_blockchain-2.4.4.dist-info/RECORD +1028 -0
  1026. chia_blockchain-2.4.4.dist-info/WHEEL +4 -0
  1027. chia_blockchain-2.4.4.dist-info/entry_points.txt +17 -0
  1028. mozilla-ca/cacert.pem +3666 -0
@@ -0,0 +1,1088 @@
1
+ from __future__ import annotations
2
+
3
+ import dataclasses
4
+ import logging
5
+ import time
6
+ from collections import deque
7
+ from typing import TYPE_CHECKING, Any, Deque, Dict, List, Optional, Set, Tuple, Union
8
+
9
+ from typing_extensions import Literal
10
+
11
+ from chia.data_layer.data_layer_wallet import DataLayerWallet
12
+ from chia.protocols.wallet_protocol import CoinState
13
+ from chia.server.ws_connection import WSChiaConnection
14
+ from chia.types.blockchain_format.coin import Coin, coin_as_list
15
+ from chia.types.blockchain_format.program import Program
16
+ from chia.types.blockchain_format.sized_bytes import bytes32
17
+ from chia.types.spend_bundle import estimate_fees
18
+ from chia.util.db_wrapper import DBWrapper2
19
+ from chia.util.hash import std_hash
20
+ from chia.util.ints import uint32, uint64
21
+ from chia.wallet.cat_wallet.cat_wallet import CATWallet
22
+ from chia.wallet.conditions import (
23
+ AssertCoinAnnouncement,
24
+ Condition,
25
+ ConditionValidTimes,
26
+ CreateCoinAnnouncement,
27
+ parse_conditions_non_consensus,
28
+ parse_timelock_info,
29
+ )
30
+ from chia.wallet.db_wallet.db_wallet_puzzles import ACS_MU_PH
31
+ from chia.wallet.nft_wallet.nft_wallet import NFTWallet
32
+ from chia.wallet.outer_puzzles import AssetType
33
+ from chia.wallet.payment import Payment
34
+ from chia.wallet.puzzle_drivers import PuzzleInfo, Solver
35
+ from chia.wallet.puzzles.load_clvm import load_clvm_maybe_recompile
36
+ from chia.wallet.trade_record import TradeRecord
37
+ from chia.wallet.trading.offer import NotarizedPayment, Offer
38
+ from chia.wallet.trading.trade_status import TradeStatus
39
+ from chia.wallet.trading.trade_store import TradeStore
40
+ from chia.wallet.transaction_record import TransactionRecord
41
+ from chia.wallet.uncurried_puzzle import uncurry_puzzle
42
+ from chia.wallet.util.compute_hints import compute_spend_hints_and_additions
43
+ from chia.wallet.util.query_filter import HashFilter
44
+ from chia.wallet.util.transaction_type import TransactionType
45
+ from chia.wallet.util.wallet_types import WalletType
46
+ from chia.wallet.vc_wallet.cr_cat_drivers import ProofsChecker, construct_pending_approval_state
47
+ from chia.wallet.vc_wallet.vc_wallet import VCWallet
48
+ from chia.wallet.wallet import Wallet
49
+ from chia.wallet.wallet_action_scope import WalletActionScope
50
+ from chia.wallet.wallet_coin_record import WalletCoinRecord
51
+ from chia.wallet.wallet_protocol import WalletProtocol
52
+
53
+ if TYPE_CHECKING:
54
+ from chia.wallet.wallet_state_manager import WalletStateManager
55
+ from chia.wallet.wallet_spend_bundle import WalletSpendBundle
56
+
57
+ OFFER_MOD = load_clvm_maybe_recompile("settlement_payments.clsp")
58
+
59
+
60
+ class TradeManager:
61
+ """
62
+ This class is a driver for creating and accepting settlement_payments.clsp style offers.
63
+
64
+ By default, standard XCH is supported but to support other types of assets you must implement certain functions on
65
+ the asset's wallet as well as create a driver for its puzzle(s). Here is a guide to integrating a new types of
66
+ assets with this trade manager:
67
+
68
+ Puzzle Drivers:
69
+ - See chia/wallet/outer_puzzles.py for a full description of how to build these
70
+ - The `solve` method must be able to be solved by a Solver that looks like this:
71
+ Solver(
72
+ {
73
+ "coin": bytes
74
+ "parent_spend": bytes
75
+ "siblings": List[bytes] # other coins of the same type being offered
76
+ "sibling_spends": List[bytes] # The parent spends for the siblings
77
+ "sibling_puzzles": List[Program] # The inner puzzles of the siblings (always OFFER_MOD)
78
+ "sibling_solutions": List[Program] # The inner solution of the siblings
79
+ }
80
+ )
81
+
82
+ Wallet:
83
+ - Segments in this code that call general wallet methods are highlighted by comments: # ATTENTION: new wallets
84
+ - To be able to be traded, a wallet must implement these methods on itself:
85
+ - generate_signed_transaction(...) -> List[TransactionRecord] (See cat_wallet.py for full API)
86
+ - convert_puzzle_hash(puzzle_hash: bytes32) -> bytes32 # Converts a puzzlehash from outer to inner puzzle
87
+ - get_puzzle_info(asset_id: bytes32) -> PuzzleInfo
88
+ - get_coins_to_offer(asset_id: bytes32, amount: uint64) -> Set[Coin]
89
+ - If you would like assets from your wallet to be referenced with just a wallet ID, you must also implement:
90
+ - get_asset_id() -> bytes32
91
+ - Finally, you must make sure that your wallet will respond appropriately when these WSM methods are called:
92
+ - get_wallet_for_puzzle_info(puzzle_info: PuzzleInfo) -> <Your wallet>
93
+ - create_wallet_for_puzzle_info(..., puzzle_info: PuzzleInfo) -> <Your wallet> (See cat_wallet.py for full API)
94
+ - get_wallet_for_asset_id(asset_id: bytes32) -> <Your wallet>
95
+ """
96
+
97
+ wallet_state_manager: WalletStateManager
98
+ log: logging.Logger
99
+ trade_store: TradeStore
100
+ most_recently_deserialized_trade: Optional[Tuple[bytes32, Offer]]
101
+
102
+ @staticmethod
103
+ async def create(
104
+ wallet_state_manager: Any,
105
+ db_wrapper: DBWrapper2,
106
+ name: Optional[str] = None,
107
+ ) -> TradeManager:
108
+ self = TradeManager()
109
+ if name:
110
+ self.log = logging.getLogger(name)
111
+ else:
112
+ self.log = logging.getLogger(__name__)
113
+
114
+ self.wallet_state_manager = wallet_state_manager
115
+ self.trade_store = await TradeStore.create(db_wrapper)
116
+ self.most_recently_deserialized_trade = None
117
+ return self
118
+
119
+ async def get_offers_with_status(self, status: TradeStatus) -> List[TradeRecord]:
120
+ records = await self.trade_store.get_trade_record_with_status(status)
121
+ return records
122
+
123
+ async def get_coins_of_interest(
124
+ self,
125
+ ) -> Set[bytes32]:
126
+ """
127
+ Returns list of coins we want to check if they are included in filter,
128
+ These will include coins that belong to us and coins that that on other side of treade
129
+ """
130
+ coin_ids = await self.trade_store.get_coin_ids_of_interest_with_trade_statuses(
131
+ trade_statuses=[TradeStatus.PENDING_ACCEPT, TradeStatus.PENDING_CONFIRM, TradeStatus.PENDING_CANCEL]
132
+ )
133
+ return coin_ids
134
+
135
+ async def get_trade_by_coin(self, coin: Coin) -> Optional[TradeRecord]:
136
+ all_trades = await self.get_all_trades()
137
+ for trade in all_trades:
138
+ if trade.status == TradeStatus.CANCELLED.value:
139
+ continue
140
+ if coin in trade.coins_of_interest:
141
+ return trade
142
+ return None
143
+
144
+ async def coins_of_interest_farmed(
145
+ self, coin_state: CoinState, fork_height: Optional[uint32], peer: WSChiaConnection
146
+ ) -> None:
147
+ """
148
+ If both our coins and other coins in trade got removed that means that trade was successfully executed
149
+ If coins from other side of trade got farmed without ours, that means that trade failed because either someone
150
+ else completed trade or other side of trade canceled the trade by doing a spend.
151
+ If our coins got farmed but coins from other side didn't, we successfully canceled trade by spending inputs.
152
+ """
153
+ self.log.info(f"coins_of_interest_farmed: {coin_state}")
154
+ trade = await self.get_trade_by_coin(coin_state.coin)
155
+ if trade is None:
156
+ self.log.error(f"Coin: {coin_state.coin}, not in any trade")
157
+ return
158
+ if coin_state.spent_height is None:
159
+ self.log.error(f"Coin: {coin_state.coin}, has not been spent so trade can remain valid")
160
+ # Then let's filter the offer into coins that WE offered
161
+ if (
162
+ self.most_recently_deserialized_trade is not None
163
+ and trade.trade_id == self.most_recently_deserialized_trade[0]
164
+ ):
165
+ offer = self.most_recently_deserialized_trade[1]
166
+ else:
167
+ offer = Offer.from_bytes(trade.offer)
168
+ self.most_recently_deserialized_trade = (trade.trade_id, offer)
169
+ primary_coin_ids = [c.name() for c in offer.removals()]
170
+ # TODO: Add `WalletCoinStore.get_coins`.
171
+ result = await self.wallet_state_manager.coin_store.get_coin_records(
172
+ coin_id_filter=HashFilter.include(primary_coin_ids)
173
+ )
174
+ our_primary_coins: List[Coin] = [cr.coin for cr in result.records]
175
+ our_additions: List[Coin] = list(
176
+ filter(lambda c: offer.get_root_removal(c) in our_primary_coins, offer.additions())
177
+ )
178
+ our_addition_ids: List[bytes32] = [c.name() for c in our_additions]
179
+
180
+ # And get all relevant coin states
181
+ coin_states = await self.wallet_state_manager.wallet_node.get_coin_state(
182
+ our_addition_ids,
183
+ peer=peer,
184
+ fork_height=fork_height,
185
+ )
186
+ assert coin_states is not None
187
+ coin_state_names: List[bytes32] = [cs.coin.name() for cs in coin_states]
188
+ # If any of our settlement_payments were spent, this offer was a success!
189
+ if set(our_addition_ids) == set(coin_state_names):
190
+ height = coin_state.spent_height
191
+ assert height is not None
192
+ await self.trade_store.set_status(trade.trade_id, TradeStatus.CONFIRMED, index=height)
193
+ tx_records: List[TransactionRecord] = await self.calculate_tx_records_for_offer(offer, False)
194
+ for tx in tx_records:
195
+ if TradeStatus(trade.status) == TradeStatus.PENDING_ACCEPT:
196
+ await self.wallet_state_manager.add_transaction(
197
+ dataclasses.replace(tx, confirmed_at_height=height, confirmed=True)
198
+ )
199
+
200
+ self.log.info(f"Trade with id: {trade.trade_id} confirmed at height: {height}")
201
+ else:
202
+ # In any other scenario this trade failed
203
+ await self.wallet_state_manager.delete_trade_transactions(trade.trade_id)
204
+ if trade.status == TradeStatus.PENDING_CANCEL.value:
205
+ await self.trade_store.set_status(trade.trade_id, TradeStatus.CANCELLED)
206
+ self.log.info(f"Trade with id: {trade.trade_id} canceled")
207
+ elif trade.status == TradeStatus.PENDING_CONFIRM.value:
208
+ await self.trade_store.set_status(trade.trade_id, TradeStatus.FAILED)
209
+ self.log.warning(f"Trade with id: {trade.trade_id} failed")
210
+
211
+ async def get_locked_coins(self) -> Dict[bytes32, WalletCoinRecord]:
212
+ """Returns a dictionary of confirmed coins that are locked by a trade."""
213
+ all_pending = []
214
+ pending_accept = await self.get_offers_with_status(TradeStatus.PENDING_ACCEPT)
215
+ pending_confirm = await self.get_offers_with_status(TradeStatus.PENDING_CONFIRM)
216
+ pending_cancel = await self.get_offers_with_status(TradeStatus.PENDING_CANCEL)
217
+ all_pending.extend(pending_accept)
218
+ all_pending.extend(pending_confirm)
219
+ all_pending.extend(pending_cancel)
220
+
221
+ coins_of_interest = []
222
+ for trade_offer in all_pending:
223
+ coins_of_interest.extend([c.name() for c in trade_offer.coins_of_interest])
224
+
225
+ # TODO:
226
+ # - No need to get the coin records here, we are only interested in the coin_id on the call site.
227
+ return (
228
+ await self.wallet_state_manager.coin_store.get_coin_records(
229
+ coin_id_filter=HashFilter.include(coins_of_interest)
230
+ )
231
+ ).coin_id_to_record
232
+
233
+ async def get_all_trades(self) -> List[TradeRecord]:
234
+ all: List[TradeRecord] = await self.trade_store.get_all_trades()
235
+ return all
236
+
237
+ async def get_trade_by_id(self, trade_id: bytes32) -> Optional[TradeRecord]:
238
+ record = await self.trade_store.get_trade_record(trade_id)
239
+ return record
240
+
241
+ async def fail_pending_offer(self, trade_id: bytes32) -> None:
242
+ await self.trade_store.set_status(trade_id, TradeStatus.FAILED)
243
+ self.wallet_state_manager.state_changed("offer_failed")
244
+
245
+ async def cancel_pending_offers(
246
+ self,
247
+ trades: List[bytes32],
248
+ action_scope: WalletActionScope,
249
+ fee: uint64 = uint64(0),
250
+ secure: bool = True, # Cancel with a transaction on chain
251
+ trade_cache: Dict[bytes32, TradeRecord] = {}, # Optional pre-fetched trade records for optimization
252
+ extra_conditions: Tuple[Condition, ...] = tuple(),
253
+ ) -> None:
254
+ """This will create a transaction that includes coins that were offered"""
255
+
256
+ # Need to do some pre-figuring of announcements that will be need to be made
257
+ announcement_nonce: bytes32 = std_hash(b"".join(trades))
258
+ trade_records: List[TradeRecord] = []
259
+ all_cancellation_coins: List[List[Coin]] = []
260
+ announcement_creations: Deque[CreateCoinAnnouncement] = deque()
261
+ announcement_assertions: Deque[AssertCoinAnnouncement] = deque()
262
+ for trade_id in trades:
263
+ if trade_id in trade_cache:
264
+ trade = trade_cache[trade_id]
265
+ else:
266
+ potential_trade = await self.trade_store.get_trade_record(trade_id)
267
+ if potential_trade is None:
268
+ self.log.error(f"Cannot find offer {trade_id.hex()}, skip cancellation.")
269
+ continue
270
+ else:
271
+ trade = potential_trade
272
+
273
+ cancellation_coins = Offer.from_bytes(trade.offer).get_cancellation_coins()
274
+ for coin in cancellation_coins:
275
+ creation = CreateCoinAnnouncement(msg=announcement_nonce, coin_id=coin.name())
276
+ announcement_creations.append(creation)
277
+ announcement_assertions.append(creation.corresponding_assertion())
278
+
279
+ trade_records.append(trade)
280
+ all_cancellation_coins.append(cancellation_coins)
281
+
282
+ # Make every coin assert the announcement from the one before them
283
+ announcement_assertions.rotate(1)
284
+
285
+ all_txs: List[TransactionRecord] = []
286
+ fee_to_pay: uint64 = fee
287
+ for trade, cancellation_coins in zip(trade_records, all_cancellation_coins):
288
+ self.log.info(f"Secure-Cancel pending offer with id trade_id {trade.trade_id.hex()}")
289
+
290
+ if not secure:
291
+ self.wallet_state_manager.state_changed("offer_cancelled")
292
+ await self.trade_store.set_status(trade.trade_id, TradeStatus.CANCELLED)
293
+ continue
294
+
295
+ cancellation_additions: List[Coin] = []
296
+ valid_times: ConditionValidTimes = parse_timelock_info(extra_conditions)
297
+ for coin in cancellation_coins:
298
+ wallet = await self.wallet_state_manager.get_wallet_for_coin(coin.name())
299
+
300
+ if wallet is None:
301
+ self.log.error(f"Cannot find wallet for offer {trade.trade_id}, skip cancellation.")
302
+ continue
303
+
304
+ new_ph = await wallet.wallet_state_manager.main_wallet.get_puzzle_hash(
305
+ new=(not action_scope.config.tx_config.reuse_puzhash)
306
+ )
307
+
308
+ if len(trade_records) > 1 or len(cancellation_coins) > 1:
309
+ announcement_conditions: Tuple[Condition, ...] = (
310
+ announcement_creations.popleft(),
311
+ announcement_assertions.popleft(),
312
+ )
313
+ else:
314
+ announcement_conditions = tuple()
315
+ async with action_scope.use() as interface:
316
+ interface.side_effects.selected_coins.append(coin)
317
+ # This should probably not switch on whether or not we're spending a XCH but it has to for now
318
+ if wallet.type() == WalletType.STANDARD_WALLET:
319
+ assert isinstance(wallet, Wallet)
320
+ if fee_to_pay > coin.amount:
321
+ selected_coins: Set[Coin] = await wallet.select_coins(
322
+ uint64(fee_to_pay - coin.amount),
323
+ action_scope,
324
+ )
325
+ selected_coins.add(coin)
326
+ else:
327
+ selected_coins = {coin}
328
+ async with self.wallet_state_manager.new_action_scope(
329
+ action_scope.config.tx_config.override(
330
+ excluded_coin_ids=[],
331
+ ),
332
+ push=False,
333
+ ) as inner_action_scope:
334
+ await wallet.generate_signed_transaction(
335
+ uint64(sum(c.amount for c in selected_coins) - fee_to_pay),
336
+ new_ph,
337
+ inner_action_scope,
338
+ origin_id=coin.name(),
339
+ fee=fee_to_pay,
340
+ coins=selected_coins,
341
+ extra_conditions=(*extra_conditions, *announcement_conditions),
342
+ )
343
+ else:
344
+ # ATTENTION: new_wallets
345
+ assert isinstance(wallet, (CATWallet, DataLayerWallet, NFTWallet))
346
+ async with self.wallet_state_manager.new_action_scope(
347
+ action_scope.config.tx_config.override(
348
+ excluded_coin_ids=[],
349
+ ),
350
+ push=False,
351
+ ) as inner_action_scope:
352
+ await wallet.generate_signed_transaction(
353
+ [coin.amount],
354
+ [new_ph],
355
+ inner_action_scope,
356
+ fee=fee_to_pay,
357
+ coins={coin},
358
+ extra_conditions=(*extra_conditions, *announcement_conditions),
359
+ )
360
+
361
+ cancellation_additions.extend(
362
+ [
363
+ add
364
+ for tx in inner_action_scope.side_effects.transactions
365
+ if tx.spend_bundle is not None
366
+ for add in tx.spend_bundle.additions()
367
+ ]
368
+ )
369
+ all_txs.extend(inner_action_scope.side_effects.transactions)
370
+ fee_to_pay = uint64(0)
371
+ extra_conditions = tuple()
372
+
373
+ incoming_tx = TransactionRecord(
374
+ confirmed_at_height=uint32(0),
375
+ created_at_time=uint64(int(time.time())),
376
+ to_puzzle_hash=new_ph,
377
+ amount=uint64(coin.amount),
378
+ fee_amount=fee,
379
+ confirmed=False,
380
+ sent=uint32(10),
381
+ spend_bundle=None,
382
+ additions=[],
383
+ removals=[coin],
384
+ wallet_id=wallet.id(),
385
+ sent_to=[],
386
+ trade_id=None,
387
+ type=uint32(TransactionType.INCOMING_TX.value),
388
+ name=cancellation_additions[0].name(),
389
+ memos=[],
390
+ valid_times=valid_times,
391
+ )
392
+ all_txs.append(incoming_tx)
393
+
394
+ await self.trade_store.set_status(trade.trade_id, TradeStatus.PENDING_CANCEL)
395
+
396
+ if secure:
397
+ async with action_scope.use() as interface:
398
+ # We have to combine the spend bundle for these since they are tied with announcements
399
+ all_tx_names = [tx.name for tx in all_txs]
400
+ interface.side_effects.transactions = [
401
+ tx for tx in interface.side_effects.transactions if tx.name not in all_tx_names
402
+ ]
403
+ final_spend_bundle = WalletSpendBundle.aggregate(
404
+ [tx.spend_bundle for tx in all_txs if tx.spend_bundle is not None]
405
+ )
406
+ interface.side_effects.transactions.append(
407
+ dataclasses.replace(all_txs[0], spend_bundle=final_spend_bundle, name=final_spend_bundle.name())
408
+ )
409
+ interface.side_effects.transactions.extend(
410
+ [dataclasses.replace(tx, spend_bundle=None, fee_amount=fee) for tx in all_txs[1:]]
411
+ )
412
+
413
+ async def save_trade(self, trade: TradeRecord, offer: Offer) -> None:
414
+ offer_name: bytes32 = offer.name()
415
+ await self.trade_store.add_trade_record(trade, offer_name)
416
+
417
+ # We want to subscribe to the coin IDs of all coins that are not the ephemeral offer coins
418
+ offered_coins: Set[Coin] = {value for values in offer.get_offered_coins().values() for value in values}
419
+ non_offer_additions: Set[Coin] = set(offer.additions()) ^ offered_coins
420
+ non_offer_removals: Set[Coin] = set(offer.removals()) ^ offered_coins
421
+ await self.wallet_state_manager.add_interested_coin_ids(
422
+ [coin.name() for coin in (*non_offer_removals, *non_offer_additions)]
423
+ )
424
+
425
+ self.wallet_state_manager.state_changed("offer_added")
426
+
427
+ async def create_offer_for_ids(
428
+ self,
429
+ offer: Dict[Union[int, bytes32], int],
430
+ action_scope: WalletActionScope,
431
+ driver_dict: Optional[Dict[bytes32, PuzzleInfo]] = None,
432
+ solver: Optional[Solver] = None,
433
+ fee: uint64 = uint64(0),
434
+ validate_only: bool = False,
435
+ extra_conditions: Tuple[Condition, ...] = tuple(),
436
+ taking: bool = False,
437
+ ) -> Union[Tuple[Literal[True], TradeRecord, None], Tuple[Literal[False], None, str]]:
438
+ if driver_dict is None:
439
+ driver_dict = {}
440
+ if solver is None:
441
+ solver = Solver({})
442
+ result = await self._create_offer_for_ids(
443
+ offer,
444
+ action_scope,
445
+ driver_dict,
446
+ solver,
447
+ fee=fee,
448
+ extra_conditions=extra_conditions,
449
+ taking=taking,
450
+ )
451
+ if not result[0] or result[1] is None:
452
+ raise Exception(f"Error creating offer: {result[2]}")
453
+
454
+ success, created_offer, error = result
455
+
456
+ now = uint64(int(time.time()))
457
+ trade_offer: TradeRecord = TradeRecord(
458
+ confirmed_at_index=uint32(0),
459
+ accepted_at_time=None,
460
+ created_at_time=now,
461
+ is_my_offer=True,
462
+ sent=uint32(0),
463
+ offer=bytes(created_offer),
464
+ taken_offer=None,
465
+ coins_of_interest=created_offer.get_involved_coins(),
466
+ trade_id=created_offer.name(),
467
+ status=uint32(TradeStatus.PENDING_ACCEPT.value),
468
+ sent_to=[],
469
+ valid_times=parse_timelock_info(extra_conditions),
470
+ )
471
+
472
+ if success is True and trade_offer is not None and not validate_only:
473
+ await self.save_trade(trade_offer, created_offer)
474
+
475
+ return success, trade_offer, error
476
+
477
+ async def _create_offer_for_ids(
478
+ self,
479
+ offer_dict: Dict[Union[int, bytes32], int],
480
+ action_scope: WalletActionScope,
481
+ driver_dict: Optional[Dict[bytes32, PuzzleInfo]] = None,
482
+ solver: Optional[Solver] = None,
483
+ fee: uint64 = uint64(0),
484
+ extra_conditions: Tuple[Condition, ...] = tuple(),
485
+ taking: bool = False,
486
+ ) -> Union[Tuple[Literal[True], Offer, None], Tuple[Literal[False], None, str]]:
487
+ """
488
+ Offer is dictionary of wallet ids and amount
489
+ """
490
+ if driver_dict is None:
491
+ driver_dict = {}
492
+ if solver is None:
493
+ solver = Solver({})
494
+ try:
495
+ coins_to_offer: Dict[Union[int, bytes32], Set[Coin]] = {}
496
+ requested_payments: Dict[Optional[bytes32], List[Payment]] = {}
497
+ offer_dict_no_ints: Dict[Optional[bytes32], int] = {}
498
+ for id, amount in offer_dict.items():
499
+ asset_id: Optional[bytes32] = None
500
+ # asset_id can either be none if asset is XCH or
501
+ # bytes32 if another asset (e.g. NFT, CAT)
502
+ if amount > 0:
503
+ # this is what we are receiving in the trade
504
+ memos: List[bytes] = []
505
+ if isinstance(id, int):
506
+ wallet_id = uint32(id)
507
+ wallet = self.wallet_state_manager.wallets.get(wallet_id)
508
+ assert isinstance(wallet, (CATWallet, Wallet))
509
+ p2_ph: bytes32 = await wallet.get_puzzle_hash(
510
+ new=not action_scope.config.tx_config.reuse_puzhash
511
+ )
512
+ if wallet.type() != WalletType.STANDARD_WALLET:
513
+ if callable(getattr(wallet, "get_asset_id", None)): # ATTENTION: new wallets
514
+ assert isinstance(wallet, CATWallet)
515
+ asset_id = bytes32(bytes.fromhex(wallet.get_asset_id()))
516
+ memos = [p2_ph]
517
+ else:
518
+ raise ValueError(
519
+ f"Cannot request assets from wallet id {wallet.id()} without more information"
520
+ )
521
+ else:
522
+ p2_ph = await self.wallet_state_manager.main_wallet.get_puzzle_hash(
523
+ new=not action_scope.config.tx_config.reuse_puzhash
524
+ )
525
+ asset_id = id
526
+ wallet = await self.wallet_state_manager.get_wallet_for_asset_id(asset_id.hex())
527
+ memos = [p2_ph]
528
+ requested_payments[asset_id] = [Payment(p2_ph, uint64(amount), memos)]
529
+ elif amount < 0:
530
+ # this is what we are sending in the trade
531
+ if isinstance(id, int):
532
+ wallet_id = uint32(id)
533
+ wallet = self.wallet_state_manager.wallets[wallet_id]
534
+ if wallet.type() != WalletType.STANDARD_WALLET:
535
+ if callable(getattr(wallet, "get_asset_id", None)): # ATTENTION: new wallets
536
+ assert isinstance(wallet, CATWallet)
537
+ asset_id = bytes32(bytes.fromhex(wallet.get_asset_id()))
538
+ else:
539
+ raise ValueError(
540
+ f"Cannot offer assets from wallet id {wallet.id()} without more information"
541
+ )
542
+ else:
543
+ asset_id = id
544
+ wallet = await self.wallet_state_manager.get_wallet_for_asset_id(asset_id.hex())
545
+ assert wallet is not None
546
+ if not callable(getattr(wallet, "get_coins_to_offer", None)): # ATTENTION: new wallets
547
+ raise ValueError(f"Cannot offer coins from wallet id {wallet.id()}")
548
+ # For the XCH wallet also include the fee amount to the coins we use to pay this offer
549
+ amount_to_select = abs(amount)
550
+ if wallet.type() == WalletType.STANDARD_WALLET:
551
+ amount_to_select += fee
552
+ assert isinstance(wallet, (CATWallet, DataLayerWallet, NFTWallet, Wallet))
553
+ if isinstance(wallet, DataLayerWallet):
554
+ assert asset_id is not None
555
+ coins_to_offer[id] = await wallet.get_coins_to_offer(launcher_id=asset_id)
556
+ elif isinstance(wallet, NFTWallet):
557
+ assert asset_id is not None
558
+ coins_to_offer[id] = await wallet.get_coins_to_offer(nft_id=asset_id)
559
+ else:
560
+ coins_to_offer[id] = await wallet.get_coins_to_offer(
561
+ asset_id=asset_id,
562
+ amount=uint64(amount_to_select),
563
+ action_scope=action_scope,
564
+ )
565
+ # Note: if we use check_for_special_offer_making, this is not used.
566
+ elif amount == 0:
567
+ raise ValueError("You cannot offer nor request 0 amount of something")
568
+
569
+ offer_dict_no_ints[asset_id] = amount
570
+
571
+ if asset_id is not None and wallet is not None: # if this asset is not XCH
572
+ if callable(getattr(wallet, "get_puzzle_info", None)):
573
+ assert isinstance(wallet, (CATWallet, DataLayerWallet, NFTWallet))
574
+ puzzle_driver: PuzzleInfo = await wallet.get_puzzle_info(asset_id)
575
+ if asset_id in driver_dict and driver_dict[asset_id] != puzzle_driver:
576
+ # ignore the case if we're an nft transferring the did owner
577
+ if self.check_for_owner_change_in_drivers(puzzle_driver, driver_dict[asset_id]):
578
+ driver_dict[asset_id] = puzzle_driver
579
+ else:
580
+ raise ValueError(
581
+ f"driver_dict specified {driver_dict[asset_id]}, was expecting {puzzle_driver}"
582
+ )
583
+ else:
584
+ driver_dict[asset_id] = puzzle_driver
585
+ else:
586
+ raise ValueError(f"Wallet for asset id {asset_id} is not properly integrated with TradeManager")
587
+
588
+ requested_payments = await self.check_for_requested_payment_modifications(
589
+ requested_payments, driver_dict, taking
590
+ )
591
+
592
+ potential_special_offer: Optional[Offer] = await self.check_for_special_offer_making(
593
+ offer_dict_no_ints,
594
+ driver_dict,
595
+ action_scope,
596
+ solver,
597
+ fee,
598
+ extra_conditions,
599
+ )
600
+
601
+ if potential_special_offer is not None:
602
+ return True, potential_special_offer, None
603
+
604
+ all_coins: List[Coin] = [c for coins in coins_to_offer.values() for c in coins]
605
+ notarized_payments: Dict[Optional[bytes32], List[NotarizedPayment]] = Offer.notarize_payments(
606
+ requested_payments, all_coins
607
+ )
608
+ announcements_to_assert = Offer.calculate_announcements(notarized_payments, driver_dict)
609
+
610
+ all_transactions: List[TransactionRecord] = []
611
+ fee_left_to_pay: uint64 = fee
612
+ # The access of the sorted keys here makes sure we create the XCH transaction first to make sure we pay fee
613
+ # with the XCH side of the offer and don't create an extra fee transaction in other wallets.
614
+ for id in sorted(coins_to_offer.keys(), key=lambda id: id != 1):
615
+ selected_coins = coins_to_offer[id]
616
+ if isinstance(id, int):
617
+ wallet = self.wallet_state_manager.wallets.get(uint32(id))
618
+ else:
619
+ wallet = await self.wallet_state_manager.get_wallet_for_asset_id(id.hex())
620
+ async with self.wallet_state_manager.new_action_scope(
621
+ action_scope.config.tx_config, push=False
622
+ ) as inner_action_scope:
623
+ # This should probably not switch on whether or not we're spending XCH but it has to for now
624
+ assert wallet is not None
625
+ if wallet.type() == WalletType.STANDARD_WALLET:
626
+ assert isinstance(wallet, Wallet)
627
+ await wallet.generate_signed_transaction(
628
+ uint64(abs(offer_dict[id])),
629
+ Offer.ph(),
630
+ inner_action_scope,
631
+ fee=fee_left_to_pay,
632
+ coins=selected_coins,
633
+ extra_conditions=(*extra_conditions, *announcements_to_assert),
634
+ )
635
+ elif wallet.type() == WalletType.NFT:
636
+ assert isinstance(wallet, NFTWallet)
637
+ # This is to generate the tx for specific nft assets, i.e. not using
638
+ # wallet_id as the selector which would select any coins from nft_wallet
639
+ amounts = [coin.amount for coin in selected_coins]
640
+ await wallet.generate_signed_transaction(
641
+ # [abs(offer_dict[id])],
642
+ amounts,
643
+ [Offer.ph()],
644
+ inner_action_scope,
645
+ fee=fee_left_to_pay,
646
+ coins=selected_coins,
647
+ extra_conditions=(*extra_conditions, *announcements_to_assert),
648
+ )
649
+ else:
650
+ # ATTENTION: new_wallets
651
+ assert isinstance(wallet, (CATWallet, DataLayerWallet))
652
+ await wallet.generate_signed_transaction(
653
+ [uint64(abs(offer_dict[id]))],
654
+ [Offer.ph()],
655
+ inner_action_scope,
656
+ fee=fee_left_to_pay,
657
+ coins=selected_coins,
658
+ extra_conditions=(*extra_conditions, *announcements_to_assert),
659
+ add_authorizations_to_cr_cats=False,
660
+ )
661
+
662
+ all_transactions.extend(inner_action_scope.side_effects.transactions)
663
+
664
+ fee_left_to_pay = uint64(0)
665
+ extra_conditions = tuple()
666
+
667
+ async with action_scope.use() as interface:
668
+ interface.side_effects.transactions.extend(all_transactions)
669
+
670
+ total_spend_bundle = WalletSpendBundle.aggregate(
671
+ [x.spend_bundle for x in all_transactions if x.spend_bundle is not None]
672
+ )
673
+
674
+ offer = Offer(notarized_payments, total_spend_bundle, driver_dict)
675
+ return True, offer, None
676
+
677
+ except Exception as e:
678
+ self.log.exception("Error creating trade offer")
679
+ return False, None, str(e)
680
+
681
+ async def maybe_create_wallets_for_offer(self, offer: Offer) -> None:
682
+ for key in offer.arbitrage():
683
+ wsm = self.wallet_state_manager
684
+ if key is None:
685
+ continue
686
+ # ATTENTION: new_wallets
687
+ exists = await wsm.get_wallet_for_puzzle_info(offer.driver_dict[key])
688
+ if exists is None:
689
+ await wsm.create_wallet_for_puzzle_info(offer.driver_dict[key])
690
+
691
+ async def check_offer_validity(self, offer: Offer, peer: WSChiaConnection) -> bool:
692
+ all_removals: List[Coin] = offer.removals()
693
+ all_removal_names: List[bytes32] = [c.name() for c in all_removals]
694
+ non_ephemeral_removals: List[Coin] = list(
695
+ filter(lambda c: c.parent_coin_info not in all_removal_names, all_removals)
696
+ )
697
+ coin_states = await self.wallet_state_manager.wallet_node.get_coin_state(
698
+ [c.name() for c in non_ephemeral_removals], peer=peer
699
+ )
700
+
701
+ return len(coin_states) == len(non_ephemeral_removals) and all([cs.spent_height is None for cs in coin_states])
702
+
703
+ async def calculate_tx_records_for_offer(self, offer: Offer, validate: bool) -> List[TransactionRecord]:
704
+ if validate:
705
+ final_spend_bundle: WalletSpendBundle = offer.to_valid_spend()
706
+ hint_dict: Dict[bytes32, bytes32] = {}
707
+ additions_dict: Dict[bytes32, Coin] = {}
708
+ for hinted_coins, _ in (
709
+ compute_spend_hints_and_additions(spend) for spend in final_spend_bundle.coin_spends
710
+ ):
711
+ hint_dict.update({id: hc.hint for id, hc in hinted_coins.items() if hc.hint is not None})
712
+ additions_dict.update({id: hc.coin for id, hc in hinted_coins.items()})
713
+ all_additions: List[Coin] = list(a for a in additions_dict.values())
714
+ else:
715
+ final_spend_bundle = offer._bundle
716
+ hint_dict = offer.hints()
717
+ all_additions = offer.additions()
718
+
719
+ settlement_coins: List[Coin] = [c for coins in offer.get_offered_coins().values() for c in coins]
720
+ settlement_coin_ids: List[bytes32] = [c.name() for c in settlement_coins]
721
+
722
+ removals: List[Coin] = final_spend_bundle.removals()
723
+ additions: List[Coin] = list(a for a in all_additions if a not in removals)
724
+ valid_times: ConditionValidTimes = parse_timelock_info(
725
+ parse_conditions_non_consensus(
726
+ condition
727
+ for spend in final_spend_bundle.coin_spends
728
+ for condition in spend.puzzle_reveal.to_program().run(spend.solution.to_program()).as_iter()
729
+ )
730
+ )
731
+ # this executes the puzzles again
732
+ all_fees = uint64(estimate_fees(final_spend_bundle))
733
+
734
+ txs = []
735
+
736
+ addition_dict: Dict[uint32, List[Coin]] = {}
737
+ for addition in additions:
738
+ wallet_identifier = await self.wallet_state_manager.get_wallet_identifier_for_coin(
739
+ addition,
740
+ hint_dict,
741
+ )
742
+ if wallet_identifier is not None:
743
+ if addition.parent_coin_info in settlement_coin_ids:
744
+ wallet = self.wallet_state_manager.wallets[wallet_identifier.id]
745
+ assert isinstance(wallet, (CATWallet, NFTWallet, Wallet))
746
+ to_puzzle_hash = await wallet.convert_puzzle_hash(addition.puzzle_hash) # ATTENTION: new wallets
747
+ txs.append(
748
+ TransactionRecord(
749
+ confirmed_at_height=uint32(0),
750
+ created_at_time=uint64(int(time.time())),
751
+ to_puzzle_hash=to_puzzle_hash,
752
+ amount=uint64(addition.amount),
753
+ fee_amount=uint64(0),
754
+ confirmed=False,
755
+ sent=uint32(10),
756
+ spend_bundle=None,
757
+ additions=[addition],
758
+ removals=[],
759
+ wallet_id=wallet_identifier.id,
760
+ sent_to=[],
761
+ trade_id=offer.name(),
762
+ type=uint32(TransactionType.INCOMING_TRADE.value),
763
+ name=std_hash(final_spend_bundle.name() + addition.name()),
764
+ memos=[(coin_id, [hint]) for coin_id, hint in hint_dict.items()],
765
+ valid_times=valid_times,
766
+ )
767
+ )
768
+ else: # This is change
769
+ addition_dict.setdefault(wallet_identifier.id, [])
770
+ addition_dict[wallet_identifier.id].append(addition)
771
+
772
+ # While we want additions to show up as separate records, removals of the same wallet should show as one
773
+ removal_dict: Dict[uint32, List[Coin]] = {}
774
+ for removal in removals:
775
+ wallet_identifier = await self.wallet_state_manager.get_wallet_identifier_for_coin(
776
+ removal,
777
+ hint_dict,
778
+ )
779
+ if wallet_identifier is not None:
780
+ removal_dict.setdefault(wallet_identifier.id, [])
781
+ removal_dict[wallet_identifier.id].append(removal)
782
+
783
+ all_removals: List[bytes32] = [r.name() for removals in removal_dict.values() for r in removals]
784
+
785
+ for wid, grouped_removals in removal_dict.items():
786
+ wallet = self.wallet_state_manager.wallets[wid]
787
+ to_puzzle_hash = bytes32([1] * 32) # We use all zeros to be clear not to send here
788
+ removal_tree_hash = Program.to([coin_as_list(rem) for rem in grouped_removals]).get_tree_hash()
789
+ # We also need to calculate the sent amount
790
+ removed: int = sum(c.amount for c in grouped_removals)
791
+ removed_ids: List[bytes32] = [c.name() for c in grouped_removals]
792
+ all_additions_from_grouped_removals: List[Coin] = [
793
+ c for c in all_additions if c.parent_coin_info in removed_ids
794
+ ]
795
+ potential_change_coins: List[Coin] = addition_dict[wid] if wid in addition_dict else []
796
+ change_coins: List[Coin] = [c for c in potential_change_coins if c.parent_coin_info in all_removals]
797
+ change_amount: int = sum(c.amount for c in change_coins)
798
+ sent_amount: int = (
799
+ removed
800
+ - change_amount
801
+ - (
802
+ removed - sum(c.amount for c in all_additions_from_grouped_removals) # removals - additions == fees
803
+ if wallet == self.wallet_state_manager.main_wallet
804
+ else 0
805
+ )
806
+ )
807
+ txs.append(
808
+ TransactionRecord(
809
+ confirmed_at_height=uint32(0),
810
+ created_at_time=uint64(int(time.time())),
811
+ to_puzzle_hash=to_puzzle_hash,
812
+ amount=uint64(sent_amount),
813
+ fee_amount=all_fees,
814
+ confirmed=False,
815
+ sent=uint32(10),
816
+ spend_bundle=None,
817
+ additions=change_coins,
818
+ removals=grouped_removals,
819
+ wallet_id=wallet.id(),
820
+ sent_to=[],
821
+ trade_id=offer.name(),
822
+ type=uint32(TransactionType.OUTGOING_TRADE.value),
823
+ name=std_hash(final_spend_bundle.name() + removal_tree_hash),
824
+ memos=[(coin_id, [hint]) for coin_id, hint in hint_dict.items()],
825
+ valid_times=valid_times,
826
+ )
827
+ )
828
+
829
+ return txs
830
+
831
+ async def respond_to_offer(
832
+ self,
833
+ offer: Offer,
834
+ peer: WSChiaConnection,
835
+ action_scope: WalletActionScope,
836
+ solver: Optional[Solver] = None,
837
+ fee: uint64 = uint64(0),
838
+ extra_conditions: Tuple[Condition, ...] = tuple(),
839
+ ) -> TradeRecord:
840
+ if solver is None:
841
+ solver = Solver({})
842
+ take_offer_dict: Dict[Union[bytes32, int], int] = {}
843
+ arbitrage: Dict[Optional[bytes32], int] = offer.arbitrage()
844
+
845
+ for asset_id, amount in arbitrage.items():
846
+ if asset_id is None:
847
+ wallet: Optional[WalletProtocol[Any]] = self.wallet_state_manager.main_wallet
848
+ assert wallet is not None
849
+ key: Union[bytes32, int] = int(wallet.id())
850
+ else:
851
+ # ATTENTION: new wallets
852
+ wallet = await self.wallet_state_manager.get_wallet_for_asset_id(asset_id.hex())
853
+ if wallet is None and amount < 0:
854
+ raise ValueError(f"Do not have a wallet for asset ID: {asset_id} to fulfill offer")
855
+ elif wallet is None or wallet.type() in [WalletType.NFT, WalletType.DATA_LAYER]:
856
+ key = asset_id
857
+ else:
858
+ key = int(wallet.id())
859
+ take_offer_dict[key] = amount
860
+
861
+ # First we validate that all of the coins in this offer exist
862
+ valid: bool = await self.check_offer_validity(offer, peer)
863
+ if not valid:
864
+ raise ValueError("This offer is no longer valid")
865
+ # We need to sandbox the transactions here because we're going to make our own
866
+ async with self.wallet_state_manager.new_action_scope(
867
+ action_scope.config.tx_config, push=False
868
+ ) as inner_action_scope:
869
+ result = await self._create_offer_for_ids(
870
+ take_offer_dict,
871
+ inner_action_scope,
872
+ offer.driver_dict,
873
+ solver,
874
+ fee=fee,
875
+ extra_conditions=extra_conditions,
876
+ taking=True,
877
+ )
878
+ if not result[0] or result[1] is None:
879
+ raise ValueError(result[2])
880
+
881
+ success, take_offer, error = result
882
+
883
+ complete_offer, valid_spend_solver = await self.check_for_final_modifications(
884
+ Offer.aggregate([offer, take_offer]), solver, inner_action_scope
885
+ )
886
+ self.log.info("COMPLETE OFFER: %s", complete_offer.to_bech32())
887
+ assert complete_offer.is_valid()
888
+ final_spend_bundle: WalletSpendBundle = complete_offer.to_valid_spend(
889
+ solver=Solver({**valid_spend_solver.info, **solver.info})
890
+ )
891
+ await self.maybe_create_wallets_for_offer(complete_offer)
892
+
893
+ tx_records: List[TransactionRecord] = await self.calculate_tx_records_for_offer(complete_offer, True)
894
+
895
+ trade_record: TradeRecord = TradeRecord(
896
+ confirmed_at_index=uint32(0),
897
+ accepted_at_time=uint64(int(time.time())),
898
+ created_at_time=uint64(int(time.time())),
899
+ is_my_offer=False,
900
+ sent=uint32(0),
901
+ offer=bytes(complete_offer),
902
+ taken_offer=bytes(offer),
903
+ coins_of_interest=complete_offer.get_involved_coins(),
904
+ trade_id=complete_offer.name(),
905
+ status=uint32(TradeStatus.PENDING_CONFIRM.value),
906
+ sent_to=[],
907
+ valid_times=parse_timelock_info(extra_conditions),
908
+ )
909
+
910
+ await self.save_trade(trade_record, offer)
911
+
912
+ async with action_scope.use() as interface:
913
+ interface.side_effects.transactions.extend(tx_records)
914
+ interface.side_effects.extra_spends.append(final_spend_bundle)
915
+
916
+ return trade_record
917
+
918
+ async def check_for_special_offer_making(
919
+ self,
920
+ offer_dict: Dict[Optional[bytes32], int],
921
+ driver_dict: Dict[bytes32, PuzzleInfo],
922
+ action_scope: WalletActionScope,
923
+ solver: Solver,
924
+ fee: uint64 = uint64(0),
925
+ extra_conditions: Tuple[Condition, ...] = tuple(),
926
+ ) -> Optional[Offer]:
927
+ for puzzle_info in driver_dict.values():
928
+ if (
929
+ puzzle_info.check_type([AssetType.SINGLETON.value, AssetType.METADATA.value, AssetType.OWNERSHIP.value])
930
+ and isinstance(puzzle_info.also().also()["transfer_program"], PuzzleInfo) # type: ignore
931
+ and puzzle_info.also().also()["transfer_program"].type() # type: ignore
932
+ == AssetType.ROYALTY_TRANSFER_PROGRAM.value
933
+ ):
934
+ return await NFTWallet.make_nft1_offer(
935
+ self.wallet_state_manager, offer_dict, driver_dict, action_scope, fee, extra_conditions
936
+ )
937
+ elif (
938
+ puzzle_info.check_type(
939
+ [
940
+ AssetType.SINGLETON.value,
941
+ AssetType.METADATA.value,
942
+ ]
943
+ )
944
+ and puzzle_info.also()["updater_hash"] == ACS_MU_PH # type: ignore
945
+ ):
946
+ return await DataLayerWallet.make_update_offer(
947
+ self.wallet_state_manager,
948
+ offer_dict,
949
+ driver_dict,
950
+ solver,
951
+ action_scope,
952
+ fee,
953
+ extra_conditions,
954
+ )
955
+ return None
956
+
957
+ def check_for_owner_change_in_drivers(self, puzzle_info: PuzzleInfo, driver_info: PuzzleInfo) -> bool:
958
+ if puzzle_info.check_type(
959
+ [
960
+ AssetType.SINGLETON.value,
961
+ AssetType.METADATA.value,
962
+ AssetType.OWNERSHIP.value,
963
+ ]
964
+ ) and driver_info.check_type(
965
+ [
966
+ AssetType.SINGLETON.value,
967
+ AssetType.METADATA.value,
968
+ AssetType.OWNERSHIP.value,
969
+ ]
970
+ ):
971
+ old_owner = driver_info.also().also().info["owner"] # type: ignore
972
+ puzzle_info.also().also().info["owner"] = old_owner # type: ignore
973
+ if driver_info == puzzle_info:
974
+ return True
975
+ return False
976
+
977
+ async def get_offer_summary(self, offer: Offer) -> Dict[str, Any]:
978
+ for puzzle_info in offer.driver_dict.values():
979
+ if (
980
+ puzzle_info.check_type(
981
+ [
982
+ AssetType.SINGLETON.value,
983
+ AssetType.METADATA.value,
984
+ ]
985
+ )
986
+ and puzzle_info.also()["updater_hash"] == ACS_MU_PH # type: ignore
987
+ ):
988
+ return await DataLayerWallet.get_offer_summary(offer)
989
+ # Otherwise just return the same thing as the RPC normally does
990
+ offered, requested, infos, valid_times = offer.summary()
991
+ return {
992
+ "offered": offered,
993
+ "requested": requested,
994
+ "fees": offer.fees(),
995
+ "additions": [c.name().hex() for c in offer.additions()],
996
+ "removals": [c.name().hex() for c in offer.removals()],
997
+ "infos": infos,
998
+ "valid_times": {
999
+ k: v
1000
+ for k, v in valid_times.to_json_dict().items()
1001
+ if k
1002
+ not in (
1003
+ "max_secs_after_created",
1004
+ "min_secs_since_created",
1005
+ "max_blocks_after_created",
1006
+ "min_blocks_since_created",
1007
+ )
1008
+ },
1009
+ }
1010
+
1011
+ async def check_for_final_modifications(
1012
+ self, offer: Offer, solver: Solver, action_scope: WalletActionScope
1013
+ ) -> Tuple[Offer, Solver]:
1014
+ for puzzle_info in offer.driver_dict.values():
1015
+ if (
1016
+ puzzle_info.check_type(
1017
+ [
1018
+ AssetType.SINGLETON.value,
1019
+ AssetType.METADATA.value,
1020
+ ]
1021
+ )
1022
+ and puzzle_info.also()["updater_hash"] == ACS_MU_PH # type: ignore
1023
+ ):
1024
+ return (await DataLayerWallet.finish_graftroot_solutions(offer, solver), Solver({}))
1025
+ elif puzzle_info.check_type(
1026
+ [
1027
+ AssetType.CAT.value,
1028
+ AssetType.CR.value,
1029
+ ]
1030
+ ):
1031
+ # get VC wallet
1032
+ for _, wallet in self.wallet_state_manager.wallets.items():
1033
+ if WalletType(wallet.type()) == WalletType.VC:
1034
+ assert isinstance(wallet, VCWallet)
1035
+ return await wallet.add_vc_authorization(offer, solver, action_scope)
1036
+ else:
1037
+ raise ValueError("No VCs to approve CR-CATs with") # pragma: no cover
1038
+
1039
+ return offer, Solver({})
1040
+
1041
+ async def check_for_requested_payment_modifications(
1042
+ self,
1043
+ requested_payments: Dict[Optional[bytes32], List[Payment]],
1044
+ driver_dict: Dict[bytes32, PuzzleInfo],
1045
+ taking: bool,
1046
+ ) -> Dict[Optional[bytes32], List[Payment]]:
1047
+ # This function exclusively deals with CR-CATs for now
1048
+ if not taking:
1049
+ for asset_id, puzzle_info in driver_dict.items():
1050
+ if puzzle_info.check_type(
1051
+ [
1052
+ AssetType.CAT.value,
1053
+ AssetType.CR.value,
1054
+ ]
1055
+ ):
1056
+ vc = await (
1057
+ await self.wallet_state_manager.get_or_create_vc_wallet()
1058
+ ).get_vc_with_provider_in_and_proofs(
1059
+ puzzle_info["also"]["authorized_providers"],
1060
+ ProofsChecker.from_program(uncurry_puzzle(puzzle_info["also"]["proofs_checker"])).flags,
1061
+ )
1062
+ if vc is None:
1063
+ raise ValueError("Cannot request CR-CATs that you cannot approve with a VC") # pragma: no cover
1064
+
1065
+ return {
1066
+ asset_id: (
1067
+ [
1068
+ dataclasses.replace(
1069
+ payment,
1070
+ puzzle_hash=construct_pending_approval_state(
1071
+ payment.puzzle_hash, payment.amount
1072
+ ).get_tree_hash(),
1073
+ )
1074
+ for payment in payments
1075
+ ]
1076
+ if asset_id is not None
1077
+ and driver_dict[asset_id].check_type(
1078
+ [
1079
+ AssetType.CAT.value,
1080
+ AssetType.CR.value,
1081
+ ]
1082
+ )
1083
+ else payments
1084
+ )
1085
+ for asset_id, payments in requested_payments.items()
1086
+ }
1087
+ else:
1088
+ return requested_payments