From 7cf58768042de01a7acafcbbc9cf15e164856fcc Mon Sep 17 00:00:00 2001 From: Will Date: Thu, 23 Sep 2021 00:13:39 -0400 Subject: [PATCH 1/6] Added implementations for synchronous get_token_largest_accounts() and get_token_supply() --- solana/rpc/api.py | 14 ++++++++------ solana/rpc/core.py | 10 ++++++++++ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/solana/rpc/api.py b/solana/rpc/api.py index a80c1e35..9e902d2e 100644 --- a/solana/rpc/api.py +++ b/solana/rpc/api.py @@ -874,13 +874,15 @@ def __get_token_accounts( args = self._get_token_accounts_args(method, pubkey, opts, commitment) return self._provider.make_request(*args) - def get_token_largest_accounts(self, pubkey: Union[PublicKey, str]) -> types.RPCResponse: - """Returns the 20 largest accounts of a particular SPL Token type (UNSTABLE).""" - raise NotImplementedError("get_token_largbest_accounts not implemented") + def get_token_largest_accounts(self, pubkey: Union[PublicKey, str], commitment: Optional[Commitment] = None) -> types.RPCResponse: + """Returns the 20 largest accounts of a particular SPL Token type.""" + args = self._get_token_largest_account_args(pubkey, commitment) + return self._provider.make_request(*args) - def get_token_supply(self, pubkey: Union[PublicKey, str]) -> types.RPCResponse: - """Returns the total supply of an SPL Token type(UNSTABLE).""" - raise NotImplementedError("get_token_supply not implemented") + def get_token_supply(self, pubkey: Union[PublicKey, str], commitment: Optional[Commitment] = None) -> types.RPCResponse: + """Returns the total supply of an SPL Token type.""" + args = self._get_token_supply_args(pubkey, commitment) + return self._provider.make_request(*args) def get_transaction_count(self, commitment: Optional[Commitment] = None) -> types.RPCResponse: """Returns the current Transaction count from the ledger. diff --git a/solana/rpc/core.py b/solana/rpc/core.py index 2738c753..62f8e9e8 100644 --- a/solana/rpc/core.py +++ b/solana/rpc/core.py @@ -275,6 +275,16 @@ def _get_token_accounts_args( return method, pubkey, acc_opts, rpc_opts + def _get_token_largest_account_args( + self, pubkey: Union[str, PublicKey], commitment: Optional[Commitment] + ) -> Tuple[types.RPCMethod, str, Dict[str, Commitment]]: + return types.RPCMethod("getTokenLargestAccounts"), str(pubkey), {self._comm_key: commitment or self._commitment} + + def _get_token_supply_args( + self, pubkey: Union[str, PublicKey], commitment: Optional[Commitment] + ) -> Tuple[types.RPCMethod, str, Dict[str, Commitment]]: + return types.RPCMethod("getTokenSupply"), str(pubkey), {self._comm_key: commitment or self._commitment} + def _get_transaction_count_args( self, commitment: Optional[Commitment] ) -> Tuple[types.RPCMethod, Dict[str, Commitment]]: From 275a59eed5c4d7289fe9c1381e6cd289f4988a3c Mon Sep 17 00:00:00 2001 From: Will Date: Thu, 23 Sep 2021 12:44:55 -0400 Subject: [PATCH 2/6] Fixed lint issues and added tests for new methods. --- solana/rpc/api.py | 8 ++++++-- solana/rpc/core.py | 2 +- tests/conftest.py | 6 ++++++ tests/integration/test_http_client.py | 14 ++++++++++++++ 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/solana/rpc/api.py b/solana/rpc/api.py index 9e902d2e..13bab6ee 100644 --- a/solana/rpc/api.py +++ b/solana/rpc/api.py @@ -874,12 +874,16 @@ def __get_token_accounts( args = self._get_token_accounts_args(method, pubkey, opts, commitment) return self._provider.make_request(*args) - def get_token_largest_accounts(self, pubkey: Union[PublicKey, str], commitment: Optional[Commitment] = None) -> types.RPCResponse: + def get_token_largest_accounts( + self, pubkey: Union[PublicKey, str], commitment: Optional[Commitment] = None + ) -> types.RPCResponse: """Returns the 20 largest accounts of a particular SPL Token type.""" args = self._get_token_largest_account_args(pubkey, commitment) return self._provider.make_request(*args) - def get_token_supply(self, pubkey: Union[PublicKey, str], commitment: Optional[Commitment] = None) -> types.RPCResponse: + def get_token_supply( + self, pubkey: Union[PublicKey, str], commitment: Optional[Commitment] = None + ) -> types.RPCResponse: """Returns the total supply of an SPL Token type.""" args = self._get_token_supply_args(pubkey, commitment) return self._provider.make_request(*args) diff --git a/solana/rpc/core.py b/solana/rpc/core.py index 62f8e9e8..1a01c290 100644 --- a/solana/rpc/core.py +++ b/solana/rpc/core.py @@ -279,7 +279,7 @@ def _get_token_largest_account_args( self, pubkey: Union[str, PublicKey], commitment: Optional[Commitment] ) -> Tuple[types.RPCMethod, str, Dict[str, Commitment]]: return types.RPCMethod("getTokenLargestAccounts"), str(pubkey), {self._comm_key: commitment or self._commitment} - + def _get_token_supply_args( self, pubkey: Union[str, PublicKey], commitment: Optional[Commitment] ) -> Tuple[types.RPCMethod, str, Dict[str, Commitment]]: diff --git a/tests/conftest.py b/tests/conftest.py index 9aa06867..0b6ea9d6 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -111,6 +111,12 @@ def async_stubbed_sender_cached_blockhash() -> Account: return Account(bytes([3] * PublicKey.LENGTH)) +@pytest.fixture(scope="session") +def stubbed_token_addr() -> PublicKey: + """An arbitrary known token address.""" + return PublicKey("DeV3CnJsrhN5TzCZQvmuQgYn1Up8nDycqmzxZJWH9DAw") + + @pytest.fixture(scope="session") def freeze_authority() -> Account: """Arbitrary known account to be used as freeze authority.""" diff --git a/tests/integration/test_http_client.py b/tests/integration/test_http_client.py index 98788863..e9725372 100644 --- a/tests/integration/test_http_client.py +++ b/tests/integration/test_http_client.py @@ -490,6 +490,20 @@ def test_get_multiple_accounts(stubbed_sender, test_http_client): assert_valid_response(resp) +@pytest.mark.integration +def test_get_token_largest_accounts(stubbed_token_addr, test_http_client): + """Test get token largest accounts.""" + resp = test_http_client.get_token_largest_accounts(stubbed_token_addr.public_key()) + assert_valid_response(resp) + + +@pytest.mark.integration +def test_get_token_supply(stubbed_token_addr, test_http_client): + """Test get token largest accounts.""" + resp = test_http_client.get_token_supply(stubbed_token_addr.public_key()) + assert_valid_response(resp) + + @pytest.mark.integration def test_get_vote_accounts(test_http_client): """Test get vote accounts.""" From ddd1a8c7fff0af4108dcf0c369cd23c200d9a598 Mon Sep 17 00:00:00 2001 From: Will Date: Thu, 23 Sep 2021 13:26:43 -0400 Subject: [PATCH 3/6] Modified test to use WRAPPED_SOL_MINT constant. --- tests/conftest.py | 6 ------ tests/integration/test_http_client.py | 9 +++++---- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 0b6ea9d6..9aa06867 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -111,12 +111,6 @@ def async_stubbed_sender_cached_blockhash() -> Account: return Account(bytes([3] * PublicKey.LENGTH)) -@pytest.fixture(scope="session") -def stubbed_token_addr() -> PublicKey: - """An arbitrary known token address.""" - return PublicKey("DeV3CnJsrhN5TzCZQvmuQgYn1Up8nDycqmzxZJWH9DAw") - - @pytest.fixture(scope="session") def freeze_authority() -> Account: """Arbitrary known account to be used as freeze authority.""" diff --git a/tests/integration/test_http_client.py b/tests/integration/test_http_client.py index e9725372..3ccee5f7 100644 --- a/tests/integration/test_http_client.py +++ b/tests/integration/test_http_client.py @@ -4,6 +4,7 @@ import solana.system_program as sp from solana.rpc.api import DataSliceOpt from solana.transaction import Transaction +from spl.token.constants import WRAPPED_SOL_MINT from .utils import AIRDROP_AMOUNT, assert_valid_response, confirm_transaction, generate_expected_meta_after_airdrop @@ -491,16 +492,16 @@ def test_get_multiple_accounts(stubbed_sender, test_http_client): @pytest.mark.integration -def test_get_token_largest_accounts(stubbed_token_addr, test_http_client): +def test_get_token_largest_accounts(test_http_client): """Test get token largest accounts.""" - resp = test_http_client.get_token_largest_accounts(stubbed_token_addr.public_key()) + resp = test_http_client.get_token_largest_accounts(WRAPPED_SOL_MINT) assert_valid_response(resp) @pytest.mark.integration -def test_get_token_supply(stubbed_token_addr, test_http_client): +def test_get_token_supply(test_http_client): """Test get token largest accounts.""" - resp = test_http_client.get_token_supply(stubbed_token_addr.public_key()) + resp = test_http_client.get_token_supply(WRAPPED_SOL_MINT) assert_valid_response(resp) From e7259042a7f8976785f37b3a0b8ff9c2f807c086 Mon Sep 17 00:00:00 2001 From: Will Date: Fri, 24 Sep 2021 11:54:42 -0400 Subject: [PATCH 4/6] Added async implementation of both methods. --- solana/rpc/async_api.py | 18 ++++++++++++------ tests/integration/test_async_http_client.py | 15 +++++++++++++++ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/solana/rpc/async_api.py b/solana/rpc/async_api.py index aecc1103..c6c312ad 100644 --- a/solana/rpc/async_api.py +++ b/solana/rpc/async_api.py @@ -870,13 +870,19 @@ async def __get_token_accounts( args = self._get_token_accounts_args(method, pubkey, opts, commitment) return await self._provider.make_request(*args) - async def get_token_largest_accounts(self, pubkey: Union[PublicKey, str]) -> types.RPCResponse: - """Returns the 20 largest accounts of a particular SPL Token type (UNSTABLE).""" - raise NotImplementedError("get_token_largbest_accounts not implemented") + async def get_token_largest_accounts( + self, pubkey: Union[PublicKey, str], commitment: Optional[Commitment] = None + ) -> types.RPCResponse: + """Returns the 20 largest accounts of a particular SPL Token type.""" + args = self._get_token_largest_account_args(pubkey, commitment) + return await self._provider.make_request(*args) - async def get_token_supply(self, pubkey: Union[PublicKey, str]) -> types.RPCResponse: - """Returns the total supply of an SPL Token type(UNSTABLE).""" - raise NotImplementedError("get_token_supply not implemented") + async def get_token_supply( + self, pubkey: Union[PublicKey, str], commitment: Optional[Commitment] = None + ) -> types.RPCResponse: + """Returns the total supply of an SPL Token type.""" + args = self._get_token_supply_args(pubkey, commitment) + return await self._provider.make_request(*args) async def get_transaction_count(self, commitment: Optional[Commitment] = None) -> types.RPCResponse: """Returns the current Transaction count from the ledger. diff --git a/tests/integration/test_async_http_client.py b/tests/integration/test_async_http_client.py index 832a6398..8e9f0e9e 100644 --- a/tests/integration/test_async_http_client.py +++ b/tests/integration/test_async_http_client.py @@ -4,6 +4,7 @@ import solana.system_program as sp from solana.rpc.api import DataSliceOpt from solana.transaction import Transaction +from spl.token.constants import WRAPPED_SOL_MINT from .utils import AIRDROP_AMOUNT, aconfirm_transaction, assert_valid_response, generate_expected_meta_after_airdrop @@ -500,6 +501,20 @@ async def test_get_supply(test_http_client_async): assert_valid_response(resp) +@pytest.mark.integration +async def test_get_token_largest_accounts(test_http_client): + """Test get token largest accounts.""" + resp = test_http_client.get_token_largest_accounts(WRAPPED_SOL_MINT) + assert_valid_response(resp) + + +@pytest.mark.integration +async def test_get_token_supply(test_http_client): + """Test get token largest accounts.""" + resp = test_http_client.get_token_supply(WRAPPED_SOL_MINT) + assert_valid_response(resp) + + @pytest.mark.integration @pytest.mark.asyncio async def test_get_transaction_count(test_http_client_async): From 470b89aa1ab6ee93e0176523f15803860472e8ee Mon Sep 17 00:00:00 2001 From: Will Date: Fri, 24 Sep 2021 14:51:59 -0400 Subject: [PATCH 5/6] Corrected decorators and parameters in test_async_http_client. --- tests/integration/test_async_http_client.py | 12 +++++++----- tests/integration/test_http_client.py | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/tests/integration/test_async_http_client.py b/tests/integration/test_async_http_client.py index 8e9f0e9e..82205c46 100644 --- a/tests/integration/test_async_http_client.py +++ b/tests/integration/test_async_http_client.py @@ -502,16 +502,18 @@ async def test_get_supply(test_http_client_async): @pytest.mark.integration -async def test_get_token_largest_accounts(test_http_client): +@pytest.mark.asyncio +async def test_get_token_largest_accounts(test_http_client_async): """Test get token largest accounts.""" - resp = test_http_client.get_token_largest_accounts(WRAPPED_SOL_MINT) + resp = test_http_client_async.get_token_largest_accounts(WRAPPED_SOL_MINT) assert_valid_response(resp) @pytest.mark.integration -async def test_get_token_supply(test_http_client): - """Test get token largest accounts.""" - resp = test_http_client.get_token_supply(WRAPPED_SOL_MINT) +@pytest.mark.asyncio +async def test_get_token_supply(test_http_client_async): + """Test get token supply.""" + resp = test_http_client_async.get_token_supply(WRAPPED_SOL_MINT) assert_valid_response(resp) diff --git a/tests/integration/test_http_client.py b/tests/integration/test_http_client.py index 3ccee5f7..4ec8f208 100644 --- a/tests/integration/test_http_client.py +++ b/tests/integration/test_http_client.py @@ -500,7 +500,7 @@ def test_get_token_largest_accounts(test_http_client): @pytest.mark.integration def test_get_token_supply(test_http_client): - """Test get token largest accounts.""" + """Test get token supply.""" resp = test_http_client.get_token_supply(WRAPPED_SOL_MINT) assert_valid_response(resp) From 722ae9ca5c0a3af249748acdf38ec8a82a76293b Mon Sep 17 00:00:00 2001 From: Will Date: Fri, 24 Sep 2021 15:04:23 -0400 Subject: [PATCH 6/6] Added 'await' in test functions. --- tests/integration/test_async_http_client.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/test_async_http_client.py b/tests/integration/test_async_http_client.py index 82205c46..bbc1172d 100644 --- a/tests/integration/test_async_http_client.py +++ b/tests/integration/test_async_http_client.py @@ -505,7 +505,7 @@ async def test_get_supply(test_http_client_async): @pytest.mark.asyncio async def test_get_token_largest_accounts(test_http_client_async): """Test get token largest accounts.""" - resp = test_http_client_async.get_token_largest_accounts(WRAPPED_SOL_MINT) + resp = await test_http_client_async.get_token_largest_accounts(WRAPPED_SOL_MINT) assert_valid_response(resp) @@ -513,7 +513,7 @@ async def test_get_token_largest_accounts(test_http_client_async): @pytest.mark.asyncio async def test_get_token_supply(test_http_client_async): """Test get token supply.""" - resp = test_http_client_async.get_token_supply(WRAPPED_SOL_MINT) + resp = await test_http_client_async.get_token_supply(WRAPPED_SOL_MINT) assert_valid_response(resp)