From 47dcfae63d3d9684070b35ca4b9a50d356996503 Mon Sep 17 00:00:00 2001 From: Geoff Taylor Date: Wed, 15 Sep 2021 20:44:28 +0100 Subject: [PATCH] Added base64+zstd as a compression option for encoding. --- mango/client.py | 10 +++++++++- mango/encoding.py | 16 ++++++++-------- requirements.txt | 1 + 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/mango/client.py b/mango/client.py index 999c1e1..110cab2 100644 --- a/mango/client.py +++ b/mango/client.py @@ -285,6 +285,14 @@ class CompatibleClient(Client): commitment = self.commitment skip_preflight: bool = opts.skip_preflight or self.skip_preflight + encoding: str = self.encoding + if encoding == "base64+zstd": + # sendTransaction() only supports base64 and base58, according to the docs: + # https://docs.solana.com/developing/clients/jsonrpc-api#sendtransaction + # The error implies it accepts more: + # Invalid params: unknown variant `base64+zstd`, expected one of `binary`, `base64`, `base58`, `json`, `jsonParsed`. + # but even that list doesn't accept base64+zstd. + encoding = "base64" try: response = self._send_request( @@ -293,7 +301,7 @@ class CompatibleClient(Client): { _SkipPreflightKey: skip_preflight, _PreflightCommitmentKey: commitment, - _EncodingKey: self.encoding, + _EncodingKey: encoding } ) self.logger.debug(f"Transaction ID response: {response}") diff --git a/mango/encoding.py b/mango/encoding.py index 3da46cf..f10be70 100644 --- a/mango/encoding.py +++ b/mango/encoding.py @@ -17,6 +17,7 @@ import base64 import base58 import typing +import zstandard from solana.publickey import PublicKey @@ -25,6 +26,9 @@ from solana.publickey import PublicKey # # This file contains some useful functions for decoding base64 and base58 data. +_decompressor: zstandard.ZstdDecompressor = zstandard.ZstdDecompressor() + + # ## decode_binary() function # # A Solana binary data structure may come back as an array with the base64 or base58 encoded data, and a text moniker saying which encoding was used. @@ -36,13 +40,15 @@ from solana.publickey import PublicKey # Alternatively, it may just be a base58-encoded string. # # `decode_binary()` decodes the data properly based on which encoding was used. - - def decode_binary(encoded: typing.Sequence) -> bytes: if isinstance(encoded, str): return base58.b58decode(encoded) elif encoded[1] == "base64": return base64.b64decode(encoded[0]) + elif encoded[1] == "base64+zstd": + compressed = base64.b64decode(encoded[0]) + with _decompressor.stream_reader(compressed) as reader: + return reader.read() else: return base58.b58decode(encoded[0]) @@ -51,8 +57,6 @@ def decode_binary(encoded: typing.Sequence) -> bytes: # # Inverse of `decode_binary()`, this takes a binary list and encodes it (using base 64), then returns the encoded string and the string "base64" in an array. # - - def encode_binary(decoded: bytes) -> typing.Sequence: return [base64.b64encode(decoded), "base64"] @@ -60,8 +64,6 @@ def encode_binary(decoded: bytes) -> typing.Sequence: # ## encode_key() function # # Encodes a `PublicKey` in the proper way for RPC calls. - - def encode_key(key: PublicKey) -> str: return str(key) @@ -69,7 +71,5 @@ def encode_key(key: PublicKey) -> str: # ## encode_int() function # # Encodes an `int` in the proper way for RPC calls. - - def encode_int(value: int) -> str: return base58.b58encode_int(value).decode('ascii') diff --git a/requirements.txt b/requirements.txt index 30314a7..860b7e9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,3 +10,4 @@ rx>=3.2.0 rxpy_backpressure>=1.0.0 solana==0.11.3 websocket-client>=1.2.1 +zstandard==0.15.2