tokencrawler/.venv/lib/python3.9/site-packages/solana/rpc/async_api.py
2022-03-17 22:16:30 +01:00

1373 lines
65 KiB
Python

"""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 List, Optional, Union
from solana.blockhash import Blockhash, BlockhashCache
from solana.keypair import Keypair
from solana.publickey import PublicKey
from solana.rpc import types
from solana.transaction import Transaction
from .commitment import COMMITMENT_RANKS, Commitment, Finalized
from .core import RPCException, UnconfirmedTxError, _ClientCore
from .providers import async_http
class AsyncClient(_ClientCore): # pylint: disable=too-many-public-methods
"""Async client class.
Args:
endpoint: URL of the RPC endpoint.
commitment: Default bank state to query. It can be either "finalized", "confirmed" or "processed".
blockhash_cache: (Experimental) If True, keep a cache of recent blockhashes to make
`send_transaction` calls faster.
You can also pass your own BlockhashCache object to customize its parameters.
The cache works as follows:
1. Retrieve the oldest unused cached blockhash that is younger than `ttl` seconds,
where `ttl` is defined in the BlockhashCache (we prefer unused blockhashes because
reusing blockhashes can cause errors in some edge cases, and we prefer slightly
older blockhashes because they're more likely to be accepted by every validator).
2. If there are no unused blockhashes in the cache, take the oldest used
blockhash that is younger than `ttl` seconds.
3. Fetch a new recent blockhash *after* sending the transaction. This is to keep the cache up-to-date.
If you want something tailored to your use case, run your own loop that fetches the recent blockhash,
and pass that value in your `.send_transaction` calls.
timeout: HTTP request timeout in seconds.
"""
def __init__(
self,
endpoint: Optional[str] = None,
commitment: Optional[Commitment] = None,
blockhash_cache: Union[BlockhashCache, bool] = False,
timeout: float = 10,
) -> None:
"""Init API client."""
super().__init__(commitment, blockhash_cache)
self._provider = async_http.AsyncHTTPProvider(endpoint, timeout=timeout)
async def __aenter__(self) -> "AsyncClient":
"""Use as a context manager."""
await self._provider.__aenter__()
return self
async def __aexit__(self, _exc_type, _exc, _tb):
"""Exits the context manager."""
await self.close()
async def close(self) -> None:
"""Use this when you are done with the client."""
await self._provider.close()
async def is_connected(self) -> bool:
"""Health check.
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.is_connected()) # doctest: +SKIP
True
Returns:
True if the client is connected.
"""
return await self._provider.is_connected()
async def get_balance(
self, pubkey: Union[PublicKey, str], commitment: Optional[Commitment] = None
) -> types.RPCResponse:
"""Returns the balance of the account of provided Pubkey.
Args:
pubkey: Pubkey of account to query, as base-58 encoded string or PublicKey object.
commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
Example:
>>> from solana.publickey import PublicKey
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_balance(PublicKey(1))) # doctest: +SKIP
{'jsonrpc': '2.0', 'result': {'context': {'slot': 228}, 'value': 0}, 'id': 1}
"""
args = self._get_balance_args(pubkey, commitment)
return await self._provider.make_request(*args)
async def get_account_info(
self,
pubkey: Union[PublicKey, str],
commitment: Optional[Commitment] = None,
encoding: str = "base64",
data_slice: Optional[types.DataSliceOpts] = None,
) -> types.RPCResponse:
"""Returns all the account info for the specified public key.
Args:
pubkey: Pubkey of account to query, as base-58 encoded string or PublicKey object.
commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
encoding: (optional) Encoding for Account data, either "base58" (slow), "base64", or
"jsonParsed". Default is "base64".
- "base58" is limited to Account data of less than 128 bytes.
- "base64" will return base64 encoded data for Account data of any size.
- "jsonParsed" encoding attempts to use program-specific state parsers to return more human-readable and explicit account state data.
If jsonParsed is requested but a parser cannot be found, the field falls back to base64 encoding,
detectable when the data field is type. (jsonParsed encoding is UNSTABLE).
data_slice: (optional) Option to limit the returned account data using the provided `offset`: <usize> and
`length`: <usize> fields; only available for "base58" or "base64" encoding.
Example:
>>> from solana.publickey import PublicKey
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_account_info(PublicKey(1))) # doctest: +SKIP
{'jsonrpc': '2.0',
'result': {'context': {'slot': 33265073},
'value': {'data': '',
'executable': False,
'lamports': 4459816188034584,
'owner': '11111111111111111111111111111111',
'rentEpoch': 90}},
'id': 1}
""" # noqa: E501 # pylint: disable=line-too-long
args = self._get_account_info_args(
pubkey=pubkey, commitment=commitment, encoding=encoding, data_slice=data_slice
)
return await self._provider.make_request(*args)
async def get_block_commitment(self, slot: int) -> types.RPCResponse:
"""Fetch the commitment for particular block.
Args:
slot: Block, identified by Slot.
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_block_commitment(0)) # doctest: +SKIP
{'jsonrpc': '2.0',
'result': {'commitment': [0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
497717120],
'totalStake': 497717120},
'id': 1}}
"""
args = self._get_block_commitment_args(slot)
return await self._provider.make_request(*args)
async def get_block_time(self, slot: int) -> types.RPCResponse:
"""Fetch the estimated production time of a block.
Args:
slot: Block, identified by Slot.
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_block_time(5)) # doctest: +SKIP
{'jsonrpc': '2.0', 'result': 1598400007, 'id': 1}
"""
args = self._get_block_time_args(slot)
return await self._provider.make_request(*args)
async def get_cluster_nodes(self) -> types.RPCResponse:
"""Returns information about all the nodes participating in the cluster.
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_cluster_nodes()) # doctest: +SKIP
{'jsonrpc': '2.0',
'result': [{'gossip': '127.0.0.1:8001',
'pubkey': 'LjvEBM78ufAikBfxqtj4RNiAECUi7Xqtz9k3QM3DzPk',
'rpc': '127.0.0.1:8899',
'tpu': '127.0.0.1:8003',
'version': '1.4.0 5332fcad'}],
'id': 1}
"""
return await self._provider.make_request(self._get_cluster_nodes)
async def get_confirmed_block(
self,
slot: int,
encoding: str = "json",
) -> types.RPCResponse:
"""Returns identity and transaction information about a confirmed block in the ledger.
Args:
slot: Slot, as u64 integer.
encoding: (optional) Encoding for the returned Transaction, either "json", "jsonParsed",
"base58" (slow), or "base64". If parameter not provided, the default encoding is JSON.
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_confirmed_block(1)O # doctest: +SKIP
{'jsonrpc': '2.0',
'result': {'blockTime': None,
'blockhash': '39pJzWsPn59k2PuHqhB7xNYBNGFXcFVkXLertHPBV4Tj',
'parentSlot': 0,
'previousBlockhash': 'EwF9gtehrrvPUoNticgmiEadAWzn4XeN8bNaNVBkS6S2',
'rewards': [],
'transactions': [{'meta': {'err': None,
'fee': 0,
'postBalances': [500000000000, 26858640, 1, 1, 1],
'preBalances': [500000000000, 26858640, 1, 1, 1],
'status': {'Ok': None}},
'transaction': {'message': {'accountKeys': ['LjvEBM78ufAikBfxqtj4RNiAECUi7Xqtz9k3QM3DzPk',
'EKAar3bMQUZvGSonq7vcPF2nPaCYowbnat44FPafW8Po',
'SysvarS1otHashes111111111111111111111111111',
'SysvarC1ock11111111111111111111111111111111',
'Vote111111111111111111111111111111111111111'],
'header': {'numReadonlySignedAccounts': 0,
'numReadonlyUnsignedAccounts': 3,
'numRequiredSignatures': 1},
'instructions': [{'accounts': [1, 2, 3, 0],
'data': '37u9WtQpcm6ULa3VmTgTKEBCtYMxq84mk82tRvKdFEwj3rALiptAzuMJ1yoVSFAMARMZYp7q',
'programIdIndex': 4}],
'recentBlockhash': 'EwF9gtehrrvPUoNticgmiEadAWzn4XeN8bNaNVBkS6S2'},
'signatures': ['63jnpMCs7TNnCjnTqUrX7Mvqc5CbJMtVkLxBjPHUQkjXyZrQuZpfhjvzA7A29D9tMqVaiQC3UNP1NeaZKFFHJyQE']}}]},
'id': 9}
>>> asyncio.run(solana_client.get_confirmed_block(1, encoding="base64")) # doctest: +SKIP
{'jsonrpc': '2.0',
'result': {'blockTime': None,
'blockhash': '39pJzWsPn59k2PuHqhB7xNYBNGFXcFVkXLertHPBV4Tj',
'parentSlot': 0,
'previousBlockhash': 'EwF9gtehrrvPUoNticgmiEadAWzn4XeN8bNaNVBkS6S2',
'rewards': [],
'transactions': [{'meta': {'err': None,
'fee': 0,
'postBalances': [500000000000, 26858640, 1, 1, 1],
'preBalances': [500000000000, 26858640, 1, 1, 1],
'status': {'Ok': None}},
'transaction': ['AfxyKHmHIjXWjkyHODGeAbVxmfQWPj1ydS9nF+ynJHo8I1vCPDp2P9Cj5aA6W1CAHEHCqY0B1FDKomCzRo3qrAsBAAMFBQ6QBWfhQF7rG02xhuEsmmrUtz3AUjBtJKkqaHPJEmvFzziDX0C0robPrl9RbOyXHoc9/Dxa0zoGL6cEjvCjLgan1RcZLwqvxvJl4/t3zHragsUp0L47E24tAFUgAAAABqfVFxjHdMkoVmOYaR1etoteuKObS21cc1VbIQAAAAAHYUgdNXR0u3xNdiTr072z2DVec9EQQ/wNo1OAAAAAAM8NSv7ISDPN9E9XNL9vX7h8LuJHWlopUcX39DxsDx23AQQEAQIDADUCAAAAAQAAAAAAAAAAAAAAAAAAAIWWp5Il3Kg312pzVk6Jt61iyFhTbtmkh/ORbj3JUQRbAA==',
'base64']}]},
'id': 10}
""" # noqa: E501 # pylint: disable=line-too-long
args = self._get_confirmed_block_args(slot, encoding)
return await self._provider.make_request(*args)
async def get_block(
self,
slot: int,
encoding: str = "json",
) -> types.RPCResponse:
"""Returns identity and transaction information about a confirmed block in the ledger.
Args:
slot: Slot, as u64 integer.
encoding: (optional) Encoding for the returned Transaction, either "json", "jsonParsed",
"base58" (slow), or "base64". If parameter not provided, the default encoding is JSON.
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_block(1)O # doctest: +SKIP
{'jsonrpc': '2.0',
'result': {'blockTime': None, 'blockHeight': 0,
'blockhash': '39pJzWsPn59k2PuHqhB7xNYBNGFXcFVkXLertHPBV4Tj',
'parentSlot': 0,
'previousBlockhash': 'EwF9gtehrrvPUoNticgmiEadAWzn4XeN8bNaNVBkS6S2',
'rewards': [],
'transactions': [{'meta': {'err': None,
'fee': 0,
'postBalances': [500000000000, 26858640, 1, 1, 1],
'preBalances': [500000000000, 26858640, 1, 1, 1],
'status': {'Ok': None}},
'transaction': {'message': {'accountKeys': ['LjvEBM78ufAikBfxqtj4RNiAECUi7Xqtz9k3QM3DzPk',
'EKAar3bMQUZvGSonq7vcPF2nPaCYowbnat44FPafW8Po',
'SysvarS1otHashes111111111111111111111111111',
'SysvarC1ock11111111111111111111111111111111',
'Vote111111111111111111111111111111111111111'],
'header': {'numReadonlySignedAccounts': 0,
'numReadonlyUnsignedAccounts': 3,
'numRequiredSignatures': 1},
'instructions': [{'accounts': [1, 2, 3, 0],
'data': '37u9WtQpcm6ULa3VmTgTKEBCtYMxq84mk82tRvKdFEwj3rALiptAzuMJ1yoVSFAMARMZYp7q',
'programIdIndex': 4}],
'recentBlockhash': 'EwF9gtehrrvPUoNticgmiEadAWzn4XeN8bNaNVBkS6S2'},
'signatures': ['63jnpMCs7TNnCjnTqUrX7Mvqc5CbJMtVkLxBjPHUQkjXyZrQuZpfhjvzA7A29D9tMqVaiQC3UNP1NeaZKFFHJyQE']}}]},
'id': 9}
>>> asyncio.run(solana_client.get_block(1, encoding="base64")) # doctest: +SKIP
{'jsonrpc': '2.0',
'result': {'blockTime': None, 'blockHeight': 0,
'blockhash': '39pJzWsPn59k2PuHqhB7xNYBNGFXcFVkXLertHPBV4Tj',
'parentSlot': 0,
'previousBlockhash': 'EwF9gtehrrvPUoNticgmiEadAWzn4XeN8bNaNVBkS6S2',
'rewards': [],
'transactions': [{'meta': {'err': None,
'fee': 0,
'postBalances': [500000000000, 26858640, 1, 1, 1],
'preBalances': [500000000000, 26858640, 1, 1, 1],
'status': {'Ok': None}},
'transaction': ['AfxyKHmHIjXWjkyHODGeAbVxmfQWPj1ydS9nF+ynJHo8I1vCPDp2P9Cj5aA6W1CAHEHCqY0B1FDKomCzRo3qrAsBAAMFBQ6QBWfhQF7rG02xhuEsmmrUtz3AUjBtJKkqaHPJEmvFzziDX0C0robPrl9RbOyXHoc9/Dxa0zoGL6cEjvCjLgan1RcZLwqvxvJl4/t3zHragsUp0L47E24tAFUgAAAABqfVFxjHdMkoVmOYaR1etoteuKObS21cc1VbIQAAAAAHYUgdNXR0u3xNdiTr072z2DVec9EQQ/wNo1OAAAAAAM8NSv7ISDPN9E9XNL9vX7h8LuJHWlopUcX39DxsDx23AQQEAQIDADUCAAAAAQAAAAAAAAAAAAAAAAAAAIWWp5Il3Kg312pzVk6Jt61iyFhTbtmkh/ORbj3JUQRbAA==',
'base64']}]},
'id': 10}
""" # noqa: E501 # pylint: disable=line-too-long
args = self._get_block_args(slot, encoding)
return await self._provider.make_request(*args)
async def get_block_height(self, commitment: Optional[Commitment] = None) -> types.RPCResponse:
"""Returns the current block height of the node.
Args:
commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_block_height()) # doctest: +SKIP
{'jsonrpc': '2.0', 'result': 1233, 'id': 1}
"""
args = self._get_block_height_args(commitment)
return await self._provider.make_request(*args)
async def get_confirmed_blocks(self, start_slot: int, end_slot: Optional[int] = None) -> types.RPCResponse:
"""Returns a list of confirmed blocks.
Args:
start_slot: Start slot, as u64 integer.
end_slot: (optional) End slot, as u64 integer.
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_confirmed_blocks(5, 10)) # doctest: +SKIP
{'jsonrpc': '2.0', 'result': [5, 6, 7, 8, 9, 10], 'id': 1}
"""
args = self._get_confirmed_blocks_args(start_slot, end_slot)
return await self._provider.make_request(*args)
async def get_blocks(self, start_slot: int, end_slot: Optional[int] = None) -> types.RPCResponse:
"""Returns a list of confirmed blocks.
Args:
start_slot: Start slot, as u64 integer.
end_slot: (optional) End slot, as u64 integer.
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_blocks(5, 10)) # doctest: +SKIP
{'jsonrpc': '2.0', 'result': [5, 6, 7, 8, 9, 10], 'id': 1}
"""
args = self._get_blocks_args(start_slot, end_slot)
return await self._provider.make_request(*args)
async def get_confirmed_signature_for_address2(
self,
account: Union[str, Keypair, PublicKey],
before: Optional[str] = None,
until: Optional[str] = None,
limit: Optional[int] = None,
commitment: Optional[Commitment] = None,
) -> types.RPCResponse:
"""Returns confirmed signatures for transactions involving an address.
Signatures are returned backwards in time from the provided signature or
most recent confirmed block.
Args:
account: Account to be queried.
before: (optional) Start searching backwards from this transaction signature.
If not provided the search starts from the top of the highest max confirmed block.
until: (optional) Search until this transaction signature, if found before limit reached.
limit: (optoinal) Maximum transaction signatures to return (between 1 and 1,000, default: 1,000).
commitment: (optional) Bank state to query. It can be either "finalized", "confirmed" or "processed".
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_confirmed_signature_for_address2("Vote111111111111111111111111111111111111111", limit=1)) # doctest: +SKIP
{'jsonrpc': '2.0',
'result': [{'err': None,
'memo': None,
'signature': 'v1BK8XcaPBzAGd7TB1K53pMdi6TBGe5CLCgx8cmZ4Bj63ZNvA6ca2QaxFpBFdvmpoFQ51VorBjifkBGLTDhwpqN',
'slot': 4290}],
'id': 2}
""" # noqa: E501 # pylint: disable=line-too-long
args = self._get_confirmed_signature_for_address2_args(account, before, until, limit, commitment)
return await self._provider.make_request(*args)
async def get_signatures_for_address(
self,
account: Union[str, Keypair, PublicKey],
before: Optional[str] = None,
until: Optional[str] = None,
limit: Optional[int] = None,
commitment: Optional[Commitment] = None,
) -> types.RPCResponse:
"""Returns confirmed signatures for transactions involving an address.
Signatures are returned backwards in time from the provided signature or
most recent confirmed block.
Args:
account: Account to be queried.
before: (optional) Start searching backwards from this transaction signature.
If not provided the search starts from the top of the highest max confirmed block.
until: (optional) Search until this transaction signature, if found before limit reached.
limit: (optional) Maximum transaction signatures to return (between 1 and 1,000, default: 1,000).
commitment: (optional) Bank state to query. It can be either "finalized", "confirmed" or "processed".
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_signatures_for_address("Vote111111111111111111111111111111111111111", limit=1)) # doctest: +SKIP
{'jsonrpc': '2.0',
'result': [{'err': None,
'memo': None,
'signature': 'v1BK8XcaPBzAGd7TB1K53pMdi6TBGe5CLCgx8cmZ4Bj63ZNvA6ca2QaxFpBFdvmpoFQ51VorBjifkBGLTDhwpqN',
'slot': 4290}],
'id': 2}
""" # noqa: E501 # pylint: disable=line-too-long
args = self._get_signatures_for_address_args(account, before, until, limit, commitment)
return await self._provider.make_request(*args)
async def get_confirmed_transaction(self, tx_sig: str, encoding: str = "json") -> types.RPCResponse:
"""Returns transaction details for a confirmed transaction.
Args:
tx_sig: Transaction signature as base-58 encoded string N encoding attempts to use program-specific
instruction parsers to return more human-readable and explicit data in the
`transaction.message.instructions` list.
encoding: (optional) Encoding for the returned Transaction, either "json", "jsonParsed",
"base58" (slow), or "base64". If parameter not provided, the default encoding is JSON.
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_confirmed_transaction("3PtGYH77LhhQqTXP4SmDVJ85hmDieWsgXCUbn14v7gYyVYPjZzygUQhTk3bSTYnfA48vCM1rmWY7zWL3j1EVKmEy")) # doctest: +SKIP
{'jsonrpc': '2.0',
'result': {'meta': {'err': None,
'fee': 5000,
'postBalances': [498449233720610510, 1000001001987940, 1],
'preBalances': [498449233721615510, 1000001000987940, 1],
'status': {'Ok': None}},
'slot': 1659335,
'transaction': {'message': {'accountKeys': ['9B5XszUGdMaxCZ7uSQhPzdks5ZQSmWxrmzCSvtJ6Ns6g',
'2KW2XRd9kwqet15Aha2oK3tYvd3nWbTFH1MBiRAv1BE1',
'11111111111111111111111111111111'],
'header': {'numReadonlySignedAccounts': 0,
'numReadonlyUnsignedAccounts': 1,
'numRequiredSignatures': 1},
'instructions': [{'accounts': [0, 1],
'data': '3Bxs4Bc3VYuGVB19',
'programIdIndex': 2}],
'recentBlockhash': 'FwcsKNptGtMLccXAA9YgnivVFK95mKzECLT1DNPi3SDr'},
'signatures': ['3PtGYH77LhhQqTXP4SmDVJ85hmDieWsgXCUbn14v7gYyVYPjZzygUQhTk3bSTYnfA48vCM1rmWY7zWL3j1EVKmEy']}},
'id': 4}
""" # noqa: E501 # pylint: disable=line-too-long
args = self._get_confirmed_transaction_args(tx_sig, encoding)
return await self._provider.make_request(*args)
async def get_transaction(self, tx_sig: str, encoding: str = "json") -> types.RPCResponse:
"""Returns transaction details for a confirmed transaction.
Args:
tx_sig: Transaction signature as base-58 encoded string N encoding attempts to use program-specific
instruction parsers to return more human-readable and explicit data in the
`transaction.message.instructions` list.
encoding: (optional) Encoding for the returned Transaction, either "json", "jsonParsed",
"base58" (slow), or "base64". If parameter not provided, the default encoding is JSON.
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_transaction("3PtGYH77LhhQqTXP4SmDVJ85hmDieWsgXCUbn14v7gYyVYPjZzygUQhTk3bSTYnfA48vCM1rmWY7zWL3j1EVKmEy")) # doctest: +SKIP
{'jsonrpc': '2.0',
'result': {'meta': {'err': None,
'fee': 5000, 'rewards': [],
'postBalances': [498449233720610510, 1000001001987940, 1],
'preBalances': [498449233721615510, 1000001000987940, 1],
'status': {'Ok': None}},
'slot': 1659335,
'transaction': {'message': {'accountKeys': ['9B5XszUGdMaxCZ7uSQhPzdks5ZQSmWxrmzCSvtJ6Ns6g',
'2KW2XRd9kwqet15Aha2oK3tYvd3nWbTFH1MBiRAv1BE1',
'11111111111111111111111111111111'],
'header': {'numReadonlySignedAccounts': 0,
'numReadonlyUnsignedAccounts': 1,
'numRequiredSignatures': 1},
'instructions': [{'accounts': [0, 1],
'data': '3Bxs4Bc3VYuGVB19',
'programIdIndex': 2}],
'recentBlockhash': 'FwcsKNptGtMLccXAA9YgnivVFK95mKzECLT1DNPi3SDr'},
'signatures': ['3PtGYH77LhhQqTXP4SmDVJ85hmDieWsgXCUbn14v7gYyVYPjZzygUQhTk3bSTYnfA48vCM1rmWY7zWL3j1EVKmEy']}},
'id': 4}
""" # noqa: E501 # pylint: disable=line-too-long
args = self._get_transaction_args(tx_sig, encoding)
return await self._provider.make_request(*args)
async def get_epoch_info(self, commitment: Optional[Commitment] = None) -> types.RPCResponse:
"""Returns information about the current epoch.
Args:
commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_epoch_info()) # doctest: +SKIP
{'jsonrpc': '2.0',
'result': {'absoluteSlot': 5150,
'blockHeight': 5150,
'epoch': 0,
'slotIndex': 5150,
'slotsInEpoch': 8192},
'id': 5}
"""
args = self._get_epoch_info_args(commitment)
return await self._provider.make_request(*args)
async def get_epoch_schedule(self) -> types.RPCResponse:
"""Returns epoch schedule information from this cluster's genesis config.
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_epoch_schedule()) # doctest: +SKIP
{'jsonrpc': '2.0',
'result': {'firstNormalEpoch': 0,
'firstNormalSlot': 0,
'leaderScheduleSlotOffset': 8192,
'slotsPerEpoch': 8192,
'warmup': False},
'id': 6}
"""
return await self._provider.make_request(self._get_epoch_schedule)
async def get_fee_calculator_for_blockhash(
self, blockhash: Union[str, Blockhash], commitment: Optional[Commitment] = None
) -> types.RPCResponse:
"""Returns the fee calculator associated with the query blockhash, or null if the blockhash has expired.
Args:
blockhash: Blockhash to query as a Base58 encoded string.
commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_fee_calculator_for_blockhash("BaQSR194dC4dZaRxATtxYyEwDkk7VgqUY8NVNkub8HFZ")) # doctest: +SKIP
{'jsonrpc': '2.0',
'result': {'context': {'slot': 7065},
'value': {'feeCalculator': {'lamportsPerSignature': 5000}}},
'id': 4}
""" # noqa: E501 # pylint: disable=line-too-long
args = self._get_fee_calculator_for_blockhash_args(blockhash, commitment)
return await self._provider.make_request(*args)
async def get_fee_rate_governor(self) -> types.RPCResponse:
"""Return the fee rate governor information from the root bank.
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_fee_rate_governor()) # doctest: +SKIP
{'jsonrpc': '2.0',
'result': {'context': {'slot': 7172},
'value': {'feeRateGovernor': {'burnPercent': 50,
'maxLamportsPerSignature': 100000,
'minLamportsPerSignature': 5000,
'targetLamportsPerSignature': 10000,
'targetSignaturesPerSlot': 20000}}},
'id': 5}
"""
return await self._provider.make_request(self._get_fee_rate_governor)
async def get_fees(self, commitment: Optional[Commitment] = None) -> types.RPCResponse:
"""Returns a recent block hash from the ledger, a fee schedule and the last slot the blockhash will be valid.
Args:
commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_fees()) # doctest: +SKIP
{'jsonrpc': '2.0',
'result': {'context': {'slot': 7727},
'value': {'blockhash': 'GGS6AEDqjF5irU6D6VQNherEZ2hckGaeBiVdfSZKg4gd',
'feeCalculator': {'lamportsPerSignature': 5000},
'lastValidSlot': 8027}},
'id': 1}
"""
args = self._get_fees_args(commitment)
return await self._provider.make_request(*args)
async def get_first_available_block(self) -> types.RPCResponse:
"""Returns the slot of the lowest confirmed block that has not been purged from the ledger.
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_fees()) # doctest: +SKIP
{'jsonrpc': '2.0', 'result': 1, 'id': 2}
"""
return await self._provider.make_request(self._get_first_available_block)
async def get_genesis_hash(self) -> types.RPCResponse:
"""Returns the genesis hash.
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_genesis_hash()) # doctest: +SKIP
{'jsonrpc': '2.0',
'result': 'EwF9gtehrrvPUoNticgmiEadAWzn4XeN8bNaNVBkS6S2',
'id': 3}
"""
return await self._provider.make_request(self._get_genesis_hash)
async def get_identity(self) -> types.RPCResponse:
"""Returns the identity pubkey for the current node.
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_identity()) # doctest: +SKIP
{'jsonrpc': '2.0',
'result': {'identity': 'LjvEBM78ufAikBfxqtj4RNiAECUi7Xqtz9k3QM3DzPk'},
'id': 4}
"""
return await self._provider.make_request(self._get_identity)
async def get_inflation_governor(self, commitment: Optional[Commitment] = None) -> types.RPCResponse:
"""Returns the current inflation governor.
Args:
commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_inflation_governor()) # doctest: +SKIP
{'jsonrpc': '2.0',
'result': {'foundation': 0.05,
'foundationTerm': 7.0,
'initial': 0.15,
'taper': 0.15,
'terminal': 0.015},
'id': 5}
"""
args = self._get_inflation_governor_args(commitment)
return await self._provider.make_request(*args)
async def get_inflation_rate(self) -> types.RPCResponse:
"""Returns the specific inflation values for the current epoch.
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_inflation_rate()) # doctest: +SKIP
{'jsonrpc': '2.0',
'result': {'epoch': 1,
'foundation': 0.007499746885736559,
'total': 0.14999493771473116,
'validator': 0.1424951908289946},
'id': 1}
"""
return await self._provider.make_request(self._get_inflation_rate)
async def get_largest_accounts(
self, filter_opt: Optional[str] = None, commitment: Optional[Commitment] = None
) -> types.RPCResponse:
"""Returns the 20 largest accounts, by lamport balance.
Args:
filter_opt: Filter results by account type; currently supported: circulating|nonCirculating.
commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_largest_accounts()) # doctest: +SKIP
{'jsonrpc': '2.0',
'result': {'context': {'slot': 8890},
'value': [{'address': '95L7AsBCLRsqghsi6ksZkzjNbs6rqDgHCzKaGZ7bJi75',
'lamports': 500000000000000000},
{'address': 'APnSR52EC1eH676m7qTBHUJ1nrGpHYpV7XKPxgRDD8gX',
'lamports': 164511033098290000},
{'address': '13LeFbG6m2EP1fqCj9k66fcXsoTHMMtgr7c78AivUrYD',
'lamports': 153333632446109120},
{'address': 'GK2zqSsXLA2rwVZk347RYhh6jJpRsCA69FjLW93ZGi3B',
'lamports': 57499999036109120},
{'address': '8HVqyX9jebh31Q9Hp8t5sMVJs665979ZeEr3eCfzitUe',
'lamports': 30301031036109120},
{'address': 'HbZ5FfmKWNHC7uwk6TF1hVi6TCs7dtYfdjEcuPGgzFAg',
'lamports': 14999999036109120},
{'address': '14FUT96s9swbmH7ZjpDvfEDywnAYy9zaNhv4xvezySGu',
'lamports': 4999999036109120},
{'address': '9huDUZfxoJ7wGMTffUE7vh1xePqef7gyrLJu9NApncqA',
'lamports': 4999999036109120},
{'address': 'C7C8odR8oashR5Feyrq2tJKaXL18id1dSj2zbkDGL2C2',
'lamports': 4999999036109120},
{'address': 'AYgECURrvuX6GtFe4tX7aAj87Xc5r5Znx96ntNk1nCv',
'lamports': 2499999518054560},
{'address': 'AogcwQ1ubM76EPMhSD5cw1ES4W5econvQCFmBL6nTW1',
'lamports': 2499999518054560},
{'address': 'gWgqQ4udVxE3uNxRHEwvftTHwpEmPHAd8JR9UzaHbR2',
'lamports': 2499999518054560},
{'address': '3D91zLQPRLamwJfGR5ZYMKQb4C18gsJNaSdmB6b2wLhw',
'lamports': 2499999518054560},
{'address': '3bHbMa5VW3np5AJazuacidrN4xPZgwhcXigmjwHmBg5e',
'lamports': 2499999518054560},
{'address': '4U3RFq7X5kLG6tZ9kcksFL8oXeGNjtuUN1YfkVKXbs5x',
'lamports': 2499999518054560},
{'address': '5cBVGBKY6kBaiTVmsQpxThJ2oqitBYuCAX9Zm2zMuV4y',
'lamports': 2499999518054560},
{'address': '8PjJTv657aeN9p5R2WoM6pPSz385chvTTytUWaEjSjkq',
'lamports': 2499999518054560},
{'address': 'AHB94zKUASftTdqgdfiDSdnPJHkEFp7zX3yMrcSxABsv',
'lamports': 2499999518054560},
{'address': 'Hc36Wh1ZqYGzGAnsJWNT9r2gY3h9n89uDpxZPsmEsiE3',
'lamports': 2499999518054560},
{'address': 'GxyRKP2eVKACaSSnso4VLSAjZKmHsFXHWUfS3A5CtiMA',
'lamports': 1940147018054560}]},
'id': 2}
"""
args = self._get_largest_accounts_args(filter_opt, commitment)
return await self._provider.make_request(*args)
async def get_leader_schedule(
self, epoch: Optional[int] = None, commitment: Optional[Commitment] = None
) -> types.RPCResponse:
"""Returns the leader schedule for an epoch.
Args:
epoch: Fetch the leader schedule for the epoch that corresponds to the provided slot.
If unspecified, the leader schedule for the current epoch is fetched.
commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_leader_schedule()) # doctest: +SKIP
{'jsonrpc': '2.0',
'result': {'EWj2cuEuVhi7RX81cnAY3TzpyFwnHzzVwvuTyfmxmhs3': [0,
1,
2,
3,
4,
5,
...]},
'id': 6}
"""
args = self._get_leader_schedule_args(epoch, commitment)
return await self._provider.make_request(*args)
async def get_minimum_balance_for_rent_exemption(
self, usize: int, commitment: Optional[Commitment] = None
) -> types.RPCResponse:
"""Returns minimum balance required to make account rent exempt.
Args:
usize: Account data length.
commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_minimum_balance_for_rent_exemption(50)) # doctest: +SKIP
{'jsonrpc': '2.0', 'result': 1238880, 'id': 7}
"""
args = self._get_minimum_balance_for_rent_exemption_args(usize, commitment)
return await self._provider.make_request(*args)
async def get_multiple_accounts(
self,
pubkeys: List[Union[PublicKey, str]],
commitment: Optional[Commitment] = None,
encoding: str = "base64",
data_slice: Optional[types.DataSliceOpts] = None,
) -> types.RPCResponse:
"""Returns all the account info for a list of public keys.
Args:
pubkeys: list of Pubkeys to query, as base-58 encoded string or PublicKey object.
commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
encoding: (optional) Encoding for Account data, either "base58" (slow), "base64", or
"jsonParsed". Default is "base64".
- "base58" is limited to Account data of less than 128 bytes.
- "base64" will return base64 encoded data for Account data of any size.
- "jsonParsed" encoding attempts to use program-specific state parsers to return more human-readable and explicit account state data.
If jsonParsed is requested but a parser cannot be found, the field falls back to base64 encoding,
detectable when the data field is type. (jsonParsed encoding is UNSTABLE).
data_slice: (optional) Option to limit the returned account data using the provided `offset`: <usize> and
`length`: <usize> fields; only available for "base58" or "base64" encoding.
Example:
>>> from solana.publickey import PublicKey
>>> solana_client = AsyncClient("http://localhost:8899")
>>> pubkeys = [PublicKey("6ZWcsUiWJ63awprYmbZgBQSreqYZ4s6opowP4b7boUdh"), PublicKey("HkcE9sqQAnjJtECiFsqGMNmUho3ptXkapUPAqgZQbBSY")]
>>> asyncio.run(solana_client.get_multiple_accounts(pubkeys)) # doctest: +SKIP
{
"jsonrpc": "2.0",
"result": {
"context": {"slot": 97531946},
"value": [
{
"data": ["", "base64"],
"executable": False,
"lamports": 1,
"owner": "11111111111111111111111111111111",
"rentEpoch": 225,
},
{
"data": ["", "base64"],
"executable": False,
"lamports": 809441127,
"owner": "11111111111111111111111111111111",
"rentEpoch": 225,
},
],
},
"id": 1,
}
""" # noqa: E501 # pylint: disable=line-too-long
args = self._get_multiple_accounts_args(
pubkeys=pubkeys, commitment=commitment, encoding=encoding, data_slice=data_slice
)
return await self._provider.make_request(*args)
async def get_program_accounts( # pylint: disable=too-many-arguments
self,
pubkey: Union[str, PublicKey],
commitment: Optional[Commitment] = Finalized,
encoding: Optional[str] = None,
data_slice: Optional[types.DataSliceOpts] = None,
data_size: Optional[int] = None,
memcmp_opts: Optional[List[types.MemcmpOpts]] = None,
) -> types.RPCResponse:
"""Returns all accounts owned by the provided program Pubkey.
Args:
pubkey: Pubkey of program, as base-58 encoded string or PublicKey object.
commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
encoding: (optional) Encoding for the returned Transaction, either jsonParsed",
"base58" (slow), or "base64". If parameter not provided, the default encoding is JSON.
data_slice: (optional) Limit the returned account data using the provided `offset`: <usize> and
`length`: <usize> fields; only available for "base58" or "base64" encoding.
data_size: (optional) Option to compare the program account data length with the provided data size.
memcmp_opts: (optional) Options to compare a provided series of bytes with program account data at a particular offset.
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> memcmp_opts = [
... types.MemcmpOpts(offset=4, bytes="3Mc6vR"),
... ]
>>> asyncio.run(solana_client.get_program_accounts("4Nd1mBQtrMJVYVfKf2PJy9NZUZdTAsp7D4xWLs4gDB4T", data_size=17, memcmp_opts=memcmp_opts)) # doctest: +SKIP
{'jsonrpc': "2.0",
'result' :[{
'account' :{
'data' :'2R9jLfiAQ9bgdcw6h8s44439',
'executable' :false,
'lamports' :15298080,
'owner' :'4Nd1mBQtrMJVYVfKf2PJy9NZUZdTAsp7D4xWLs4gDB4T',
'rentEpoch' :28},
'pubkey' :'CxELquR1gPP8wHe33gZ4QxqGB3sZ9RSwsJ2KshVewkFY'}],
'id' :1}
""" # noqa: E501 # pylint: disable=line-too-long
args = self._get_program_accounts_args(
pubkey=pubkey,
commitment=commitment,
encoding=encoding,
data_slice=data_slice,
data_size=data_size,
memcmp_opts=memcmp_opts,
)
return await self._provider.make_request(*args)
async def get_recent_blockhash(self, commitment: Optional[Commitment] = None) -> types.RPCResponse:
"""Returns a recent block hash from the ledger.
Response also includes a fee schedule that can be used to compute the cost
of submitting a transaction using it.
Args:
commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_recent_blockhash()) # doctest: +SKIP
{'jsonrpc': '2.0',
'result': {'context': {'slot': 1637},
'value': {'blockhash': 'EALChog1mXQ9nEgEUQpWAtmA5UueUZvZiL16ZivmR7eb',
'feeCalculator': {'lamportsPerSignature': 5000}}},
'id': 2}
"""
args = self._get_recent_blockhash_args(commitment)
return await self._provider.make_request(*args)
async def get_signature_statuses(
self, signatures: List[Union[str, bytes]], search_transaction_history: bool = False
) -> types.RPCResponse:
"""Returns the statuses of a list of signatures.
Unless the `search_transaction_history` configuration parameter is included, this method only
searches the recent status cache of signatures, which retains statuses for all active slots plus
`MAX_RECENT_BLOCKHASHES` rooted slots.
Args:
signatures: An array of transaction signatures to confirm.
search_transaction_history: If true, a Solana node will search its ledger cache for
any signatures not found in the recent status cache.
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> signatures = [
... "5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW",
... "5j7s6NiJS3JAkvgkoc18WVAsiSaci2pxB2A6ueCJP4tprA2TFg9wSyTLeYouxPBJEMzJinENTkpA52YStRW5Dia7"]
>>> asyncio.run(solana_client.get_signature_statuses(signatures)) # doctest: +SKIP
{'jsonrpc': '2.0',
'result': {
'context': {'slot':82},
'value': [{
'slot': 72,
'confirmations': 10,
'err': null,
'status': {'Ok': null}}, null]},
'id': 1}
"""
args = self._get_signature_statuses_args(signatures, search_transaction_history)
return await self._provider.make_request(*args)
async def get_slot(self, commitment: Optional[Commitment] = None) -> types.RPCResponse:
"""Returns the current slot the node is processing.
Args:
commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_slot()) # doctest: +SKIP
{'jsonrpc': '2.0', 'result': 7515, 'id': 1}
"""
args = self._get_slot_args(commitment)
return await self._provider.make_request(*args)
async def get_slot_leader(self, commitment: Optional[Commitment] = None) -> types.RPCResponse:
"""Returns the current slot leader.
Args:
commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_slot_leader()) # doctest: +SKIP
{'jsonrpc': '2.0',
'result': 'EWj2cuEuVhi7RX81cnAY3TzpyFwnHzzVwvuTyfmxmhs3',
'id': 1}
"""
args = self._get_slot_leader_args(commitment)
return await self._provider.make_request(*args)
async def get_stake_activation(
self, pubkey: Union[PublicKey, str], epoch: Optional[int] = None, commitment: Optional[Commitment] = None
) -> types.RPCResponse:
"""Returns epoch activation information for a stake account.
Args:
pubkey: Pubkey of stake account to query, as base-58 encoded string or PublicKey object.
epoch: (optional) Epoch for which to calculate activation details. If parameter not provided,
defaults to current epoch.
commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_stake_activation()) # doctest: +SKIP
{'jsonrpc': '2.0','result': {'active': 124429280, 'inactive': 73287840, 'state': 'activating'}, 'id': 1}}
"""
args = self._get_stake_activation_args(pubkey, epoch, commitment)
return await self._provider.make_request(*args)
async def get_supply(self, commitment: Optional[Commitment] = None) -> types.RPCResponse:
"""Returns information about the current supply.
Args:
commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_supply()) # doctest: +SKIP
{'jsonrpc': '2.0',
'result': {'context': {'slot': 3846},
'value': {'circulating': 683635192454157660,
'nonCirculating': 316364808037127120,
'nonCirculatingAccounts': ['ETfDYz7Cg5p9SDFmdpRerjBN5puKK7xydEBZZGM2V4Ay',
'7cKxv6UznFoWRuJkgw5bWj5rp5PiKTcXZeEaLqyd3Bbm',
'CV7qh8ZoqeUSTQagosGpkLptXoojf9yCszxkRx1jTD12',
'FZ9S7X9jMbCaMyJjRfSoBhFyarUMVwvx7HWRe4LnZHsg',
...]
'total': 1000000000491284780}},
'id': 1}
"""
args = self._get_supply_args(commitment)
return await self._provider.make_request(*args)
async def get_token_account_balance(self, pubkey: Union[str, PublicKey], commitment: Optional[Commitment] = None):
"""Returns the token balance of an SPL Token account (UNSTABLE).
Args:
pubkey: Pubkey of Token account to query, as base-58 encoded string or PublicKey object.
commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_token_account_balance("7fUAJdStEuGbc3sM84cKRL6yYaaSstyLSU4ve5oovLS7")) # noqa: E501 # pylint: disable=line-too-long # doctest: +SKIP
{'jsonrpc': '2.0','result': {
'context': {'slot':1114},
'value': {
'uiAmount': 98.64,
'amount': '9864',
'decimals': 2},
'id' :1}
"""
args = self._get_token_account_balance_args(pubkey, commitment)
return await self._provider.make_request(*args)
async def get_token_accounts_by_delegate(
self,
delegate: PublicKey,
opts: types.TokenAccountOpts,
commitment: Optional[Commitment] = None,
) -> types.RPCResponse:
"""Returns all SPL Token accounts by approved Delegate (UNSTABLE).
Args:
delegate: Public key of the delegate owner to query.
opts: Token account option specifying at least one of `mint` or `program_id`.
commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
"""
args = self._get_token_accounts_by_delegate_args(delegate, opts, commitment)
return await self.__get_token_accounts(*args)
async def get_token_accounts_by_owner(
self,
owner: PublicKey,
opts: types.TokenAccountOpts,
commitment: Optional[Commitment] = None,
) -> types.RPCResponse:
"""Returns all SPL Token accounts by token owner (UNSTABLE).
Args:
owner: Public key of the account owner to query.
opts: Token account option specifying at least one of `mint` or `program_id`.
commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
"""
args = self._get_token_accounts_by_owner_args(owner, opts, commitment)
return await self.__get_token_accounts(*args)
async def __get_token_accounts(
self,
method: types.RPCMethod,
pubkey: str,
opts: types.TokenAccountOpts,
commitment: Commitment,
) -> types.RPCResponse:
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], 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], 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.
Args:
commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_transaction_count()) # doctest: +SKIP
{'jsonrpc': '2.0', 'result': 4554, 'id': 1}
"""
args = self._get_transaction_count_args(commitment)
return await self._provider.make_request(*args)
async def get_minimum_ledger_slot(self) -> types.RPCResponse:
"""Returns the lowest slot that the node has information about in its ledger.
This value may increase over time if the node is configured to purge older ledger data.
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_minimum_ledger_slot()) # doctest: +SKIP
{'jsonrpc': '2.0', 'result': 1234, 'id': 1}
"""
return await self._provider.make_request(self._minimum_ledger_slot)
async def get_version(self) -> types.RPCResponse:
"""Returns the current solana versions running on the node.
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_version()) # doctest: +SKIP
{'jsonrpc': '2.0', 'result': {'solana-core': '1.4.0 5332fcad'}, 'id': 1}
"""
return await self._provider.make_request(self._get_version)
async def get_vote_accounts(self, commitment: Optional[Commitment] = None):
"""Returns the account info and associated stake for all the voting accounts in the current bank.
Args:
commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.get_vote_accounts()) # doctest: +SKIP
{'jsonrpc': '2.0',
'result': {'current': [{'activatedStake': 0,
'commission': 100,
'epochCredits': [[165, 714644, 707372],
[166, 722092, 714644],
[167, 730285, 722092],
[168, 738476, 730285],
...]
'epochVoteAccount': True,
'lastVote': 1872294,
'nodePubkey': 'J7v9ndmcoBuo9to2MnHegLnBkC9x3SAVbQBJo5MMJrN1',
'rootSlot': 1872263,
'votePubkey': 'HiFjzpR7e5Kv2tdU9jtE4FbH1X8Z9Syia3Uadadx18b5'},
{'activatedStake': 500029968930560,
'commission': 100,
'epochCredits': [[165, 1359689, 1351498],
[166, 1367881, 1359689],
[167, 1376073, 1367881],
[168, 1384265, 1376073],
...],
'epochVoteAccount': True,
'lastVote': 1872295,
'nodePubkey': 'dv1LfzJvDF7S1fBKpFgKoKXK5yoSosmkAdfbxBo1GqJ',
'rootSlot': 1872264,
'votePubkey': '5MMCR4NbTZqjthjLGywmeT66iwE9J9f7kjtxzJjwfUx2'},
{'activatedStake': 0,
'commission': 100,
'epochCredits': [[227, 2751, 0], [228, 7188, 2751]],
'epochVoteAccount': True,
'lastVote': 1872295,
'nodePubkey': 'H1wDvJ5HJc1SzhHoWtaycpzQpFbsL7g8peaRV3obKShs',
'rootSlot': 1872264,
'votePubkey': 'DPqpgoLQVU3aq72HEqSMsB9qh4KoXc9fGEpvgEuiwnp6'}],
'delinquent': []},
'id': 1}
"""
args = self._get_vote_accounts_args(commitment)
return await self._provider.make_request(*args)
async def request_airdrop(
self, pubkey: Union[PublicKey, str], lamports: int, commitment: Optional[Commitment] = None
) -> types.RPCResponse:
"""Requests an airdrop of lamports to a Pubkey.
Args:
pubkey: Pubkey of account to receive lamports, as base-58 encoded string or public key object.
lamports: Amount of lamports.
commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
Example:
>>> from solana.publickey import PublicKey
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.request_airdrop(PublicKey(1), 10000)) # doctest: +SKIP
{'jsonrpc': '2.0',
'result': 'uK6gbLbhnTEgjgmwn36D5BRTRkG4AT8r7Q162TLnJzQnHUZVL9r6BYZVfRttrhmkmno6Fp4VQELzL4AiriCo61U',
'id': 1}
"""
args = self._request_airdrop_args(pubkey, lamports, commitment)
return await self._provider.make_request(*args)
async def send_raw_transaction(
self, txn: Union[bytes, str], opts: types.TxOpts = types.TxOpts()
) -> types.RPCResponse:
"""Send a transaction that has already been signed and serialized into the wire format.
Args:
txn: Fully-signed Transaction object, a fully sign transaction in wire format,
or a fully transaction as base-64 encoded string.
opts: (optional) Transaction options.
Before submitting, the following preflight checks are performed (unless disabled with the `skip_preflight` option):
- The transaction signatures are verified.
- The transaction is simulated against the latest max confirmed bank and on failure an error
will be returned. Preflight checks may be disabled if desired.
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> full_signed_tx_str = (
... "AbN5XM+qw+7oOLsFw7goQSLBis7c1kXJFP6OF4w7YmQNhhbQYcyBiybKuOzzhV7McvoRP3Mey9AhXojtwDCdbwoBAAEDE5j2"
... "LG0aRXxRumpLXz29L2n8qTIWIY3ImX5Ba9F9k8poq0Z3/7HyiU3QphU8Ix1F7ENq5TrmAUnb4V8y5LhwPwAAAAAAAAAAAAAA"
... "AAAAAAAAAAAAAAAAAAAAAAAAAAAAg5YY9wG6fpuieuWYJd1ta7ZtFPbV0OriFRYdcYUaEGkBAgIAAQwCAAAAQEIPAAAAAAA=")
>>> asyncio.run(solana_client.send_raw_transaction(full_signed_tx_str)) # doctest: +SKIP
{'jsonrpc': '2.0',
'result': 'CMwyESM2NE74mghfbvsHJDERF7xMYKshwwm6VgH6GFqXzx8LfBFuP5ruccumfhTguha6seUHPpiHzzHUQXzq2kN',
'id': 1}
""" # noqa: E501 # pylint: disable=line-too-long
args = self._send_raw_transaction_args(txn, opts)
resp = await self._provider.make_request(*args)
if opts.skip_confirmation:
return self._post_send(resp)
post_send_args = self._send_raw_transaction_post_send_args(resp, opts)
return await self.__post_send_with_confirm(*post_send_args)
async def send_transaction(
self,
txn: Transaction,
*signers: Keypair,
opts: types.TxOpts = types.TxOpts(),
recent_blockhash: Optional[Blockhash] = None,
) -> types.RPCResponse:
"""Send a transaction.
Args:
txn: Transaction object.
signers: Signers to sign the transaction.
opts: (optional) Transaction options.
recent_blockhash: (optional) Pass a valid recent blockhash here if you want to
skip fetching the recent blockhash or relying on the cache.
Example:
>>> from solana.keypair import Keypair
>>> from solana.system_program import TransferParams, transfer
>>> from solana.transaction import Transaction
>>> sender, receiver = Keypair.from_seed(bytes(PublicKey(1))), Keypair.from_seed(bytes(PublicKey(2)))
>>> txn = Transaction().add(transfer(TransferParams(
... from_pubkey=sender.public_key, to_pubkey=receiver.public_key, lamports=1000)))
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.send_transaction(txn, sender)) # doctest: +SKIP
{'jsonrpc': '2.0',
'result': '236zSA5w4NaVuLXXHK1mqiBuBxkNBu84X6cfLBh1v6zjPrLfyECz4zdedofBaZFhs4gdwzSmij9VkaSo2tR5LTgG',
'id': 12}
"""
if recent_blockhash is None:
if self.blockhash_cache:
try:
recent_blockhash = self.blockhash_cache.get()
except ValueError:
blockhash_resp = await self.get_recent_blockhash(Finalized)
recent_blockhash = self._process_blockhash_resp(blockhash_resp, used_immediately=True)
else:
blockhash_resp = await self.get_recent_blockhash(Finalized)
recent_blockhash = self.parse_recent_blockhash(blockhash_resp)
txn.recent_blockhash = recent_blockhash
txn.sign(*signers)
txn_resp = await self.send_raw_transaction(txn.serialize(), opts=opts)
if self.blockhash_cache:
blockhash_resp = await self.get_recent_blockhash(Finalized)
self._process_blockhash_resp(blockhash_resp, used_immediately=False)
return txn_resp
async def simulate_transaction(
self, txn: Union[bytes, str, Transaction], sig_verify: bool = False, commitment: Optional[Commitment] = None
) -> types.RPCResponse:
"""Simulate sending a transaction.
Args:
txn: A Transaction object, a transaction in wire format, or a transaction as base-64 encoded string
The transaction must have a valid blockhash, but is not required to be signed.
sig_verify: If true the transaction signatures will be verified (default: false).
commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> tx_str = (
... "4hXTCkRzt9WyecNzV1XPgCDfGAZzQKNxLXgynz5QDuWWPSAZBZSHptvWRL3BjCvzUXRdKvHL2b7yGrRQcWyaqsaBCncVG7BF"
... "ggS8w9snUts67BSh3EqKpXLUm5UMHfD7ZBe9GhARjbNQMLJ1QD3Spr6oMTBU6EhdB4RD8CP2xUxr2u3d6fos36PD98XS6oX8"
... "TQjLpsMwncs5DAMiD4nNnR8NBfyghGCWvCVifVwvA8B8TJxE1aiyiv2L429BCWfyzAme5sZW8rDb14NeCQHhZbtNqfXhcp2t"
... )
>>> asyncio.run(solana_client.simulate_transaction(tx_str)) # doctest: +SKIP
{'jsonrpc' :'2.0',
'result': {'context': {'slot': 218},
'value': {
'err': null,
'logs': ['BPF program 83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri success']},
'id':1}
""" # noqa: E501 # pylint: disable=line-too-long
args = self._simulate_transaction_args(txn, sig_verify, commitment)
return await self._provider.make_request(*args)
async def set_log_filter(self, log_filter: str) -> types.RPCResponse:
"""Sets the log filter on the validator.
Args:
log_filter: The new log filter to use.
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> asyncio.run(solana_client.set_log_filter("solana_core=debug")) # doctest: +SKIP
{'jsonrpc': '2.0', 'result': None, 'id': 1}
"""
args = self._set_log_filter_args(log_filter)
return await self._provider.make_request(*args)
async def validator_exit(self) -> types.RPCResponse:
"""Request to have the validator exit.
Validator must have booted with RPC exit enabled (`--enable-rpc-exit` parameter).
Example:
>>> solana_client = AsyncClient("http://localhost:8899")
>>> solana_client.validator_exit() # doctest: +SKIP
{'jsonrpc': '2.0', 'result': true, 'id': 1}
"""
return await self._provider.make_request(self._validator_exit)
async def __post_send_with_confirm(self, resp: types.RPCResponse, conf_comm: Commitment) -> types.RPCResponse:
resp = self._post_send(resp)
self._provider.logger.info(
"Transaction sent to %s. Signature %s: ", self._provider.endpoint_uri, resp["result"]
)
await self.confirm_transaction(resp["result"], conf_comm)
return resp
async def confirm_transaction(
self, tx_sig: str, commitment: Commitment = Finalized, sleep_seconds: float = 0.5
) -> types.RPCResponse:
"""Confirm the transaction identified by the specified signature.
Args:
tx_sig: the transaction signature to confirm.
commitment: Bank state to query. It can be either "finalized", "confirmed" or "processed".
sleep_seconds: The number of seconds to sleep when polling the signature status.
"""
timeout = time() + 30
while time() < timeout:
resp = await self.get_signature_statuses([tx_sig])
maybe_rpc_error = resp.get("error")
if maybe_rpc_error is not None:
raise RPCException(maybe_rpc_error)
resp_value = resp["result"]["value"][0]
if resp_value is not None:
confirmation_status = resp_value["confirmationStatus"]
confirmation_rank = COMMITMENT_RANKS[confirmation_status]
commitment_rank = COMMITMENT_RANKS[commitment]
if confirmation_rank >= commitment_rank:
break
await asyncio.sleep(sleep_seconds)
else:
maybe_rpc_error = resp.get("error")
if maybe_rpc_error is not None:
raise RPCException(maybe_rpc_error)
raise UnconfirmedTxError(f"Unable to confirm transaction {tx_sig}")
return resp