From 1fb0f305b0b2b92e70f65422fdbae2ae62bf320b Mon Sep 17 00:00:00 2001 From: Rui Qi Chen Date: Wed, 17 Apr 2024 00:45:31 +0000 Subject: [PATCH] test and format --- src/solana/_layouts/vote_instructions.py | 1 + src/solana/exceptions.py | 1 + src/solana/rpc/api.py | 1 + src/solana/rpc/async_api.py | 1 + src/solana/rpc/commitment.py | 1 + src/solana/rpc/core.py | 12 ++++--- src/solana/rpc/providers/async_base.py | 1 + src/solana/rpc/providers/async_http.py | 19 ++++------- src/solana/rpc/providers/base.py | 1 + src/solana/rpc/providers/core.py | 37 ++++++++------------- src/solana/rpc/providers/http.py | 19 ++++------- src/solana/rpc/types.py | 1 + src/solana/rpc/websocket_api.py | 1 + src/solana/transaction.py | 1 + src/solana/utils/security_txt.py | 1 - src/solana/utils/validate.py | 1 + src/solana/vote_program.py | 1 + src/spl/memo/constants.py | 1 + src/spl/memo/instructions.py | 1 + src/spl/token/_layouts.py | 1 + src/spl/token/async_client.py | 8 ++++- src/spl/token/client.py | 8 ++++- src/spl/token/instructions.py | 6 ++-- tests/conftest.py | 1 + tests/integration/test_async_http_client.py | 7 ++-- tests/integration/test_http_client.py | 7 ++-- tests/integration/test_memo.py | 1 + tests/integration/test_websockets.py | 25 ++++++++++++++ tests/unit/test_async_client.py | 1 + tests/unit/test_client.py | 1 + tests/unit/test_spl_token_instructions.py | 1 + tests/unit/test_transaction.py | 1 + tests/unit/test_vote_program.py | 1 + tests/utils.py | 1 + 34 files changed, 105 insertions(+), 67 deletions(-) diff --git a/src/solana/_layouts/vote_instructions.py b/src/solana/_layouts/vote_instructions.py index 4dafcffc..fb475c34 100644 --- a/src/solana/_layouts/vote_instructions.py +++ b/src/solana/_layouts/vote_instructions.py @@ -1,4 +1,5 @@ """Byte layouts for vote program instructions.""" + from enum import IntEnum from construct import ( diff --git a/src/solana/exceptions.py b/src/solana/exceptions.py index a868cce7..1ffa377e 100644 --- a/src/solana/exceptions.py +++ b/src/solana/exceptions.py @@ -1,4 +1,5 @@ """Exceptions native to solana-py.""" + from typing import Any, Callable diff --git a/src/solana/rpc/api.py b/src/solana/rpc/api.py index cbfed693..9e70ab7c 100644 --- a/src/solana/rpc/api.py +++ b/src/solana/rpc/api.py @@ -1,4 +1,5 @@ """API client to interact with the Solana JSON RPC Endpoint.""" # pylint: disable=too-many-lines + from __future__ import annotations from time import sleep, time diff --git a/src/solana/rpc/async_api.py b/src/solana/rpc/async_api.py index 53bc01d8..bd7831e8 100644 --- a/src/solana/rpc/async_api.py +++ b/src/solana/rpc/async_api.py @@ -1,4 +1,5 @@ """Async API client to interact with the Solana JSON RPC Endpoint.""" # pylint: disable=too-many-lines + import asyncio from time import time from typing import Dict, List, Optional, Sequence, Union diff --git a/src/solana/rpc/commitment.py b/src/solana/rpc/commitment.py index b0f9dbbe..e3bfb8cf 100644 --- a/src/solana/rpc/commitment.py +++ b/src/solana/rpc/commitment.py @@ -4,6 +4,7 @@ In descending order of commitment (most finalized to least finalized), clients may specify: """ + from typing import NewType Commitment = NewType("Commitment", str) diff --git a/src/solana/rpc/core.py b/src/solana/rpc/core.py index 8033dc96..09f40230 100644 --- a/src/solana/rpc/core.py +++ b/src/solana/rpc/core.py @@ -379,7 +379,11 @@ def _get_token_accounts_convert( pubkey: Pubkey, opts: types.TokenAccountOpts, commitment: Optional[Commitment], - ) -> Tuple[Pubkey, Union[RpcTokenAccountsFilterMint, RpcTokenAccountsFilterProgramId], RpcAccountInfoConfig,]: + ) -> Tuple[ + Pubkey, + Union[RpcTokenAccountsFilterMint, RpcTokenAccountsFilterProgramId], + RpcAccountInfoConfig, + ]: commitment_to_use = _COMMITMENT_TO_SOLDERS[commitment or self._commitment] encoding_to_use = _ACCOUNT_ENCODING_TO_SOLDERS[opts.encoding] maybe_data_slice = opts.data_slice @@ -486,14 +490,12 @@ def _send_raw_transaction_post_send_args( @overload def _simulate_transaction_body( self, txn: Transaction, sig_verify: bool, commitment: Optional[Commitment] - ) -> SimulateLegacyTransaction: - ... + ) -> SimulateLegacyTransaction: ... @overload def _simulate_transaction_body( self, txn: VersionedTransaction, sig_verify: bool, commitment: Optional[Commitment] - ) -> SimulateVersionedTransaction: - ... + ) -> SimulateVersionedTransaction: ... def _simulate_transaction_body( self, txn: Union[Transaction, VersionedTransaction], sig_verify: bool, commitment: Optional[Commitment] diff --git a/src/solana/rpc/providers/async_base.py b/src/solana/rpc/providers/async_base.py index fd144338..85bc01be 100644 --- a/src/solana/rpc/providers/async_base.py +++ b/src/solana/rpc/providers/async_base.py @@ -1,4 +1,5 @@ """Async base RPC Provider.""" + from typing import Type from solders.rpc.requests import Body diff --git a/src/solana/rpc/providers/async_http.py b/src/solana/rpc/providers/async_http.py index e86ba566..a7471ff7 100644 --- a/src/solana/rpc/providers/async_http.py +++ b/src/solana/rpc/providers/async_http.py @@ -1,4 +1,5 @@ """Async HTTP RPC Provider.""" + from typing import Dict, Optional, Tuple, Type, overload import httpx @@ -72,28 +73,22 @@ async def make_batch_request_unparsed(self, reqs: Tuple[Body, ...]) -> str: return _after_request_unparsed(raw_response) @overload - async def make_batch_request(self, reqs: _BodiesTup, parsers: _Tup) -> _RespTup: - ... + async def make_batch_request(self, reqs: _BodiesTup, parsers: _Tup) -> _RespTup: ... @overload - async def make_batch_request(self, reqs: _BodiesTup1, parsers: _Tup1) -> _RespTup1: - ... + async def make_batch_request(self, reqs: _BodiesTup1, parsers: _Tup1) -> _RespTup1: ... @overload - async def make_batch_request(self, reqs: _BodiesTup2, parsers: _Tup2) -> _RespTup2: - ... + async def make_batch_request(self, reqs: _BodiesTup2, parsers: _Tup2) -> _RespTup2: ... @overload - async def make_batch_request(self, reqs: _BodiesTup3, parsers: _Tup3) -> _RespTup3: - ... + async def make_batch_request(self, reqs: _BodiesTup3, parsers: _Tup3) -> _RespTup3: ... @overload - async def make_batch_request(self, reqs: _BodiesTup4, parsers: _Tup4) -> _RespTup4: - ... + async def make_batch_request(self, reqs: _BodiesTup4, parsers: _Tup4) -> _RespTup4: ... @overload - async def make_batch_request(self, reqs: _BodiesTup5, parsers: _Tup5) -> _RespTup5: - ... + async def make_batch_request(self, reqs: _BodiesTup5, parsers: _Tup5) -> _RespTup5: ... async def make_batch_request(self, reqs: Tuple[Body, ...], parsers: _Tuples) -> Tuple[RPCResult, ...]: """Make an async HTTP batch request to an http rpc endpoint. diff --git a/src/solana/rpc/providers/base.py b/src/solana/rpc/providers/base.py index be58fcc1..fc9584ad 100644 --- a/src/solana/rpc/providers/base.py +++ b/src/solana/rpc/providers/base.py @@ -1,4 +1,5 @@ """Base RPC Provider.""" + from solders.rpc.requests import Body from typing_extensions import Type diff --git a/src/solana/rpc/providers/core.py b/src/solana/rpc/providers/core.py index 0be1a350..87e54634 100644 --- a/src/solana/rpc/providers/core.py +++ b/src/solana/rpc/providers/core.py @@ -1,4 +1,5 @@ """Helper code for HTTP provider classes.""" + import itertools import logging import os @@ -99,33 +100,27 @@ def _parse_raw(raw: str, parser: Type[T]) -> T: @overload -def _parse_raw_batch(raw: str, parsers: _Tup) -> _RespTup: - ... +def _parse_raw_batch(raw: str, parsers: _Tup) -> _RespTup: ... @overload -def _parse_raw_batch(raw: str, parsers: _Tup1) -> _RespTup1: - ... +def _parse_raw_batch(raw: str, parsers: _Tup1) -> _RespTup1: ... @overload -def _parse_raw_batch(raw: str, parsers: _Tup2) -> _RespTup2: - ... +def _parse_raw_batch(raw: str, parsers: _Tup2) -> _RespTup2: ... @overload -def _parse_raw_batch(raw: str, parsers: _Tup3) -> _RespTup3: - ... +def _parse_raw_batch(raw: str, parsers: _Tup3) -> _RespTup3: ... @overload -def _parse_raw_batch(raw: str, parsers: _Tup4) -> _RespTup4: - ... +def _parse_raw_batch(raw: str, parsers: _Tup4) -> _RespTup4: ... @overload -def _parse_raw_batch(raw: str, parsers: _Tup5) -> _RespTup5: - ... +def _parse_raw_batch(raw: str, parsers: _Tup5) -> _RespTup5: ... def _parse_raw_batch(raw: str, parsers: _Tuples) -> Tuple[RPCResult, ...]: @@ -138,33 +133,27 @@ def _after_request_unparsed(raw_response: httpx.Response) -> str: @overload -def _after_batch_request(raw_response: httpx.Response, parsers: _Tup) -> _RespTup: - ... +def _after_batch_request(raw_response: httpx.Response, parsers: _Tup) -> _RespTup: ... @overload -def _after_batch_request(raw_response: httpx.Response, parsers: _Tup1) -> _RespTup1: - ... +def _after_batch_request(raw_response: httpx.Response, parsers: _Tup1) -> _RespTup1: ... @overload -def _after_batch_request(raw_response: httpx.Response, parsers: _Tup2) -> _RespTup2: - ... +def _after_batch_request(raw_response: httpx.Response, parsers: _Tup2) -> _RespTup2: ... @overload -def _after_batch_request(raw_response: httpx.Response, parsers: _Tup3) -> _RespTup3: - ... +def _after_batch_request(raw_response: httpx.Response, parsers: _Tup3) -> _RespTup3: ... @overload -def _after_batch_request(raw_response: httpx.Response, parsers: _Tup4) -> _RespTup4: - ... +def _after_batch_request(raw_response: httpx.Response, parsers: _Tup4) -> _RespTup4: ... @overload -def _after_batch_request(raw_response: httpx.Response, parsers: _Tup5) -> _RespTup5: - ... +def _after_batch_request(raw_response: httpx.Response, parsers: _Tup5) -> _RespTup5: ... def _after_batch_request(raw_response: httpx.Response, parsers: _Tuples) -> Tuple[RPCResult, ...]: diff --git a/src/solana/rpc/providers/http.py b/src/solana/rpc/providers/http.py index f6757e97..5f42ac5d 100644 --- a/src/solana/rpc/providers/http.py +++ b/src/solana/rpc/providers/http.py @@ -1,4 +1,5 @@ """HTTP RPC Provider.""" + from typing import Tuple, Type, overload import httpx @@ -61,28 +62,22 @@ def make_batch_request_unparsed(self, reqs: Tuple[Body, ...]) -> str: return _after_request_unparsed(raw_response) @overload - def make_batch_request(self, reqs: _BodiesTup, parsers: _Tup) -> _RespTup: - ... + def make_batch_request(self, reqs: _BodiesTup, parsers: _Tup) -> _RespTup: ... @overload - def make_batch_request(self, reqs: _BodiesTup1, parsers: _Tup1) -> _RespTup1: - ... + def make_batch_request(self, reqs: _BodiesTup1, parsers: _Tup1) -> _RespTup1: ... @overload - def make_batch_request(self, reqs: _BodiesTup2, parsers: _Tup2) -> _RespTup2: - ... + def make_batch_request(self, reqs: _BodiesTup2, parsers: _Tup2) -> _RespTup2: ... @overload - def make_batch_request(self, reqs: _BodiesTup3, parsers: _Tup3) -> _RespTup3: - ... + def make_batch_request(self, reqs: _BodiesTup3, parsers: _Tup3) -> _RespTup3: ... @overload - def make_batch_request(self, reqs: _BodiesTup4, parsers: _Tup4) -> _RespTup4: - ... + def make_batch_request(self, reqs: _BodiesTup4, parsers: _Tup4) -> _RespTup4: ... @overload - def make_batch_request(self, reqs: _BodiesTup5, parsers: _Tup5) -> _RespTup5: - ... + def make_batch_request(self, reqs: _BodiesTup5, parsers: _Tup5) -> _RespTup5: ... def make_batch_request(self, reqs: Tuple[Body, ...], parsers: _Tuples) -> Tuple[RPCResult, ...]: """Make a HTTP batch request to an http rpc endpoint. diff --git a/src/solana/rpc/types.py b/src/solana/rpc/types.py index 17e834e9..6036e370 100644 --- a/src/solana/rpc/types.py +++ b/src/solana/rpc/types.py @@ -1,4 +1,5 @@ """RPC types.""" + from typing import NamedTuple, NewType, Optional from solders.pubkey import Pubkey diff --git a/src/solana/rpc/websocket_api.py b/src/solana/rpc/websocket_api.py index 2d2c4d4f..e043625f 100644 --- a/src/solana/rpc/websocket_api.py +++ b/src/solana/rpc/websocket_api.py @@ -1,4 +1,5 @@ """This module contains code for interacting with the RPC Websocket endpoint.""" + import itertools from typing import Any, Dict, List, Optional, Sequence, Union, cast diff --git a/src/solana/transaction.py b/src/solana/transaction.py index b7525262..dbcd178c 100644 --- a/src/solana/transaction.py +++ b/src/solana/transaction.py @@ -1,4 +1,5 @@ """Library to package an atomic sequence of instructions to a transaction.""" + from __future__ import annotations from typing import Any, List, NamedTuple, Optional, Sequence, Tuple, Union diff --git a/src/solana/utils/security_txt.py b/src/solana/utils/security_txt.py index 6c226364..7f8ef81d 100644 --- a/src/solana/utils/security_txt.py +++ b/src/solana/utils/security_txt.py @@ -1,6 +1,5 @@ """Utils for security.txt.""" - from dataclasses import dataclass, fields from typing import Any, List, Optional diff --git a/src/solana/utils/validate.py b/src/solana/utils/validate.py index ee83c584..0f0ab4f6 100644 --- a/src/solana/utils/validate.py +++ b/src/solana/utils/validate.py @@ -1,4 +1,5 @@ """Validation utilities.""" + from __future__ import annotations from enum import IntEnum diff --git a/src/solana/vote_program.py b/src/solana/vote_program.py index e1f5f1a8..875445a9 100644 --- a/src/solana/vote_program.py +++ b/src/solana/vote_program.py @@ -1,4 +1,5 @@ """Library to interface with the vote program.""" + from __future__ import annotations from typing import NamedTuple diff --git a/src/spl/memo/constants.py b/src/spl/memo/constants.py index 07f41cc8..23c65edd 100644 --- a/src/spl/memo/constants.py +++ b/src/spl/memo/constants.py @@ -1,4 +1,5 @@ """Memo program constants.""" + from solders.pubkey import Pubkey MEMO_PROGRAM_ID: Pubkey = Pubkey.from_string("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr") diff --git a/src/spl/memo/instructions.py b/src/spl/memo/instructions.py index 8313804f..eebefc59 100644 --- a/src/spl/memo/instructions.py +++ b/src/spl/memo/instructions.py @@ -1,4 +1,5 @@ """Memo program instructions.""" + from __future__ import annotations from typing import NamedTuple diff --git a/src/spl/token/_layouts.py b/src/spl/token/_layouts.py index f9228f17..7dcc1269 100644 --- a/src/spl/token/_layouts.py +++ b/src/spl/token/_layouts.py @@ -1,4 +1,5 @@ """Token instruction layouts.""" + from enum import IntEnum from construct import Bytes, Int8ul, Int32ul, Int64ul, Pass, Switch diff --git a/src/spl/token/async_client.py b/src/spl/token/async_client.py index 640d67a9..1531010e 100644 --- a/src/spl/token/async_client.py +++ b/src/spl/token/async_client.py @@ -306,7 +306,13 @@ async def create_wrapped_native_account( """ # Allocate memory for the account balance_needed = await AsyncToken.get_min_balance_rent_for_exempt_for_account(conn) - (new_account_public_key, txn, payer, new_account, opts,) = _TokenCore._create_wrapped_native_account_args( + ( + new_account_public_key, + txn, + payer, + new_account, + opts, + ) = _TokenCore._create_wrapped_native_account_args( program_id, owner, payer, diff --git a/src/spl/token/client.py b/src/spl/token/client.py index e44f5309..4f79079e 100644 --- a/src/spl/token/client.py +++ b/src/spl/token/client.py @@ -305,7 +305,13 @@ def create_wrapped_native_account( """ # Allocate memory for the account balance_needed = Token.get_min_balance_rent_for_exempt_for_account(conn) - (new_account_public_key, txn, payer, new_account, opts,) = _TokenCore._create_wrapped_native_account_args( + ( + new_account_public_key, + txn, + payer, + new_account, + opts, + ) = _TokenCore._create_wrapped_native_account_args( program_id, owner, payer, diff --git a/src/spl/token/instructions.py b/src/spl/token/instructions.py index 705d5ece..e420ea67 100644 --- a/src/spl/token/instructions.py +++ b/src/spl/token/instructions.py @@ -326,9 +326,9 @@ def decode_initialize_mint(instruction: Instruction) -> InitializeMintParams: program_id=instruction.program_id, mint=instruction.accounts[0].pubkey, mint_authority=Pubkey(parsed_data.args.mint_authority), - freeze_authority=Pubkey(parsed_data.args.freeze_authority) - if parsed_data.args.freeze_authority_option - else None, + freeze_authority=( + Pubkey(parsed_data.args.freeze_authority) if parsed_data.args.freeze_authority_option else None + ), ) diff --git a/tests/conftest.py b/tests/conftest.py index 7f665ef5..e58d3517 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,4 +1,5 @@ """Fixtures for pytest.""" + import asyncio import time from typing import NamedTuple diff --git a/tests/integration/test_async_http_client.py b/tests/integration/test_async_http_client.py index 2947278c..ced4a68a 100644 --- a/tests/integration/test_async_http_client.py +++ b/tests/integration/test_async_http_client.py @@ -1,4 +1,5 @@ """Tests for the HTTP API Client.""" + from typing import Tuple import pytest @@ -615,10 +616,8 @@ async def test_batch_request(test_http_client_async: AsyncClient): """Test get vote accounts.""" reqs = (GetBlockHeight(), GetFirstAvailableBlock()) parsers = (GetBlockHeightResp, GetFirstAvailableBlockResp) - resp: Tuple[ - Resp[GetBlockHeightResp], Resp[GetFirstAvailableBlockResp] - ] = await test_http_client_async._provider.make_batch_request( # pylint: disable=protected-access - reqs, parsers + resp: Tuple[Resp[GetBlockHeightResp], Resp[GetFirstAvailableBlockResp]] = ( + await test_http_client_async._provider.make_batch_request(reqs, parsers) # pylint: disable=protected-access ) assert_valid_response(resp[0]) assert_valid_response(resp[1]) diff --git a/tests/integration/test_http_client.py b/tests/integration/test_http_client.py index ca23607e..52b1c285 100644 --- a/tests/integration/test_http_client.py +++ b/tests/integration/test_http_client.py @@ -1,4 +1,5 @@ """Tests for the HTTP API Client.""" + from typing import Tuple import pytest @@ -591,10 +592,8 @@ def test_batch_request(test_http_client: Client): """Test get vote accounts.""" reqs = (GetBlockHeight(), GetFirstAvailableBlock()) parsers = (GetBlockHeightResp, GetFirstAvailableBlockResp) - resp: Tuple[ - Resp[GetBlockHeightResp], Resp[GetFirstAvailableBlockResp] - ] = test_http_client._provider.make_batch_request( # pylint: disable=protected-access - reqs, parsers + resp: Tuple[Resp[GetBlockHeightResp], Resp[GetFirstAvailableBlockResp]] = ( + test_http_client._provider.make_batch_request(reqs, parsers) # pylint: disable=protected-access ) assert_valid_response(resp[0]) assert_valid_response(resp[1]) diff --git a/tests/integration/test_memo.py b/tests/integration/test_memo.py index 1c7b3446..bdc72149 100644 --- a/tests/integration/test_memo.py +++ b/tests/integration/test_memo.py @@ -1,4 +1,5 @@ """Tests for the Memo program.""" + import pytest from solders.keypair import Keypair from solders.transaction_status import ParsedInstruction diff --git a/tests/integration/test_websockets.py b/tests/integration/test_websockets.py index 9bd49789..b88ddc8f 100644 --- a/tests/integration/test_websockets.py +++ b/tests/integration/test_websockets.py @@ -12,6 +12,7 @@ from solders.rpc.responses import ( AccountNotification, LogsNotification, + BlockNotification, ProgramNotification, RootNotification, SignatureNotification, @@ -103,6 +104,18 @@ async def logs_subscribed_mentions_filter( await websocket.logs_unsubscribe(subscription_id) +@pytest.fixture +async def block_subscribed(websocket: SolanaWsClientProtocol) -> AsyncGenerator[None, None]: + """Setup block subscription.""" + await websocket.block_subscribe() + first_resp = await websocket.recv() + msg = first_resp[0] + assert isinstance(msg, SubscriptionResult) + subscription_id = msg.result + yield + await websocket.block_unsubscribe(subscription_id) + + @pytest.fixture async def program_subscribed( websocket: SolanaWsClientProtocol, test_http_client_async: AsyncClient @@ -250,6 +263,18 @@ async def test_logs_subscribe_mentions_filter( assert msg.result.value.logs[0] == "Program 11111111111111111111111111111111 invoke [1]" +@pytest.mark.integration +async def test_block_subscribe( + websocket: SolanaWsClientProtocol, + block_subscribed: None, +): + """Test block subscription.""" + main_resp = await websocket.recv() + msg = main_resp[0] + assert isinstance(msg, BlockNotification) + assert msg.result.value.slot >= 0 + + @pytest.mark.integration async def test_program_subscribe( test_http_client_async: AsyncClient, diff --git a/tests/unit/test_async_client.py b/tests/unit/test_async_client.py index d413e302..1b14f8ff 100644 --- a/tests/unit/test_async_client.py +++ b/tests/unit/test_async_client.py @@ -1,4 +1,5 @@ """Test async client.""" + from unittest.mock import patch import pytest diff --git a/tests/unit/test_client.py b/tests/unit/test_client.py index 07e0b0ea..74645750 100644 --- a/tests/unit/test_client.py +++ b/tests/unit/test_client.py @@ -1,4 +1,5 @@ """Test sync client.""" + from unittest.mock import patch import pytest diff --git a/tests/unit/test_spl_token_instructions.py b/tests/unit/test_spl_token_instructions.py index f3a12132..c74eb25b 100644 --- a/tests/unit/test_spl_token_instructions.py +++ b/tests/unit/test_spl_token_instructions.py @@ -1,4 +1,5 @@ """Unit tests for SPL-token instructions.""" + import spl.token.instructions as spl_token from solders.pubkey import Pubkey from spl.token.constants import TOKEN_PROGRAM_ID, WRAPPED_SOL_MINT diff --git a/tests/unit/test_transaction.py b/tests/unit/test_transaction.py index 17bb82fa..2e24b9a1 100644 --- a/tests/unit/test_transaction.py +++ b/tests/unit/test_transaction.py @@ -1,4 +1,5 @@ """Unit tests for solana.transaction.""" + from base64 import b64decode, b64encode import pytest diff --git a/tests/unit/test_vote_program.py b/tests/unit/test_vote_program.py index ec8c1a48..6f6d3b06 100644 --- a/tests/unit/test_vote_program.py +++ b/tests/unit/test_vote_program.py @@ -1,4 +1,5 @@ """Unit tests for solana.vote_program.""" + import base64 from solders.hash import Hash diff --git a/tests/utils.py b/tests/utils.py index ab439a3d..6c65e954 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,4 +1,5 @@ """Integration test utils.""" + from typing import get_args from solders.rpc.responses import RPCError, RPCResult