graphsense-python 2.13.2__tar.gz → 2.15.0__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.
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/PKG-INFO +44 -4
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/README.md +43 -3
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/__init__.py +44 -2
- graphsense_python-2.15.0/graphsense/address_scan/__init__.py +11 -0
- graphsense_python-2.15.0/graphsense/address_scan/decompress.py +175 -0
- graphsense_python-2.15.0/graphsense/address_scan/detectors.py +124 -0
- graphsense_python-2.15.0/graphsense/address_scan/scanner.py +182 -0
- graphsense_python-2.15.0/graphsense/address_scan/validators.py +383 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/api/__init__.py +1 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/api/addresses_api.py +16 -16
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/api/blocks_api.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/api/bulk_api.py +8 -8
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/api/clusters_api.py +19 -19
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/api/entities_api.py +19 -19
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/api/general_api.py +1 -1
- graphsense_python-2.15.0/graphsense/api/graph_api.py +692 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/api/rates_api.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/api/tags_api.py +7 -7
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/api/tokens_api.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/api/txs_api.py +4 -4
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/api_client.py +2 -2
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/cli/main.py +2 -0
- graphsense_python-2.15.0/graphsense/cli/scan.py +118 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/configuration.py +3 -3
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/exceptions.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/gs_files/__init__.py +6 -0
- graphsense_python-2.15.0/graphsense/gs_files/encoder.py +758 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/__init__.py +21 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/actor.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/actor_context.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/address.py +3 -3
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/address_output.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/address_tag.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/address_tags.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/address_tx.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/address_tx_utxo.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/address_txs.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/block.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/block_at_date.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/change_heuristics.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/cluster.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/cluster_addresses.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/coin_join_consensus.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/coin_join_heuristics.py +1 -1
- graphsense_python-2.15.0/graphsense/models/comparison_signal.py +107 -0
- graphsense_python-2.15.0/graphsense/models/comparison_verdict.py +109 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/concept.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/consensus_entry.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/currency_stats.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/direct_change_heuristic.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/entity.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/entity_addresses.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/external_conversion.py +1 -1
- graphsense_python-2.15.0/graphsense/models/graph_address_network_summary.py +132 -0
- graphsense_python-2.15.0/graphsense/models/graph_address_overall.py +140 -0
- graphsense_python-2.15.0/graphsense/models/graph_address_ref.py +88 -0
- graphsense_python-2.15.0/graphsense/models/graph_address_summary.py +99 -0
- graphsense_python-2.15.0/graphsense/models/graph_compare_note.py +94 -0
- graphsense_python-2.15.0/graphsense/models/graph_compare_request.py +107 -0
- graphsense_python-2.15.0/graphsense/models/graph_compare_signal.py +113 -0
- graphsense_python-2.15.0/graphsense/models/graph_compare_verdict.py +115 -0
- graphsense_python-2.15.0/graphsense/models/graph_compared_tx.py +100 -0
- graphsense_python-2.15.0/graphsense/models/graph_comparison.py +120 -0
- graphsense_python-2.15.0/graphsense/models/graph_lineage_edge.py +101 -0
- graphsense_python-2.15.0/graphsense/models/graph_note.py +99 -0
- graphsense_python-2.15.0/graphsense/models/graph_summary.py +96 -0
- graphsense_python-2.15.0/graphsense/models/graph_summary_request.py +104 -0
- graphsense_python-2.15.0/graphsense/models/graph_tx_characteristics.py +108 -0
- graphsense_python-2.15.0/graphsense/models/graph_tx_network_summary.py +120 -0
- graphsense_python-2.15.0/graphsense/models/graph_tx_overall.py +109 -0
- graphsense_python-2.15.0/graphsense/models/graph_tx_ref.py +88 -0
- graphsense_python-2.15.0/graphsense/models/graph_tx_summary.py +99 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/http_validation_error.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/join_market_heuristic.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/label_summary.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/labeled_item_ref.py +1 -1
- graphsense_python-2.15.0/graphsense/models/lineage_edge.py +101 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/link.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/link_utxo.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/links.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/links_inner.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/location_inner.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/multi_input_change_heuristic.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/neighbor_address.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/neighbor_addresses.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/neighbor_cluster.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/neighbor_clusters.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/neighbor_entities.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/neighbor_entity.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/one_time_change_heuristic.py +1 -1
- graphsense_python-2.15.0/graphsense/models/per_tx_inner.py +193 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/rate.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/rates.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/related_address.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/related_addresses.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/search_result.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/search_result_by_currency.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/search_result_level1.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/search_result_level2.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/search_result_level3.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/search_result_level4.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/search_result_level5.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/search_result_level6.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/stats.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/tag.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/tag_cloud_entry.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/tag_summary.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/taxonomy.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/token_config.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/token_configs.py +1 -1
- graphsense_python-2.15.0/graphsense/models/transaction_comparison.py +120 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/tx.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/tx_account.py +1 -1
- graphsense_python-2.15.0/graphsense/models/tx_characteristics.py +108 -0
- graphsense_python-2.15.0/graphsense/models/tx_compared_item.py +100 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/tx_ref.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/tx_summary.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/tx_utxo.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/tx_value.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/user_reported_tag.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/user_tag_report_response.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/utxo_heuristics.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/validation_error.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/values.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/wasabi_heuristic.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/whirlpool_coin_join_heuristic.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/models/whirlpool_tx0_heuristic.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/rest.py +1 -1
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense_python.egg-info/PKG-INFO +44 -4
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense_python.egg-info/SOURCES.txt +34 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/pyproject.toml +1 -1
- graphsense_python-2.15.0/tests/test_cli_scan.py +60 -0
- graphsense_python-2.13.2/graphsense/gs_files/encoder.py +0 -336
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/api_response.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/cli/__init__.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/cli/__main__.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/cli/bulk_cmd.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/cli/context.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/cli/convenience.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/cli/errors.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/cli/gs.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/cli/raw.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/compat.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/ext/__init__.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/ext/bulk.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/ext/client.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/ext/deprecation.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/ext/io.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/ext/output.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/ext/selectors.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/gs_files/parser.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/gs_files/summary.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/gs_files/writer.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/__init__.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/actor.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/actor_context.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/address.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/address_tag.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/address_tags.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/address_tx.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/address_tx_utxo.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/address_txs.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/block.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/block_at_date.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/concept.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/currency_stats.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/entity.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/entity_addresses.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/external_conversion.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/http_validation_error.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/label_summary.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/labeled_item_ref.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/link.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/link_utxo.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/links.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/links_inner.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/location_inner.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/neighbor_address.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/neighbor_addresses.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/neighbor_entities.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/neighbor_entity.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/rate.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/rates.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/related_address.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/related_addresses.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/search_result.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/search_result_by_currency.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/search_result_level1.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/search_result_level2.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/search_result_level3.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/search_result_level4.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/search_result_level5.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/search_result_level6.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/stats.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/tag.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/tag_cloud_entry.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/tag_summary.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/taxonomy.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/token_config.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/token_configs.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/tx.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/tx_account.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/tx_ref.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/tx_summary.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/tx_utxo.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/tx_value.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/user_reported_tag.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/user_tag_report_response.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/validation_error.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/model/values.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense/py.typed +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense_python.egg-info/dependency_links.txt +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense_python.egg-info/entry_points.txt +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense_python.egg-info/requires.txt +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/graphsense_python.egg-info/top_level.txt +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/setup.cfg +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/tests/test_cli_bulk.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/tests/test_cli_convenience.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/tests/test_cli_errors.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/tests/test_cli_gs.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/tests/test_cli_io_pipes.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/tests/test_cli_raw_mirror.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/tests/test_cli_tags_and_dates.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/tests/test_ext_bulk.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/tests/test_ext_client.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/tests/test_ext_io.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/tests/test_ext_output.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/tests/test_ext_selectors.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/tests/test_readme_template.py +0 -0
- {graphsense_python-2.13.2 → graphsense_python-2.15.0}/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.
|
|
3
|
+
Version: 2.15.0
|
|
4
4
|
Summary: GraphSense API
|
|
5
5
|
Author-email: Iknaio Cryptoasset Analytics GmbH <contact@iknaio.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -26,7 +26,7 @@ multiple ledgers. Use it to explore addresses, clusters, blocks, transactions,
|
|
|
26
26
|
tags, token activity, and exchange-rate context, and to integrate investigation
|
|
27
27
|
workflows into your own applications and automation.
|
|
28
28
|
|
|
29
|
-
## Versioning
|
|
29
|
+
## Versioning & deprecation
|
|
30
30
|
|
|
31
31
|
The API follows semantic versioning. Minor releases are additive and
|
|
32
32
|
backwards-compatible; breaking changes only happen in major releases, which
|
|
@@ -42,11 +42,29 @@ introduced before the deprecated surface is removed.
|
|
|
42
42
|
See the [full versioning and deprecation policy](https://github.com/graphsense/graphsense-lib/blob/master/README.md#rest-api-evolution-and-deprecation-policy)
|
|
43
43
|
for details.
|
|
44
44
|
|
|
45
|
+
## AI assistant access (MCP)
|
|
46
|
+
|
|
47
|
+
In addition to this REST API, this deployment exposes a **Model
|
|
48
|
+
Context Protocol (MCP)** interface that lets AI assistants query
|
|
49
|
+
GraphSense directly in natural language, without writing code against
|
|
50
|
+
the endpoints below.
|
|
51
|
+
|
|
52
|
+
The MCP interface is available at the `/mcp` path of this server,
|
|
53
|
+
relative to the address this documentation is served from. It offers a
|
|
54
|
+
curated selection of the most useful operations, so an assistant can
|
|
55
|
+
answer questions about addresses, transactions, clusters, and tags on
|
|
56
|
+
your behalf.
|
|
57
|
+
|
|
58
|
+
To use it, add that `/mcp` URL to an MCP-capable assistant as a new
|
|
59
|
+
connector or tool source; the assistant then handles the rest.
|
|
60
|
+
|
|
61
|
+
**Authentication:** the MCP endpoint is protected by OAuth. When adding the connector in your assistant, use the client ID `iknaio-mcp`.
|
|
62
|
+
|
|
45
63
|
|
|
46
64
|
This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
|
47
65
|
|
|
48
|
-
- API version: 2.
|
|
49
|
-
- Package version: 2.
|
|
66
|
+
- API version: 2.15.0
|
|
67
|
+
- Package version: 2.15.0
|
|
50
68
|
- Generator version: 7.19.0
|
|
51
69
|
- Build package: org.openapitools.codegen.languages.PythonClientCodegen
|
|
52
70
|
For more information, please visit [https://www.iknaio.com/](https://www.iknaio.com/)
|
|
@@ -172,6 +190,8 @@ Class | Method | HTTP request | Description
|
|
|
172
190
|
*EntitiesApi* | [**search_entity_neighbors**](docs/EntitiesApi.md#search_entity_neighbors) | **GET** /{currency}/entities/{entity}/search | Search entity neighborhood
|
|
173
191
|
*GeneralApi* | [**get_statistics**](docs/GeneralApi.md#get_statistics) | **GET** /stats | Get platform statistics for supported currencies
|
|
174
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)
|
|
175
195
|
*RatesApi* | [**get_exchange_rates**](docs/RatesApi.md#get_exchange_rates) | **GET** /{currency}/rates/{height} | Get fiat exchange rates at a block height
|
|
176
196
|
*TagsApi* | [**get_actor**](docs/TagsApi.md#get_actor) | **GET** /tags/actors/{actor} | Get actor details by ID
|
|
177
197
|
*TagsApi* | [**get_actor_tags**](docs/TagsApi.md#get_actor_tags) | **GET** /tags/actors/{actor}/tags | List tags associated with an actor
|
|
@@ -214,6 +234,25 @@ Class | Method | HTTP request | Description
|
|
|
214
234
|
- [Entity](docs/Entity.md)
|
|
215
235
|
- [EntityAddresses](docs/EntityAddresses.md)
|
|
216
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)
|
|
217
256
|
- [HTTPValidationError](docs/HTTPValidationError.md)
|
|
218
257
|
- [JoinMarketHeuristic](docs/JoinMarketHeuristic.md)
|
|
219
258
|
- [LabelSummary](docs/LabelSummary.md)
|
|
@@ -231,6 +270,7 @@ Class | Method | HTTP request | Description
|
|
|
231
270
|
- [NeighborEntities](docs/NeighborEntities.md)
|
|
232
271
|
- [NeighborEntity](docs/NeighborEntity.md)
|
|
233
272
|
- [OneTimeChangeHeuristic](docs/OneTimeChangeHeuristic.md)
|
|
273
|
+
- [PerTxInner](docs/PerTxInner.md)
|
|
234
274
|
- [Rate](docs/Rate.md)
|
|
235
275
|
- [Rates](docs/Rates.md)
|
|
236
276
|
- [RelatedAddress](docs/RelatedAddress.md)
|
|
@@ -4,7 +4,7 @@ multiple ledgers. Use it to explore addresses, clusters, blocks, transactions,
|
|
|
4
4
|
tags, token activity, and exchange-rate context, and to integrate investigation
|
|
5
5
|
workflows into your own applications and automation.
|
|
6
6
|
|
|
7
|
-
## Versioning
|
|
7
|
+
## Versioning & deprecation
|
|
8
8
|
|
|
9
9
|
The API follows semantic versioning. Minor releases are additive and
|
|
10
10
|
backwards-compatible; breaking changes only happen in major releases, which
|
|
@@ -20,11 +20,29 @@ introduced before the deprecated surface is removed.
|
|
|
20
20
|
See the [full versioning and deprecation policy](https://github.com/graphsense/graphsense-lib/blob/master/README.md#rest-api-evolution-and-deprecation-policy)
|
|
21
21
|
for details.
|
|
22
22
|
|
|
23
|
+
## AI assistant access (MCP)
|
|
24
|
+
|
|
25
|
+
In addition to this REST API, this deployment exposes a **Model
|
|
26
|
+
Context Protocol (MCP)** interface that lets AI assistants query
|
|
27
|
+
GraphSense directly in natural language, without writing code against
|
|
28
|
+
the endpoints below.
|
|
29
|
+
|
|
30
|
+
The MCP interface is available at the `/mcp` path of this server,
|
|
31
|
+
relative to the address this documentation is served from. It offers a
|
|
32
|
+
curated selection of the most useful operations, so an assistant can
|
|
33
|
+
answer questions about addresses, transactions, clusters, and tags on
|
|
34
|
+
your behalf.
|
|
35
|
+
|
|
36
|
+
To use it, add that `/mcp` URL to an MCP-capable assistant as a new
|
|
37
|
+
connector or tool source; the assistant then handles the rest.
|
|
38
|
+
|
|
39
|
+
**Authentication:** the MCP endpoint is protected by OAuth. When adding the connector in your assistant, use the client ID `iknaio-mcp`.
|
|
40
|
+
|
|
23
41
|
|
|
24
42
|
This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
|
25
43
|
|
|
26
|
-
- API version: 2.
|
|
27
|
-
- Package version: 2.
|
|
44
|
+
- API version: 2.15.0
|
|
45
|
+
- Package version: 2.15.0
|
|
28
46
|
- Generator version: 7.19.0
|
|
29
47
|
- Build package: org.openapitools.codegen.languages.PythonClientCodegen
|
|
30
48
|
For more information, please visit [https://www.iknaio.com/](https://www.iknaio.com/)
|
|
@@ -150,6 +168,8 @@ Class | Method | HTTP request | Description
|
|
|
150
168
|
*EntitiesApi* | [**search_entity_neighbors**](docs/EntitiesApi.md#search_entity_neighbors) | **GET** /{currency}/entities/{entity}/search | Search entity neighborhood
|
|
151
169
|
*GeneralApi* | [**get_statistics**](docs/GeneralApi.md#get_statistics) | **GET** /stats | Get platform statistics for supported currencies
|
|
152
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)
|
|
153
173
|
*RatesApi* | [**get_exchange_rates**](docs/RatesApi.md#get_exchange_rates) | **GET** /{currency}/rates/{height} | Get fiat exchange rates at a block height
|
|
154
174
|
*TagsApi* | [**get_actor**](docs/TagsApi.md#get_actor) | **GET** /tags/actors/{actor} | Get actor details by ID
|
|
155
175
|
*TagsApi* | [**get_actor_tags**](docs/TagsApi.md#get_actor_tags) | **GET** /tags/actors/{actor}/tags | List tags associated with an actor
|
|
@@ -192,6 +212,25 @@ Class | Method | HTTP request | Description
|
|
|
192
212
|
- [Entity](docs/Entity.md)
|
|
193
213
|
- [EntityAddresses](docs/EntityAddresses.md)
|
|
194
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)
|
|
195
234
|
- [HTTPValidationError](docs/HTTPValidationError.md)
|
|
196
235
|
- [JoinMarketHeuristic](docs/JoinMarketHeuristic.md)
|
|
197
236
|
- [LabelSummary](docs/LabelSummary.md)
|
|
@@ -209,6 +248,7 @@ Class | Method | HTTP request | Description
|
|
|
209
248
|
- [NeighborEntities](docs/NeighborEntities.md)
|
|
210
249
|
- [NeighborEntity](docs/NeighborEntity.md)
|
|
211
250
|
- [OneTimeChangeHeuristic](docs/OneTimeChangeHeuristic.md)
|
|
251
|
+
- [PerTxInner](docs/PerTxInner.md)
|
|
212
252
|
- [Rate](docs/Rate.md)
|
|
213
253
|
- [Rates](docs/Rates.md)
|
|
214
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
|
|
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.
|
|
15
|
+
__version__ = "2.15.0"
|
|
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
|
+
]
|