graphsense-python 2.13.5__tar.gz → 2.15.1__tar.gz

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 (231) hide show
  1. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/PKG-INFO +27 -3
  2. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/README.md +26 -2
  3. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/__init__.py +44 -2
  4. graphsense_python-2.15.1/graphsense/address_scan/__init__.py +11 -0
  5. graphsense_python-2.15.1/graphsense/address_scan/decompress.py +175 -0
  6. graphsense_python-2.15.1/graphsense/address_scan/detectors.py +124 -0
  7. graphsense_python-2.15.1/graphsense/address_scan/scanner.py +182 -0
  8. graphsense_python-2.15.1/graphsense/address_scan/validators.py +383 -0
  9. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/api/__init__.py +1 -0
  10. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/api/addresses_api.py +19 -19
  11. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/api/blocks_api.py +1 -1
  12. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/api/bulk_api.py +20 -14
  13. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/api/clusters_api.py +22 -22
  14. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/api/entities_api.py +22 -22
  15. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/api/general_api.py +1 -1
  16. graphsense_python-2.15.1/graphsense/api/graph_api.py +692 -0
  17. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/api/rates_api.py +1 -1
  18. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/api/tags_api.py +7 -7
  19. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/api/tokens_api.py +1 -1
  20. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/api/txs_api.py +4 -4
  21. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/api_client.py +2 -2
  22. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/cli/main.py +2 -0
  23. graphsense_python-2.15.1/graphsense/cli/scan.py +118 -0
  24. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/configuration.py +3 -3
  25. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/exceptions.py +1 -1
  26. graphsense_python-2.15.1/graphsense/ext/bulk.py +116 -0
  27. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/ext/client.py +20 -3
  28. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/gs_files/__init__.py +4 -0
  29. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/gs_files/encoder.py +113 -17
  30. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/__init__.py +21 -1
  31. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/actor.py +1 -1
  32. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/actor_context.py +1 -1
  33. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/address.py +3 -3
  34. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/address_output.py +1 -1
  35. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/address_tag.py +1 -1
  36. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/address_tags.py +1 -1
  37. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/address_tx.py +1 -1
  38. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/address_tx_utxo.py +1 -1
  39. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/address_txs.py +1 -1
  40. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/block.py +1 -1
  41. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/block_at_date.py +1 -1
  42. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/change_heuristics.py +1 -1
  43. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/cluster.py +1 -1
  44. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/cluster_addresses.py +1 -1
  45. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/coin_join_consensus.py +1 -1
  46. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/coin_join_heuristics.py +1 -1
  47. graphsense_python-2.15.1/graphsense/models/comparison_signal.py +107 -0
  48. graphsense_python-2.15.1/graphsense/models/comparison_verdict.py +109 -0
  49. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/concept.py +1 -1
  50. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/consensus_entry.py +1 -1
  51. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/currency_stats.py +1 -1
  52. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/direct_change_heuristic.py +1 -1
  53. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/entity.py +2 -2
  54. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/entity_addresses.py +1 -1
  55. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/external_conversion.py +1 -1
  56. graphsense_python-2.15.1/graphsense/models/graph_address_network_summary.py +132 -0
  57. graphsense_python-2.15.1/graphsense/models/graph_address_overall.py +140 -0
  58. graphsense_python-2.15.1/graphsense/models/graph_address_ref.py +88 -0
  59. graphsense_python-2.15.1/graphsense/models/graph_address_summary.py +99 -0
  60. graphsense_python-2.15.1/graphsense/models/graph_compare_note.py +94 -0
  61. graphsense_python-2.15.1/graphsense/models/graph_compare_request.py +107 -0
  62. graphsense_python-2.15.1/graphsense/models/graph_compare_signal.py +113 -0
  63. graphsense_python-2.15.1/graphsense/models/graph_compare_verdict.py +115 -0
  64. graphsense_python-2.15.1/graphsense/models/graph_compared_tx.py +100 -0
  65. graphsense_python-2.15.1/graphsense/models/graph_comparison.py +120 -0
  66. graphsense_python-2.15.1/graphsense/models/graph_lineage_edge.py +101 -0
  67. graphsense_python-2.15.1/graphsense/models/graph_note.py +99 -0
  68. graphsense_python-2.15.1/graphsense/models/graph_summary.py +96 -0
  69. graphsense_python-2.15.1/graphsense/models/graph_summary_request.py +104 -0
  70. graphsense_python-2.15.1/graphsense/models/graph_tx_characteristics.py +108 -0
  71. graphsense_python-2.15.1/graphsense/models/graph_tx_network_summary.py +120 -0
  72. graphsense_python-2.15.1/graphsense/models/graph_tx_overall.py +109 -0
  73. graphsense_python-2.15.1/graphsense/models/graph_tx_ref.py +88 -0
  74. graphsense_python-2.15.1/graphsense/models/graph_tx_summary.py +99 -0
  75. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/http_validation_error.py +1 -1
  76. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/join_market_heuristic.py +1 -1
  77. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/label_summary.py +1 -1
  78. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/labeled_item_ref.py +1 -1
  79. graphsense_python-2.15.1/graphsense/models/lineage_edge.py +101 -0
  80. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/link.py +1 -1
  81. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/link_utxo.py +1 -1
  82. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/links.py +1 -1
  83. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/links_inner.py +1 -1
  84. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/location_inner.py +1 -1
  85. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/multi_input_change_heuristic.py +1 -1
  86. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/neighbor_address.py +4 -4
  87. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/neighbor_addresses.py +1 -1
  88. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/neighbor_cluster.py +4 -4
  89. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/neighbor_clusters.py +1 -1
  90. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/neighbor_entities.py +1 -1
  91. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/neighbor_entity.py +4 -4
  92. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/one_time_change_heuristic.py +1 -1
  93. graphsense_python-2.15.1/graphsense/models/per_tx_inner.py +193 -0
  94. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/rate.py +1 -1
  95. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/rates.py +1 -1
  96. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/related_address.py +1 -1
  97. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/related_addresses.py +1 -1
  98. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/search_result.py +1 -1
  99. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/search_result_by_currency.py +1 -1
  100. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/search_result_level1.py +1 -1
  101. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/search_result_level2.py +1 -1
  102. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/search_result_level3.py +1 -1
  103. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/search_result_level4.py +1 -1
  104. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/search_result_level5.py +1 -1
  105. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/search_result_level6.py +1 -1
  106. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/stats.py +1 -1
  107. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/tag.py +1 -1
  108. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/tag_cloud_entry.py +1 -1
  109. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/tag_summary.py +1 -1
  110. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/taxonomy.py +1 -1
  111. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/token_config.py +1 -1
  112. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/token_configs.py +1 -1
  113. graphsense_python-2.15.1/graphsense/models/transaction_comparison.py +120 -0
  114. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/tx.py +1 -1
  115. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/tx_account.py +1 -1
  116. graphsense_python-2.15.1/graphsense/models/tx_characteristics.py +108 -0
  117. graphsense_python-2.15.1/graphsense/models/tx_compared_item.py +100 -0
  118. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/tx_ref.py +1 -1
  119. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/tx_summary.py +1 -1
  120. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/tx_utxo.py +1 -1
  121. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/tx_value.py +1 -1
  122. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/user_reported_tag.py +1 -1
  123. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/user_tag_report_response.py +1 -1
  124. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/utxo_heuristics.py +1 -1
  125. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/validation_error.py +1 -1
  126. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/values.py +1 -1
  127. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/wasabi_heuristic.py +1 -1
  128. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/whirlpool_coin_join_heuristic.py +1 -1
  129. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/models/whirlpool_tx0_heuristic.py +1 -1
  130. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/rest.py +1 -1
  131. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense_python.egg-info/PKG-INFO +27 -3
  132. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense_python.egg-info/SOURCES.txt +34 -0
  133. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/pyproject.toml +1 -1
  134. graphsense_python-2.15.1/tests/test_cli_scan.py +60 -0
  135. graphsense_python-2.15.1/tests/test_ext_bulk.py +105 -0
  136. graphsense_python-2.13.5/graphsense/ext/bulk.py +0 -51
  137. graphsense_python-2.13.5/tests/test_ext_bulk.py +0 -53
  138. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/api_response.py +0 -0
  139. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/cli/__init__.py +0 -0
  140. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/cli/__main__.py +0 -0
  141. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/cli/bulk_cmd.py +0 -0
  142. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/cli/context.py +0 -0
  143. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/cli/convenience.py +0 -0
  144. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/cli/errors.py +0 -0
  145. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/cli/gs.py +0 -0
  146. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/cli/raw.py +0 -0
  147. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/compat.py +0 -0
  148. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/ext/__init__.py +0 -0
  149. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/ext/deprecation.py +0 -0
  150. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/ext/io.py +0 -0
  151. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/ext/output.py +0 -0
  152. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/ext/selectors.py +0 -0
  153. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/gs_files/parser.py +0 -0
  154. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/gs_files/summary.py +0 -0
  155. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/gs_files/writer.py +0 -0
  156. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/__init__.py +0 -0
  157. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/actor.py +0 -0
  158. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/actor_context.py +0 -0
  159. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/address.py +0 -0
  160. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/address_tag.py +0 -0
  161. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/address_tags.py +0 -0
  162. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/address_tx.py +0 -0
  163. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/address_tx_utxo.py +0 -0
  164. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/address_txs.py +0 -0
  165. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/block.py +0 -0
  166. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/block_at_date.py +0 -0
  167. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/concept.py +0 -0
  168. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/currency_stats.py +0 -0
  169. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/entity.py +0 -0
  170. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/entity_addresses.py +0 -0
  171. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/external_conversion.py +0 -0
  172. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/http_validation_error.py +0 -0
  173. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/label_summary.py +0 -0
  174. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/labeled_item_ref.py +0 -0
  175. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/link.py +0 -0
  176. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/link_utxo.py +0 -0
  177. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/links.py +0 -0
  178. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/links_inner.py +0 -0
  179. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/location_inner.py +0 -0
  180. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/neighbor_address.py +0 -0
  181. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/neighbor_addresses.py +0 -0
  182. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/neighbor_entities.py +0 -0
  183. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/neighbor_entity.py +0 -0
  184. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/rate.py +0 -0
  185. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/rates.py +0 -0
  186. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/related_address.py +0 -0
  187. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/related_addresses.py +0 -0
  188. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/search_result.py +0 -0
  189. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/search_result_by_currency.py +0 -0
  190. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/search_result_level1.py +0 -0
  191. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/search_result_level2.py +0 -0
  192. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/search_result_level3.py +0 -0
  193. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/search_result_level4.py +0 -0
  194. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/search_result_level5.py +0 -0
  195. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/search_result_level6.py +0 -0
  196. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/stats.py +0 -0
  197. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/tag.py +0 -0
  198. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/tag_cloud_entry.py +0 -0
  199. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/tag_summary.py +0 -0
  200. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/taxonomy.py +0 -0
  201. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/token_config.py +0 -0
  202. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/token_configs.py +0 -0
  203. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/tx.py +0 -0
  204. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/tx_account.py +0 -0
  205. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/tx_ref.py +0 -0
  206. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/tx_summary.py +0 -0
  207. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/tx_utxo.py +0 -0
  208. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/tx_value.py +0 -0
  209. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/user_reported_tag.py +0 -0
  210. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/user_tag_report_response.py +0 -0
  211. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/validation_error.py +0 -0
  212. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/model/values.py +0 -0
  213. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense/py.typed +0 -0
  214. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense_python.egg-info/dependency_links.txt +0 -0
  215. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense_python.egg-info/entry_points.txt +0 -0
  216. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense_python.egg-info/requires.txt +0 -0
  217. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/graphsense_python.egg-info/top_level.txt +0 -0
  218. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/setup.cfg +0 -0
  219. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/tests/test_cli_bulk.py +0 -0
  220. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/tests/test_cli_convenience.py +0 -0
  221. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/tests/test_cli_errors.py +0 -0
  222. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/tests/test_cli_gs.py +0 -0
  223. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/tests/test_cli_io_pipes.py +0 -0
  224. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/tests/test_cli_raw_mirror.py +0 -0
  225. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/tests/test_cli_tags_and_dates.py +0 -0
  226. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/tests/test_ext_client.py +0 -0
  227. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/tests/test_ext_io.py +0 -0
  228. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/tests/test_ext_output.py +0 -0
  229. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/tests/test_ext_selectors.py +0 -0
  230. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/tests/test_readme_template.py +0 -0
  231. {graphsense_python-2.13.5 → graphsense_python-2.15.1}/tests/test_regen_survives.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: graphsense-python
3
- Version: 2.13.5
3
+ Version: 2.15.1
4
4
  Summary: GraphSense API
5
5
  Author-email: Iknaio Cryptoasset Analytics GmbH <contact@iknaio.com>
6
6
  License-Expression: MIT
@@ -58,11 +58,13 @@ your behalf.
58
58
  To use it, add that `/mcp` URL to an MCP-capable assistant as a new
59
59
  connector or tool source; the assistant then handles the rest.
60
60
 
61
+ **Authentication:** the MCP endpoint is protected by OAuth. When adding the connector in your assistant, use the client ID `iknaio-mcp`.
62
+
61
63
 
62
64
  This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
63
65
 
64
- - API version: 2.13.5
65
- - Package version: 2.13.5
66
+ - API version: 2.15.1
67
+ - Package version: 2.15.1
66
68
  - Generator version: 7.19.0
67
69
  - Build package: org.openapitools.codegen.languages.PythonClientCodegen
68
70
  For more information, please visit [https://www.iknaio.com/](https://www.iknaio.com/)
@@ -188,6 +190,8 @@ Class | Method | HTTP request | Description
188
190
  *EntitiesApi* | [**search_entity_neighbors**](docs/EntitiesApi.md#search_entity_neighbors) | **GET** /{currency}/entities/{entity}/search | Search entity neighborhood
189
191
  *GeneralApi* | [**get_statistics**](docs/GeneralApi.md#get_statistics) | **GET** /stats | Get platform statistics for supported currencies
190
192
  *GeneralApi* | [**search**](docs/GeneralApi.md#search) | **GET** /search | Search addresses, transactions, actors, and labels
193
+ *GraphApi* | [**graph_compare**](docs/GraphApi.md#graph_compare) | **POST** /graph/compare | Compare multiple transactions (beta)
194
+ *GraphApi* | [**graph_summary**](docs/GraphApi.md#graph_summary) | **POST** /graph/summary | Summarize a set of transactions and/or addresses (beta)
191
195
  *RatesApi* | [**get_exchange_rates**](docs/RatesApi.md#get_exchange_rates) | **GET** /{currency}/rates/{height} | Get fiat exchange rates at a block height
192
196
  *TagsApi* | [**get_actor**](docs/TagsApi.md#get_actor) | **GET** /tags/actors/{actor} | Get actor details by ID
193
197
  *TagsApi* | [**get_actor_tags**](docs/TagsApi.md#get_actor_tags) | **GET** /tags/actors/{actor}/tags | List tags associated with an actor
@@ -230,6 +234,25 @@ Class | Method | HTTP request | Description
230
234
  - [Entity](docs/Entity.md)
231
235
  - [EntityAddresses](docs/EntityAddresses.md)
232
236
  - [ExternalConversion](docs/ExternalConversion.md)
237
+ - [GraphAddressNetworkSummary](docs/GraphAddressNetworkSummary.md)
238
+ - [GraphAddressOverall](docs/GraphAddressOverall.md)
239
+ - [GraphAddressRef](docs/GraphAddressRef.md)
240
+ - [GraphAddressSummary](docs/GraphAddressSummary.md)
241
+ - [GraphCompareNote](docs/GraphCompareNote.md)
242
+ - [GraphCompareRequest](docs/GraphCompareRequest.md)
243
+ - [GraphCompareSignal](docs/GraphCompareSignal.md)
244
+ - [GraphCompareVerdict](docs/GraphCompareVerdict.md)
245
+ - [GraphComparedTx](docs/GraphComparedTx.md)
246
+ - [GraphComparison](docs/GraphComparison.md)
247
+ - [GraphLineageEdge](docs/GraphLineageEdge.md)
248
+ - [GraphNote](docs/GraphNote.md)
249
+ - [GraphSummary](docs/GraphSummary.md)
250
+ - [GraphSummaryRequest](docs/GraphSummaryRequest.md)
251
+ - [GraphTxCharacteristics](docs/GraphTxCharacteristics.md)
252
+ - [GraphTxNetworkSummary](docs/GraphTxNetworkSummary.md)
253
+ - [GraphTxOverall](docs/GraphTxOverall.md)
254
+ - [GraphTxRef](docs/GraphTxRef.md)
255
+ - [GraphTxSummary](docs/GraphTxSummary.md)
233
256
  - [HTTPValidationError](docs/HTTPValidationError.md)
234
257
  - [JoinMarketHeuristic](docs/JoinMarketHeuristic.md)
235
258
  - [LabelSummary](docs/LabelSummary.md)
@@ -247,6 +270,7 @@ Class | Method | HTTP request | Description
247
270
  - [NeighborEntities](docs/NeighborEntities.md)
248
271
  - [NeighborEntity](docs/NeighborEntity.md)
249
272
  - [OneTimeChangeHeuristic](docs/OneTimeChangeHeuristic.md)
273
+ - [PerTxInner](docs/PerTxInner.md)
250
274
  - [Rate](docs/Rate.md)
251
275
  - [Rates](docs/Rates.md)
252
276
  - [RelatedAddress](docs/RelatedAddress.md)
@@ -36,11 +36,13 @@ your behalf.
36
36
  To use it, add that `/mcp` URL to an MCP-capable assistant as a new
37
37
  connector or tool source; the assistant then handles the rest.
38
38
 
39
+ **Authentication:** the MCP endpoint is protected by OAuth. When adding the connector in your assistant, use the client ID `iknaio-mcp`.
40
+
39
41
 
40
42
  This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
41
43
 
42
- - API version: 2.13.5
43
- - Package version: 2.13.5
44
+ - API version: 2.15.1
45
+ - Package version: 2.15.1
44
46
  - Generator version: 7.19.0
45
47
  - Build package: org.openapitools.codegen.languages.PythonClientCodegen
46
48
  For more information, please visit [https://www.iknaio.com/](https://www.iknaio.com/)
@@ -166,6 +168,8 @@ Class | Method | HTTP request | Description
166
168
  *EntitiesApi* | [**search_entity_neighbors**](docs/EntitiesApi.md#search_entity_neighbors) | **GET** /{currency}/entities/{entity}/search | Search entity neighborhood
167
169
  *GeneralApi* | [**get_statistics**](docs/GeneralApi.md#get_statistics) | **GET** /stats | Get platform statistics for supported currencies
168
170
  *GeneralApi* | [**search**](docs/GeneralApi.md#search) | **GET** /search | Search addresses, transactions, actors, and labels
171
+ *GraphApi* | [**graph_compare**](docs/GraphApi.md#graph_compare) | **POST** /graph/compare | Compare multiple transactions (beta)
172
+ *GraphApi* | [**graph_summary**](docs/GraphApi.md#graph_summary) | **POST** /graph/summary | Summarize a set of transactions and/or addresses (beta)
169
173
  *RatesApi* | [**get_exchange_rates**](docs/RatesApi.md#get_exchange_rates) | **GET** /{currency}/rates/{height} | Get fiat exchange rates at a block height
170
174
  *TagsApi* | [**get_actor**](docs/TagsApi.md#get_actor) | **GET** /tags/actors/{actor} | Get actor details by ID
171
175
  *TagsApi* | [**get_actor_tags**](docs/TagsApi.md#get_actor_tags) | **GET** /tags/actors/{actor}/tags | List tags associated with an actor
@@ -208,6 +212,25 @@ Class | Method | HTTP request | Description
208
212
  - [Entity](docs/Entity.md)
209
213
  - [EntityAddresses](docs/EntityAddresses.md)
210
214
  - [ExternalConversion](docs/ExternalConversion.md)
215
+ - [GraphAddressNetworkSummary](docs/GraphAddressNetworkSummary.md)
216
+ - [GraphAddressOverall](docs/GraphAddressOverall.md)
217
+ - [GraphAddressRef](docs/GraphAddressRef.md)
218
+ - [GraphAddressSummary](docs/GraphAddressSummary.md)
219
+ - [GraphCompareNote](docs/GraphCompareNote.md)
220
+ - [GraphCompareRequest](docs/GraphCompareRequest.md)
221
+ - [GraphCompareSignal](docs/GraphCompareSignal.md)
222
+ - [GraphCompareVerdict](docs/GraphCompareVerdict.md)
223
+ - [GraphComparedTx](docs/GraphComparedTx.md)
224
+ - [GraphComparison](docs/GraphComparison.md)
225
+ - [GraphLineageEdge](docs/GraphLineageEdge.md)
226
+ - [GraphNote](docs/GraphNote.md)
227
+ - [GraphSummary](docs/GraphSummary.md)
228
+ - [GraphSummaryRequest](docs/GraphSummaryRequest.md)
229
+ - [GraphTxCharacteristics](docs/GraphTxCharacteristics.md)
230
+ - [GraphTxNetworkSummary](docs/GraphTxNetworkSummary.md)
231
+ - [GraphTxOverall](docs/GraphTxOverall.md)
232
+ - [GraphTxRef](docs/GraphTxRef.md)
233
+ - [GraphTxSummary](docs/GraphTxSummary.md)
211
234
  - [HTTPValidationError](docs/HTTPValidationError.md)
212
235
  - [JoinMarketHeuristic](docs/JoinMarketHeuristic.md)
213
236
  - [LabelSummary](docs/LabelSummary.md)
@@ -225,6 +248,7 @@ Class | Method | HTTP request | Description
225
248
  - [NeighborEntities](docs/NeighborEntities.md)
226
249
  - [NeighborEntity](docs/NeighborEntity.md)
227
250
  - [OneTimeChangeHeuristic](docs/OneTimeChangeHeuristic.md)
251
+ - [PerTxInner](docs/PerTxInner.md)
228
252
  - [Rate](docs/Rate.md)
229
253
  - [Rates](docs/Rates.md)
230
254
  - [RelatedAddress](docs/RelatedAddress.md)
@@ -5,14 +5,14 @@
5
5
  """
6
6
  GraphSense API
7
7
 
8
- GraphSense API provides programmatic access to blockchain analytics data across multiple ledgers. Use it to explore addresses, clusters, blocks, transactions, tags, token activity, and exchange-rate context, and to integrate investigation workflows into your own applications and automation. ## Versioning & deprecation The API follows semantic versioning. Minor releases are additive and backwards-compatible; breaking changes only happen in major releases, which are rare and announced in advance. Deprecated endpoints and fields remain fully functional for at least six months after they are marked deprecated. During that window they are highlighted with a strikethrough in the docs and in generated clients, and responses from deprecated endpoints carry a `Deprecation` HTTP header that client tooling can detect. Replacement endpoints and fields are always introduced before the deprecated surface is removed. See the [full versioning and deprecation policy](https://github.com/graphsense/graphsense-lib/blob/master/README.md#rest-api-evolution-and-deprecation-policy) for details. ## AI assistant access (MCP) In addition to this REST API, this deployment exposes a **Model Context Protocol (MCP)** interface that lets AI assistants query GraphSense directly in natural language, without writing code against the endpoints below. The MCP interface is available at the `/mcp` path of this server, relative to the address this documentation is served from. It offers a curated selection of the most useful operations, so an assistant can answer questions about addresses, transactions, clusters, and tags on your behalf. To use it, add that `/mcp` URL to an MCP-capable assistant as a new connector or tool source; the assistant then handles the rest. # noqa: E501
8
+ GraphSense API provides programmatic access to blockchain analytics data across multiple ledgers. Use it to explore addresses, clusters, blocks, transactions, tags, token activity, and exchange-rate context, and to integrate investigation workflows into your own applications and automation. ## Versioning & deprecation The API follows semantic versioning. Minor releases are additive and backwards-compatible; breaking changes only happen in major releases, which are rare and announced in advance. Deprecated endpoints and fields remain fully functional for at least six months after they are marked deprecated. During that window they are highlighted with a strikethrough in the docs and in generated clients, and responses from deprecated endpoints carry a `Deprecation` HTTP header that client tooling can detect. Replacement endpoints and fields are always introduced before the deprecated surface is removed. See the [full versioning and deprecation policy](https://github.com/graphsense/graphsense-lib/blob/master/README.md#rest-api-evolution-and-deprecation-policy) for details. ## AI assistant access (MCP) In addition to this REST API, this deployment exposes a **Model Context Protocol (MCP)** interface that lets AI assistants query GraphSense directly in natural language, without writing code against the endpoints below. The MCP interface is available at the `/mcp` path of this server, relative to the address this documentation is served from. It offers a curated selection of the most useful operations, so an assistant can answer questions about addresses, transactions, clusters, and tags on your behalf. To use it, add that `/mcp` URL to an MCP-capable assistant as a new connector or tool source; the assistant then handles the rest. **Authentication:** the MCP endpoint is protected by OAuth. When adding the connector in your assistant, use the client ID `iknaio-mcp`. # noqa: E501
9
9
 
10
10
  Contact: contact@iknaio.com
11
11
  Generated by: https://openapi-generator.tech
12
12
  """
13
13
 
14
14
 
15
- __version__ = "2.13.5"
15
+ __version__ = "2.15.1"
16
16
 
17
17
  # Define package exports
18
18
  __all__ = [
@@ -22,6 +22,7 @@ __all__ = [
22
22
  "ClustersApi",
23
23
  "EntitiesApi",
24
24
  "GeneralApi",
25
+ "GraphApi",
25
26
  "RatesApi",
26
27
  "TagsApi",
27
28
  "TokensApi",
@@ -58,6 +59,25 @@ __all__ = [
58
59
  "Entity",
59
60
  "EntityAddresses",
60
61
  "ExternalConversion",
62
+ "GraphAddressNetworkSummary",
63
+ "GraphAddressOverall",
64
+ "GraphAddressRef",
65
+ "GraphAddressSummary",
66
+ "GraphCompareNote",
67
+ "GraphCompareRequest",
68
+ "GraphCompareSignal",
69
+ "GraphCompareVerdict",
70
+ "GraphComparedTx",
71
+ "GraphComparison",
72
+ "GraphLineageEdge",
73
+ "GraphNote",
74
+ "GraphSummary",
75
+ "GraphSummaryRequest",
76
+ "GraphTxCharacteristics",
77
+ "GraphTxNetworkSummary",
78
+ "GraphTxOverall",
79
+ "GraphTxRef",
80
+ "GraphTxSummary",
61
81
  "HTTPValidationError",
62
82
  "JoinMarketHeuristic",
63
83
  "LabelSummary",
@@ -75,6 +95,7 @@ __all__ = [
75
95
  "NeighborEntities",
76
96
  "NeighborEntity",
77
97
  "OneTimeChangeHeuristic",
98
+ "PerTxInner",
78
99
  "Rate",
79
100
  "Rates",
80
101
  "RelatedAddress",
@@ -120,6 +141,7 @@ from graphsense.api.bulk_api import BulkApi as BulkApi
120
141
  from graphsense.api.clusters_api import ClustersApi as ClustersApi
121
142
  from graphsense.api.entities_api import EntitiesApi as EntitiesApi
122
143
  from graphsense.api.general_api import GeneralApi as GeneralApi
144
+ from graphsense.api.graph_api import GraphApi as GraphApi
123
145
  from graphsense.api.rates_api import RatesApi as RatesApi
124
146
  from graphsense.api.tags_api import TagsApi as TagsApi
125
147
  from graphsense.api.tokens_api import TokensApi as TokensApi
@@ -160,6 +182,25 @@ from graphsense.models.direct_change_heuristic import DirectChangeHeuristic as D
160
182
  from graphsense.models.entity import Entity as Entity
161
183
  from graphsense.models.entity_addresses import EntityAddresses as EntityAddresses
162
184
  from graphsense.models.external_conversion import ExternalConversion as ExternalConversion
185
+ from graphsense.models.graph_address_network_summary import GraphAddressNetworkSummary as GraphAddressNetworkSummary
186
+ from graphsense.models.graph_address_overall import GraphAddressOverall as GraphAddressOverall
187
+ from graphsense.models.graph_address_ref import GraphAddressRef as GraphAddressRef
188
+ from graphsense.models.graph_address_summary import GraphAddressSummary as GraphAddressSummary
189
+ from graphsense.models.graph_compare_note import GraphCompareNote as GraphCompareNote
190
+ from graphsense.models.graph_compare_request import GraphCompareRequest as GraphCompareRequest
191
+ from graphsense.models.graph_compare_signal import GraphCompareSignal as GraphCompareSignal
192
+ from graphsense.models.graph_compare_verdict import GraphCompareVerdict as GraphCompareVerdict
193
+ from graphsense.models.graph_compared_tx import GraphComparedTx as GraphComparedTx
194
+ from graphsense.models.graph_comparison import GraphComparison as GraphComparison
195
+ from graphsense.models.graph_lineage_edge import GraphLineageEdge as GraphLineageEdge
196
+ from graphsense.models.graph_note import GraphNote as GraphNote
197
+ from graphsense.models.graph_summary import GraphSummary as GraphSummary
198
+ from graphsense.models.graph_summary_request import GraphSummaryRequest as GraphSummaryRequest
199
+ from graphsense.models.graph_tx_characteristics import GraphTxCharacteristics as GraphTxCharacteristics
200
+ from graphsense.models.graph_tx_network_summary import GraphTxNetworkSummary as GraphTxNetworkSummary
201
+ from graphsense.models.graph_tx_overall import GraphTxOverall as GraphTxOverall
202
+ from graphsense.models.graph_tx_ref import GraphTxRef as GraphTxRef
203
+ from graphsense.models.graph_tx_summary import GraphTxSummary as GraphTxSummary
163
204
  from graphsense.models.http_validation_error import HTTPValidationError as HTTPValidationError
164
205
  from graphsense.models.join_market_heuristic import JoinMarketHeuristic as JoinMarketHeuristic
165
206
  from graphsense.models.label_summary import LabelSummary as LabelSummary
@@ -177,6 +218,7 @@ from graphsense.models.neighbor_clusters import NeighborClusters as NeighborClus
177
218
  from graphsense.models.neighbor_entities import NeighborEntities as NeighborEntities
178
219
  from graphsense.models.neighbor_entity import NeighborEntity as NeighborEntity
179
220
  from graphsense.models.one_time_change_heuristic import OneTimeChangeHeuristic as OneTimeChangeHeuristic
221
+ from graphsense.models.per_tx_inner import PerTxInner as PerTxInner
180
222
  from graphsense.models.rate import Rate as Rate
181
223
  from graphsense.models.rates import Rates as Rates
182
224
  from graphsense.models.related_address import RelatedAddress as RelatedAddress
@@ -0,0 +1,11 @@
1
+ # AUTO-GENERATED — DO NOT EDIT.
2
+ # Synced from src/graphsenselib/convert/address_scan/__init__.py via
3
+ # clients/python/scripts/sync_address_scan.py. Edit the source and re-run
4
+ # `make -C clients/python sync-address-scan`.
5
+ """Scan text/SQL files (and compressed containers) for cryptocurrency addresses.
6
+
7
+ Extraction is deliberately permissive; the real filter is checksum validation
8
+ (reusing :mod:`graphsenselib.utils.address`), which removes the many
9
+ address-shaped false positives found in database dumps (hashes, session ids,
10
+ base64 blobs, filenames).
11
+ """
@@ -0,0 +1,175 @@
1
+ # AUTO-GENERATED — DO NOT EDIT.
2
+ # Synced from src/graphsenselib/convert/address_scan/decompress.py via
3
+ # clients/python/scripts/sync_address_scan.py. Edit the source and re-run
4
+ # `make -C clients/python sync-address-scan`.
5
+ """Transparently unwrap compressed containers before scanning.
6
+
7
+ Addresses often hide inside compressed data (.gz dumps, zip exports, or raw
8
+ zlib/gzip blobs embedded in a binary). We unwrap known containers, recurse
9
+ (so .tar.gz works), and optionally carve embedded streams. A byte budget guards
10
+ against decompression bombs.
11
+
12
+ Supported: gzip, zlib, bz2, xz, zip, tar (recursively), GraphSense ``.gs`` save
13
+ files (LZW + base64 + JSON, decoded via
14
+ :func:`graphsenselib.convert.gs_files.parser.lzw_unpack`), and -- with
15
+ ``carve=True`` -- zlib/gzip streams embedded anywhere in a binary.
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import base64
21
+ import bz2
22
+ import io
23
+ import lzma
24
+ import re
25
+ import struct
26
+ import tarfile
27
+ import zipfile
28
+ import zlib
29
+ from typing import Iterator
30
+
31
+ from graphsense.gs_files.parser import lzw_unpack
32
+
33
+ MAX_DEPTH = 6
34
+ DEFAULT_BUDGET = 1024 * 1024 * 1024 # 1 GiB of decompressed output per file
35
+ GS_AUTO_MAX = 64 * 1024 * 1024 # only auto-probe .gs on smallish files
36
+
37
+
38
+ def _decode_gs(data: bytes, name: str) -> "bytes | None":
39
+ """Return the inner JSON bytes of a GraphSense ``.gs`` file, or None.
40
+
41
+ Headerless format, so we validate structurally: size is a non-zero multiple
42
+ of 4, the first LZW code is a base-dictionary char (<256), and the payload
43
+ base64-decodes to something that starts like JSON. That combination makes
44
+ false positives on arbitrary binaries essentially nil.
45
+ """
46
+ if not data or len(data) % 4 != 0:
47
+ return None
48
+ forced = name.lower().endswith(".gs")
49
+ if not forced and len(data) > GS_AUTO_MAX:
50
+ return None # avoid an expensive LZW pass on large non-.gs blobs
51
+ codes = struct.unpack(f"<{len(data) // 4}I", data)
52
+ if codes[0] >= 256:
53
+ return None
54
+ try:
55
+ payload = base64.b64decode(lzw_unpack(list(codes)), validate=True)
56
+ except Exception:
57
+ return None
58
+ return payload if payload.lstrip()[:1] in (b"[", b"{") else None
59
+
60
+
61
+ def _bounded(decompressor: object, data: bytes, limit: int) -> bytes:
62
+ """Streaming-decompress ``data``, stopping once ``limit`` bytes are produced."""
63
+ out = bytearray()
64
+ step = 1 << 20
65
+ try:
66
+ for pos in range(0, len(data), step):
67
+ out += decompressor.decompress(data[pos : pos + step]) # type: ignore[attr-defined]
68
+ if len(out) >= limit:
69
+ return bytes(out[:limit])
70
+ flush = getattr(decompressor, "flush", None)
71
+ if callable(flush):
72
+ out += flush()
73
+ except Exception:
74
+ pass # truncated/garbage tail -> keep whatever decoded so far
75
+ return bytes(out[:limit])
76
+
77
+
78
+ def _is_zlib(data: bytes) -> bool:
79
+ return (
80
+ len(data) > 2 and (data[0] & 0x0F) == 8 and ((data[0] << 8) | data[1]) % 31 == 0
81
+ )
82
+
83
+
84
+ def _decompress_layer(
85
+ data: bytes, name: str, budget: list[int]
86
+ ) -> Iterator[tuple[str, bytes]]:
87
+ """Yield (label, bytes) for each container format ``data`` unwraps into."""
88
+ if budget[0] <= 0:
89
+ return
90
+ limit = budget[0]
91
+
92
+ if data[:2] == b"\x1f\x8b": # gzip
93
+ out = _bounded(zlib.decompressobj(zlib.MAX_WBITS | 16), data, limit)
94
+ if out:
95
+ budget[0] -= len(out)
96
+ yield f"{name} :: gzip", out
97
+ elif _is_zlib(data): # raw zlib
98
+ out = _bounded(zlib.decompressobj(), data, limit)
99
+ if out:
100
+ budget[0] -= len(out)
101
+ yield f"{name} :: zlib", out
102
+ elif data[:3] == b"BZh": # bzip2
103
+ out = _bounded(bz2.BZ2Decompressor(), data, limit)
104
+ if out:
105
+ budget[0] -= len(out)
106
+ yield f"{name} :: bz2", out
107
+ elif data[:6] == b"\xfd7zXZ\x00": # xz
108
+ out = _bounded(lzma.LZMADecompressor(), data, limit)
109
+ if out:
110
+ budget[0] -= len(out)
111
+ yield f"{name} :: xz", out
112
+
113
+ if data[:4] in (b"PK\x03\x04", b"PK\x05\x06"): # zip
114
+ try:
115
+ with zipfile.ZipFile(io.BytesIO(data)) as zf:
116
+ for info in zf.infolist():
117
+ if info.is_dir() or budget[0] <= 0:
118
+ continue
119
+ with zf.open(info) as fh:
120
+ out = fh.read(budget[0] + 1)[: budget[0]]
121
+ budget[0] -= len(out)
122
+ yield f"{name} :: zip[{info.filename}]", out
123
+ except Exception:
124
+ pass
125
+ elif tarfile.is_tarfile(io.BytesIO(data)): # tar (incl. plain, not gz here)
126
+ try:
127
+ with tarfile.open(fileobj=io.BytesIO(data)) as tf:
128
+ for member in tf:
129
+ if not member.isfile() or budget[0] <= 0:
130
+ continue
131
+ fh = tf.extractfile(member)
132
+ if fh is None:
133
+ continue
134
+ out = fh.read(budget[0] + 1)[: budget[0]]
135
+ budget[0] -= len(out)
136
+ yield f"{name} :: tar[{member.name}]", out
137
+ except Exception:
138
+ pass
139
+
140
+ gs = _decode_gs(data, name) # GraphSense .gs (LZW + base64 + JSON)
141
+ if gs is not None and budget[0] > 0:
142
+ gs = gs[: budget[0]]
143
+ budget[0] -= len(gs)
144
+ yield f"{name} :: gs/lzw", gs
145
+
146
+
147
+ def _carve_zlib(
148
+ data: bytes, name: str, budget: list[int]
149
+ ) -> Iterator[tuple[str, bytes]]:
150
+ """Best-effort: find gzip/zlib streams anywhere in ``data`` and inflate them."""
151
+ seen = 0
152
+ for m in re.finditer(rb"\x1f\x8b\x08|\x78[\x01\x9c\xda]", data):
153
+ if budget[0] <= 0 or seen >= 200:
154
+ break
155
+ off = m.start()
156
+ wbits = zlib.MAX_WBITS | 16 if data[off] == 0x1F else zlib.MAX_WBITS
157
+ out = _bounded(zlib.decompressobj(wbits), data[off:], budget[0])
158
+ if len(out) >= 16: # ignore trivially short / bogus inflations
159
+ budget[0] -= len(out)
160
+ seen += 1
161
+ yield f"{name} :: carved@{off}", out
162
+
163
+
164
+ def iter_streams(
165
+ data: bytes, name: str, carve: bool, budget: list[int], depth: int = 0
166
+ ) -> Iterator[tuple[str, bytes]]:
167
+ """Yield the raw file plus every decompressed stream, recursively."""
168
+ yield name, data
169
+ if depth >= MAX_DEPTH:
170
+ return
171
+ for label, inner in _decompress_layer(data, name, budget):
172
+ yield from iter_streams(inner, label, carve, budget, depth + 1)
173
+ if carve:
174
+ for label, inner in _carve_zlib(data, name, budget):
175
+ yield from iter_streams(inner, label, carve, budget, depth + 1)
@@ -0,0 +1,124 @@
1
+ # AUTO-GENERATED — DO NOT EDIT.
2
+ # Synced from src/graphsenselib/convert/address_scan/detectors.py via
3
+ # clients/python/scripts/sync_address_scan.py. Edit the source and re-run
4
+ # `make -C clients/python sync-address-scan`.
5
+ """Regex detectors and validators for the address scanner.
6
+
7
+ Each detector pairs a permissive regex (to *extract* address-shaped runs) with
8
+ a validator (to *confirm* them). The validators reuse the checksum logic in
9
+ :mod:`graphsenselib.utils.address` wherever possible; only XMR (no cheap
10
+ checksum) and the opt-in tx-hash candidates are format-level heuristics.
11
+
12
+ Supported with full checksum validation:
13
+ - Bitcoin : legacy (1.../3...), bech32/bech32m (bc1...)
14
+ - Litecoin : legacy (L/M...), bech32 (ltc1...)
15
+ - Ethereum : 0x + 40 hex (EIP-55 mixed-case checksum verified when present)
16
+ - TRON : T... base58check
17
+ - Zcash : transparent t1/t3 base58check
18
+ - XRP : classic r-addresses (base58check, ripple alphabet)
19
+ Reported as candidates only (no cheap checksum):
20
+ - Monero : 4.../8... 95-char addresses
21
+ """
22
+
23
+ from __future__ import annotations
24
+
25
+ from typing import Callable, NamedTuple, Optional
26
+
27
+ from graphsense.address_scan.validators import validate_address, validate_xrp_address
28
+
29
+
30
+ def decodes_to_text(hex_body: str, threshold: float = 0.7) -> bool:
31
+ """True if ``hex_body`` decodes mostly to printable ASCII.
32
+
33
+ SQL dumps store blobs as ``0x...``/hex literals; a run that decodes to
34
+ readable text is encoded content (e.g. stored HTML/JS), not an address.
35
+ Real ETH/XMR addresses are effectively random bytes and fail this test.
36
+ """
37
+ try:
38
+ raw = bytes.fromhex(hex_body)
39
+ except ValueError:
40
+ return False
41
+ if not raw:
42
+ return False
43
+ printable = sum(1 for b in raw if 0x20 <= b <= 0x7E)
44
+ return printable / len(raw) >= threshold
45
+
46
+
47
+ def _eth_valid(addr: str) -> bool:
48
+ # Drop hex-encoded text blobs before the (stricter) EIP-55 check.
49
+ if decodes_to_text(addr[2:]):
50
+ return False
51
+ return validate_address("eth", addr)
52
+
53
+
54
+ def _xmr_candidate_valid(s: str) -> bool:
55
+ """Monero has no cheap checksum, so reject the common false positives:
56
+ pure-hex strings (SQL blob literals) and hex that decodes to text."""
57
+ if all(c in "0123456789abcdefABCDEF" for c in s):
58
+ return False # a real base58 Monero address is ~never all-hex
59
+ if decodes_to_text(s):
60
+ return False
61
+ return True
62
+
63
+
64
+ def txhash_valid(s: str) -> bool:
65
+ """A tx hash is 32 random bytes with NO checksum -- unverifiable by form.
66
+ We can only drop the obvious non-hashes: hex that decodes to ASCII text."""
67
+ return not decodes_to_text(s[2:] if s[:2].lower() == "0x" else s)
68
+
69
+
70
+ class Detector(NamedTuple):
71
+ label: str
72
+ pattern: str
73
+ validator: Optional[Callable[[str], bool]]
74
+
75
+
76
+ # Lookarounds keep matches from being slices of a longer hex/base58 run.
77
+ _H = r"[a-fA-F0-9]"
78
+
79
+ DETECTORS: list[Detector] = [
80
+ Detector(
81
+ "BTC legacy/P2SH",
82
+ r"[13][1-9A-HJ-NP-Za-km-z]{25,34}",
83
+ lambda m: validate_address("btc", m),
84
+ ),
85
+ Detector(
86
+ "BTC bech32", r"bc1[0-9ac-hj-np-z]{11,87}", lambda m: validate_address("btc", m)
87
+ ),
88
+ Detector(
89
+ "LTC legacy",
90
+ r"[LM][1-9A-HJ-NP-Za-km-z]{25,34}",
91
+ lambda m: validate_address("ltc", m),
92
+ ),
93
+ Detector(
94
+ "LTC bech32",
95
+ r"ltc1[0-9ac-hj-np-z]{11,87}",
96
+ lambda m: validate_address("ltc", m),
97
+ ),
98
+ Detector("ETH", rf"(?<!{_H})0x{_H}{{40}}(?!{_H})", _eth_valid),
99
+ Detector("TRX", r"T[1-9A-HJ-NP-Za-km-z]{33}", lambda m: validate_address("trx", m)),
100
+ Detector(
101
+ "ZEC transparent",
102
+ r"t[13][1-9A-HJ-NP-Za-km-z]{33}",
103
+ lambda m: validate_address("zec", m),
104
+ ),
105
+ Detector("XRP", r"r[1-9A-HJ-NP-Za-km-z]{24,34}", validate_xrp_address),
106
+ Detector(
107
+ "XMR (candidate)", r"[48][0-9AB][1-9A-HJ-NP-Za-km-z]{93}", _xmr_candidate_valid
108
+ ),
109
+ ]
110
+
111
+ # Opt-in only (--tx-hashes): format-level, NOT checksum-verifiable. Every 64-hex
112
+ # digest (SHA-256 file hashes, tokens, etc.) matches, so results are candidates.
113
+ # The 0x form is matched first; the bare form excludes an 'x'-prefixed run so a
114
+ # single 0x<64hex> is not double-counted.
115
+ TX_DETECTORS: list[Detector] = [
116
+ Detector(
117
+ "TX-hash candidate (0x+64hex)", rf"(?<!{_H})0x{_H}{{64}}(?!{_H})", txhash_valid
118
+ ),
119
+ Detector(
120
+ "TX-hash candidate (64hex)",
121
+ rf"(?<![a-fA-F0-9xX]){_H}{{64}}(?!{_H})",
122
+ txhash_valid,
123
+ ),
124
+ ]