diff --git a/.github/workflows/python_ci.yaml b/.github/workflows/python_ci.yaml index 5c5bdcf5..45eb7778 100644 --- a/.github/workflows/python_ci.yaml +++ b/.github/workflows/python_ci.yaml @@ -80,3 +80,15 @@ jobs: run: | poetry run isort --profile black . git diff --exit-code || exit 1 + + pre-commit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: ./.github/actions/python_prepare + - name: Install Dependencies + run: | + pip install pre-commit + - name: Run Pre-Commit + run: | + pre-commit run --all-files \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..e348caff --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,9 @@ + repos: + - repo: https://github.com/kongzii/pre-commit-hooks + rev: peter/web3 + hooks: + - id: detect-private-key + - id: check-added-large-files + args: ['--maxkb=5000'] + - id: detect-web3-private-key + exclude: 'poetry.lock' diff --git a/README.md b/README.md index b87b7d4a..db757aea 100644 --- a/README.md +++ b/README.md @@ -133,4 +133,4 @@ This API can be built on top of to create your application. See [here](https://g See the [Issues](https://github.com/gnosis/prediction-market-agent-tooling/issues) for ideas of things that need fixing or implementing. The team is also receptive to new issues and PRs. -We use `mypy` for static type checking, and `isort`, `black` and `autoflake` for linting. These all run as steps in CI. +We use `mypy` for static type checking, and `isort`, `black` and `autoflake` for linting, and `pre-commit` to minimise unwanted pushes to the public repositories. These all run as steps in CI, but `pre-commit` also needs to be installed locally using the provided `install_hooks.sh` script. diff --git a/install_hooks.sh b/install_hooks.sh new file mode 100755 index 00000000..bae18c74 --- /dev/null +++ b/install_hooks.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# Install pre-commit if not already installed +if ! command -v pre-commit &> /dev/null +then + echo "pre-commit is not installed. Installing now..." + brew install pre-commit +fi + +# Install the hooks +pre-commit install + +echo "Pre-commit hooks installed successfully." diff --git a/poetry.lock b/poetry.lock index a5e66fe8..906c7a07 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "aiohappyeyeballs" @@ -1663,12 +1663,12 @@ files = [ google-auth = ">=2.14.1,<3.0.dev0" googleapis-common-protos = ">=1.56.2,<2.0.dev0" grpcio = [ - {version = ">=1.49.1,<2.0dev", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}, {version = ">=1.33.2,<2.0dev", optional = true, markers = "python_version < \"3.11\" and extra == \"grpc\""}, + {version = ">=1.49.1,<2.0dev", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}, ] grpcio-status = [ - {version = ">=1.49.1,<2.0.dev0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}, {version = ">=1.33.2,<2.0.dev0", optional = true, markers = "python_version < \"3.11\" and extra == \"grpc\""}, + {version = ">=1.49.1,<2.0.dev0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}, ] proto-plus = ">=1.22.3,<2.0.0dev" protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0.dev0" @@ -3514,8 +3514,8 @@ files = [ [package.dependencies] numpy = [ - {version = ">=1.23.2", markers = "python_version == \"3.11\""}, {version = ">=1.22.4", markers = "python_version < \"3.11\""}, + {version = ">=1.23.2", markers = "python_version == \"3.11\""}, {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, ] python-dateutil = ">=2.8.2" @@ -4005,6 +4005,7 @@ files = [ {file = "psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:bb89f0a835bcfc1d42ccd5f41f04870c1b936d8507c6df12b7737febc40f0909"}, {file = "psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f0c2d907a1e102526dd2986df638343388b94c33860ff3bbe1384130828714b1"}, {file = "psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f8157bed2f51db683f31306aa497311b560f2265998122abe1dce6428bd86567"}, + {file = "psycopg2_binary-2.9.10-cp313-cp313-win_amd64.whl", hash = "sha256:27422aa5f11fbcd9b18da48373eb67081243662f9b46e6fd07c3eb46e4535142"}, {file = "psycopg2_binary-2.9.10-cp38-cp38-macosx_12_0_x86_64.whl", hash = "sha256:eb09aa7f9cecb45027683bb55aebaaf45a0df8bf6de68801a6afdc7947bb09d4"}, {file = "psycopg2_binary-2.9.10-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b73d6d7f0ccdad7bc43e6d34273f70d587ef62f824d7261c4ae9b8b1b6af90e8"}, {file = "psycopg2_binary-2.9.10-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce5ab4bf46a211a8e924d307c1b1fcda82368586a19d0a24f8ae166f5c784864"}, @@ -4255,6 +4256,7 @@ description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs optional = false python-versions = ">=3.8" files = [ + {file = "pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629"}, {file = "pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034"}, ] @@ -4265,6 +4267,7 @@ description = "A collection of ASN.1-based protocols modules" optional = false python-versions = ">=3.8" files = [ + {file = "pyasn1_modules-0.4.1-py3-none-any.whl", hash = "sha256:49bfa96b45a292b711e986f222502c1c9a5e1f4e568fc30e2574a6c7d07838fd"}, {file = "pyasn1_modules-0.4.1.tar.gz", hash = "sha256:c28e2dbf9c06ad61c71a075c7e0f9fd0f1b0bb2d2ad4377f240d33ac2ab60a7c"}, ] @@ -6335,4 +6338,4 @@ optuna = ["optuna"] [metadata] lock-version = "2.0" python-versions = ">=3.10,<3.13" -content-hash = "248ddd11705c3552209c98fe50f18c91f3aeec9173c169421a83ac5da63e69d7" +content-hash = "09ca1a54df359f2366f7c3d1ee7ab9490b20c6a4250cf06e186e22fe13f5202c" diff --git a/prediction_market_agent_tooling/gtypes.py b/prediction_market_agent_tooling/gtypes.py index 49b04985..955fdc30 100644 --- a/prediction_market_agent_tooling/gtypes.py +++ b/prediction_market_agent_tooling/gtypes.py @@ -82,5 +82,5 @@ def secretstr_to_v1_secretstr(s: SecretStr | None) -> SecretStrV1 | None: def int_to_hexbytes(v: int) -> HexBytes: - # Example: 1 -> HexBytes("0x0000000000000000000000000000000000000000000000000000000000000001"). + # Example: 1 -> HexBytes("0x0000000000000000000000000000000000000000000000000000000000000001"). # web3-private-key-ok return HexBytes.fromhex(format(v, "064x")) diff --git a/prediction_market_agent_tooling/markets/omen/data_models.py b/prediction_market_agent_tooling/markets/omen/data_models.py index bb1fecd9..109fb25e 100644 --- a/prediction_market_agent_tooling/markets/omen/data_models.py +++ b/prediction_market_agent_tooling/markets/omen/data_models.py @@ -584,7 +584,7 @@ class FixedProductMarketMakersResponse(BaseModel): class RealityQuestion(BaseModel): - # This `id` is in form of `0x79e32ae03fb27b07c89c0c568f80287c01ca2e57-0x2d362f435e7b5159794ff0b5457a900283fca41fe6301dc855a647595903db13`, + # This `id` is in form of `0x79e32ae03fb27b07c89c0c568f80287c01ca2e57-0x2d362f435e7b5159794ff0b5457a900283fca41fe6301dc855a647595903db13`, # web3-private-key-ok # which I couldn't find how it is created, but based on how it looks like I assume it's composed of `answerId-questionId`. # (Why is answer id as part of the question object? Because this question object is actually received from the answer object below). # And because all the contract methods so far needed bytes32 input, when asked for question id, `questionId` field was the correct one to use so far. diff --git a/prediction_market_agent_tooling/markets/omen/omen.py b/prediction_market_agent_tooling/markets/omen/omen.py index f80328db..41043547 100644 --- a/prediction_market_agent_tooling/markets/omen/omen.py +++ b/prediction_market_agent_tooling/markets/omen/omen.py @@ -1209,7 +1209,7 @@ def omen_remove_fund_market_tx( amount_per_index_set = get_conditional_tokens_balance_for_market( market, from_address, web3 ) - # We fetch the minimum balance of outcome token - for ex, in this tx (https://gnosisscan.io/tx/0xc31c4e9bc6a60cf7db9991a40ec2f2a06e3539f8cb8dd81b6af893cef6f40cd7#eventlog) - event #460, this should yield 9804940144070370149. This amount matches what is displayed in the Omen UI. + # We fetch the minimum balance of outcome token - for ex, in this tx (https://gnosisscan.io/tx/0xc31c4e9bc6a60cf7db9991a40ec2f2a06e3539f8cb8dd81b6af893cef6f40cd7#eventlog) - event #460, this should yield 9804940144070370149. This amount matches what is displayed in the Omen UI. # web3-private-key-ok # See similar logic from Olas # https://github.com/valory-xyz/market-creator/blob/4bc47f696fb5ecb61c3b7ec8c001ff2ab6c60fcf/packages/valory/skills/market_creation_manager_abci/behaviours.py#L1308 amount_to_merge = min(amount_per_index_set.values()) diff --git a/prediction_market_agent_tooling/tools/hexbytes_custom.py b/prediction_market_agent_tooling/tools/hexbytes_custom.py index 303b1e6e..ebd09cc2 100644 --- a/prediction_market_agent_tooling/tools/hexbytes_custom.py +++ b/prediction_market_agent_tooling/tools/hexbytes_custom.py @@ -23,7 +23,7 @@ class BaseHex: "0xd4e56740", "0xd4e56740f876aef8", "0xd4e56740f876aef8c010b86a40d5f567", - "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", + "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", # web3-private-key-ok ) @classmethod diff --git a/pyproject.toml b/pyproject.toml index 0e478369..a3808f52 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,6 +54,7 @@ pinatapy-vourhey = "^0.2.0" hishel = "^0.0.31" pytest-postgresql = "^6.1.1" optuna = { version = "^4.1.0", optional = true} +eth-keys = "^0.6.1" [tool.poetry.extras] openai = ["openai"] diff --git a/scripts/store_prediction.py b/scripts/store_prediction.py index 42526671..ecb44851 100644 --- a/scripts/store_prediction.py +++ b/scripts/store_prediction.py @@ -31,9 +31,7 @@ def main( SAFE_ADDRESS=None, ) market_address = Web3.to_checksum_address(api_keys.public_key) - dummy_transaction_hash = ( - "0x3750ffa211dab39b4d0711eb27b02b56a17fa9d257ee549baa3110725fd1d41b" - ) + dummy_transaction_hash = "0x3750ffa211dab39b4d0711eb27b02b56a17fa9d257ee549baa3110725fd1d41b" # web3-private-key-ok contract_prediction = ContractPrediction( tx_hashes=[HexBytes(dummy_transaction_hash)], estimated_probability_bps=5454, diff --git a/tests/markets/omen/test_omen_subgraph_handler.py b/tests/markets/omen/test_omen_subgraph_handler.py index e3e57d23..3c916cd8 100644 --- a/tests/markets/omen/test_omen_subgraph_handler.py +++ b/tests/markets/omen/test_omen_subgraph_handler.py @@ -150,9 +150,15 @@ def test_get_user_positions_1( ) # Assert 3 conditionIds are included expected_condition_ids = [ - HexBytes("0x9c7711bee0902cc8e6838179058726a7ba769cc97d4d0ea47b31370d2d7a117b"), - HexBytes("0xe2bf80af2a936cdabeef4f511620a2eec46f1caf8e75eb5dc189372367a9154c"), - HexBytes("0x3f8153364001b26b983dd92191a084de8230f199b5ad0b045e9e1df61089b30d"), + HexBytes( + "0x9c7711bee0902cc8e6838179058726a7ba769cc97d4d0ea47b31370d2d7a117b" # web3-private-key-ok + ), + HexBytes( + "0xe2bf80af2a936cdabeef4f511620a2eec46f1caf8e75eb5dc189372367a9154c" # web3-private-key-ok + ), + HexBytes( + "0x3f8153364001b26b983dd92191a084de8230f199b5ad0b045e9e1df61089b30d" # web3-private-key-ok + ), ] unique_condition_ids: list[HexBytes] = sum( [u.position.conditionIds for u in user_positions], [] @@ -162,7 +168,9 @@ def test_get_user_positions_1( def test_get_answers(omen_subgraph_handler: OmenSubgraphHandler) -> None: question_id = HexBytes.fromhex( - HexStr("0xdcb2691a9ec05e25a6e595a9972b482ea65b789d978b27c0c06ff97345fce919") + HexStr( + "0xdcb2691a9ec05e25a6e595a9972b482ea65b789d978b27c0c06ff97345fce919" # web3-private-key-ok + ) ) answers = omen_subgraph_handler.get_answers(question_id) assert len(answers) == 1 @@ -174,7 +182,9 @@ def test_get_answers(omen_subgraph_handler: OmenSubgraphHandler) -> None: def test_get_responses(omen_subgraph_handler: OmenSubgraphHandler) -> None: question_id = HexBytes.fromhex( - HexStr("0xdcb2691a9ec05e25a6e595a9972b482ea65b789d978b27c0c06ff97345fce919") + HexStr( + "0xdcb2691a9ec05e25a6e595a9972b482ea65b789d978b27c0c06ff97345fce919" # web3-private-key-ok + ) ) responses = omen_subgraph_handler.get_responses(limit=None, question_id=question_id) assert len(responses) == 1 @@ -190,23 +200,23 @@ def test_get_responses(omen_subgraph_handler: OmenSubgraphHandler) -> None: None, [ HexBytes( - "0x00f57ca97d4fc07c70c0900df502dacfca455dd435643fcfab44e122b7da8684" + "0x00f57ca97d4fc07c70c0900df502dacfca455dd435643fcfab44e122b7da8684" # web3-private-key-ok ) ], [ HexBytes( - "0x00f57ca97d4fc07c70c0900df502dacfca455dd435643fcfab44e122b7da8684" + "0x00f57ca97d4fc07c70c0900df502dacfca455dd435643fcfab44e122b7da8684" # web3-private-key-ok ), HexBytes( - "0xfa2f09d7375837e791c66f7ccee06d4fa7955812baf668883c2a5f939670ef33" + "0xfa2f09d7375837e791c66f7ccee06d4fa7955812baf668883c2a5f939670ef33" # web3-private-key-ok ), ], [ HexBytes( - "0x00f57ca97d4fc07c70c0900df502dacfca455dd435643fcfab44e122b7da8684" + "0x00f57ca97d4fc07c70c0900df502dacfca455dd435643fcfab44e122b7da8684" # web3-private-key-ok ), HexBytes( - "0xfa2f09d7375837e791c66f7ccee06d4fa7955812baf668883c2a5f939670ef33" + "0xfa2f09d7375837e791c66f7ccee06d4fa7955812baf668883c2a5f939670ef33" # web3-private-key-ok ), ] * 100, # Multiply to test if API won't fail with many IDs in the list. @@ -233,7 +243,9 @@ def test_get_market_with_condition_ids( omen_subgraph_handler: OmenSubgraphHandler, ) -> None: condition_ids = [ - HexBytes("0x9c7711bee0902cc8e6838179058726a7ba769cc97d4d0ea47b31370d2d7a117b") + HexBytes( + "0x9c7711bee0902cc8e6838179058726a7ba769cc97d4d0ea47b31370d2d7a117b" # web3-private-key-ok + ) ] expected_market_title = ( "Will the Federal Reserve cut interest rates on 28 March 2024?" @@ -251,8 +263,12 @@ def test_get_markets_from_multiple_user_positions( omen_subgraph_handler: OmenSubgraphHandler, ) -> None: condition_ids = [ - HexBytes("0xe2bf80af2a936cdabeef4f511620a2eec46f1caf8e75eb5dc189372367a9154c"), - HexBytes("0x3f8153364001b26b983dd92191a084de8230f199b5ad0b045e9e1df61089b30d"), + HexBytes( + "0xe2bf80af2a936cdabeef4f511620a2eec46f1caf8e75eb5dc189372367a9154c" # web3-private-key-ok + ), + HexBytes( + "0x3f8153364001b26b983dd92191a084de8230f199b5ad0b045e9e1df61089b30d" # web3-private-key-ok + ), ] user_positions = [ build_incomplete_user_position_from_condition_ids([condition_id]) @@ -268,7 +284,7 @@ def test_get_positions_by_condition_id( omen_subgraph_handler: OmenSubgraphHandler, ) -> None: condition_id = HexBytes( - "0xffe4bf3e61be010728813a2a61ef422fd7d07b410170b64a5dfced9549f2e057" + "0xffe4bf3e61be010728813a2a61ef422fd7d07b410170b64a5dfced9549f2e057" # web3-private-key-ok ) positions = omen_subgraph_handler.get_positions(condition_id) assert len(positions) == 2 @@ -365,7 +381,7 @@ def test_get_arbitrated_market_with_answer( assert omen_subgraph_handler.get_questions( limit=None, question_id=HexBytes( - "0xfd9c313aca5b704d6d4920ab7dd4c6d1ebcdfa0242df8dc517a050643419285b" + "0xfd9c313aca5b704d6d4920ab7dd4c6d1ebcdfa0242df8dc517a050643419285b" # web3-private-key-ok ), with_answers=True, ), "Should return it, because that questionId has an answer." @@ -374,11 +390,11 @@ def test_get_arbitrated_market_with_answer( def test_do_not_get_arbitrated_market_without_answer( omen_subgraph_handler: OmenSubgraphHandler, ) -> None: - # If this test starts to fail, check if `0xfd9c313aca5b704d6d4920ab7dd4c6d1ebcdfa0242df8dc517a050643419285b` isn't arbitrated anymore, and if so simply delete this test. + # If this test starts to fail, check if `0xfd9c313aca5b704d6d4920ab7dd4c6d1ebcdfa0242df8dc517a050643419285b` isn't arbitrated anymore, and if so simply delete this test. # web3-private-key-ok assert not omen_subgraph_handler.get_questions( limit=None, question_id=HexBytes( - "0xfd9c313aca5b704d6d4920ab7dd4c6d1ebcdfa0242df8dc517a050643419285b" + "0xfd9c313aca5b704d6d4920ab7dd4c6d1ebcdfa0242df8dc517a050643419285b" # web3-private-key-ok ), with_answers=False, ), "Should not return anything, because that questionId has an answer." diff --git a/tests/tools/test_web3_utils.py b/tests/tools/test_web3_utils.py index ec26d203..65f0ef53 100644 --- a/tests/tools/test_web3_utils.py +++ b/tests/tools/test_web3_utils.py @@ -13,9 +13,7 @@ def test_private_key_to_public_key() -> None: - ganache_private_key_example = ( - "0x94c589f92a38698b984605efbc0bff47208c43eac85ab6ea553cc9e17c4a49fe" - ) + ganache_private_key_example = "0x94c589f92a38698b984605efbc0bff47208c43eac85ab6ea553cc9e17c4a49fe" # web3-private-key-ok ganache_public_key_example = "0x4c24e51488429E013f259A7FB6Ac174c715BB66a" actual_public_key = private_key_to_public_key( SecretStr(ganache_private_key_example) diff --git a/tests_integration_with_local_chain/markets/omen/test_omen.py b/tests_integration_with_local_chain/markets/omen/test_omen.py index 9cfd5cde..de3165be 100644 --- a/tests_integration_with_local_chain/markets/omen/test_omen.py +++ b/tests_integration_with_local_chain/markets/omen/test_omen.py @@ -455,14 +455,15 @@ def get_position_balance_by_position_id( @pytest.mark.parametrize( "ipfs_hash", - ["0x3750ffa211dab39b4d0711eb27b02b56a17fa9d257ee549baa3110725fd1d41b", HASH_ZERO], + [ + "0x3750ffa211dab39b4d0711eb27b02b56a17fa9d257ee549baa3110725fd1d41b", # web3-private-key-ok + HASH_ZERO, + ], ) def test_add_predictions(local_web3: Web3, test_keys: APIKeys, ipfs_hash: str) -> None: agent_result_mapping = OmenAgentResultMappingContract() market_address = test_keys.public_key - dummy_transaction_hash = ( - "0x3750ffa211dab39b4d0711eb27b02b56a17fa9d257ee549baa3110725fd1d41b" - ) + dummy_transaction_hash = "0x3750ffa211dab39b4d0711eb27b02b56a17fa9d257ee549baa3110725fd1d41b" # web3-private-key-ok stored_predictions = agent_result_mapping.get_predictions( market_address, web3=local_web3 ) diff --git a/tests_integration_with_local_chain/safe/test_constants.py b/tests_integration_with_local_chain/safe/test_constants.py index bdc0dc26..c64ccb2d 100644 --- a/tests_integration_with_local_chain/safe/test_constants.py +++ b/tests_integration_with_local_chain/safe/test_constants.py @@ -1 +1 @@ -ANVIL_PKEY1 = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" +ANVIL_PKEY1 = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" # web3-private-key-ok