Can now use a separate commitment for fetching the recent blockhash.

This commit is contained in:
Geoff Taylor 2021-09-16 15:36:52 +01:00
parent 47dcfae63d
commit 43be1fa192
4 changed files with 38 additions and 15 deletions

View File

@ -158,12 +158,13 @@ class CachedBlockhash(typing.NamedTuple):
# some common operations better from our point of view. # some common operations better from our point of view.
# #
class CompatibleClient(Client): class CompatibleClient(Client):
def __init__(self, name: str, cluster_name: str, cluster_url: str, commitment: Commitment, skip_preflight: bool, encoding: str, blockhash_cache_duration: datetime.timedelta, instruction_reporter: InstructionReporter): def __init__(self, name: str, cluster_name: str, cluster_url: str, commitment: Commitment, blockhash_commitment: Commitment, skip_preflight: bool, encoding: str, blockhash_cache_duration: datetime.timedelta, instruction_reporter: InstructionReporter):
self.logger: logging.Logger = logging.getLogger(self.__class__.__name__) self.logger: logging.Logger = logging.getLogger(self.__class__.__name__)
self.name: str = name self.name: str = name
self.cluster_name: str = cluster_name self.cluster_name: str = cluster_name
self.cluster_url: str = cluster_url self.cluster_url: str = cluster_url
self.commitment: Commitment = commitment self.commitment: Commitment = commitment
self.blockhash_commitment: Commitment = blockhash_commitment
self.skip_preflight: bool = skip_preflight self.skip_preflight: bool = skip_preflight
self.encoding: str = encoding self.encoding: str = encoding
self.blockhash_cache_duration: datetime.timedelta = blockhash_cache_duration self.blockhash_cache_duration: datetime.timedelta = blockhash_cache_duration
@ -275,7 +276,7 @@ class CompatibleClient(Client):
return self._send_request("getMultipleAccounts", pubkey_strings, options) return self._send_request("getMultipleAccounts", pubkey_strings, options)
def send_transaction(self, transaction: Transaction, *signers: Account, opts: TxOpts = TxOpts(preflight_commitment=UnspecifiedCommitment)) -> RPCResponse: def send_transaction(self, transaction: Transaction, *signers: Account, opts: TxOpts = TxOpts(preflight_commitment=UnspecifiedCommitment)) -> RPCResponse:
transaction.recent_blockhash = self.get_cached_recent_blockhash() transaction.recent_blockhash = self.get_cached_recent_blockhash(self.blockhash_commitment)
transaction.sign(*signers) transaction.sign(*signers)
encoded_transaction: str = b64encode(transaction.serialize()).decode("utf-8") encoded_transaction: str = b64encode(transaction.serialize()).decode("utf-8")
@ -423,6 +424,14 @@ class BetterClient:
def commitment(self, value: Commitment) -> None: def commitment(self, value: Commitment) -> None:
self.compatible_client.commitment = value self.compatible_client.commitment = value
@property
def blockhash_commitment(self) -> Commitment:
return self.compatible_client.blockhash_commitment
@blockhash_commitment.setter
def blockhash_commitment(self, value: Commitment) -> None:
self.compatible_client.blockhash_commitment = value
@property @property
def skip_preflight(self) -> bool: def skip_preflight(self) -> bool:
return self.compatible_client.skip_preflight return self.compatible_client.skip_preflight
@ -440,8 +449,8 @@ class BetterClient:
self.compatible_client.instruction_reporter = value self.compatible_client.instruction_reporter = value
@staticmethod @staticmethod
def from_configuration(name: str, cluster_name: str, cluster_url: str, commitment: Commitment, skip_preflight: bool, encoding: str, blockhash_cache_duration: datetime.timedelta, instruction_reporter: InstructionReporter) -> "BetterClient": def from_configuration(name: str, cluster_name: str, cluster_url: str, commitment: Commitment, blockhash_commitment: Commitment, skip_preflight: bool, encoding: str, blockhash_cache_duration: datetime.timedelta, instruction_reporter: InstructionReporter) -> "BetterClient":
compatible = CompatibleClient(name, cluster_name, cluster_url, commitment, skip_preflight, compatible = CompatibleClient(name, cluster_name, cluster_url, commitment, blockhash_commitment, skip_preflight,
encoding, blockhash_cache_duration, instruction_reporter) encoding, blockhash_cache_duration, instruction_reporter)
return BetterClient(compatible) return BetterClient(compatible)

View File

@ -36,17 +36,17 @@ from .tokenlookup import TokenLookup
# A `Context` object to manage Solana connection and Mango configuration. # A `Context` object to manage Solana connection and Mango configuration.
# #
class Context: class Context:
def __init__(self, name: str, cluster_name: str, cluster_url: str, skip_preflight: bool, encoding: str, def __init__(self, name: str, cluster_name: str, cluster_url: str, skip_preflight: bool, commitment: str,
blockhash_cache_duration: datetime.timedelta, mango_program_address: PublicKey, blockhash_commitment: str, encoding: str, blockhash_cache_duration: datetime.timedelta,
serum_program_address: PublicKey, group_name: str, group_address: PublicKey, mango_program_address: PublicKey, serum_program_address: PublicKey, group_name: str,
gma_chunk_size: Decimal, gma_chunk_pause: Decimal, group_address: PublicKey, gma_chunk_size: Decimal, gma_chunk_pause: Decimal,
token_lookup: TokenLookup, market_lookup: MarketLookup): token_lookup: TokenLookup, market_lookup: MarketLookup):
self.logger: logging.Logger = logging.getLogger(self.__class__.__name__) self.logger: logging.Logger = logging.getLogger(self.__class__.__name__)
self.name: str = name self.name: str = name
instruction_reporter: InstructionReporter = CompoundInstructionReporter.from_addresses( instruction_reporter: InstructionReporter = CompoundInstructionReporter.from_addresses(
mango_program_address, serum_program_address) mango_program_address, serum_program_address)
self.client: BetterClient = BetterClient.from_configuration( self.client: BetterClient = BetterClient.from_configuration(
name, cluster_name, cluster_url, Commitment("processed"), skip_preflight, encoding, blockhash_cache_duration, instruction_reporter) name, cluster_name, cluster_url, Commitment(commitment), Commitment(blockhash_commitment), skip_preflight, encoding, blockhash_cache_duration, instruction_reporter)
self.mango_program_address: PublicKey = mango_program_address self.mango_program_address: PublicKey = mango_program_address
self.serum_program_address: PublicKey = serum_program_address self.serum_program_address: PublicKey = serum_program_address
self.group_name: str = group_name self.group_name: str = group_name

View File

@ -71,6 +71,10 @@ class ContextBuilder:
parser.add_argument("--mango-program-address", type=PublicKey, default=None, help="Mango program address") parser.add_argument("--mango-program-address", type=PublicKey, default=None, help="Mango program address")
parser.add_argument("--serum-program-address", type=PublicKey, default=None, help="Serum program address") parser.add_argument("--serum-program-address", type=PublicKey, default=None, help="Serum program address")
parser.add_argument("--skip-preflight", default=False, action="store_true", help="Skip pre-flight checks") parser.add_argument("--skip-preflight", default=False, action="store_true", help="Skip pre-flight checks")
parser.add_argument("--commitment", type=str, default=None,
help="Commitment to use when sending transactions (can be 'finalized', 'confirmed' or 'processed')")
parser.add_argument("--blockhash-commitment", type=str, default=None,
help="Commitment to use specifically when fetching recent blockhash (can be 'finalized', 'confirmed' or 'processed')")
parser.add_argument("--encoding", type=str, default=None, parser.add_argument("--encoding", type=str, default=None,
help="Encoding to request when receiving data from Solana (options are 'base58' (slow), 'base64', 'base64+zstd', or 'jsonParsed')") help="Encoding to request when receiving data from Solana (options are 'base58' (slow), 'base64', 'base64+zstd', or 'jsonParsed')")
parser.add_argument("--blockhash-cache-duration", type=int, help="How long to cache 'recent' blockhashes") parser.add_argument("--blockhash-cache-duration", type=int, help="How long to cache 'recent' blockhashes")
@ -98,6 +102,8 @@ class ContextBuilder:
mango_program_address: typing.Optional[PublicKey] = args.mango_program_address mango_program_address: typing.Optional[PublicKey] = args.mango_program_address
serum_program_address: typing.Optional[PublicKey] = args.serum_program_address serum_program_address: typing.Optional[PublicKey] = args.serum_program_address
skip_preflight: bool = bool(args.skip_preflight) skip_preflight: bool = bool(args.skip_preflight)
commitment: typing.Optional[str] = args.commitment
blockhash_commitment: typing.Optional[str] = args.blockhash_commitment
encoding: typing.Optional[str] = args.encoding encoding: typing.Optional[str] = args.encoding
blockhash_cache_duration: typing.Optional[datetime.timedelta] = datetime.timedelta( blockhash_cache_duration: typing.Optional[datetime.timedelta] = datetime.timedelta(
seconds=args.blockhash_cache_duration) if args.blockhash_cache_duration is not None else None seconds=args.blockhash_cache_duration) if args.blockhash_cache_duration is not None else None
@ -105,16 +111,17 @@ class ContextBuilder:
gma_chunk_pause: typing.Optional[Decimal] = args.gma_chunk_pause gma_chunk_pause: typing.Optional[Decimal] = args.gma_chunk_pause
token_filename: str = args.token_data_file token_filename: str = args.token_data_file
return ContextBuilder._build(name, cluster_name, cluster_url, skip_preflight, encoding, blockhash_cache_duration, group_name, group_address, mango_program_address, serum_program_address, gma_chunk_size, gma_chunk_pause, token_filename) return ContextBuilder._build(name, cluster_name, cluster_url, skip_preflight, commitment, blockhash_commitment, encoding, blockhash_cache_duration, group_name, group_address, mango_program_address, serum_program_address, gma_chunk_size, gma_chunk_pause, token_filename)
@staticmethod @staticmethod
def default(): def default():
return ContextBuilder._build(None, None, None, False, None, None, None, None, None, None, None, None, SplTokenLookup.DefaultDataFilepath) return ContextBuilder._build(None, None, None, False, None, None, None, None, None, None, None, None, None, None, SplTokenLookup.DefaultDataFilepath)
@staticmethod @staticmethod
def from_group_name(context: Context, group_name: str) -> Context: def from_group_name(context: Context, group_name: str) -> Context:
return ContextBuilder._build(context.name, context.client.cluster_name, context.client.cluster_url, return ContextBuilder._build(context.name, context.client.cluster_name, context.client.cluster_url,
context.client.skip_preflight, context.client.encoding, context.client.skip_preflight, context.client.commitment,
context.client.blockhash_commitment, context.client.encoding,
context.client.compatible_client.blockhash_cache_duration, context.client.compatible_client.blockhash_cache_duration,
group_name, None, None, None, context.gma_chunk_size, context.gma_chunk_pause, group_name, None, None, None, context.gma_chunk_size, context.gma_chunk_pause,
SplTokenLookup.DefaultDataFilepath) SplTokenLookup.DefaultDataFilepath)
@ -128,6 +135,7 @@ class ContextBuilder:
cluster_name, cluster_name,
cluster_url, cluster_url,
context.client.commitment, context.client.commitment,
context.client.blockhash_commitment,
context.client.skip_preflight, context.client.skip_preflight,
context.client.encoding, context.client.encoding,
context.client.compatible_client.blockhash_cache_duration, context.client.compatible_client.blockhash_cache_duration,
@ -144,6 +152,7 @@ class ContextBuilder:
cluster_name, cluster_name,
cluster_url, cluster_url,
context.client.commitment, context.client.commitment,
context.client.blockhash_commitment,
context.client.skip_preflight, context.client.skip_preflight,
context.client.encoding, context.client.encoding,
context.client.compatible_client.blockhash_cache_duration, context.client.compatible_client.blockhash_cache_duration,
@ -159,7 +168,8 @@ class ContextBuilder:
# #
@staticmethod @staticmethod
def _build(name: typing.Optional[str], cluster_name: typing.Optional[str], cluster_url: typing.Optional[str], def _build(name: typing.Optional[str], cluster_name: typing.Optional[str], cluster_url: typing.Optional[str],
skip_preflight: bool, encoding: typing.Optional[str], skip_preflight: bool, commitment: typing.Optional[str],
blockhash_commitment: typing.Optional[str], encoding: typing.Optional[str],
blockhash_cache_duration: typing.Optional[datetime.timedelta], blockhash_cache_duration: typing.Optional[datetime.timedelta],
group_name: typing.Optional[str], group_address: typing.Optional[PublicKey], group_name: typing.Optional[str], group_address: typing.Optional[PublicKey],
program_address: typing.Optional[PublicKey], serum_program_address: typing.Optional[PublicKey], program_address: typing.Optional[PublicKey], serum_program_address: typing.Optional[PublicKey],
@ -181,6 +191,8 @@ class ContextBuilder:
default_group_data = group_data default_group_data = group_data
break break
actual_commitment: str = commitment or "processed"
actual_blockhash_commitment: str = blockhash_commitment or commitment or "processed"
actual_encoding: str = encoding or "base64" actual_encoding: str = encoding or "base64"
actual_blockhash_cache_duration: datetime.timedelta = blockhash_cache_duration or datetime.timedelta(seconds=0) actual_blockhash_cache_duration: datetime.timedelta = blockhash_cache_duration or datetime.timedelta(seconds=0)
@ -231,4 +243,4 @@ class ContextBuilder:
all_market_lookup = CompoundMarketLookup([ids_json_market_lookup, devnet_serum_market_lookup]) all_market_lookup = CompoundMarketLookup([ids_json_market_lookup, devnet_serum_market_lookup])
market_lookup: MarketLookup = all_market_lookup market_lookup: MarketLookup = all_market_lookup
return Context(actual_name, actual_cluster, actual_cluster_url, actual_skip_preflight, actual_encoding, actual_blockhash_cache_duration, actual_program_address, actual_serum_program_address, actual_group_name, actual_group_address, actual_gma_chunk_size, actual_gma_chunk_pause, token_lookup, market_lookup) return Context(actual_name, actual_cluster, actual_cluster_url, actual_skip_preflight, actual_commitment, actual_blockhash_commitment, actual_encoding, actual_blockhash_cache_duration, actual_program_address, actual_serum_program_address, actual_group_name, actual_group_address, actual_gma_chunk_size, actual_gma_chunk_pause, token_lookup, market_lookup)

View File

@ -14,7 +14,7 @@ from solana.rpc.types import RPCResponse
class MockCompatibleClient(mango.CompatibleClient): class MockCompatibleClient(mango.CompatibleClient):
def __init__(self): def __init__(self):
super().__init__("test", "local", "http://localhost", "processed", super().__init__("test", "local", "http://localhost", "processed", "processed",
False, "base64", datetime.timedelta(seconds=5), mango.InstructionReporter()) False, "base64", datetime.timedelta(seconds=5), mango.InstructionReporter())
self.token_accounts_by_owner = [] self.token_accounts_by_owner = []
@ -59,6 +59,8 @@ def fake_context() -> mango.Context:
cluster_name="test", cluster_name="test",
cluster_url="http://localhost", cluster_url="http://localhost",
skip_preflight=False, skip_preflight=False,
commitment="processed",
blockhash_commitment="processed",
encoding="base64", encoding="base64",
blockhash_cache_duration=datetime.timedelta(seconds=5), blockhash_cache_duration=datetime.timedelta(seconds=5),
mango_program_address=fake_seeded_public_key("Mango program address"), mango_program_address=fake_seeded_public_key("Mango program address"),