From 29061d117edd8c76977f847dd68401d3def6f6e9 Mon Sep 17 00:00:00 2001
From: sina <20732540+SinaKhalili@users.noreply.github.com>
Date: Tue, 31 Dec 2024 04:49:10 -0800
Subject: [PATCH 01/15] Add codegen
---
.../accounts/grpc/geyser_codegen/README.md | 86 +++
.../grpc/geyser_codegen/geyser_pb2.py | 142 +++++
.../grpc/geyser_codegen/geyser_pb2.pyi | 490 ++++++++++++++++++
.../grpc/geyser_codegen/geyser_pb2_grpc.py | 355 +++++++++++++
.../grpc/geyser_codegen/solana_storage_pb2.py | 75 +++
.../geyser_codegen/solana_storage_pb2.pyi | 238 +++++++++
.../geyser_codegen/solana_storage_pb2_grpc.py | 24 +
.../grpc/geyser_codegen/subscribe_geyser.py | 106 ++++
src/driftpy/types.py | 8 +
9 files changed, 1524 insertions(+)
create mode 100644 src/driftpy/accounts/grpc/geyser_codegen/README.md
create mode 100644 src/driftpy/accounts/grpc/geyser_codegen/geyser_pb2.py
create mode 100644 src/driftpy/accounts/grpc/geyser_codegen/geyser_pb2.pyi
create mode 100644 src/driftpy/accounts/grpc/geyser_codegen/geyser_pb2_grpc.py
create mode 100644 src/driftpy/accounts/grpc/geyser_codegen/solana_storage_pb2.py
create mode 100644 src/driftpy/accounts/grpc/geyser_codegen/solana_storage_pb2.pyi
create mode 100644 src/driftpy/accounts/grpc/geyser_codegen/solana_storage_pb2_grpc.py
create mode 100644 src/driftpy/accounts/grpc/geyser_codegen/subscribe_geyser.py
diff --git a/src/driftpy/accounts/grpc/geyser_codegen/README.md b/src/driftpy/accounts/grpc/geyser_codegen/README.md
new file mode 100644
index 00000000..29af1afa
--- /dev/null
+++ b/src/driftpy/accounts/grpc/geyser_codegen/README.md
@@ -0,0 +1,86 @@
+# Note for driftpy:
+
+These generated `geyser_pb2` files were generated following
+the instructions on https://github.com/jito-labs/jito-python/ and committed here.
+
+Original readme below:
+
+
+# Python example
+
+## DISCLAIMER
+
+This example can contains errors or be behind of the latest stable version, please use it only as an example of how your subscription can looks like. If you want well tested production ready example, please check our implementation on Rust.
+
+
+
+## Instruction
+
+This Python example uses [grpc.io](https://grpc.io/) library.
+It assumes your CA trust store on your machine allows trust the CA from your RPC endpoint.
+
+## Installation
+
+Create a virtual environment and install its dependencies:
+```bash
+$ python -m venv venv
+$ . venv/bin/activate
+(venv) $ python -m pip install -U pip
+(venv) $ python -m pip install -r requirements.txt
+```
+
+## Launch the helloworld_geyser
+
+Print the usage:
+
+```bash
+(venv) $ python helloworld_geyser.py --help
+Usage: helloworld_geyser.py [OPTIONS]
+
+ Simple program to get the latest solana slot number
+
+Options:
+ --rpc-fqdn TEXT Fully Qualified domain name of your RPC endpoint
+ --x-token TEXT x-token to authenticate each gRPC call
+ --help Show this message and exit.
+```
+
+- `rpc-fqdn`: is the fully qualified domain name without the `https://`, such as `index.rpcpool.com`.
+- `x-token` : is the x-token to authenticate yourself to the RPC node.
+
+Here is a full example:
+
+```bash
+(venv) $ python helloworld_geyser.py --rpc-fqdn 'index.rpcpool.com' --x-token '2625ae71-0823-41b3-b3bc-4ff89d762d52'
+slot: 264236514
+
+```
+
+**NOTE**: `2625ae71-0823-41b3-b3bc-4ff89d762d52` is a fake x-token, you need to provide your own token.
+
+## Generate gRPC service and request signatures
+
+The library `grpcio` generates the stubs for you.
+
+From the directory of `helloword_geyser.py` you can generate all the stubs and data types using the following command:
+
+```bash
+(venv) $ python -m grpc_tools.protoc -I../../yellowstone-grpc-proto/proto/ --python_out=. --pyi_out=. --grpc_python_out=. ../../yellowstone-grpc-proto/proto/*
+```
+
+This will generate:
+- geyser_pb2.py
+- geyser_pb2.pyi
+- geyser_pb2_grpc.py
+- solana_storage_pb2.py
+- solana_storage_pb2.pyi
+- solana_storage_pb2_grpc.py
+
+Which you can then import into your code.
+
+
+## Useful documentation for grpcio authentication process
+
+- [secure_channel](https://grpc.github.io/grpc/python/grpc.html#create-client-credentials)
+
+- [extend auth method via call credentials](https://grpc.io/docs/guides/auth/#extending-grpc-to-support-other-authentication-mechanisms)
diff --git a/src/driftpy/accounts/grpc/geyser_codegen/geyser_pb2.py b/src/driftpy/accounts/grpc/geyser_codegen/geyser_pb2.py
new file mode 100644
index 00000000..9d8e9670
--- /dev/null
+++ b/src/driftpy/accounts/grpc/geyser_codegen/geyser_pb2.py
@@ -0,0 +1,142 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: geyser.proto
+# Protobuf Python Version: 5.28.1
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 28,
+ 1,
+ '',
+ 'geyser.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2
+import driftpy.accounts.grpc.geyser_codegen.solana_storage_pb2 as solana__storage__pb2
+
+from driftpy.accounts.grpc.geyser_codegen.solana_storage_pb2 import *
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0cgeyser.proto\x12\x06geyser\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x14solana-storage.proto\"\x9c\n\n\x10SubscribeRequest\x12\x38\n\x08\x61\x63\x63ounts\x18\x01 \x03(\x0b\x32&.geyser.SubscribeRequest.AccountsEntry\x12\x32\n\x05slots\x18\x02 \x03(\x0b\x32#.geyser.SubscribeRequest.SlotsEntry\x12@\n\x0ctransactions\x18\x03 \x03(\x0b\x32*.geyser.SubscribeRequest.TransactionsEntry\x12M\n\x13transactions_status\x18\n \x03(\x0b\x32\x30.geyser.SubscribeRequest.TransactionsStatusEntry\x12\x34\n\x06\x62locks\x18\x04 \x03(\x0b\x32$.geyser.SubscribeRequest.BlocksEntry\x12=\n\x0b\x62locks_meta\x18\x05 \x03(\x0b\x32(.geyser.SubscribeRequest.BlocksMetaEntry\x12\x32\n\x05\x65ntry\x18\x08 \x03(\x0b\x32#.geyser.SubscribeRequest.EntryEntry\x12\x30\n\ncommitment\x18\x06 \x01(\x0e\x32\x17.geyser.CommitmentLevelH\x00\x88\x01\x01\x12\x46\n\x13\x61\x63\x63ounts_data_slice\x18\x07 \x03(\x0b\x32).geyser.SubscribeRequestAccountsDataSlice\x12/\n\x04ping\x18\t \x01(\x0b\x32\x1c.geyser.SubscribeRequestPingH\x01\x88\x01\x01\x12\x16\n\tfrom_slot\x18\x0b \x01(\x04H\x02\x88\x01\x01\x1aW\n\rAccountsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x35\n\x05value\x18\x02 \x01(\x0b\x32&.geyser.SubscribeRequestFilterAccounts:\x02\x38\x01\x1aQ\n\nSlotsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x32\n\x05value\x18\x02 \x01(\x0b\x32#.geyser.SubscribeRequestFilterSlots:\x02\x38\x01\x1a_\n\x11TransactionsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x39\n\x05value\x18\x02 \x01(\x0b\x32*.geyser.SubscribeRequestFilterTransactions:\x02\x38\x01\x1a\x65\n\x17TransactionsStatusEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x39\n\x05value\x18\x02 \x01(\x0b\x32*.geyser.SubscribeRequestFilterTransactions:\x02\x38\x01\x1aS\n\x0b\x42locksEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x33\n\x05value\x18\x02 \x01(\x0b\x32$.geyser.SubscribeRequestFilterBlocks:\x02\x38\x01\x1a[\n\x0f\x42locksMetaEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x37\n\x05value\x18\x02 \x01(\x0b\x32(.geyser.SubscribeRequestFilterBlocksMeta:\x02\x38\x01\x1aQ\n\nEntryEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x32\n\x05value\x18\x02 \x01(\x0b\x32#.geyser.SubscribeRequestFilterEntry:\x02\x38\x01\x42\r\n\x0b_commitmentB\x07\n\x05_pingB\x0c\n\n_from_slot\"\xbf\x01\n\x1eSubscribeRequestFilterAccounts\x12\x0f\n\x07\x61\x63\x63ount\x18\x02 \x03(\t\x12\r\n\x05owner\x18\x03 \x03(\t\x12=\n\x07\x66ilters\x18\x04 \x03(\x0b\x32,.geyser.SubscribeRequestFilterAccountsFilter\x12#\n\x16nonempty_txn_signature\x18\x05 \x01(\x08H\x00\x88\x01\x01\x42\x19\n\x17_nonempty_txn_signature\"\xf3\x01\n$SubscribeRequestFilterAccountsFilter\x12\x44\n\x06memcmp\x18\x01 \x01(\x0b\x32\x32.geyser.SubscribeRequestFilterAccountsFilterMemcmpH\x00\x12\x12\n\x08\x64\x61tasize\x18\x02 \x01(\x04H\x00\x12\x1d\n\x13token_account_state\x18\x03 \x01(\x08H\x00\x12H\n\x08lamports\x18\x04 \x01(\x0b\x32\x34.geyser.SubscribeRequestFilterAccountsFilterLamportsH\x00\x42\x08\n\x06\x66ilter\"y\n*SubscribeRequestFilterAccountsFilterMemcmp\x12\x0e\n\x06offset\x18\x01 \x01(\x04\x12\x0f\n\x05\x62ytes\x18\x02 \x01(\x0cH\x00\x12\x10\n\x06\x62\x61se58\x18\x03 \x01(\tH\x00\x12\x10\n\x06\x62\x61se64\x18\x04 \x01(\tH\x00\x42\x06\n\x04\x64\x61ta\"m\n,SubscribeRequestFilterAccountsFilterLamports\x12\x0c\n\x02\x65q\x18\x01 \x01(\x04H\x00\x12\x0c\n\x02ne\x18\x02 \x01(\x04H\x00\x12\x0c\n\x02lt\x18\x03 \x01(\x04H\x00\x12\x0c\n\x02gt\x18\x04 \x01(\x04H\x00\x42\x05\n\x03\x63mp\"Y\n\x1bSubscribeRequestFilterSlots\x12!\n\x14\x66ilter_by_commitment\x18\x01 \x01(\x08H\x00\x88\x01\x01\x42\x17\n\x15_filter_by_commitment\"\xd2\x01\n\"SubscribeRequestFilterTransactions\x12\x11\n\x04vote\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x13\n\x06\x66\x61iled\x18\x02 \x01(\x08H\x01\x88\x01\x01\x12\x16\n\tsignature\x18\x05 \x01(\tH\x02\x88\x01\x01\x12\x17\n\x0f\x61\x63\x63ount_include\x18\x03 \x03(\t\x12\x17\n\x0f\x61\x63\x63ount_exclude\x18\x04 \x03(\t\x12\x18\n\x10\x61\x63\x63ount_required\x18\x06 \x03(\tB\x07\n\x05_voteB\t\n\x07_failedB\x0c\n\n_signature\"\xd9\x01\n\x1cSubscribeRequestFilterBlocks\x12\x17\n\x0f\x61\x63\x63ount_include\x18\x01 \x03(\t\x12!\n\x14include_transactions\x18\x02 \x01(\x08H\x00\x88\x01\x01\x12\x1d\n\x10include_accounts\x18\x03 \x01(\x08H\x01\x88\x01\x01\x12\x1c\n\x0finclude_entries\x18\x04 \x01(\x08H\x02\x88\x01\x01\x42\x17\n\x15_include_transactionsB\x13\n\x11_include_accountsB\x12\n\x10_include_entries\"\"\n SubscribeRequestFilterBlocksMeta\"\x1d\n\x1bSubscribeRequestFilterEntry\"C\n!SubscribeRequestAccountsDataSlice\x12\x0e\n\x06offset\x18\x01 \x01(\x04\x12\x0e\n\x06length\x18\x02 \x01(\x04\"\"\n\x14SubscribeRequestPing\x12\n\n\x02id\x18\x01 \x01(\x05\"\xb5\x04\n\x0fSubscribeUpdate\x12\x0f\n\x07\x66ilters\x18\x01 \x03(\t\x12\x31\n\x07\x61\x63\x63ount\x18\x02 \x01(\x0b\x32\x1e.geyser.SubscribeUpdateAccountH\x00\x12+\n\x04slot\x18\x03 \x01(\x0b\x32\x1b.geyser.SubscribeUpdateSlotH\x00\x12\x39\n\x0btransaction\x18\x04 \x01(\x0b\x32\".geyser.SubscribeUpdateTransactionH\x00\x12\x46\n\x12transaction_status\x18\n \x01(\x0b\x32(.geyser.SubscribeUpdateTransactionStatusH\x00\x12-\n\x05\x62lock\x18\x05 \x01(\x0b\x32\x1c.geyser.SubscribeUpdateBlockH\x00\x12+\n\x04ping\x18\x06 \x01(\x0b\x32\x1b.geyser.SubscribeUpdatePingH\x00\x12+\n\x04pong\x18\t \x01(\x0b\x32\x1b.geyser.SubscribeUpdatePongH\x00\x12\x36\n\nblock_meta\x18\x07 \x01(\x0b\x32 .geyser.SubscribeUpdateBlockMetaH\x00\x12-\n\x05\x65ntry\x18\x08 \x01(\x0b\x32\x1c.geyser.SubscribeUpdateEntryH\x00\x12.\n\ncreated_at\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x0e\n\x0cupdate_oneof\"o\n\x16SubscribeUpdateAccount\x12\x33\n\x07\x61\x63\x63ount\x18\x01 \x01(\x0b\x32\".geyser.SubscribeUpdateAccountInfo\x12\x0c\n\x04slot\x18\x02 \x01(\x04\x12\x12\n\nis_startup\x18\x03 \x01(\x08\"\xc8\x01\n\x1aSubscribeUpdateAccountInfo\x12\x0e\n\x06pubkey\x18\x01 \x01(\x0c\x12\x10\n\x08lamports\x18\x02 \x01(\x04\x12\r\n\x05owner\x18\x03 \x01(\x0c\x12\x12\n\nexecutable\x18\x04 \x01(\x08\x12\x12\n\nrent_epoch\x18\x05 \x01(\x04\x12\x0c\n\x04\x64\x61ta\x18\x06 \x01(\x0c\x12\x15\n\rwrite_version\x18\x07 \x01(\x04\x12\x1a\n\rtxn_signature\x18\x08 \x01(\x0cH\x00\x88\x01\x01\x42\x10\n\x0e_txn_signature\"\x94\x01\n\x13SubscribeUpdateSlot\x12\x0c\n\x04slot\x18\x01 \x01(\x04\x12\x13\n\x06parent\x18\x02 \x01(\x04H\x00\x88\x01\x01\x12\'\n\x06status\x18\x03 \x01(\x0e\x32\x17.geyser.CommitmentLevel\x12\x17\n\ndead_error\x18\x04 \x01(\tH\x01\x88\x01\x01\x42\t\n\x07_parentB\r\n\x0b_dead_error\"g\n\x1aSubscribeUpdateTransaction\x12;\n\x0btransaction\x18\x01 \x01(\x0b\x32&.geyser.SubscribeUpdateTransactionInfo\x12\x0c\n\x04slot\x18\x02 \x01(\x04\"\xd8\x01\n\x1eSubscribeUpdateTransactionInfo\x12\x11\n\tsignature\x18\x01 \x01(\x0c\x12\x0f\n\x07is_vote\x18\x02 \x01(\x08\x12?\n\x0btransaction\x18\x03 \x01(\x0b\x32*.solana.storage.ConfirmedBlock.Transaction\x12\x42\n\x04meta\x18\x04 \x01(\x0b\x32\x34.solana.storage.ConfirmedBlock.TransactionStatusMeta\x12\r\n\x05index\x18\x05 \x01(\x04\"\xa1\x01\n SubscribeUpdateTransactionStatus\x12\x0c\n\x04slot\x18\x01 \x01(\x04\x12\x11\n\tsignature\x18\x02 \x01(\x0c\x12\x0f\n\x07is_vote\x18\x03 \x01(\x08\x12\r\n\x05index\x18\x04 \x01(\x04\x12<\n\x03\x65rr\x18\x05 \x01(\x0b\x32/.solana.storage.ConfirmedBlock.TransactionError\"\xa0\x04\n\x14SubscribeUpdateBlock\x12\x0c\n\x04slot\x18\x01 \x01(\x04\x12\x11\n\tblockhash\x18\x02 \x01(\t\x12\x37\n\x07rewards\x18\x03 \x01(\x0b\x32&.solana.storage.ConfirmedBlock.Rewards\x12@\n\nblock_time\x18\x04 \x01(\x0b\x32,.solana.storage.ConfirmedBlock.UnixTimestamp\x12@\n\x0c\x62lock_height\x18\x05 \x01(\x0b\x32*.solana.storage.ConfirmedBlock.BlockHeight\x12\x13\n\x0bparent_slot\x18\x07 \x01(\x04\x12\x18\n\x10parent_blockhash\x18\x08 \x01(\t\x12\"\n\x1a\x65xecuted_transaction_count\x18\t \x01(\x04\x12<\n\x0ctransactions\x18\x06 \x03(\x0b\x32&.geyser.SubscribeUpdateTransactionInfo\x12\x1d\n\x15updated_account_count\x18\n \x01(\x04\x12\x34\n\x08\x61\x63\x63ounts\x18\x0b \x03(\x0b\x32\".geyser.SubscribeUpdateAccountInfo\x12\x15\n\rentries_count\x18\x0c \x01(\x04\x12-\n\x07\x65ntries\x18\r \x03(\x0b\x32\x1c.geyser.SubscribeUpdateEntry\"\xe2\x02\n\x18SubscribeUpdateBlockMeta\x12\x0c\n\x04slot\x18\x01 \x01(\x04\x12\x11\n\tblockhash\x18\x02 \x01(\t\x12\x37\n\x07rewards\x18\x03 \x01(\x0b\x32&.solana.storage.ConfirmedBlock.Rewards\x12@\n\nblock_time\x18\x04 \x01(\x0b\x32,.solana.storage.ConfirmedBlock.UnixTimestamp\x12@\n\x0c\x62lock_height\x18\x05 \x01(\x0b\x32*.solana.storage.ConfirmedBlock.BlockHeight\x12\x13\n\x0bparent_slot\x18\x06 \x01(\x04\x12\x18\n\x10parent_blockhash\x18\x07 \x01(\t\x12\"\n\x1a\x65xecuted_transaction_count\x18\x08 \x01(\x04\x12\x15\n\rentries_count\x18\t \x01(\x04\"\x9d\x01\n\x14SubscribeUpdateEntry\x12\x0c\n\x04slot\x18\x01 \x01(\x04\x12\r\n\x05index\x18\x02 \x01(\x04\x12\x12\n\nnum_hashes\x18\x03 \x01(\x04\x12\x0c\n\x04hash\x18\x04 \x01(\x0c\x12\"\n\x1a\x65xecuted_transaction_count\x18\x05 \x01(\x04\x12\"\n\x1astarting_transaction_index\x18\x06 \x01(\x04\"\x15\n\x13SubscribeUpdatePing\"!\n\x13SubscribeUpdatePong\x12\n\n\x02id\x18\x01 \x01(\x05\"\x1c\n\x0bPingRequest\x12\r\n\x05\x63ount\x18\x01 \x01(\x05\"\x1d\n\x0cPongResponse\x12\r\n\x05\x63ount\x18\x01 \x01(\x05\"\\\n\x19GetLatestBlockhashRequest\x12\x30\n\ncommitment\x18\x01 \x01(\x0e\x32\x17.geyser.CommitmentLevelH\x00\x88\x01\x01\x42\r\n\x0b_commitment\"^\n\x1aGetLatestBlockhashResponse\x12\x0c\n\x04slot\x18\x01 \x01(\x04\x12\x11\n\tblockhash\x18\x02 \x01(\t\x12\x1f\n\x17last_valid_block_height\x18\x03 \x01(\x04\"X\n\x15GetBlockHeightRequest\x12\x30\n\ncommitment\x18\x01 \x01(\x0e\x32\x17.geyser.CommitmentLevelH\x00\x88\x01\x01\x42\r\n\x0b_commitment\".\n\x16GetBlockHeightResponse\x12\x14\n\x0c\x62lock_height\x18\x01 \x01(\x04\"Q\n\x0eGetSlotRequest\x12\x30\n\ncommitment\x18\x01 \x01(\x0e\x32\x17.geyser.CommitmentLevelH\x00\x88\x01\x01\x42\r\n\x0b_commitment\"\x1f\n\x0fGetSlotResponse\x12\x0c\n\x04slot\x18\x01 \x01(\x04\"\x13\n\x11GetVersionRequest\"%\n\x12GetVersionResponse\x12\x0f\n\x07version\x18\x01 \x01(\t\"m\n\x17IsBlockhashValidRequest\x12\x11\n\tblockhash\x18\x01 \x01(\t\x12\x30\n\ncommitment\x18\x02 \x01(\x0e\x32\x17.geyser.CommitmentLevelH\x00\x88\x01\x01\x42\r\n\x0b_commitment\"7\n\x18IsBlockhashValidResponse\x12\x0c\n\x04slot\x18\x01 \x01(\x04\x12\r\n\x05valid\x18\x02 \x01(\x08*\x83\x01\n\x0f\x43ommitmentLevel\x12\r\n\tPROCESSED\x10\x00\x12\r\n\tCONFIRMED\x10\x01\x12\r\n\tFINALIZED\x10\x02\x12\x18\n\x14\x46IRST_SHRED_RECEIVED\x10\x03\x12\r\n\tCOMPLETED\x10\x04\x12\x10\n\x0c\x43REATED_BANK\x10\x05\x12\x08\n\x04\x44\x45\x41\x44\x10\x06\x32\x93\x04\n\x06Geyser\x12\x44\n\tSubscribe\x12\x18.geyser.SubscribeRequest\x1a\x17.geyser.SubscribeUpdate\"\x00(\x01\x30\x01\x12\x33\n\x04Ping\x12\x13.geyser.PingRequest\x1a\x14.geyser.PongResponse\"\x00\x12]\n\x12GetLatestBlockhash\x12!.geyser.GetLatestBlockhashRequest\x1a\".geyser.GetLatestBlockhashResponse\"\x00\x12Q\n\x0eGetBlockHeight\x12\x1d.geyser.GetBlockHeightRequest\x1a\x1e.geyser.GetBlockHeightResponse\"\x00\x12<\n\x07GetSlot\x12\x16.geyser.GetSlotRequest\x1a\x17.geyser.GetSlotResponse\"\x00\x12W\n\x10IsBlockhashValid\x12\x1f.geyser.IsBlockhashValidRequest\x1a .geyser.IsBlockhashValidResponse\"\x00\x12\x45\n\nGetVersion\x12\x19.geyser.GetVersionRequest\x1a\x1a.geyser.GetVersionResponse\"\x00\x42;Z9github.com/rpcpool/yellowstone-grpc/examples/golang/protoP\x01\x62\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'geyser_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'Z9github.com/rpcpool/yellowstone-grpc/examples/golang/proto'
+ _globals['_SUBSCRIBEREQUEST_ACCOUNTSENTRY']._loaded_options = None
+ _globals['_SUBSCRIBEREQUEST_ACCOUNTSENTRY']._serialized_options = b'8\001'
+ _globals['_SUBSCRIBEREQUEST_SLOTSENTRY']._loaded_options = None
+ _globals['_SUBSCRIBEREQUEST_SLOTSENTRY']._serialized_options = b'8\001'
+ _globals['_SUBSCRIBEREQUEST_TRANSACTIONSENTRY']._loaded_options = None
+ _globals['_SUBSCRIBEREQUEST_TRANSACTIONSENTRY']._serialized_options = b'8\001'
+ _globals['_SUBSCRIBEREQUEST_TRANSACTIONSSTATUSENTRY']._loaded_options = None
+ _globals['_SUBSCRIBEREQUEST_TRANSACTIONSSTATUSENTRY']._serialized_options = b'8\001'
+ _globals['_SUBSCRIBEREQUEST_BLOCKSENTRY']._loaded_options = None
+ _globals['_SUBSCRIBEREQUEST_BLOCKSENTRY']._serialized_options = b'8\001'
+ _globals['_SUBSCRIBEREQUEST_BLOCKSMETAENTRY']._loaded_options = None
+ _globals['_SUBSCRIBEREQUEST_BLOCKSMETAENTRY']._serialized_options = b'8\001'
+ _globals['_SUBSCRIBEREQUEST_ENTRYENTRY']._loaded_options = None
+ _globals['_SUBSCRIBEREQUEST_ENTRYENTRY']._serialized_options = b'8\001'
+ _globals['_COMMITMENTLEVEL']._serialized_start=6139
+ _globals['_COMMITMENTLEVEL']._serialized_end=6270
+ _globals['_SUBSCRIBEREQUEST']._serialized_start=80
+ _globals['_SUBSCRIBEREQUEST']._serialized_end=1388
+ _globals['_SUBSCRIBEREQUEST_ACCOUNTSENTRY']._serialized_start=719
+ _globals['_SUBSCRIBEREQUEST_ACCOUNTSENTRY']._serialized_end=806
+ _globals['_SUBSCRIBEREQUEST_SLOTSENTRY']._serialized_start=808
+ _globals['_SUBSCRIBEREQUEST_SLOTSENTRY']._serialized_end=889
+ _globals['_SUBSCRIBEREQUEST_TRANSACTIONSENTRY']._serialized_start=891
+ _globals['_SUBSCRIBEREQUEST_TRANSACTIONSENTRY']._serialized_end=986
+ _globals['_SUBSCRIBEREQUEST_TRANSACTIONSSTATUSENTRY']._serialized_start=988
+ _globals['_SUBSCRIBEREQUEST_TRANSACTIONSSTATUSENTRY']._serialized_end=1089
+ _globals['_SUBSCRIBEREQUEST_BLOCKSENTRY']._serialized_start=1091
+ _globals['_SUBSCRIBEREQUEST_BLOCKSENTRY']._serialized_end=1174
+ _globals['_SUBSCRIBEREQUEST_BLOCKSMETAENTRY']._serialized_start=1176
+ _globals['_SUBSCRIBEREQUEST_BLOCKSMETAENTRY']._serialized_end=1267
+ _globals['_SUBSCRIBEREQUEST_ENTRYENTRY']._serialized_start=1269
+ _globals['_SUBSCRIBEREQUEST_ENTRYENTRY']._serialized_end=1350
+ _globals['_SUBSCRIBEREQUESTFILTERACCOUNTS']._serialized_start=1391
+ _globals['_SUBSCRIBEREQUESTFILTERACCOUNTS']._serialized_end=1582
+ _globals['_SUBSCRIBEREQUESTFILTERACCOUNTSFILTER']._serialized_start=1585
+ _globals['_SUBSCRIBEREQUESTFILTERACCOUNTSFILTER']._serialized_end=1828
+ _globals['_SUBSCRIBEREQUESTFILTERACCOUNTSFILTERMEMCMP']._serialized_start=1830
+ _globals['_SUBSCRIBEREQUESTFILTERACCOUNTSFILTERMEMCMP']._serialized_end=1951
+ _globals['_SUBSCRIBEREQUESTFILTERACCOUNTSFILTERLAMPORTS']._serialized_start=1953
+ _globals['_SUBSCRIBEREQUESTFILTERACCOUNTSFILTERLAMPORTS']._serialized_end=2062
+ _globals['_SUBSCRIBEREQUESTFILTERSLOTS']._serialized_start=2064
+ _globals['_SUBSCRIBEREQUESTFILTERSLOTS']._serialized_end=2153
+ _globals['_SUBSCRIBEREQUESTFILTERTRANSACTIONS']._serialized_start=2156
+ _globals['_SUBSCRIBEREQUESTFILTERTRANSACTIONS']._serialized_end=2366
+ _globals['_SUBSCRIBEREQUESTFILTERBLOCKS']._serialized_start=2369
+ _globals['_SUBSCRIBEREQUESTFILTERBLOCKS']._serialized_end=2586
+ _globals['_SUBSCRIBEREQUESTFILTERBLOCKSMETA']._serialized_start=2588
+ _globals['_SUBSCRIBEREQUESTFILTERBLOCKSMETA']._serialized_end=2622
+ _globals['_SUBSCRIBEREQUESTFILTERENTRY']._serialized_start=2624
+ _globals['_SUBSCRIBEREQUESTFILTERENTRY']._serialized_end=2653
+ _globals['_SUBSCRIBEREQUESTACCOUNTSDATASLICE']._serialized_start=2655
+ _globals['_SUBSCRIBEREQUESTACCOUNTSDATASLICE']._serialized_end=2722
+ _globals['_SUBSCRIBEREQUESTPING']._serialized_start=2724
+ _globals['_SUBSCRIBEREQUESTPING']._serialized_end=2758
+ _globals['_SUBSCRIBEUPDATE']._serialized_start=2761
+ _globals['_SUBSCRIBEUPDATE']._serialized_end=3326
+ _globals['_SUBSCRIBEUPDATEACCOUNT']._serialized_start=3328
+ _globals['_SUBSCRIBEUPDATEACCOUNT']._serialized_end=3439
+ _globals['_SUBSCRIBEUPDATEACCOUNTINFO']._serialized_start=3442
+ _globals['_SUBSCRIBEUPDATEACCOUNTINFO']._serialized_end=3642
+ _globals['_SUBSCRIBEUPDATESLOT']._serialized_start=3645
+ _globals['_SUBSCRIBEUPDATESLOT']._serialized_end=3793
+ _globals['_SUBSCRIBEUPDATETRANSACTION']._serialized_start=3795
+ _globals['_SUBSCRIBEUPDATETRANSACTION']._serialized_end=3898
+ _globals['_SUBSCRIBEUPDATETRANSACTIONINFO']._serialized_start=3901
+ _globals['_SUBSCRIBEUPDATETRANSACTIONINFO']._serialized_end=4117
+ _globals['_SUBSCRIBEUPDATETRANSACTIONSTATUS']._serialized_start=4120
+ _globals['_SUBSCRIBEUPDATETRANSACTIONSTATUS']._serialized_end=4281
+ _globals['_SUBSCRIBEUPDATEBLOCK']._serialized_start=4284
+ _globals['_SUBSCRIBEUPDATEBLOCK']._serialized_end=4828
+ _globals['_SUBSCRIBEUPDATEBLOCKMETA']._serialized_start=4831
+ _globals['_SUBSCRIBEUPDATEBLOCKMETA']._serialized_end=5185
+ _globals['_SUBSCRIBEUPDATEENTRY']._serialized_start=5188
+ _globals['_SUBSCRIBEUPDATEENTRY']._serialized_end=5345
+ _globals['_SUBSCRIBEUPDATEPING']._serialized_start=5347
+ _globals['_SUBSCRIBEUPDATEPING']._serialized_end=5368
+ _globals['_SUBSCRIBEUPDATEPONG']._serialized_start=5370
+ _globals['_SUBSCRIBEUPDATEPONG']._serialized_end=5403
+ _globals['_PINGREQUEST']._serialized_start=5405
+ _globals['_PINGREQUEST']._serialized_end=5433
+ _globals['_PONGRESPONSE']._serialized_start=5435
+ _globals['_PONGRESPONSE']._serialized_end=5464
+ _globals['_GETLATESTBLOCKHASHREQUEST']._serialized_start=5466
+ _globals['_GETLATESTBLOCKHASHREQUEST']._serialized_end=5558
+ _globals['_GETLATESTBLOCKHASHRESPONSE']._serialized_start=5560
+ _globals['_GETLATESTBLOCKHASHRESPONSE']._serialized_end=5654
+ _globals['_GETBLOCKHEIGHTREQUEST']._serialized_start=5656
+ _globals['_GETBLOCKHEIGHTREQUEST']._serialized_end=5744
+ _globals['_GETBLOCKHEIGHTRESPONSE']._serialized_start=5746
+ _globals['_GETBLOCKHEIGHTRESPONSE']._serialized_end=5792
+ _globals['_GETSLOTREQUEST']._serialized_start=5794
+ _globals['_GETSLOTREQUEST']._serialized_end=5875
+ _globals['_GETSLOTRESPONSE']._serialized_start=5877
+ _globals['_GETSLOTRESPONSE']._serialized_end=5908
+ _globals['_GETVERSIONREQUEST']._serialized_start=5910
+ _globals['_GETVERSIONREQUEST']._serialized_end=5929
+ _globals['_GETVERSIONRESPONSE']._serialized_start=5931
+ _globals['_GETVERSIONRESPONSE']._serialized_end=5968
+ _globals['_ISBLOCKHASHVALIDREQUEST']._serialized_start=5970
+ _globals['_ISBLOCKHASHVALIDREQUEST']._serialized_end=6079
+ _globals['_ISBLOCKHASHVALIDRESPONSE']._serialized_start=6081
+ _globals['_ISBLOCKHASHVALIDRESPONSE']._serialized_end=6136
+ _globals['_GEYSER']._serialized_start=6273
+ _globals['_GEYSER']._serialized_end=6804
+# @@protoc_insertion_point(module_scope)
diff --git a/src/driftpy/accounts/grpc/geyser_codegen/geyser_pb2.pyi b/src/driftpy/accounts/grpc/geyser_codegen/geyser_pb2.pyi
new file mode 100644
index 00000000..a90209e2
--- /dev/null
+++ b/src/driftpy/accounts/grpc/geyser_codegen/geyser_pb2.pyi
@@ -0,0 +1,490 @@
+from google.protobuf import timestamp_pb2 as _timestamp_pb2
+import solana_storage_pb2 as _solana_storage_pb2
+from google.protobuf.internal import containers as _containers
+from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import message as _message
+from typing import ClassVar as _ClassVar, Iterable as _Iterable, Mapping as _Mapping, Optional as _Optional, Union as _Union
+from solana_storage_pb2 import ConfirmedBlock as ConfirmedBlock
+from solana_storage_pb2 import ConfirmedTransaction as ConfirmedTransaction
+from solana_storage_pb2 import Transaction as Transaction
+from solana_storage_pb2 import Message as Message
+from solana_storage_pb2 import MessageHeader as MessageHeader
+from solana_storage_pb2 import MessageAddressTableLookup as MessageAddressTableLookup
+from solana_storage_pb2 import TransactionStatusMeta as TransactionStatusMeta
+from solana_storage_pb2 import TransactionError as TransactionError
+from solana_storage_pb2 import InnerInstructions as InnerInstructions
+from solana_storage_pb2 import InnerInstruction as InnerInstruction
+from solana_storage_pb2 import CompiledInstruction as CompiledInstruction
+from solana_storage_pb2 import TokenBalance as TokenBalance
+from solana_storage_pb2 import UiTokenAmount as UiTokenAmount
+from solana_storage_pb2 import ReturnData as ReturnData
+from solana_storage_pb2 import Reward as Reward
+from solana_storage_pb2 import Rewards as Rewards
+from solana_storage_pb2 import UnixTimestamp as UnixTimestamp
+from solana_storage_pb2 import BlockHeight as BlockHeight
+from solana_storage_pb2 import NumPartitions as NumPartitions
+from solana_storage_pb2 import RewardType as RewardType
+
+DESCRIPTOR: _descriptor.FileDescriptor
+Unspecified: _solana_storage_pb2.RewardType
+Fee: _solana_storage_pb2.RewardType
+Rent: _solana_storage_pb2.RewardType
+Staking: _solana_storage_pb2.RewardType
+Voting: _solana_storage_pb2.RewardType
+
+class CommitmentLevel(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
+ __slots__ = ()
+ PROCESSED: _ClassVar[CommitmentLevel]
+ CONFIRMED: _ClassVar[CommitmentLevel]
+ FINALIZED: _ClassVar[CommitmentLevel]
+ FIRST_SHRED_RECEIVED: _ClassVar[CommitmentLevel]
+ COMPLETED: _ClassVar[CommitmentLevel]
+ CREATED_BANK: _ClassVar[CommitmentLevel]
+ DEAD: _ClassVar[CommitmentLevel]
+PROCESSED: CommitmentLevel
+CONFIRMED: CommitmentLevel
+FINALIZED: CommitmentLevel
+FIRST_SHRED_RECEIVED: CommitmentLevel
+COMPLETED: CommitmentLevel
+CREATED_BANK: CommitmentLevel
+DEAD: CommitmentLevel
+
+class SubscribeRequest(_message.Message):
+ __slots__ = ("accounts", "slots", "transactions", "transactions_status", "blocks", "blocks_meta", "entry", "commitment", "accounts_data_slice", "ping", "from_slot")
+ class AccountsEntry(_message.Message):
+ __slots__ = ("key", "value")
+ KEY_FIELD_NUMBER: _ClassVar[int]
+ VALUE_FIELD_NUMBER: _ClassVar[int]
+ key: str
+ value: SubscribeRequestFilterAccounts
+ def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[SubscribeRequestFilterAccounts, _Mapping]] = ...) -> None: ...
+ class SlotsEntry(_message.Message):
+ __slots__ = ("key", "value")
+ KEY_FIELD_NUMBER: _ClassVar[int]
+ VALUE_FIELD_NUMBER: _ClassVar[int]
+ key: str
+ value: SubscribeRequestFilterSlots
+ def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[SubscribeRequestFilterSlots, _Mapping]] = ...) -> None: ...
+ class TransactionsEntry(_message.Message):
+ __slots__ = ("key", "value")
+ KEY_FIELD_NUMBER: _ClassVar[int]
+ VALUE_FIELD_NUMBER: _ClassVar[int]
+ key: str
+ value: SubscribeRequestFilterTransactions
+ def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[SubscribeRequestFilterTransactions, _Mapping]] = ...) -> None: ...
+ class TransactionsStatusEntry(_message.Message):
+ __slots__ = ("key", "value")
+ KEY_FIELD_NUMBER: _ClassVar[int]
+ VALUE_FIELD_NUMBER: _ClassVar[int]
+ key: str
+ value: SubscribeRequestFilterTransactions
+ def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[SubscribeRequestFilterTransactions, _Mapping]] = ...) -> None: ...
+ class BlocksEntry(_message.Message):
+ __slots__ = ("key", "value")
+ KEY_FIELD_NUMBER: _ClassVar[int]
+ VALUE_FIELD_NUMBER: _ClassVar[int]
+ key: str
+ value: SubscribeRequestFilterBlocks
+ def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[SubscribeRequestFilterBlocks, _Mapping]] = ...) -> None: ...
+ class BlocksMetaEntry(_message.Message):
+ __slots__ = ("key", "value")
+ KEY_FIELD_NUMBER: _ClassVar[int]
+ VALUE_FIELD_NUMBER: _ClassVar[int]
+ key: str
+ value: SubscribeRequestFilterBlocksMeta
+ def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[SubscribeRequestFilterBlocksMeta, _Mapping]] = ...) -> None: ...
+ class EntryEntry(_message.Message):
+ __slots__ = ("key", "value")
+ KEY_FIELD_NUMBER: _ClassVar[int]
+ VALUE_FIELD_NUMBER: _ClassVar[int]
+ key: str
+ value: SubscribeRequestFilterEntry
+ def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[SubscribeRequestFilterEntry, _Mapping]] = ...) -> None: ...
+ ACCOUNTS_FIELD_NUMBER: _ClassVar[int]
+ SLOTS_FIELD_NUMBER: _ClassVar[int]
+ TRANSACTIONS_FIELD_NUMBER: _ClassVar[int]
+ TRANSACTIONS_STATUS_FIELD_NUMBER: _ClassVar[int]
+ BLOCKS_FIELD_NUMBER: _ClassVar[int]
+ BLOCKS_META_FIELD_NUMBER: _ClassVar[int]
+ ENTRY_FIELD_NUMBER: _ClassVar[int]
+ COMMITMENT_FIELD_NUMBER: _ClassVar[int]
+ ACCOUNTS_DATA_SLICE_FIELD_NUMBER: _ClassVar[int]
+ PING_FIELD_NUMBER: _ClassVar[int]
+ FROM_SLOT_FIELD_NUMBER: _ClassVar[int]
+ accounts: _containers.MessageMap[str, SubscribeRequestFilterAccounts]
+ slots: _containers.MessageMap[str, SubscribeRequestFilterSlots]
+ transactions: _containers.MessageMap[str, SubscribeRequestFilterTransactions]
+ transactions_status: _containers.MessageMap[str, SubscribeRequestFilterTransactions]
+ blocks: _containers.MessageMap[str, SubscribeRequestFilterBlocks]
+ blocks_meta: _containers.MessageMap[str, SubscribeRequestFilterBlocksMeta]
+ entry: _containers.MessageMap[str, SubscribeRequestFilterEntry]
+ commitment: CommitmentLevel
+ accounts_data_slice: _containers.RepeatedCompositeFieldContainer[SubscribeRequestAccountsDataSlice]
+ ping: SubscribeRequestPing
+ from_slot: int
+ def __init__(self, accounts: _Optional[_Mapping[str, SubscribeRequestFilterAccounts]] = ..., slots: _Optional[_Mapping[str, SubscribeRequestFilterSlots]] = ..., transactions: _Optional[_Mapping[str, SubscribeRequestFilterTransactions]] = ..., transactions_status: _Optional[_Mapping[str, SubscribeRequestFilterTransactions]] = ..., blocks: _Optional[_Mapping[str, SubscribeRequestFilterBlocks]] = ..., blocks_meta: _Optional[_Mapping[str, SubscribeRequestFilterBlocksMeta]] = ..., entry: _Optional[_Mapping[str, SubscribeRequestFilterEntry]] = ..., commitment: _Optional[_Union[CommitmentLevel, str]] = ..., accounts_data_slice: _Optional[_Iterable[_Union[SubscribeRequestAccountsDataSlice, _Mapping]]] = ..., ping: _Optional[_Union[SubscribeRequestPing, _Mapping]] = ..., from_slot: _Optional[int] = ...) -> None: ...
+
+class SubscribeRequestFilterAccounts(_message.Message):
+ __slots__ = ("account", "owner", "filters", "nonempty_txn_signature")
+ ACCOUNT_FIELD_NUMBER: _ClassVar[int]
+ OWNER_FIELD_NUMBER: _ClassVar[int]
+ FILTERS_FIELD_NUMBER: _ClassVar[int]
+ NONEMPTY_TXN_SIGNATURE_FIELD_NUMBER: _ClassVar[int]
+ account: _containers.RepeatedScalarFieldContainer[str]
+ owner: _containers.RepeatedScalarFieldContainer[str]
+ filters: _containers.RepeatedCompositeFieldContainer[SubscribeRequestFilterAccountsFilter]
+ nonempty_txn_signature: bool
+ def __init__(self, account: _Optional[_Iterable[str]] = ..., owner: _Optional[_Iterable[str]] = ..., filters: _Optional[_Iterable[_Union[SubscribeRequestFilterAccountsFilter, _Mapping]]] = ..., nonempty_txn_signature: bool = ...) -> None: ...
+
+class SubscribeRequestFilterAccountsFilter(_message.Message):
+ __slots__ = ("memcmp", "datasize", "token_account_state", "lamports")
+ MEMCMP_FIELD_NUMBER: _ClassVar[int]
+ DATASIZE_FIELD_NUMBER: _ClassVar[int]
+ TOKEN_ACCOUNT_STATE_FIELD_NUMBER: _ClassVar[int]
+ LAMPORTS_FIELD_NUMBER: _ClassVar[int]
+ memcmp: SubscribeRequestFilterAccountsFilterMemcmp
+ datasize: int
+ token_account_state: bool
+ lamports: SubscribeRequestFilterAccountsFilterLamports
+ def __init__(self, memcmp: _Optional[_Union[SubscribeRequestFilterAccountsFilterMemcmp, _Mapping]] = ..., datasize: _Optional[int] = ..., token_account_state: bool = ..., lamports: _Optional[_Union[SubscribeRequestFilterAccountsFilterLamports, _Mapping]] = ...) -> None: ...
+
+class SubscribeRequestFilterAccountsFilterMemcmp(_message.Message):
+ __slots__ = ("offset", "bytes", "base58", "base64")
+ OFFSET_FIELD_NUMBER: _ClassVar[int]
+ BYTES_FIELD_NUMBER: _ClassVar[int]
+ BASE58_FIELD_NUMBER: _ClassVar[int]
+ BASE64_FIELD_NUMBER: _ClassVar[int]
+ offset: int
+ bytes: bytes
+ base58: str
+ base64: str
+ def __init__(self, offset: _Optional[int] = ..., bytes: _Optional[bytes] = ..., base58: _Optional[str] = ..., base64: _Optional[str] = ...) -> None: ...
+
+class SubscribeRequestFilterAccountsFilterLamports(_message.Message):
+ __slots__ = ("eq", "ne", "lt", "gt")
+ EQ_FIELD_NUMBER: _ClassVar[int]
+ NE_FIELD_NUMBER: _ClassVar[int]
+ LT_FIELD_NUMBER: _ClassVar[int]
+ GT_FIELD_NUMBER: _ClassVar[int]
+ eq: int
+ ne: int
+ lt: int
+ gt: int
+ def __init__(self, eq: _Optional[int] = ..., ne: _Optional[int] = ..., lt: _Optional[int] = ..., gt: _Optional[int] = ...) -> None: ...
+
+class SubscribeRequestFilterSlots(_message.Message):
+ __slots__ = ("filter_by_commitment",)
+ FILTER_BY_COMMITMENT_FIELD_NUMBER: _ClassVar[int]
+ filter_by_commitment: bool
+ def __init__(self, filter_by_commitment: bool = ...) -> None: ...
+
+class SubscribeRequestFilterTransactions(_message.Message):
+ __slots__ = ("vote", "failed", "signature", "account_include", "account_exclude", "account_required")
+ VOTE_FIELD_NUMBER: _ClassVar[int]
+ FAILED_FIELD_NUMBER: _ClassVar[int]
+ SIGNATURE_FIELD_NUMBER: _ClassVar[int]
+ ACCOUNT_INCLUDE_FIELD_NUMBER: _ClassVar[int]
+ ACCOUNT_EXCLUDE_FIELD_NUMBER: _ClassVar[int]
+ ACCOUNT_REQUIRED_FIELD_NUMBER: _ClassVar[int]
+ vote: bool
+ failed: bool
+ signature: str
+ account_include: _containers.RepeatedScalarFieldContainer[str]
+ account_exclude: _containers.RepeatedScalarFieldContainer[str]
+ account_required: _containers.RepeatedScalarFieldContainer[str]
+ def __init__(self, vote: bool = ..., failed: bool = ..., signature: _Optional[str] = ..., account_include: _Optional[_Iterable[str]] = ..., account_exclude: _Optional[_Iterable[str]] = ..., account_required: _Optional[_Iterable[str]] = ...) -> None: ...
+
+class SubscribeRequestFilterBlocks(_message.Message):
+ __slots__ = ("account_include", "include_transactions", "include_accounts", "include_entries")
+ ACCOUNT_INCLUDE_FIELD_NUMBER: _ClassVar[int]
+ INCLUDE_TRANSACTIONS_FIELD_NUMBER: _ClassVar[int]
+ INCLUDE_ACCOUNTS_FIELD_NUMBER: _ClassVar[int]
+ INCLUDE_ENTRIES_FIELD_NUMBER: _ClassVar[int]
+ account_include: _containers.RepeatedScalarFieldContainer[str]
+ include_transactions: bool
+ include_accounts: bool
+ include_entries: bool
+ def __init__(self, account_include: _Optional[_Iterable[str]] = ..., include_transactions: bool = ..., include_accounts: bool = ..., include_entries: bool = ...) -> None: ...
+
+class SubscribeRequestFilterBlocksMeta(_message.Message):
+ __slots__ = ()
+ def __init__(self) -> None: ...
+
+class SubscribeRequestFilterEntry(_message.Message):
+ __slots__ = ()
+ def __init__(self) -> None: ...
+
+class SubscribeRequestAccountsDataSlice(_message.Message):
+ __slots__ = ("offset", "length")
+ OFFSET_FIELD_NUMBER: _ClassVar[int]
+ LENGTH_FIELD_NUMBER: _ClassVar[int]
+ offset: int
+ length: int
+ def __init__(self, offset: _Optional[int] = ..., length: _Optional[int] = ...) -> None: ...
+
+class SubscribeRequestPing(_message.Message):
+ __slots__ = ("id",)
+ ID_FIELD_NUMBER: _ClassVar[int]
+ id: int
+ def __init__(self, id: _Optional[int] = ...) -> None: ...
+
+class SubscribeUpdate(_message.Message):
+ __slots__ = ("filters", "account", "slot", "transaction", "transaction_status", "block", "ping", "pong", "block_meta", "entry", "created_at")
+ FILTERS_FIELD_NUMBER: _ClassVar[int]
+ ACCOUNT_FIELD_NUMBER: _ClassVar[int]
+ SLOT_FIELD_NUMBER: _ClassVar[int]
+ TRANSACTION_FIELD_NUMBER: _ClassVar[int]
+ TRANSACTION_STATUS_FIELD_NUMBER: _ClassVar[int]
+ BLOCK_FIELD_NUMBER: _ClassVar[int]
+ PING_FIELD_NUMBER: _ClassVar[int]
+ PONG_FIELD_NUMBER: _ClassVar[int]
+ BLOCK_META_FIELD_NUMBER: _ClassVar[int]
+ ENTRY_FIELD_NUMBER: _ClassVar[int]
+ CREATED_AT_FIELD_NUMBER: _ClassVar[int]
+ filters: _containers.RepeatedScalarFieldContainer[str]
+ account: SubscribeUpdateAccount
+ slot: SubscribeUpdateSlot
+ transaction: SubscribeUpdateTransaction
+ transaction_status: SubscribeUpdateTransactionStatus
+ block: SubscribeUpdateBlock
+ ping: SubscribeUpdatePing
+ pong: SubscribeUpdatePong
+ block_meta: SubscribeUpdateBlockMeta
+ entry: SubscribeUpdateEntry
+ created_at: _timestamp_pb2.Timestamp
+ def __init__(self, filters: _Optional[_Iterable[str]] = ..., account: _Optional[_Union[SubscribeUpdateAccount, _Mapping]] = ..., slot: _Optional[_Union[SubscribeUpdateSlot, _Mapping]] = ..., transaction: _Optional[_Union[SubscribeUpdateTransaction, _Mapping]] = ..., transaction_status: _Optional[_Union[SubscribeUpdateTransactionStatus, _Mapping]] = ..., block: _Optional[_Union[SubscribeUpdateBlock, _Mapping]] = ..., ping: _Optional[_Union[SubscribeUpdatePing, _Mapping]] = ..., pong: _Optional[_Union[SubscribeUpdatePong, _Mapping]] = ..., block_meta: _Optional[_Union[SubscribeUpdateBlockMeta, _Mapping]] = ..., entry: _Optional[_Union[SubscribeUpdateEntry, _Mapping]] = ..., created_at: _Optional[_Union[_timestamp_pb2.Timestamp, _Mapping]] = ...) -> None: ...
+
+class SubscribeUpdateAccount(_message.Message):
+ __slots__ = ("account", "slot", "is_startup")
+ ACCOUNT_FIELD_NUMBER: _ClassVar[int]
+ SLOT_FIELD_NUMBER: _ClassVar[int]
+ IS_STARTUP_FIELD_NUMBER: _ClassVar[int]
+ account: SubscribeUpdateAccountInfo
+ slot: int
+ is_startup: bool
+ def __init__(self, account: _Optional[_Union[SubscribeUpdateAccountInfo, _Mapping]] = ..., slot: _Optional[int] = ..., is_startup: bool = ...) -> None: ...
+
+class SubscribeUpdateAccountInfo(_message.Message):
+ __slots__ = ("pubkey", "lamports", "owner", "executable", "rent_epoch", "data", "write_version", "txn_signature")
+ PUBKEY_FIELD_NUMBER: _ClassVar[int]
+ LAMPORTS_FIELD_NUMBER: _ClassVar[int]
+ OWNER_FIELD_NUMBER: _ClassVar[int]
+ EXECUTABLE_FIELD_NUMBER: _ClassVar[int]
+ RENT_EPOCH_FIELD_NUMBER: _ClassVar[int]
+ DATA_FIELD_NUMBER: _ClassVar[int]
+ WRITE_VERSION_FIELD_NUMBER: _ClassVar[int]
+ TXN_SIGNATURE_FIELD_NUMBER: _ClassVar[int]
+ pubkey: bytes
+ lamports: int
+ owner: bytes
+ executable: bool
+ rent_epoch: int
+ data: bytes
+ write_version: int
+ txn_signature: bytes
+ def __init__(self, pubkey: _Optional[bytes] = ..., lamports: _Optional[int] = ..., owner: _Optional[bytes] = ..., executable: bool = ..., rent_epoch: _Optional[int] = ..., data: _Optional[bytes] = ..., write_version: _Optional[int] = ..., txn_signature: _Optional[bytes] = ...) -> None: ...
+
+class SubscribeUpdateSlot(_message.Message):
+ __slots__ = ("slot", "parent", "status", "dead_error")
+ SLOT_FIELD_NUMBER: _ClassVar[int]
+ PARENT_FIELD_NUMBER: _ClassVar[int]
+ STATUS_FIELD_NUMBER: _ClassVar[int]
+ DEAD_ERROR_FIELD_NUMBER: _ClassVar[int]
+ slot: int
+ parent: int
+ status: CommitmentLevel
+ dead_error: str
+ def __init__(self, slot: _Optional[int] = ..., parent: _Optional[int] = ..., status: _Optional[_Union[CommitmentLevel, str]] = ..., dead_error: _Optional[str] = ...) -> None: ...
+
+class SubscribeUpdateTransaction(_message.Message):
+ __slots__ = ("transaction", "slot")
+ TRANSACTION_FIELD_NUMBER: _ClassVar[int]
+ SLOT_FIELD_NUMBER: _ClassVar[int]
+ transaction: SubscribeUpdateTransactionInfo
+ slot: int
+ def __init__(self, transaction: _Optional[_Union[SubscribeUpdateTransactionInfo, _Mapping]] = ..., slot: _Optional[int] = ...) -> None: ...
+
+class SubscribeUpdateTransactionInfo(_message.Message):
+ __slots__ = ("signature", "is_vote", "transaction", "meta", "index")
+ SIGNATURE_FIELD_NUMBER: _ClassVar[int]
+ IS_VOTE_FIELD_NUMBER: _ClassVar[int]
+ TRANSACTION_FIELD_NUMBER: _ClassVar[int]
+ META_FIELD_NUMBER: _ClassVar[int]
+ INDEX_FIELD_NUMBER: _ClassVar[int]
+ signature: bytes
+ is_vote: bool
+ transaction: _solana_storage_pb2.Transaction
+ meta: _solana_storage_pb2.TransactionStatusMeta
+ index: int
+ def __init__(self, signature: _Optional[bytes] = ..., is_vote: bool = ..., transaction: _Optional[_Union[_solana_storage_pb2.Transaction, _Mapping]] = ..., meta: _Optional[_Union[_solana_storage_pb2.TransactionStatusMeta, _Mapping]] = ..., index: _Optional[int] = ...) -> None: ...
+
+class SubscribeUpdateTransactionStatus(_message.Message):
+ __slots__ = ("slot", "signature", "is_vote", "index", "err")
+ SLOT_FIELD_NUMBER: _ClassVar[int]
+ SIGNATURE_FIELD_NUMBER: _ClassVar[int]
+ IS_VOTE_FIELD_NUMBER: _ClassVar[int]
+ INDEX_FIELD_NUMBER: _ClassVar[int]
+ ERR_FIELD_NUMBER: _ClassVar[int]
+ slot: int
+ signature: bytes
+ is_vote: bool
+ index: int
+ err: _solana_storage_pb2.TransactionError
+ def __init__(self, slot: _Optional[int] = ..., signature: _Optional[bytes] = ..., is_vote: bool = ..., index: _Optional[int] = ..., err: _Optional[_Union[_solana_storage_pb2.TransactionError, _Mapping]] = ...) -> None: ...
+
+class SubscribeUpdateBlock(_message.Message):
+ __slots__ = ("slot", "blockhash", "rewards", "block_time", "block_height", "parent_slot", "parent_blockhash", "executed_transaction_count", "transactions", "updated_account_count", "accounts", "entries_count", "entries")
+ SLOT_FIELD_NUMBER: _ClassVar[int]
+ BLOCKHASH_FIELD_NUMBER: _ClassVar[int]
+ REWARDS_FIELD_NUMBER: _ClassVar[int]
+ BLOCK_TIME_FIELD_NUMBER: _ClassVar[int]
+ BLOCK_HEIGHT_FIELD_NUMBER: _ClassVar[int]
+ PARENT_SLOT_FIELD_NUMBER: _ClassVar[int]
+ PARENT_BLOCKHASH_FIELD_NUMBER: _ClassVar[int]
+ EXECUTED_TRANSACTION_COUNT_FIELD_NUMBER: _ClassVar[int]
+ TRANSACTIONS_FIELD_NUMBER: _ClassVar[int]
+ UPDATED_ACCOUNT_COUNT_FIELD_NUMBER: _ClassVar[int]
+ ACCOUNTS_FIELD_NUMBER: _ClassVar[int]
+ ENTRIES_COUNT_FIELD_NUMBER: _ClassVar[int]
+ ENTRIES_FIELD_NUMBER: _ClassVar[int]
+ slot: int
+ blockhash: str
+ rewards: _solana_storage_pb2.Rewards
+ block_time: _solana_storage_pb2.UnixTimestamp
+ block_height: _solana_storage_pb2.BlockHeight
+ parent_slot: int
+ parent_blockhash: str
+ executed_transaction_count: int
+ transactions: _containers.RepeatedCompositeFieldContainer[SubscribeUpdateTransactionInfo]
+ updated_account_count: int
+ accounts: _containers.RepeatedCompositeFieldContainer[SubscribeUpdateAccountInfo]
+ entries_count: int
+ entries: _containers.RepeatedCompositeFieldContainer[SubscribeUpdateEntry]
+ def __init__(self, slot: _Optional[int] = ..., blockhash: _Optional[str] = ..., rewards: _Optional[_Union[_solana_storage_pb2.Rewards, _Mapping]] = ..., block_time: _Optional[_Union[_solana_storage_pb2.UnixTimestamp, _Mapping]] = ..., block_height: _Optional[_Union[_solana_storage_pb2.BlockHeight, _Mapping]] = ..., parent_slot: _Optional[int] = ..., parent_blockhash: _Optional[str] = ..., executed_transaction_count: _Optional[int] = ..., transactions: _Optional[_Iterable[_Union[SubscribeUpdateTransactionInfo, _Mapping]]] = ..., updated_account_count: _Optional[int] = ..., accounts: _Optional[_Iterable[_Union[SubscribeUpdateAccountInfo, _Mapping]]] = ..., entries_count: _Optional[int] = ..., entries: _Optional[_Iterable[_Union[SubscribeUpdateEntry, _Mapping]]] = ...) -> None: ...
+
+class SubscribeUpdateBlockMeta(_message.Message):
+ __slots__ = ("slot", "blockhash", "rewards", "block_time", "block_height", "parent_slot", "parent_blockhash", "executed_transaction_count", "entries_count")
+ SLOT_FIELD_NUMBER: _ClassVar[int]
+ BLOCKHASH_FIELD_NUMBER: _ClassVar[int]
+ REWARDS_FIELD_NUMBER: _ClassVar[int]
+ BLOCK_TIME_FIELD_NUMBER: _ClassVar[int]
+ BLOCK_HEIGHT_FIELD_NUMBER: _ClassVar[int]
+ PARENT_SLOT_FIELD_NUMBER: _ClassVar[int]
+ PARENT_BLOCKHASH_FIELD_NUMBER: _ClassVar[int]
+ EXECUTED_TRANSACTION_COUNT_FIELD_NUMBER: _ClassVar[int]
+ ENTRIES_COUNT_FIELD_NUMBER: _ClassVar[int]
+ slot: int
+ blockhash: str
+ rewards: _solana_storage_pb2.Rewards
+ block_time: _solana_storage_pb2.UnixTimestamp
+ block_height: _solana_storage_pb2.BlockHeight
+ parent_slot: int
+ parent_blockhash: str
+ executed_transaction_count: int
+ entries_count: int
+ def __init__(self, slot: _Optional[int] = ..., blockhash: _Optional[str] = ..., rewards: _Optional[_Union[_solana_storage_pb2.Rewards, _Mapping]] = ..., block_time: _Optional[_Union[_solana_storage_pb2.UnixTimestamp, _Mapping]] = ..., block_height: _Optional[_Union[_solana_storage_pb2.BlockHeight, _Mapping]] = ..., parent_slot: _Optional[int] = ..., parent_blockhash: _Optional[str] = ..., executed_transaction_count: _Optional[int] = ..., entries_count: _Optional[int] = ...) -> None: ...
+
+class SubscribeUpdateEntry(_message.Message):
+ __slots__ = ("slot", "index", "num_hashes", "hash", "executed_transaction_count", "starting_transaction_index")
+ SLOT_FIELD_NUMBER: _ClassVar[int]
+ INDEX_FIELD_NUMBER: _ClassVar[int]
+ NUM_HASHES_FIELD_NUMBER: _ClassVar[int]
+ HASH_FIELD_NUMBER: _ClassVar[int]
+ EXECUTED_TRANSACTION_COUNT_FIELD_NUMBER: _ClassVar[int]
+ STARTING_TRANSACTION_INDEX_FIELD_NUMBER: _ClassVar[int]
+ slot: int
+ index: int
+ num_hashes: int
+ hash: bytes
+ executed_transaction_count: int
+ starting_transaction_index: int
+ def __init__(self, slot: _Optional[int] = ..., index: _Optional[int] = ..., num_hashes: _Optional[int] = ..., hash: _Optional[bytes] = ..., executed_transaction_count: _Optional[int] = ..., starting_transaction_index: _Optional[int] = ...) -> None: ...
+
+class SubscribeUpdatePing(_message.Message):
+ __slots__ = ()
+ def __init__(self) -> None: ...
+
+class SubscribeUpdatePong(_message.Message):
+ __slots__ = ("id",)
+ ID_FIELD_NUMBER: _ClassVar[int]
+ id: int
+ def __init__(self, id: _Optional[int] = ...) -> None: ...
+
+class PingRequest(_message.Message):
+ __slots__ = ("count",)
+ COUNT_FIELD_NUMBER: _ClassVar[int]
+ count: int
+ def __init__(self, count: _Optional[int] = ...) -> None: ...
+
+class PongResponse(_message.Message):
+ __slots__ = ("count",)
+ COUNT_FIELD_NUMBER: _ClassVar[int]
+ count: int
+ def __init__(self, count: _Optional[int] = ...) -> None: ...
+
+class GetLatestBlockhashRequest(_message.Message):
+ __slots__ = ("commitment",)
+ COMMITMENT_FIELD_NUMBER: _ClassVar[int]
+ commitment: CommitmentLevel
+ def __init__(self, commitment: _Optional[_Union[CommitmentLevel, str]] = ...) -> None: ...
+
+class GetLatestBlockhashResponse(_message.Message):
+ __slots__ = ("slot", "blockhash", "last_valid_block_height")
+ SLOT_FIELD_NUMBER: _ClassVar[int]
+ BLOCKHASH_FIELD_NUMBER: _ClassVar[int]
+ LAST_VALID_BLOCK_HEIGHT_FIELD_NUMBER: _ClassVar[int]
+ slot: int
+ blockhash: str
+ last_valid_block_height: int
+ def __init__(self, slot: _Optional[int] = ..., blockhash: _Optional[str] = ..., last_valid_block_height: _Optional[int] = ...) -> None: ...
+
+class GetBlockHeightRequest(_message.Message):
+ __slots__ = ("commitment",)
+ COMMITMENT_FIELD_NUMBER: _ClassVar[int]
+ commitment: CommitmentLevel
+ def __init__(self, commitment: _Optional[_Union[CommitmentLevel, str]] = ...) -> None: ...
+
+class GetBlockHeightResponse(_message.Message):
+ __slots__ = ("block_height",)
+ BLOCK_HEIGHT_FIELD_NUMBER: _ClassVar[int]
+ block_height: int
+ def __init__(self, block_height: _Optional[int] = ...) -> None: ...
+
+class GetSlotRequest(_message.Message):
+ __slots__ = ("commitment",)
+ COMMITMENT_FIELD_NUMBER: _ClassVar[int]
+ commitment: CommitmentLevel
+ def __init__(self, commitment: _Optional[_Union[CommitmentLevel, str]] = ...) -> None: ...
+
+class GetSlotResponse(_message.Message):
+ __slots__ = ("slot",)
+ SLOT_FIELD_NUMBER: _ClassVar[int]
+ slot: int
+ def __init__(self, slot: _Optional[int] = ...) -> None: ...
+
+class GetVersionRequest(_message.Message):
+ __slots__ = ()
+ def __init__(self) -> None: ...
+
+class GetVersionResponse(_message.Message):
+ __slots__ = ("version",)
+ VERSION_FIELD_NUMBER: _ClassVar[int]
+ version: str
+ def __init__(self, version: _Optional[str] = ...) -> None: ...
+
+class IsBlockhashValidRequest(_message.Message):
+ __slots__ = ("blockhash", "commitment")
+ BLOCKHASH_FIELD_NUMBER: _ClassVar[int]
+ COMMITMENT_FIELD_NUMBER: _ClassVar[int]
+ blockhash: str
+ commitment: CommitmentLevel
+ def __init__(self, blockhash: _Optional[str] = ..., commitment: _Optional[_Union[CommitmentLevel, str]] = ...) -> None: ...
+
+class IsBlockhashValidResponse(_message.Message):
+ __slots__ = ("slot", "valid")
+ SLOT_FIELD_NUMBER: _ClassVar[int]
+ VALID_FIELD_NUMBER: _ClassVar[int]
+ slot: int
+ valid: bool
+ def __init__(self, slot: _Optional[int] = ..., valid: bool = ...) -> None: ...
diff --git a/src/driftpy/accounts/grpc/geyser_codegen/geyser_pb2_grpc.py b/src/driftpy/accounts/grpc/geyser_codegen/geyser_pb2_grpc.py
new file mode 100644
index 00000000..c4d89408
--- /dev/null
+++ b/src/driftpy/accounts/grpc/geyser_codegen/geyser_pb2_grpc.py
@@ -0,0 +1,355 @@
+# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
+"""Client and server classes corresponding to protobuf-defined services."""
+import grpc
+import warnings
+
+import driftpy.accounts.grpc.geyser_codegen.geyser_pb2 as geyser__pb2
+
+GRPC_GENERATED_VERSION = '1.68.1'
+GRPC_VERSION = grpc.__version__
+_version_not_supported = False
+
+try:
+ from grpc._utilities import first_version_is_lower
+ _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION)
+except ImportError:
+ _version_not_supported = True
+
+if _version_not_supported:
+ raise RuntimeError(
+ f'The grpc package installed is at version {GRPC_VERSION},'
+ + f' but the generated code in geyser_pb2_grpc.py depends on'
+ + f' grpcio>={GRPC_GENERATED_VERSION}.'
+ + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}'
+ + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.'
+ )
+
+
+class GeyserStub(object):
+ """Missing associated documentation comment in .proto file."""
+
+ def __init__(self, channel):
+ """Constructor.
+
+ Args:
+ channel: A grpc.Channel.
+ """
+ self.Subscribe = channel.stream_stream(
+ '/geyser.Geyser/Subscribe',
+ request_serializer=geyser__pb2.SubscribeRequest.SerializeToString,
+ response_deserializer=geyser__pb2.SubscribeUpdate.FromString,
+ _registered_method=True)
+ self.Ping = channel.unary_unary(
+ '/geyser.Geyser/Ping',
+ request_serializer=geyser__pb2.PingRequest.SerializeToString,
+ response_deserializer=geyser__pb2.PongResponse.FromString,
+ _registered_method=True)
+ self.GetLatestBlockhash = channel.unary_unary(
+ '/geyser.Geyser/GetLatestBlockhash',
+ request_serializer=geyser__pb2.GetLatestBlockhashRequest.SerializeToString,
+ response_deserializer=geyser__pb2.GetLatestBlockhashResponse.FromString,
+ _registered_method=True)
+ self.GetBlockHeight = channel.unary_unary(
+ '/geyser.Geyser/GetBlockHeight',
+ request_serializer=geyser__pb2.GetBlockHeightRequest.SerializeToString,
+ response_deserializer=geyser__pb2.GetBlockHeightResponse.FromString,
+ _registered_method=True)
+ self.GetSlot = channel.unary_unary(
+ '/geyser.Geyser/GetSlot',
+ request_serializer=geyser__pb2.GetSlotRequest.SerializeToString,
+ response_deserializer=geyser__pb2.GetSlotResponse.FromString,
+ _registered_method=True)
+ self.IsBlockhashValid = channel.unary_unary(
+ '/geyser.Geyser/IsBlockhashValid',
+ request_serializer=geyser__pb2.IsBlockhashValidRequest.SerializeToString,
+ response_deserializer=geyser__pb2.IsBlockhashValidResponse.FromString,
+ _registered_method=True)
+ self.GetVersion = channel.unary_unary(
+ '/geyser.Geyser/GetVersion',
+ request_serializer=geyser__pb2.GetVersionRequest.SerializeToString,
+ response_deserializer=geyser__pb2.GetVersionResponse.FromString,
+ _registered_method=True)
+
+
+class GeyserServicer(object):
+ """Missing associated documentation comment in .proto file."""
+
+ def Subscribe(self, request_iterator, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def Ping(self, request, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def GetLatestBlockhash(self, request, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def GetBlockHeight(self, request, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def GetSlot(self, request, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def IsBlockhashValid(self, request, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+ def GetVersion(self, request, context):
+ """Missing associated documentation comment in .proto file."""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+
+def add_GeyserServicer_to_server(servicer, server):
+ rpc_method_handlers = {
+ 'Subscribe': grpc.stream_stream_rpc_method_handler(
+ servicer.Subscribe,
+ request_deserializer=geyser__pb2.SubscribeRequest.FromString,
+ response_serializer=geyser__pb2.SubscribeUpdate.SerializeToString,
+ ),
+ 'Ping': grpc.unary_unary_rpc_method_handler(
+ servicer.Ping,
+ request_deserializer=geyser__pb2.PingRequest.FromString,
+ response_serializer=geyser__pb2.PongResponse.SerializeToString,
+ ),
+ 'GetLatestBlockhash': grpc.unary_unary_rpc_method_handler(
+ servicer.GetLatestBlockhash,
+ request_deserializer=geyser__pb2.GetLatestBlockhashRequest.FromString,
+ response_serializer=geyser__pb2.GetLatestBlockhashResponse.SerializeToString,
+ ),
+ 'GetBlockHeight': grpc.unary_unary_rpc_method_handler(
+ servicer.GetBlockHeight,
+ request_deserializer=geyser__pb2.GetBlockHeightRequest.FromString,
+ response_serializer=geyser__pb2.GetBlockHeightResponse.SerializeToString,
+ ),
+ 'GetSlot': grpc.unary_unary_rpc_method_handler(
+ servicer.GetSlot,
+ request_deserializer=geyser__pb2.GetSlotRequest.FromString,
+ response_serializer=geyser__pb2.GetSlotResponse.SerializeToString,
+ ),
+ 'IsBlockhashValid': grpc.unary_unary_rpc_method_handler(
+ servicer.IsBlockhashValid,
+ request_deserializer=geyser__pb2.IsBlockhashValidRequest.FromString,
+ response_serializer=geyser__pb2.IsBlockhashValidResponse.SerializeToString,
+ ),
+ 'GetVersion': grpc.unary_unary_rpc_method_handler(
+ servicer.GetVersion,
+ request_deserializer=geyser__pb2.GetVersionRequest.FromString,
+ response_serializer=geyser__pb2.GetVersionResponse.SerializeToString,
+ ),
+ }
+ generic_handler = grpc.method_handlers_generic_handler(
+ 'geyser.Geyser', rpc_method_handlers)
+ server.add_generic_rpc_handlers((generic_handler,))
+ server.add_registered_method_handlers('geyser.Geyser', rpc_method_handlers)
+
+
+ # This class is part of an EXPERIMENTAL API.
+class Geyser(object):
+ """Missing associated documentation comment in .proto file."""
+
+ @staticmethod
+ def Subscribe(request_iterator,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.stream_stream(
+ request_iterator,
+ target,
+ '/geyser.Geyser/Subscribe',
+ geyser__pb2.SubscribeRequest.SerializeToString,
+ geyser__pb2.SubscribeUpdate.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
+
+ @staticmethod
+ def Ping(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(
+ request,
+ target,
+ '/geyser.Geyser/Ping',
+ geyser__pb2.PingRequest.SerializeToString,
+ geyser__pb2.PongResponse.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
+
+ @staticmethod
+ def GetLatestBlockhash(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(
+ request,
+ target,
+ '/geyser.Geyser/GetLatestBlockhash',
+ geyser__pb2.GetLatestBlockhashRequest.SerializeToString,
+ geyser__pb2.GetLatestBlockhashResponse.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
+
+ @staticmethod
+ def GetBlockHeight(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(
+ request,
+ target,
+ '/geyser.Geyser/GetBlockHeight',
+ geyser__pb2.GetBlockHeightRequest.SerializeToString,
+ geyser__pb2.GetBlockHeightResponse.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
+
+ @staticmethod
+ def GetSlot(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(
+ request,
+ target,
+ '/geyser.Geyser/GetSlot',
+ geyser__pb2.GetSlotRequest.SerializeToString,
+ geyser__pb2.GetSlotResponse.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
+
+ @staticmethod
+ def IsBlockhashValid(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(
+ request,
+ target,
+ '/geyser.Geyser/IsBlockhashValid',
+ geyser__pb2.IsBlockhashValidRequest.SerializeToString,
+ geyser__pb2.IsBlockhashValidResponse.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
+
+ @staticmethod
+ def GetVersion(request,
+ target,
+ options=(),
+ channel_credentials=None,
+ call_credentials=None,
+ insecure=False,
+ compression=None,
+ wait_for_ready=None,
+ timeout=None,
+ metadata=None):
+ return grpc.experimental.unary_unary(
+ request,
+ target,
+ '/geyser.Geyser/GetVersion',
+ geyser__pb2.GetVersionRequest.SerializeToString,
+ geyser__pb2.GetVersionResponse.FromString,
+ options,
+ channel_credentials,
+ insecure,
+ call_credentials,
+ compression,
+ wait_for_ready,
+ timeout,
+ metadata,
+ _registered_method=True)
diff --git a/src/driftpy/accounts/grpc/geyser_codegen/solana_storage_pb2.py b/src/driftpy/accounts/grpc/geyser_codegen/solana_storage_pb2.py
new file mode 100644
index 00000000..f4349867
--- /dev/null
+++ b/src/driftpy/accounts/grpc/geyser_codegen/solana_storage_pb2.py
@@ -0,0 +1,75 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: solana-storage.proto
+# Protobuf Python Version: 5.28.1
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 28,
+ 1,
+ '',
+ 'solana-storage.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14solana-storage.proto\x12\x1dsolana.storage.ConfirmedBlock\"\xa1\x03\n\x0e\x43onfirmedBlock\x12\x1a\n\x12previous_blockhash\x18\x01 \x01(\t\x12\x11\n\tblockhash\x18\x02 \x01(\t\x12\x13\n\x0bparent_slot\x18\x03 \x01(\x04\x12I\n\x0ctransactions\x18\x04 \x03(\x0b\x32\x33.solana.storage.ConfirmedBlock.ConfirmedTransaction\x12\x36\n\x07rewards\x18\x05 \x03(\x0b\x32%.solana.storage.ConfirmedBlock.Reward\x12@\n\nblock_time\x18\x06 \x01(\x0b\x32,.solana.storage.ConfirmedBlock.UnixTimestamp\x12@\n\x0c\x62lock_height\x18\x07 \x01(\x0b\x32*.solana.storage.ConfirmedBlock.BlockHeight\x12\x44\n\x0enum_partitions\x18\x08 \x01(\x0b\x32,.solana.storage.ConfirmedBlock.NumPartitions\"\x9b\x01\n\x14\x43onfirmedTransaction\x12?\n\x0btransaction\x18\x01 \x01(\x0b\x32*.solana.storage.ConfirmedBlock.Transaction\x12\x42\n\x04meta\x18\x02 \x01(\x0b\x32\x34.solana.storage.ConfirmedBlock.TransactionStatusMeta\"Z\n\x0bTransaction\x12\x12\n\nsignatures\x18\x01 \x03(\x0c\x12\x37\n\x07message\x18\x02 \x01(\x0b\x32&.solana.storage.ConfirmedBlock.Message\"\xad\x02\n\x07Message\x12<\n\x06header\x18\x01 \x01(\x0b\x32,.solana.storage.ConfirmedBlock.MessageHeader\x12\x14\n\x0c\x61\x63\x63ount_keys\x18\x02 \x03(\x0c\x12\x18\n\x10recent_blockhash\x18\x03 \x01(\x0c\x12H\n\x0cinstructions\x18\x04 \x03(\x0b\x32\x32.solana.storage.ConfirmedBlock.CompiledInstruction\x12\x11\n\tversioned\x18\x05 \x01(\x08\x12W\n\x15\x61\x64\x64ress_table_lookups\x18\x06 \x03(\x0b\x32\x38.solana.storage.ConfirmedBlock.MessageAddressTableLookup\"~\n\rMessageHeader\x12\x1f\n\x17num_required_signatures\x18\x01 \x01(\r\x12$\n\x1cnum_readonly_signed_accounts\x18\x02 \x01(\r\x12&\n\x1enum_readonly_unsigned_accounts\x18\x03 \x01(\r\"d\n\x19MessageAddressTableLookup\x12\x13\n\x0b\x61\x63\x63ount_key\x18\x01 \x01(\x0c\x12\x18\n\x10writable_indexes\x18\x02 \x01(\x0c\x12\x18\n\x10readonly_indexes\x18\x03 \x01(\x0c\"\xda\x05\n\x15TransactionStatusMeta\x12<\n\x03\x65rr\x18\x01 \x01(\x0b\x32/.solana.storage.ConfirmedBlock.TransactionError\x12\x0b\n\x03\x66\x65\x65\x18\x02 \x01(\x04\x12\x14\n\x0cpre_balances\x18\x03 \x03(\x04\x12\x15\n\rpost_balances\x18\x04 \x03(\x04\x12L\n\x12inner_instructions\x18\x05 \x03(\x0b\x32\x30.solana.storage.ConfirmedBlock.InnerInstructions\x12\x1f\n\x17inner_instructions_none\x18\n \x01(\x08\x12\x14\n\x0clog_messages\x18\x06 \x03(\t\x12\x19\n\x11log_messages_none\x18\x0b \x01(\x08\x12G\n\x12pre_token_balances\x18\x07 \x03(\x0b\x32+.solana.storage.ConfirmedBlock.TokenBalance\x12H\n\x13post_token_balances\x18\x08 \x03(\x0b\x32+.solana.storage.ConfirmedBlock.TokenBalance\x12\x36\n\x07rewards\x18\t \x03(\x0b\x32%.solana.storage.ConfirmedBlock.Reward\x12!\n\x19loaded_writable_addresses\x18\x0c \x03(\x0c\x12!\n\x19loaded_readonly_addresses\x18\r \x03(\x0c\x12>\n\x0breturn_data\x18\x0e \x01(\x0b\x32).solana.storage.ConfirmedBlock.ReturnData\x12\x18\n\x10return_data_none\x18\x0f \x01(\x08\x12#\n\x16\x63ompute_units_consumed\x18\x10 \x01(\x04H\x00\x88\x01\x01\x42\x19\n\x17_compute_units_consumed\"\x1f\n\x10TransactionError\x12\x0b\n\x03\x65rr\x18\x01 \x01(\x0c\"i\n\x11InnerInstructions\x12\r\n\x05index\x18\x01 \x01(\r\x12\x45\n\x0cinstructions\x18\x02 \x03(\x0b\x32/.solana.storage.ConfirmedBlock.InnerInstruction\"x\n\x10InnerInstruction\x12\x18\n\x10program_id_index\x18\x01 \x01(\r\x12\x10\n\x08\x61\x63\x63ounts\x18\x02 \x01(\x0c\x12\x0c\n\x04\x64\x61ta\x18\x03 \x01(\x0c\x12\x19\n\x0cstack_height\x18\x04 \x01(\rH\x00\x88\x01\x01\x42\x0f\n\r_stack_height\"O\n\x13\x43ompiledInstruction\x12\x18\n\x10program_id_index\x18\x01 \x01(\r\x12\x10\n\x08\x61\x63\x63ounts\x18\x02 \x01(\x0c\x12\x0c\n\x04\x64\x61ta\x18\x03 \x01(\x0c\"\x9d\x01\n\x0cTokenBalance\x12\x15\n\raccount_index\x18\x01 \x01(\r\x12\x0c\n\x04mint\x18\x02 \x01(\t\x12\x45\n\x0fui_token_amount\x18\x03 \x01(\x0b\x32,.solana.storage.ConfirmedBlock.UiTokenAmount\x12\r\n\x05owner\x18\x04 \x01(\t\x12\x12\n\nprogram_id\x18\x05 \x01(\t\"^\n\rUiTokenAmount\x12\x11\n\tui_amount\x18\x01 \x01(\x01\x12\x10\n\x08\x64\x65\x63imals\x18\x02 \x01(\r\x12\x0e\n\x06\x61mount\x18\x03 \x01(\t\x12\x18\n\x10ui_amount_string\x18\x04 \x01(\t\".\n\nReturnData\x12\x12\n\nprogram_id\x18\x01 \x01(\x0c\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\"\x94\x01\n\x06Reward\x12\x0e\n\x06pubkey\x18\x01 \x01(\t\x12\x10\n\x08lamports\x18\x02 \x01(\x03\x12\x14\n\x0cpost_balance\x18\x03 \x01(\x04\x12>\n\x0breward_type\x18\x04 \x01(\x0e\x32).solana.storage.ConfirmedBlock.RewardType\x12\x12\n\ncommission\x18\x05 \x01(\t\"\x87\x01\n\x07Rewards\x12\x36\n\x07rewards\x18\x01 \x03(\x0b\x32%.solana.storage.ConfirmedBlock.Reward\x12\x44\n\x0enum_partitions\x18\x02 \x01(\x0b\x32,.solana.storage.ConfirmedBlock.NumPartitions\"\"\n\rUnixTimestamp\x12\x11\n\ttimestamp\x18\x01 \x01(\x03\"#\n\x0b\x42lockHeight\x12\x14\n\x0c\x62lock_height\x18\x01 \x01(\x04\"\'\n\rNumPartitions\x12\x16\n\x0enum_partitions\x18\x01 \x01(\x04*I\n\nRewardType\x12\x0f\n\x0bUnspecified\x10\x00\x12\x07\n\x03\x46\x65\x65\x10\x01\x12\x08\n\x04Rent\x10\x02\x12\x0b\n\x07Staking\x10\x03\x12\n\n\x06Voting\x10\x04\x42;Z9github.com/rpcpool/yellowstone-grpc/examples/golang/protob\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'solana_storage_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'Z9github.com/rpcpool/yellowstone-grpc/examples/golang/proto'
+ _globals['_REWARDTYPE']._serialized_start=3042
+ _globals['_REWARDTYPE']._serialized_end=3115
+ _globals['_CONFIRMEDBLOCK']._serialized_start=56
+ _globals['_CONFIRMEDBLOCK']._serialized_end=473
+ _globals['_CONFIRMEDTRANSACTION']._serialized_start=476
+ _globals['_CONFIRMEDTRANSACTION']._serialized_end=631
+ _globals['_TRANSACTION']._serialized_start=633
+ _globals['_TRANSACTION']._serialized_end=723
+ _globals['_MESSAGE']._serialized_start=726
+ _globals['_MESSAGE']._serialized_end=1027
+ _globals['_MESSAGEHEADER']._serialized_start=1029
+ _globals['_MESSAGEHEADER']._serialized_end=1155
+ _globals['_MESSAGEADDRESSTABLELOOKUP']._serialized_start=1157
+ _globals['_MESSAGEADDRESSTABLELOOKUP']._serialized_end=1257
+ _globals['_TRANSACTIONSTATUSMETA']._serialized_start=1260
+ _globals['_TRANSACTIONSTATUSMETA']._serialized_end=1990
+ _globals['_TRANSACTIONERROR']._serialized_start=1992
+ _globals['_TRANSACTIONERROR']._serialized_end=2023
+ _globals['_INNERINSTRUCTIONS']._serialized_start=2025
+ _globals['_INNERINSTRUCTIONS']._serialized_end=2130
+ _globals['_INNERINSTRUCTION']._serialized_start=2132
+ _globals['_INNERINSTRUCTION']._serialized_end=2252
+ _globals['_COMPILEDINSTRUCTION']._serialized_start=2254
+ _globals['_COMPILEDINSTRUCTION']._serialized_end=2333
+ _globals['_TOKENBALANCE']._serialized_start=2336
+ _globals['_TOKENBALANCE']._serialized_end=2493
+ _globals['_UITOKENAMOUNT']._serialized_start=2495
+ _globals['_UITOKENAMOUNT']._serialized_end=2589
+ _globals['_RETURNDATA']._serialized_start=2591
+ _globals['_RETURNDATA']._serialized_end=2637
+ _globals['_REWARD']._serialized_start=2640
+ _globals['_REWARD']._serialized_end=2788
+ _globals['_REWARDS']._serialized_start=2791
+ _globals['_REWARDS']._serialized_end=2926
+ _globals['_UNIXTIMESTAMP']._serialized_start=2928
+ _globals['_UNIXTIMESTAMP']._serialized_end=2962
+ _globals['_BLOCKHEIGHT']._serialized_start=2964
+ _globals['_BLOCKHEIGHT']._serialized_end=2999
+ _globals['_NUMPARTITIONS']._serialized_start=3001
+ _globals['_NUMPARTITIONS']._serialized_end=3040
+# @@protoc_insertion_point(module_scope)
diff --git a/src/driftpy/accounts/grpc/geyser_codegen/solana_storage_pb2.pyi b/src/driftpy/accounts/grpc/geyser_codegen/solana_storage_pb2.pyi
new file mode 100644
index 00000000..10312a60
--- /dev/null
+++ b/src/driftpy/accounts/grpc/geyser_codegen/solana_storage_pb2.pyi
@@ -0,0 +1,238 @@
+from google.protobuf.internal import containers as _containers
+from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import message as _message
+from typing import ClassVar as _ClassVar, Iterable as _Iterable, Mapping as _Mapping, Optional as _Optional, Union as _Union
+
+DESCRIPTOR: _descriptor.FileDescriptor
+
+class RewardType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
+ __slots__ = ()
+ Unspecified: _ClassVar[RewardType]
+ Fee: _ClassVar[RewardType]
+ Rent: _ClassVar[RewardType]
+ Staking: _ClassVar[RewardType]
+ Voting: _ClassVar[RewardType]
+Unspecified: RewardType
+Fee: RewardType
+Rent: RewardType
+Staking: RewardType
+Voting: RewardType
+
+class ConfirmedBlock(_message.Message):
+ __slots__ = ("previous_blockhash", "blockhash", "parent_slot", "transactions", "rewards", "block_time", "block_height", "num_partitions")
+ PREVIOUS_BLOCKHASH_FIELD_NUMBER: _ClassVar[int]
+ BLOCKHASH_FIELD_NUMBER: _ClassVar[int]
+ PARENT_SLOT_FIELD_NUMBER: _ClassVar[int]
+ TRANSACTIONS_FIELD_NUMBER: _ClassVar[int]
+ REWARDS_FIELD_NUMBER: _ClassVar[int]
+ BLOCK_TIME_FIELD_NUMBER: _ClassVar[int]
+ BLOCK_HEIGHT_FIELD_NUMBER: _ClassVar[int]
+ NUM_PARTITIONS_FIELD_NUMBER: _ClassVar[int]
+ previous_blockhash: str
+ blockhash: str
+ parent_slot: int
+ transactions: _containers.RepeatedCompositeFieldContainer[ConfirmedTransaction]
+ rewards: _containers.RepeatedCompositeFieldContainer[Reward]
+ block_time: UnixTimestamp
+ block_height: BlockHeight
+ num_partitions: NumPartitions
+ def __init__(self, previous_blockhash: _Optional[str] = ..., blockhash: _Optional[str] = ..., parent_slot: _Optional[int] = ..., transactions: _Optional[_Iterable[_Union[ConfirmedTransaction, _Mapping]]] = ..., rewards: _Optional[_Iterable[_Union[Reward, _Mapping]]] = ..., block_time: _Optional[_Union[UnixTimestamp, _Mapping]] = ..., block_height: _Optional[_Union[BlockHeight, _Mapping]] = ..., num_partitions: _Optional[_Union[NumPartitions, _Mapping]] = ...) -> None: ...
+
+class ConfirmedTransaction(_message.Message):
+ __slots__ = ("transaction", "meta")
+ TRANSACTION_FIELD_NUMBER: _ClassVar[int]
+ META_FIELD_NUMBER: _ClassVar[int]
+ transaction: Transaction
+ meta: TransactionStatusMeta
+ def __init__(self, transaction: _Optional[_Union[Transaction, _Mapping]] = ..., meta: _Optional[_Union[TransactionStatusMeta, _Mapping]] = ...) -> None: ...
+
+class Transaction(_message.Message):
+ __slots__ = ("signatures", "message")
+ SIGNATURES_FIELD_NUMBER: _ClassVar[int]
+ MESSAGE_FIELD_NUMBER: _ClassVar[int]
+ signatures: _containers.RepeatedScalarFieldContainer[bytes]
+ message: Message
+ def __init__(self, signatures: _Optional[_Iterable[bytes]] = ..., message: _Optional[_Union[Message, _Mapping]] = ...) -> None: ...
+
+class Message(_message.Message):
+ __slots__ = ("header", "account_keys", "recent_blockhash", "instructions", "versioned", "address_table_lookups")
+ HEADER_FIELD_NUMBER: _ClassVar[int]
+ ACCOUNT_KEYS_FIELD_NUMBER: _ClassVar[int]
+ RECENT_BLOCKHASH_FIELD_NUMBER: _ClassVar[int]
+ INSTRUCTIONS_FIELD_NUMBER: _ClassVar[int]
+ VERSIONED_FIELD_NUMBER: _ClassVar[int]
+ ADDRESS_TABLE_LOOKUPS_FIELD_NUMBER: _ClassVar[int]
+ header: MessageHeader
+ account_keys: _containers.RepeatedScalarFieldContainer[bytes]
+ recent_blockhash: bytes
+ instructions: _containers.RepeatedCompositeFieldContainer[CompiledInstruction]
+ versioned: bool
+ address_table_lookups: _containers.RepeatedCompositeFieldContainer[MessageAddressTableLookup]
+ def __init__(self, header: _Optional[_Union[MessageHeader, _Mapping]] = ..., account_keys: _Optional[_Iterable[bytes]] = ..., recent_blockhash: _Optional[bytes] = ..., instructions: _Optional[_Iterable[_Union[CompiledInstruction, _Mapping]]] = ..., versioned: bool = ..., address_table_lookups: _Optional[_Iterable[_Union[MessageAddressTableLookup, _Mapping]]] = ...) -> None: ...
+
+class MessageHeader(_message.Message):
+ __slots__ = ("num_required_signatures", "num_readonly_signed_accounts", "num_readonly_unsigned_accounts")
+ NUM_REQUIRED_SIGNATURES_FIELD_NUMBER: _ClassVar[int]
+ NUM_READONLY_SIGNED_ACCOUNTS_FIELD_NUMBER: _ClassVar[int]
+ NUM_READONLY_UNSIGNED_ACCOUNTS_FIELD_NUMBER: _ClassVar[int]
+ num_required_signatures: int
+ num_readonly_signed_accounts: int
+ num_readonly_unsigned_accounts: int
+ def __init__(self, num_required_signatures: _Optional[int] = ..., num_readonly_signed_accounts: _Optional[int] = ..., num_readonly_unsigned_accounts: _Optional[int] = ...) -> None: ...
+
+class MessageAddressTableLookup(_message.Message):
+ __slots__ = ("account_key", "writable_indexes", "readonly_indexes")
+ ACCOUNT_KEY_FIELD_NUMBER: _ClassVar[int]
+ WRITABLE_INDEXES_FIELD_NUMBER: _ClassVar[int]
+ READONLY_INDEXES_FIELD_NUMBER: _ClassVar[int]
+ account_key: bytes
+ writable_indexes: bytes
+ readonly_indexes: bytes
+ def __init__(self, account_key: _Optional[bytes] = ..., writable_indexes: _Optional[bytes] = ..., readonly_indexes: _Optional[bytes] = ...) -> None: ...
+
+class TransactionStatusMeta(_message.Message):
+ __slots__ = ("err", "fee", "pre_balances", "post_balances", "inner_instructions", "inner_instructions_none", "log_messages", "log_messages_none", "pre_token_balances", "post_token_balances", "rewards", "loaded_writable_addresses", "loaded_readonly_addresses", "return_data", "return_data_none", "compute_units_consumed")
+ ERR_FIELD_NUMBER: _ClassVar[int]
+ FEE_FIELD_NUMBER: _ClassVar[int]
+ PRE_BALANCES_FIELD_NUMBER: _ClassVar[int]
+ POST_BALANCES_FIELD_NUMBER: _ClassVar[int]
+ INNER_INSTRUCTIONS_FIELD_NUMBER: _ClassVar[int]
+ INNER_INSTRUCTIONS_NONE_FIELD_NUMBER: _ClassVar[int]
+ LOG_MESSAGES_FIELD_NUMBER: _ClassVar[int]
+ LOG_MESSAGES_NONE_FIELD_NUMBER: _ClassVar[int]
+ PRE_TOKEN_BALANCES_FIELD_NUMBER: _ClassVar[int]
+ POST_TOKEN_BALANCES_FIELD_NUMBER: _ClassVar[int]
+ REWARDS_FIELD_NUMBER: _ClassVar[int]
+ LOADED_WRITABLE_ADDRESSES_FIELD_NUMBER: _ClassVar[int]
+ LOADED_READONLY_ADDRESSES_FIELD_NUMBER: _ClassVar[int]
+ RETURN_DATA_FIELD_NUMBER: _ClassVar[int]
+ RETURN_DATA_NONE_FIELD_NUMBER: _ClassVar[int]
+ COMPUTE_UNITS_CONSUMED_FIELD_NUMBER: _ClassVar[int]
+ err: TransactionError
+ fee: int
+ pre_balances: _containers.RepeatedScalarFieldContainer[int]
+ post_balances: _containers.RepeatedScalarFieldContainer[int]
+ inner_instructions: _containers.RepeatedCompositeFieldContainer[InnerInstructions]
+ inner_instructions_none: bool
+ log_messages: _containers.RepeatedScalarFieldContainer[str]
+ log_messages_none: bool
+ pre_token_balances: _containers.RepeatedCompositeFieldContainer[TokenBalance]
+ post_token_balances: _containers.RepeatedCompositeFieldContainer[TokenBalance]
+ rewards: _containers.RepeatedCompositeFieldContainer[Reward]
+ loaded_writable_addresses: _containers.RepeatedScalarFieldContainer[bytes]
+ loaded_readonly_addresses: _containers.RepeatedScalarFieldContainer[bytes]
+ return_data: ReturnData
+ return_data_none: bool
+ compute_units_consumed: int
+ def __init__(self, err: _Optional[_Union[TransactionError, _Mapping]] = ..., fee: _Optional[int] = ..., pre_balances: _Optional[_Iterable[int]] = ..., post_balances: _Optional[_Iterable[int]] = ..., inner_instructions: _Optional[_Iterable[_Union[InnerInstructions, _Mapping]]] = ..., inner_instructions_none: bool = ..., log_messages: _Optional[_Iterable[str]] = ..., log_messages_none: bool = ..., pre_token_balances: _Optional[_Iterable[_Union[TokenBalance, _Mapping]]] = ..., post_token_balances: _Optional[_Iterable[_Union[TokenBalance, _Mapping]]] = ..., rewards: _Optional[_Iterable[_Union[Reward, _Mapping]]] = ..., loaded_writable_addresses: _Optional[_Iterable[bytes]] = ..., loaded_readonly_addresses: _Optional[_Iterable[bytes]] = ..., return_data: _Optional[_Union[ReturnData, _Mapping]] = ..., return_data_none: bool = ..., compute_units_consumed: _Optional[int] = ...) -> None: ...
+
+class TransactionError(_message.Message):
+ __slots__ = ("err",)
+ ERR_FIELD_NUMBER: _ClassVar[int]
+ err: bytes
+ def __init__(self, err: _Optional[bytes] = ...) -> None: ...
+
+class InnerInstructions(_message.Message):
+ __slots__ = ("index", "instructions")
+ INDEX_FIELD_NUMBER: _ClassVar[int]
+ INSTRUCTIONS_FIELD_NUMBER: _ClassVar[int]
+ index: int
+ instructions: _containers.RepeatedCompositeFieldContainer[InnerInstruction]
+ def __init__(self, index: _Optional[int] = ..., instructions: _Optional[_Iterable[_Union[InnerInstruction, _Mapping]]] = ...) -> None: ...
+
+class InnerInstruction(_message.Message):
+ __slots__ = ("program_id_index", "accounts", "data", "stack_height")
+ PROGRAM_ID_INDEX_FIELD_NUMBER: _ClassVar[int]
+ ACCOUNTS_FIELD_NUMBER: _ClassVar[int]
+ DATA_FIELD_NUMBER: _ClassVar[int]
+ STACK_HEIGHT_FIELD_NUMBER: _ClassVar[int]
+ program_id_index: int
+ accounts: bytes
+ data: bytes
+ stack_height: int
+ def __init__(self, program_id_index: _Optional[int] = ..., accounts: _Optional[bytes] = ..., data: _Optional[bytes] = ..., stack_height: _Optional[int] = ...) -> None: ...
+
+class CompiledInstruction(_message.Message):
+ __slots__ = ("program_id_index", "accounts", "data")
+ PROGRAM_ID_INDEX_FIELD_NUMBER: _ClassVar[int]
+ ACCOUNTS_FIELD_NUMBER: _ClassVar[int]
+ DATA_FIELD_NUMBER: _ClassVar[int]
+ program_id_index: int
+ accounts: bytes
+ data: bytes
+ def __init__(self, program_id_index: _Optional[int] = ..., accounts: _Optional[bytes] = ..., data: _Optional[bytes] = ...) -> None: ...
+
+class TokenBalance(_message.Message):
+ __slots__ = ("account_index", "mint", "ui_token_amount", "owner", "program_id")
+ ACCOUNT_INDEX_FIELD_NUMBER: _ClassVar[int]
+ MINT_FIELD_NUMBER: _ClassVar[int]
+ UI_TOKEN_AMOUNT_FIELD_NUMBER: _ClassVar[int]
+ OWNER_FIELD_NUMBER: _ClassVar[int]
+ PROGRAM_ID_FIELD_NUMBER: _ClassVar[int]
+ account_index: int
+ mint: str
+ ui_token_amount: UiTokenAmount
+ owner: str
+ program_id: str
+ def __init__(self, account_index: _Optional[int] = ..., mint: _Optional[str] = ..., ui_token_amount: _Optional[_Union[UiTokenAmount, _Mapping]] = ..., owner: _Optional[str] = ..., program_id: _Optional[str] = ...) -> None: ...
+
+class UiTokenAmount(_message.Message):
+ __slots__ = ("ui_amount", "decimals", "amount", "ui_amount_string")
+ UI_AMOUNT_FIELD_NUMBER: _ClassVar[int]
+ DECIMALS_FIELD_NUMBER: _ClassVar[int]
+ AMOUNT_FIELD_NUMBER: _ClassVar[int]
+ UI_AMOUNT_STRING_FIELD_NUMBER: _ClassVar[int]
+ ui_amount: float
+ decimals: int
+ amount: str
+ ui_amount_string: str
+ def __init__(self, ui_amount: _Optional[float] = ..., decimals: _Optional[int] = ..., amount: _Optional[str] = ..., ui_amount_string: _Optional[str] = ...) -> None: ...
+
+class ReturnData(_message.Message):
+ __slots__ = ("program_id", "data")
+ PROGRAM_ID_FIELD_NUMBER: _ClassVar[int]
+ DATA_FIELD_NUMBER: _ClassVar[int]
+ program_id: bytes
+ data: bytes
+ def __init__(self, program_id: _Optional[bytes] = ..., data: _Optional[bytes] = ...) -> None: ...
+
+class Reward(_message.Message):
+ __slots__ = ("pubkey", "lamports", "post_balance", "reward_type", "commission")
+ PUBKEY_FIELD_NUMBER: _ClassVar[int]
+ LAMPORTS_FIELD_NUMBER: _ClassVar[int]
+ POST_BALANCE_FIELD_NUMBER: _ClassVar[int]
+ REWARD_TYPE_FIELD_NUMBER: _ClassVar[int]
+ COMMISSION_FIELD_NUMBER: _ClassVar[int]
+ pubkey: str
+ lamports: int
+ post_balance: int
+ reward_type: RewardType
+ commission: str
+ def __init__(self, pubkey: _Optional[str] = ..., lamports: _Optional[int] = ..., post_balance: _Optional[int] = ..., reward_type: _Optional[_Union[RewardType, str]] = ..., commission: _Optional[str] = ...) -> None: ...
+
+class Rewards(_message.Message):
+ __slots__ = ("rewards", "num_partitions")
+ REWARDS_FIELD_NUMBER: _ClassVar[int]
+ NUM_PARTITIONS_FIELD_NUMBER: _ClassVar[int]
+ rewards: _containers.RepeatedCompositeFieldContainer[Reward]
+ num_partitions: NumPartitions
+ def __init__(self, rewards: _Optional[_Iterable[_Union[Reward, _Mapping]]] = ..., num_partitions: _Optional[_Union[NumPartitions, _Mapping]] = ...) -> None: ...
+
+class UnixTimestamp(_message.Message):
+ __slots__ = ("timestamp",)
+ TIMESTAMP_FIELD_NUMBER: _ClassVar[int]
+ timestamp: int
+ def __init__(self, timestamp: _Optional[int] = ...) -> None: ...
+
+class BlockHeight(_message.Message):
+ __slots__ = ("block_height",)
+ BLOCK_HEIGHT_FIELD_NUMBER: _ClassVar[int]
+ block_height: int
+ def __init__(self, block_height: _Optional[int] = ...) -> None: ...
+
+class NumPartitions(_message.Message):
+ __slots__ = ("num_partitions",)
+ NUM_PARTITIONS_FIELD_NUMBER: _ClassVar[int]
+ num_partitions: int
+ def __init__(self, num_partitions: _Optional[int] = ...) -> None: ...
diff --git a/src/driftpy/accounts/grpc/geyser_codegen/solana_storage_pb2_grpc.py b/src/driftpy/accounts/grpc/geyser_codegen/solana_storage_pb2_grpc.py
new file mode 100644
index 00000000..a777633a
--- /dev/null
+++ b/src/driftpy/accounts/grpc/geyser_codegen/solana_storage_pb2_grpc.py
@@ -0,0 +1,24 @@
+# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
+"""Client and server classes corresponding to protobuf-defined services."""
+import grpc
+import warnings
+
+
+GRPC_GENERATED_VERSION = '1.68.1'
+GRPC_VERSION = grpc.__version__
+_version_not_supported = False
+
+try:
+ from grpc._utilities import first_version_is_lower
+ _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION)
+except ImportError:
+ _version_not_supported = True
+
+if _version_not_supported:
+ raise RuntimeError(
+ f'The grpc package installed is at version {GRPC_VERSION},'
+ + f' but the generated code in solana_storage_pb2_grpc.py depends on'
+ + f' grpcio>={GRPC_GENERATED_VERSION}.'
+ + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}'
+ + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.'
+ )
diff --git a/src/driftpy/accounts/grpc/geyser_codegen/subscribe_geyser.py b/src/driftpy/accounts/grpc/geyser_codegen/subscribe_geyser.py
new file mode 100644
index 00000000..a2ea6d18
--- /dev/null
+++ b/src/driftpy/accounts/grpc/geyser_codegen/subscribe_geyser.py
@@ -0,0 +1,106 @@
+import logging
+import os
+import time
+from typing import Iterator, Optional
+
+import geyser_pb2
+import geyser_pb2_grpc
+import grpc
+
+
+def _triton_sign_request(
+ callback: grpc.AuthMetadataPluginCallback,
+ x_token: Optional[str],
+ error: Optional[Exception],
+):
+ metadata = (("x-token", x_token),)
+ return callback(metadata, error)
+
+
+class TritonAuthMetadataPlugin(grpc.AuthMetadataPlugin):
+ def __init__(self, x_token: str):
+ self.x_token = x_token
+
+ def __call__(
+ self,
+ context: grpc.AuthMetadataContext,
+ callback: grpc.AuthMetadataPluginCallback,
+ ):
+ return _triton_sign_request(callback, self.x_token, None)
+
+
+def create_subscribe_request() -> Iterator[geyser_pb2.SubscribeRequest]:
+ request = geyser_pb2.SubscribeRequest()
+
+ # Create the account filter
+ account_filter = geyser_pb2.SubscribeRequestFilterAccounts()
+
+ # Add a specific account to monitor
+ # Note: This needs to be the base58 encoded public key
+ account_filter.account.append("dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH")
+ account_filter.account.append("DRiP8pChV3hr8FkdgPpxpVwQh3dHnTzHgdbn5Z3fmwHc")
+ account_filter.account.append("Fe4hMZrg7R97ZrbSScWBXUpQwZB9gzBnhodTCGyjkHsG")
+ account_filter.nonempty_txn_signature = True
+
+ # Copy the filter into the request
+ request.accounts["account_monitor"].CopyFrom(account_filter)
+ request.commitment = geyser_pb2.CommitmentLevel.CONFIRMED
+
+ yield request
+
+ # Keep connection alive with pings
+ while True:
+ time.sleep(30)
+ ping_request = geyser_pb2.SubscribeRequest()
+ ping_request.ping.id = int(time.time())
+ yield ping_request
+
+
+def handle_subscribe_updates(stub: geyser_pb2_grpc.GeyserStub):
+ """
+ Handles the streaming updates from the subscription.
+ Each update can contain different types of data based on our filters.
+ """
+ try:
+ request_iterator = create_subscribe_request()
+ print("Starting subscription stream...")
+
+ response_stream = stub.Subscribe(request_iterator)
+
+ for update in response_stream:
+ if update.HasField("account"):
+ print("\nAccount Update:")
+ print(f" Pubkey: {update.account.account.pubkey.hex()}")
+ print(f" Owner: {update.account.account.owner.hex()}")
+ print(f" Lamports: {update.account.account.lamports}")
+ print(f" Slot: {update.account.slot}")
+ if update.account.account.txn_signature:
+ print(
+ f" Transaction: {update.account.account.txn_signature.hex()}"
+ )
+
+ elif update.HasField("pong"):
+ print(f"Received pong: {update.pong.id}")
+
+ except grpc.RpcError as e:
+ logging.error(f"RPC error occurred: {str(e)}")
+ raise
+
+
+def run_subscription_client():
+ rpc_fqdn = os.environ.get("RPC_FDQN")
+ x_token = os.environ.get("X_TOKEN")
+
+ auth = TritonAuthMetadataPlugin(x_token)
+ ssl_creds = grpc.ssl_channel_credentials()
+ call_creds = grpc.metadata_call_credentials(auth)
+ combined_creds = grpc.composite_channel_credentials(ssl_creds, call_creds)
+
+ with grpc.secure_channel(rpc_fqdn, credentials=combined_creds) as channel:
+ stub = geyser_pb2_grpc.GeyserStub(channel)
+ handle_subscribe_updates(stub)
+
+
+if __name__ == "__main__":
+ logging.basicConfig(level=logging.INFO)
+ run_subscription_client()
diff --git a/src/driftpy/types.py b/src/driftpy/types.py
index ec4dc9e9..5a8982ea 100644
--- a/src/driftpy/types.py
+++ b/src/driftpy/types.py
@@ -5,6 +5,7 @@
from urllib.parse import urlparse, urlunparse
from borsh_construct.enum import _rust_enum
+from solana.rpc.commitment import Commitment
from solders.pubkey import Pubkey
from sumtypes import constructor
@@ -1412,3 +1413,10 @@ class PriceFeedMessage:
class PriceUpdateV2:
price_message: PriceFeedMessage
posted_slot: int
+
+
+@dataclass
+class GrpcConfig:
+ endpoint: str
+ token: str
+ commitment: Commitment = Commitment("confirmed")
From 31086ed818db5a4f3b53555ed1fba0be00605fff Mon Sep 17 00:00:00 2001
From: sina <20732540+SinaKhalili@users.noreply.github.com>
Date: Tue, 31 Dec 2024 04:49:58 -0800
Subject: [PATCH 02/15] Update deps, remove jito
---
poetry.lock | 754 +++++++++++++++---------------
pyproject.toml | 5 +-
src/driftpy/tx/jito_subscriber.py | 28 +-
src/driftpy/tx/jito_tx_sender.py | 29 +-
4 files changed, 416 insertions(+), 400 deletions(-)
diff --git a/poetry.lock b/poetry.lock
index 80684716..67675ebd 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -258,13 +258,13 @@ graphql = ["graphql-core (>=3.0.0)"]
[[package]]
name = "async-timeout"
-version = "4.0.2"
+version = "4.0.3"
description = "Timeout context manager for asyncio programs"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.7"
files = [
- {file = "async-timeout-4.0.2.tar.gz", hash = "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15"},
- {file = "async_timeout-4.0.2-py3-none-any.whl", hash = "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"},
+ {file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"},
+ {file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"},
]
[[package]]
@@ -535,13 +535,13 @@ unicode-backport = ["unicodedata2"]
[[package]]
name = "click"
-version = "8.1.7"
+version = "8.1.8"
description = "Composable command line interface toolkit"
optional = false
python-versions = ">=3.7"
files = [
- {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
- {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
+ {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"},
+ {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"},
]
[package.dependencies]
@@ -587,20 +587,20 @@ construct = "2.10.68"
[[package]]
name = "deprecated"
-version = "1.2.14"
+version = "1.2.15"
description = "Python @deprecated decorator to deprecate old python classes, functions or methods."
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7"
files = [
- {file = "Deprecated-1.2.14-py2.py3-none-any.whl", hash = "sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c"},
- {file = "Deprecated-1.2.14.tar.gz", hash = "sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3"},
+ {file = "Deprecated-1.2.15-py2.py3-none-any.whl", hash = "sha256:353bc4a8ac4bfc96800ddab349d89c25dec1079f65fd53acdcc1e0b975b21320"},
+ {file = "deprecated-1.2.15.tar.gz", hash = "sha256:683e561a90de76239796e6b6feac66b99030d2dd3fcf61ef996330f14bbb9b0d"},
]
[package.dependencies]
wrapt = ">=1.10,<2"
[package.extras]
-dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"]
+dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "jinja2 (>=3.0.3,<3.1.0)", "setuptools", "sphinx (<2)", "tox"]
[[package]]
name = "dnspython"
@@ -763,61 +763,70 @@ dev = ["flake8", "markdown", "twine", "wheel"]
[[package]]
name = "grpcio"
-version = "1.65.1"
+version = "1.68.1"
description = "HTTP/2-based RPC framework"
optional = false
python-versions = ">=3.8"
files = [
- {file = "grpcio-1.65.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:3dc5f928815b8972fb83b78d8db5039559f39e004ec93ebac316403fe031a062"},
- {file = "grpcio-1.65.1-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:8333ca46053c35484c9f2f7e8d8ec98c1383a8675a449163cea31a2076d93de8"},
- {file = "grpcio-1.65.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:7af64838b6e615fff0ec711960ed9b6ee83086edfa8c32670eafb736f169d719"},
- {file = "grpcio-1.65.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbb64b4166362d9326f7efbf75b1c72106c1aa87f13a8c8b56a1224fac152f5c"},
- {file = "grpcio-1.65.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8422dc13ad93ec8caa2612b5032a2b9cd6421c13ed87f54db4a3a2c93afaf77"},
- {file = "grpcio-1.65.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:4effc0562b6c65d4add6a873ca132e46ba5e5a46f07c93502c37a9ae7f043857"},
- {file = "grpcio-1.65.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a6c71575a2fedf259724981fd73a18906513d2f306169c46262a5bae956e6364"},
- {file = "grpcio-1.65.1-cp310-cp310-win32.whl", hash = "sha256:34966cf526ef0ea616e008d40d989463e3db157abb213b2f20c6ce0ae7928875"},
- {file = "grpcio-1.65.1-cp310-cp310-win_amd64.whl", hash = "sha256:ca931de5dd6d9eb94ff19a2c9434b23923bce6f767179fef04dfa991f282eaad"},
- {file = "grpcio-1.65.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:bbb46330cc643ecf10bd9bd4ca8e7419a14b6b9dedd05f671c90fb2c813c6037"},
- {file = "grpcio-1.65.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d827a6fb9215b961eb73459ad7977edb9e748b23e3407d21c845d1d8ef6597e5"},
- {file = "grpcio-1.65.1-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:6e71aed8835f8d9fbcb84babc93a9da95955d1685021cceb7089f4f1e717d719"},
- {file = "grpcio-1.65.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a1c84560b3b2d34695c9ba53ab0264e2802721c530678a8f0a227951f453462"},
- {file = "grpcio-1.65.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27adee2338d697e71143ed147fe286c05810965d5d30ec14dd09c22479bfe48a"},
- {file = "grpcio-1.65.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:f62652ddcadc75d0e7aa629e96bb61658f85a993e748333715b4ab667192e4e8"},
- {file = "grpcio-1.65.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:71a05fd814700dd9cb7d9a507f2f6a1ef85866733ccaf557eedacec32d65e4c2"},
- {file = "grpcio-1.65.1-cp311-cp311-win32.whl", hash = "sha256:b590f1ad056294dfaeac0b7e1b71d3d5ace638d8dd1f1147ce4bd13458783ba8"},
- {file = "grpcio-1.65.1-cp311-cp311-win_amd64.whl", hash = "sha256:12e9bdf3b5fd48e5fbe5b3da382ad8f97c08b47969f3cca81dd9b36b86ed39e2"},
- {file = "grpcio-1.65.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:54cb822e177374b318b233e54b6856c692c24cdbd5a3ba5335f18a47396bac8f"},
- {file = "grpcio-1.65.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:aaf3c54419a28d45bd1681372029f40e5bfb58e5265e3882eaf21e4a5f81a119"},
- {file = "grpcio-1.65.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:557de35bdfbe8bafea0a003dbd0f4da6d89223ac6c4c7549d78e20f92ead95d9"},
- {file = "grpcio-1.65.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8bfd95ef3b097f0cc86ade54eafefa1c8ed623aa01a26fbbdcd1a3650494dd11"},
- {file = "grpcio-1.65.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e6a8f3d6c41e6b642870afe6cafbaf7b61c57317f9ec66d0efdaf19db992b90"},
- {file = "grpcio-1.65.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1faaf7355ceed07ceaef0b9dcefa4c98daf1dd8840ed75c2de128c3f4a4d859d"},
- {file = "grpcio-1.65.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:60f1f38eed830488ad2a1b11579ef0f345ff16fffdad1d24d9fbc97ba31804ff"},
- {file = "grpcio-1.65.1-cp312-cp312-win32.whl", hash = "sha256:e75acfa52daf5ea0712e8aa82f0003bba964de7ae22c26d208cbd7bc08500177"},
- {file = "grpcio-1.65.1-cp312-cp312-win_amd64.whl", hash = "sha256:ff5a84907e51924973aa05ed8759210d8cdae7ffcf9e44fd17646cf4a902df59"},
- {file = "grpcio-1.65.1-cp38-cp38-linux_armv7l.whl", hash = "sha256:1fbd6331f18c3acd7e09d17fd840c096f56eaf0ef830fbd50af45ae9dc8dfd83"},
- {file = "grpcio-1.65.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:de5b6be29116e094c5ef9d9e4252e7eb143e3d5f6bd6d50a78075553ab4930b0"},
- {file = "grpcio-1.65.1-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:e4a3cdba62b2d6aeae6027ae65f350de6dc082b72e6215eccf82628e79efe9ba"},
- {file = "grpcio-1.65.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:941c4869aa229d88706b78187d60d66aca77fe5c32518b79e3c3e03fc26109a2"},
- {file = "grpcio-1.65.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f40cebe5edb518d78b8131e87cb83b3ee688984de38a232024b9b44e74ee53d3"},
- {file = "grpcio-1.65.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2ca684ba331fb249d8a1ce88db5394e70dbcd96e58d8c4b7e0d7b141a453dce9"},
- {file = "grpcio-1.65.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8558f0083ddaf5de64a59c790bffd7568e353914c0c551eae2955f54ee4b857f"},
- {file = "grpcio-1.65.1-cp38-cp38-win32.whl", hash = "sha256:8d8143a3e3966f85dce6c5cc45387ec36552174ba5712c5dc6fcc0898fb324c0"},
- {file = "grpcio-1.65.1-cp38-cp38-win_amd64.whl", hash = "sha256:76e81a86424d6ca1ce7c16b15bdd6a964a42b40544bf796a48da241fdaf61153"},
- {file = "grpcio-1.65.1-cp39-cp39-linux_armv7l.whl", hash = "sha256:cb5175f45c980ff418998723ea1b3869cce3766d2ab4e4916fbd3cedbc9d0ed3"},
- {file = "grpcio-1.65.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b12c1aa7b95abe73b3e04e052c8b362655b41c7798da69f1eaf8d186c7d204df"},
- {file = "grpcio-1.65.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:3019fb50128b21a5e018d89569ffaaaa361680e1346c2f261bb84a91082eb3d3"},
- {file = "grpcio-1.65.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ae15275ed98ea267f64ee9ddedf8ecd5306a5b5bb87972a48bfe24af24153e8"},
- {file = "grpcio-1.65.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f096ffb881f37e8d4f958b63c74bfc400c7cebd7a944b027357cd2fb8d91a57"},
- {file = "grpcio-1.65.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2f56b5a68fdcf17a0a1d524bf177218c3c69b3947cb239ea222c6f1867c3ab68"},
- {file = "grpcio-1.65.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:941596d419b9736ab548aa0feb5bbba922f98872668847bf0720b42d1d227b9e"},
- {file = "grpcio-1.65.1-cp39-cp39-win32.whl", hash = "sha256:5fd7337a823b890215f07d429f4f193d24b80d62a5485cf88ee06648591a0c57"},
- {file = "grpcio-1.65.1-cp39-cp39-win_amd64.whl", hash = "sha256:1bceeec568372cbebf554eae1b436b06c2ff24cfaf04afade729fb9035408c6c"},
- {file = "grpcio-1.65.1.tar.gz", hash = "sha256:3c492301988cd720cd145d84e17318d45af342e29ef93141228f9cd73222368b"},
+ {file = "grpcio-1.68.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:d35740e3f45f60f3c37b1e6f2f4702c23867b9ce21c6410254c9c682237da68d"},
+ {file = "grpcio-1.68.1-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:d99abcd61760ebb34bdff37e5a3ba333c5cc09feda8c1ad42547bea0416ada78"},
+ {file = "grpcio-1.68.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:f8261fa2a5f679abeb2a0a93ad056d765cdca1c47745eda3f2d87f874ff4b8c9"},
+ {file = "grpcio-1.68.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0feb02205a27caca128627bd1df4ee7212db051019a9afa76f4bb6a1a80ca95e"},
+ {file = "grpcio-1.68.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:919d7f18f63bcad3a0f81146188e90274fde800a94e35d42ffe9eadf6a9a6330"},
+ {file = "grpcio-1.68.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:963cc8d7d79b12c56008aabd8b457f400952dbea8997dd185f155e2f228db079"},
+ {file = "grpcio-1.68.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ccf2ebd2de2d6661e2520dae293298a3803a98ebfc099275f113ce1f6c2a80f1"},
+ {file = "grpcio-1.68.1-cp310-cp310-win32.whl", hash = "sha256:2cc1fd04af8399971bcd4f43bd98c22d01029ea2e56e69c34daf2bf8470e47f5"},
+ {file = "grpcio-1.68.1-cp310-cp310-win_amd64.whl", hash = "sha256:ee2e743e51cb964b4975de572aa8fb95b633f496f9fcb5e257893df3be854746"},
+ {file = "grpcio-1.68.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:55857c71641064f01ff0541a1776bfe04a59db5558e82897d35a7793e525774c"},
+ {file = "grpcio-1.68.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4b177f5547f1b995826ef529d2eef89cca2f830dd8b2c99ffd5fde4da734ba73"},
+ {file = "grpcio-1.68.1-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:3522c77d7e6606d6665ec8d50e867f13f946a4e00c7df46768f1c85089eae515"},
+ {file = "grpcio-1.68.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9d1fae6bbf0816415b81db1e82fb3bf56f7857273c84dcbe68cbe046e58e1ccd"},
+ {file = "grpcio-1.68.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:298ee7f80e26f9483f0b6f94cc0a046caf54400a11b644713bb5b3d8eb387600"},
+ {file = "grpcio-1.68.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cbb5780e2e740b6b4f2d208e90453591036ff80c02cc605fea1af8e6fc6b1bbe"},
+ {file = "grpcio-1.68.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ddda1aa22495d8acd9dfbafff2866438d12faec4d024ebc2e656784d96328ad0"},
+ {file = "grpcio-1.68.1-cp311-cp311-win32.whl", hash = "sha256:b33bd114fa5a83f03ec6b7b262ef9f5cac549d4126f1dc702078767b10c46ed9"},
+ {file = "grpcio-1.68.1-cp311-cp311-win_amd64.whl", hash = "sha256:7f20ebec257af55694d8f993e162ddf0d36bd82d4e57f74b31c67b3c6d63d8b2"},
+ {file = "grpcio-1.68.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:8829924fffb25386995a31998ccbbeaa7367223e647e0122043dfc485a87c666"},
+ {file = "grpcio-1.68.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:3aed6544e4d523cd6b3119b0916cef3d15ef2da51e088211e4d1eb91a6c7f4f1"},
+ {file = "grpcio-1.68.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:4efac5481c696d5cb124ff1c119a78bddbfdd13fc499e3bc0ca81e95fc573684"},
+ {file = "grpcio-1.68.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ab2d912ca39c51f46baf2a0d92aa265aa96b2443266fc50d234fa88bf877d8e"},
+ {file = "grpcio-1.68.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95c87ce2a97434dffe7327a4071839ab8e8bffd0054cc74cbe971fba98aedd60"},
+ {file = "grpcio-1.68.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e4842e4872ae4ae0f5497bf60a0498fa778c192cc7a9e87877abd2814aca9475"},
+ {file = "grpcio-1.68.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:255b1635b0ed81e9f91da4fcc8d43b7ea5520090b9a9ad9340d147066d1d3613"},
+ {file = "grpcio-1.68.1-cp312-cp312-win32.whl", hash = "sha256:7dfc914cc31c906297b30463dde0b9be48e36939575eaf2a0a22a8096e69afe5"},
+ {file = "grpcio-1.68.1-cp312-cp312-win_amd64.whl", hash = "sha256:a0c8ddabef9c8f41617f213e527254c41e8b96ea9d387c632af878d05db9229c"},
+ {file = "grpcio-1.68.1-cp313-cp313-linux_armv7l.whl", hash = "sha256:a47faedc9ea2e7a3b6569795c040aae5895a19dde0c728a48d3c5d7995fda385"},
+ {file = "grpcio-1.68.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:390eee4225a661c5cd133c09f5da1ee3c84498dc265fd292a6912b65c421c78c"},
+ {file = "grpcio-1.68.1-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:66a24f3d45c33550703f0abb8b656515b0ab777970fa275693a2f6dc8e35f1c1"},
+ {file = "grpcio-1.68.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c08079b4934b0bf0a8847f42c197b1d12cba6495a3d43febd7e99ecd1cdc8d54"},
+ {file = "grpcio-1.68.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8720c25cd9ac25dd04ee02b69256d0ce35bf8a0f29e20577427355272230965a"},
+ {file = "grpcio-1.68.1-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:04cfd68bf4f38f5bb959ee2361a7546916bd9a50f78617a346b3aeb2b42e2161"},
+ {file = "grpcio-1.68.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:c28848761a6520c5c6071d2904a18d339a796ebe6b800adc8b3f474c5ce3c3ad"},
+ {file = "grpcio-1.68.1-cp313-cp313-win32.whl", hash = "sha256:77d65165fc35cff6e954e7fd4229e05ec76102d4406d4576528d3a3635fc6172"},
+ {file = "grpcio-1.68.1-cp313-cp313-win_amd64.whl", hash = "sha256:a8040f85dcb9830d8bbb033ae66d272614cec6faceee88d37a88a9bd1a7a704e"},
+ {file = "grpcio-1.68.1-cp38-cp38-linux_armv7l.whl", hash = "sha256:eeb38ff04ab6e5756a2aef6ad8d94e89bb4a51ef96e20f45c44ba190fa0bcaad"},
+ {file = "grpcio-1.68.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8a3869a6661ec8f81d93f4597da50336718bde9eb13267a699ac7e0a1d6d0bea"},
+ {file = "grpcio-1.68.1-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:2c4cec6177bf325eb6faa6bd834d2ff6aa8bb3b29012cceb4937b86f8b74323c"},
+ {file = "grpcio-1.68.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:12941d533f3cd45d46f202e3667be8ebf6bcb3573629c7ec12c3e211d99cfccf"},
+ {file = "grpcio-1.68.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80af6f1e69c5e68a2be529990684abdd31ed6622e988bf18850075c81bb1ad6e"},
+ {file = "grpcio-1.68.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:e8dbe3e00771bfe3d04feed8210fc6617006d06d9a2679b74605b9fed3e8362c"},
+ {file = "grpcio-1.68.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:83bbf5807dc3ee94ce1de2dfe8a356e1d74101e4b9d7aa8c720cc4818a34aded"},
+ {file = "grpcio-1.68.1-cp38-cp38-win32.whl", hash = "sha256:8cb620037a2fd9eeee97b4531880e439ebfcd6d7d78f2e7dcc3726428ab5ef63"},
+ {file = "grpcio-1.68.1-cp38-cp38-win_amd64.whl", hash = "sha256:52fbf85aa71263380d330f4fce9f013c0798242e31ede05fcee7fbe40ccfc20d"},
+ {file = "grpcio-1.68.1-cp39-cp39-linux_armv7l.whl", hash = "sha256:cb400138e73969eb5e0535d1d06cae6a6f7a15f2cc74add320e2130b8179211a"},
+ {file = "grpcio-1.68.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a1b988b40f2fd9de5c820f3a701a43339d8dcf2cb2f1ca137e2c02671cc83ac1"},
+ {file = "grpcio-1.68.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:96f473cdacfdd506008a5d7579c9f6a7ff245a9ade92c3c0265eb76cc591914f"},
+ {file = "grpcio-1.68.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:37ea3be171f3cf3e7b7e412a98b77685eba9d4fd67421f4a34686a63a65d99f9"},
+ {file = "grpcio-1.68.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ceb56c4285754e33bb3c2fa777d055e96e6932351a3082ce3559be47f8024f0"},
+ {file = "grpcio-1.68.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:dffd29a2961f3263a16d73945b57cd44a8fd0b235740cb14056f0612329b345e"},
+ {file = "grpcio-1.68.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:025f790c056815b3bf53da850dd70ebb849fd755a4b1ac822cb65cd631e37d43"},
+ {file = "grpcio-1.68.1-cp39-cp39-win32.whl", hash = "sha256:1098f03dedc3b9810810568060dea4ac0822b4062f537b0f53aa015269be0a76"},
+ {file = "grpcio-1.68.1-cp39-cp39-win_amd64.whl", hash = "sha256:334ab917792904245a028f10e803fcd5b6f36a7b2173a820c0b5b076555825e1"},
+ {file = "grpcio-1.68.1.tar.gz", hash = "sha256:44a8502dd5de653ae6a73e2de50a401d84184f0331d0ac3daeb044e66d5c5054"},
]
[package.extras]
-protobuf = ["grpcio-tools (>=1.65.1)"]
+protobuf = ["grpcio-tools (>=1.68.1)"]
[[package]]
name = "h11"
@@ -898,13 +907,13 @@ files = [
[[package]]
name = "jinja2"
-version = "3.1.4"
+version = "3.1.5"
description = "A very fast and expressive template engine."
optional = false
python-versions = ">=3.7"
files = [
- {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"},
- {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"},
+ {file = "jinja2-3.1.5-py3-none-any.whl", hash = "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb"},
+ {file = "jinja2-3.1.5.tar.gz", hash = "sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb"},
]
[package.dependencies]
@@ -913,23 +922,6 @@ MarkupSafe = ">=2.0"
[package.extras]
i18n = ["Babel (>=2.7)"]
-[[package]]
-name = "jito-searcher-client"
-version = "0.1.4"
-description = "Jito Labs Python Searcher Client"
-optional = false
-python-versions = "<4.0,>=3.10"
-files = [
- {file = "jito_searcher_client-0.1.4-py3-none-any.whl", hash = "sha256:51e65778f5519dcdbd9066b9f81130e840e25f63f65176d964efdeae813dd406"},
- {file = "jito_searcher_client-0.1.4.tar.gz", hash = "sha256:498d29aeaa1f520218f5e3859b03a8a0048e96566c13dfa545dbaeb36b57c5fa"},
-]
-
-[package.dependencies]
-click = ">=8.1.3,<9.0.0"
-grpcio = ">=1.62.1,<2.0.0"
-protobuf = ">=4.25.3,<5.0.0"
-solana = "0.34.0"
-
[[package]]
name = "jsonalias"
version = "0.1.1"
@@ -1010,13 +1002,13 @@ dev = ["Sphinx (>=4.1.1)", "black (>=19.10b0)", "colorama (>=0.3.4)", "docutils
[[package]]
name = "markdown"
-version = "3.6"
+version = "3.7"
description = "Python implementation of John Gruber's Markdown."
optional = false
python-versions = ">=3.8"
files = [
- {file = "Markdown-3.6-py3-none-any.whl", hash = "sha256:48f276f4d8cfb8ce6527c8f79e2ee29708508bf4d40aa410fbc3b4ee832c850f"},
- {file = "Markdown-3.6.tar.gz", hash = "sha256:ed4f41f6daecbeeb96e576ce414c41d2d876daa9a16cb35fa8ed8c2ddfad0224"},
+ {file = "Markdown-3.7-py3-none-any.whl", hash = "sha256:7eb6df5690b81a1d7942992c97fad2938e956e79df20cbc6186e9c3a77b1c803"},
+ {file = "markdown-3.7.tar.gz", hash = "sha256:2ae2471477cfd02dbbf038d5d9bc226d40def84b4fe2986e49b59b6b472bbed2"},
]
[package.extras]
@@ -1025,71 +1017,72 @@ testing = ["coverage", "pyyaml"]
[[package]]
name = "markupsafe"
-version = "2.1.5"
+version = "3.0.2"
description = "Safely add untrusted strings to HTML/XML markup."
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.9"
files = [
- {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"},
- {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"},
- {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"},
- {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"},
- {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"},
- {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"},
- {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"},
- {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"},
- {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"},
- {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"},
- {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"},
- {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"},
- {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"},
- {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"},
- {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"},
- {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"},
- {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"},
- {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"},
- {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"},
- {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"},
- {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"},
- {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"},
- {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"},
- {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"},
- {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"},
- {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"},
- {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"},
- {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"},
- {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"},
- {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"},
- {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"},
- {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"},
- {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"},
- {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"},
- {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"},
- {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"},
- {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"},
- {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"},
- {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"},
- {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"},
- {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"},
- {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"},
- {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"},
- {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"},
- {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"},
- {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"},
- {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"},
- {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"},
- {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"},
- {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"},
- {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"},
- {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"},
- {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"},
- {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"},
- {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"},
- {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"},
- {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"},
- {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"},
- {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"},
- {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a"},
+ {file = "markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0"},
]
[[package]]
@@ -1116,13 +1109,13 @@ files = [
[[package]]
name = "mkdocs"
-version = "1.6.0"
+version = "1.6.1"
description = "Project documentation with Markdown."
optional = false
python-versions = ">=3.8"
files = [
- {file = "mkdocs-1.6.0-py3-none-any.whl", hash = "sha256:1eb5cb7676b7d89323e62b56235010216319217d4af5ddc543a91beb8d125ea7"},
- {file = "mkdocs-1.6.0.tar.gz", hash = "sha256:a73f735824ef83a4f3bcb7a231dcab23f5a838f88b7efc54a0eef5fbdbc3c512"},
+ {file = "mkdocs-1.6.1-py3-none-any.whl", hash = "sha256:db91759624d1647f3f34aa0c3f327dd2601beae39a366d6e064c03468d35c20e"},
+ {file = "mkdocs-1.6.1.tar.gz", hash = "sha256:7b432f01d928c084353ab39c57282f29f92136665bdd6abf7c1ec8d822ef86f2"},
]
[package.dependencies]
@@ -1146,13 +1139,13 @@ min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-imp
[[package]]
name = "mkdocs-autorefs"
-version = "1.0.1"
+version = "1.2.0"
description = "Automatically link across pages in MkDocs."
optional = false
python-versions = ">=3.8"
files = [
- {file = "mkdocs_autorefs-1.0.1-py3-none-any.whl", hash = "sha256:aacdfae1ab197780fb7a2dac92ad8a3d8f7ca8049a9cbe56a4218cd52e8da570"},
- {file = "mkdocs_autorefs-1.0.1.tar.gz", hash = "sha256:f684edf847eced40b570b57846b15f0bf57fb93ac2c510450775dcf16accb971"},
+ {file = "mkdocs_autorefs-1.2.0-py3-none-any.whl", hash = "sha256:d588754ae89bd0ced0c70c06f58566a4ee43471eeeee5202427da7de9ef85a2f"},
+ {file = "mkdocs_autorefs-1.2.0.tar.gz", hash = "sha256:a86b93abff653521bda71cf3fc5596342b7a23982093915cb74273f67522190f"},
]
[package.dependencies]
@@ -1323,47 +1316,53 @@ files = [
[[package]]
name = "mypy"
-version = "1.11.0"
+version = "1.14.0"
description = "Optional static typing for Python"
optional = false
python-versions = ">=3.8"
files = [
- {file = "mypy-1.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3824187c99b893f90c845bab405a585d1ced4ff55421fdf5c84cb7710995229"},
- {file = "mypy-1.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:96f8dbc2c85046c81bcddc246232d500ad729cb720da4e20fce3b542cab91287"},
- {file = "mypy-1.11.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1a5d8d8dd8613a3e2be3eae829ee891b6b2de6302f24766ff06cb2875f5be9c6"},
- {file = "mypy-1.11.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:72596a79bbfb195fd41405cffa18210af3811beb91ff946dbcb7368240eed6be"},
- {file = "mypy-1.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:35ce88b8ed3a759634cb4eb646d002c4cef0a38f20565ee82b5023558eb90c00"},
- {file = "mypy-1.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:98790025861cb2c3db8c2f5ad10fc8c336ed2a55f4daf1b8b3f877826b6ff2eb"},
- {file = "mypy-1.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:25bcfa75b9b5a5f8d67147a54ea97ed63a653995a82798221cca2a315c0238c1"},
- {file = "mypy-1.11.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bea2a0e71c2a375c9fa0ede3d98324214d67b3cbbfcbd55ac8f750f85a414e3"},
- {file = "mypy-1.11.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d2b3d36baac48e40e3064d2901f2fbd2a2d6880ec6ce6358825c85031d7c0d4d"},
- {file = "mypy-1.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:d8e2e43977f0e09f149ea69fd0556623919f816764e26d74da0c8a7b48f3e18a"},
- {file = "mypy-1.11.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:1d44c1e44a8be986b54b09f15f2c1a66368eb43861b4e82573026e04c48a9e20"},
- {file = "mypy-1.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cea3d0fb69637944dd321f41bc896e11d0fb0b0aa531d887a6da70f6e7473aba"},
- {file = "mypy-1.11.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a83ec98ae12d51c252be61521aa5731f5512231d0b738b4cb2498344f0b840cd"},
- {file = "mypy-1.11.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c7b73a856522417beb78e0fb6d33ef89474e7a622db2653bc1285af36e2e3e3d"},
- {file = "mypy-1.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:f2268d9fcd9686b61ab64f077be7ffbc6fbcdfb4103e5dd0cc5eaab53a8886c2"},
- {file = "mypy-1.11.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:940bfff7283c267ae6522ef926a7887305945f716a7704d3344d6d07f02df850"},
- {file = "mypy-1.11.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:14f9294528b5f5cf96c721f231c9f5b2733164e02c1c018ed1a0eff8a18005ac"},
- {file = "mypy-1.11.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7b54c27783991399046837df5c7c9d325d921394757d09dbcbf96aee4649fe9"},
- {file = "mypy-1.11.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:65f190a6349dec29c8d1a1cd4aa71284177aee5949e0502e6379b42873eddbe7"},
- {file = "mypy-1.11.0-cp38-cp38-win_amd64.whl", hash = "sha256:dbe286303241fea8c2ea5466f6e0e6a046a135a7e7609167b07fd4e7baf151bf"},
- {file = "mypy-1.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:104e9c1620c2675420abd1f6c44bab7dd33cc85aea751c985006e83dcd001095"},
- {file = "mypy-1.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f006e955718ecd8d159cee9932b64fba8f86ee6f7728ca3ac66c3a54b0062abe"},
- {file = "mypy-1.11.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:becc9111ca572b04e7e77131bc708480cc88a911adf3d0239f974c034b78085c"},
- {file = "mypy-1.11.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6801319fe76c3f3a3833f2b5af7bd2c17bb93c00026a2a1b924e6762f5b19e13"},
- {file = "mypy-1.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:c1a184c64521dc549324ec6ef7cbaa6b351912be9cb5edb803c2808a0d7e85ac"},
- {file = "mypy-1.11.0-py3-none-any.whl", hash = "sha256:56913ec8c7638b0091ef4da6fcc9136896914a9d60d54670a75880c3e5b99ace"},
- {file = "mypy-1.11.0.tar.gz", hash = "sha256:93743608c7348772fdc717af4aeee1997293a1ad04bc0ea6efa15bf65385c538"},
+ {file = "mypy-1.14.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e971c1c667007f9f2b397ffa80fa8e1e0adccff336e5e77e74cb5f22868bee87"},
+ {file = "mypy-1.14.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e86aaeaa3221a278c66d3d673b297232947d873773d61ca3ee0e28b2ff027179"},
+ {file = "mypy-1.14.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1628c5c3ce823d296e41e2984ff88c5861499041cb416a8809615d0c1f41740e"},
+ {file = "mypy-1.14.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7fadb29b77fc14a0dd81304ed73c828c3e5cde0016c7e668a86a3e0dfc9f3af3"},
+ {file = "mypy-1.14.0-cp310-cp310-win_amd64.whl", hash = "sha256:3fa76988dc760da377c1e5069200a50d9eaaccf34f4ea18428a3337034ab5a44"},
+ {file = "mypy-1.14.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6e73c8a154eed31db3445fe28f63ad2d97b674b911c00191416cf7f6459fd49a"},
+ {file = "mypy-1.14.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:273e70fcb2e38c5405a188425aa60b984ffdcef65d6c746ea5813024b68c73dc"},
+ {file = "mypy-1.14.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1daca283d732943731a6a9f20fdbcaa927f160bc51602b1d4ef880a6fb252015"},
+ {file = "mypy-1.14.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7e68047bedb04c1c25bba9901ea46ff60d5eaac2d71b1f2161f33107e2b368eb"},
+ {file = "mypy-1.14.0-cp311-cp311-win_amd64.whl", hash = "sha256:7a52f26b9c9b1664a60d87675f3bae00b5c7f2806e0c2800545a32c325920bcc"},
+ {file = "mypy-1.14.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d5326ab70a6db8e856d59ad4cb72741124950cbbf32e7b70e30166ba7bbf61dd"},
+ {file = "mypy-1.14.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bf4ec4980bec1e0e24e5075f449d014011527ae0055884c7e3abc6a99cd2c7f1"},
+ {file = "mypy-1.14.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:390dfb898239c25289495500f12fa73aa7f24a4c6d90ccdc165762462b998d63"},
+ {file = "mypy-1.14.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7e026d55ddcd76e29e87865c08cbe2d0104e2b3153a523c529de584759379d3d"},
+ {file = "mypy-1.14.0-cp312-cp312-win_amd64.whl", hash = "sha256:585ed36031d0b3ee362e5107ef449a8b5dfd4e9c90ccbe36414ee405ee6b32ba"},
+ {file = "mypy-1.14.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9f6f4c0b27401d14c483c622bc5105eff3911634d576bbdf6695b9a7c1ba741"},
+ {file = "mypy-1.14.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:56b2280cedcb312c7a79f5001ae5325582d0d339bce684e4a529069d0e7ca1e7"},
+ {file = "mypy-1.14.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:342de51c48bab326bfc77ce056ba08c076d82ce4f5a86621f972ed39970f94d8"},
+ {file = "mypy-1.14.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:00df23b42e533e02a6f0055e54de9a6ed491cd8b7ea738647364fd3a39ea7efc"},
+ {file = "mypy-1.14.0-cp313-cp313-win_amd64.whl", hash = "sha256:e8c8387e5d9dff80e7daf961df357c80e694e942d9755f3ad77d69b0957b8e3f"},
+ {file = "mypy-1.14.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b16738b1d80ec4334654e89e798eb705ac0c36c8a5c4798496cd3623aa02286"},
+ {file = "mypy-1.14.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:10065fcebb7c66df04b05fc799a854b1ae24d9963c8bb27e9064a9bdb43aa8ad"},
+ {file = "mypy-1.14.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fbb7d683fa6bdecaa106e8368aa973ecc0ddb79a9eaeb4b821591ecd07e9e03c"},
+ {file = "mypy-1.14.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3498cb55448dc5533e438cd13d6ddd28654559c8c4d1fd4b5ca57a31b81bac01"},
+ {file = "mypy-1.14.0-cp38-cp38-win_amd64.whl", hash = "sha256:c7b243408ea43755f3a21a0a08e5c5ae30eddb4c58a80f415ca6b118816e60aa"},
+ {file = "mypy-1.14.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:14117b9da3305b39860d0aa34b8f1ff74d209a368829a584eb77524389a9c13e"},
+ {file = "mypy-1.14.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:af98c5a958f9c37404bd4eef2f920b94874507e146ed6ee559f185b8809c44cc"},
+ {file = "mypy-1.14.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f0b343a1d3989547024377c2ba0dca9c74a2428ad6ed24283c213af8dbb0710b"},
+ {file = "mypy-1.14.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:cdb5563c1726c85fb201be383168f8c866032db95e1095600806625b3a648cb7"},
+ {file = "mypy-1.14.0-cp39-cp39-win_amd64.whl", hash = "sha256:74e925649c1ee0a79aa7448baf2668d81cc287dc5782cff6a04ee93f40fb8d3f"},
+ {file = "mypy-1.14.0-py3-none-any.whl", hash = "sha256:2238d7f93fc4027ed1efc944507683df3ba406445a2b6c96e79666a045aadfab"},
+ {file = "mypy-1.14.0.tar.gz", hash = "sha256:822dbd184d4a9804df5a7d5335a68cf7662930e70b8c1bc976645d1509f9a9d6"},
]
[package.dependencies]
-mypy-extensions = ">=1.0.0"
+mypy_extensions = ">=1.0.0"
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
-typing-extensions = ">=4.6.0"
+typing_extensions = ">=4.6.0"
[package.extras]
dmypy = ["psutil (>=4.0)"]
+faster-cache = ["orjson"]
install-types = ["pip"]
mypyc = ["setuptools (>=50)"]
reports = ["lxml"]
@@ -1462,19 +1461,19 @@ files = [
[[package]]
name = "platformdirs"
-version = "4.2.2"
+version = "4.3.6"
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`."
optional = false
python-versions = ">=3.8"
files = [
- {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"},
- {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"},
+ {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"},
+ {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"},
]
[package.extras]
-docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"]
-test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"]
-type = ["mypy (>=1.8)"]
+docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"]
+test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"]
+type = ["mypy (>=1.11.2)"]
[[package]]
name = "pluggy"
@@ -1493,22 +1492,22 @@ testing = ["pytest", "pytest-benchmark"]
[[package]]
name = "protobuf"
-version = "4.25.4"
+version = "5.29.2"
description = ""
optional = false
python-versions = ">=3.8"
files = [
- {file = "protobuf-4.25.4-cp310-abi3-win32.whl", hash = "sha256:db9fd45183e1a67722cafa5c1da3e85c6492a5383f127c86c4c4aa4845867dc4"},
- {file = "protobuf-4.25.4-cp310-abi3-win_amd64.whl", hash = "sha256:ba3d8504116a921af46499471c63a85260c1a5fc23333154a427a310e015d26d"},
- {file = "protobuf-4.25.4-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:eecd41bfc0e4b1bd3fa7909ed93dd14dd5567b98c941d6c1ad08fdcab3d6884b"},
- {file = "protobuf-4.25.4-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:4c8a70fdcb995dcf6c8966cfa3a29101916f7225e9afe3ced4395359955d3835"},
- {file = "protobuf-4.25.4-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:3319e073562e2515c6ddc643eb92ce20809f5d8f10fead3332f71c63be6a7040"},
- {file = "protobuf-4.25.4-cp38-cp38-win32.whl", hash = "sha256:7e372cbbda66a63ebca18f8ffaa6948455dfecc4e9c1029312f6c2edcd86c4e1"},
- {file = "protobuf-4.25.4-cp38-cp38-win_amd64.whl", hash = "sha256:051e97ce9fa6067a4546e75cb14f90cf0232dcb3e3d508c448b8d0e4265b61c1"},
- {file = "protobuf-4.25.4-cp39-cp39-win32.whl", hash = "sha256:90bf6fd378494eb698805bbbe7afe6c5d12c8e17fca817a646cd6a1818c696ca"},
- {file = "protobuf-4.25.4-cp39-cp39-win_amd64.whl", hash = "sha256:ac79a48d6b99dfed2729ccccee547b34a1d3d63289c71cef056653a846a2240f"},
- {file = "protobuf-4.25.4-py3-none-any.whl", hash = "sha256:bfbebc1c8e4793cfd58589acfb8a1026be0003e852b9da7db5a4285bde996978"},
- {file = "protobuf-4.25.4.tar.gz", hash = "sha256:0dc4a62cc4052a036ee2204d26fe4d835c62827c855c8a03f29fe6da146b380d"},
+ {file = "protobuf-5.29.2-cp310-abi3-win32.whl", hash = "sha256:c12ba8249f5624300cf51c3d0bfe5be71a60c63e4dcf51ffe9a68771d958c851"},
+ {file = "protobuf-5.29.2-cp310-abi3-win_amd64.whl", hash = "sha256:842de6d9241134a973aab719ab42b008a18a90f9f07f06ba480df268f86432f9"},
+ {file = "protobuf-5.29.2-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:a0c53d78383c851bfa97eb42e3703aefdc96d2036a41482ffd55dc5f529466eb"},
+ {file = "protobuf-5.29.2-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:494229ecd8c9009dd71eda5fd57528395d1eacdf307dbece6c12ad0dd09e912e"},
+ {file = "protobuf-5.29.2-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:b6b0d416bbbb9d4fbf9d0561dbfc4e324fd522f61f7af0fe0f282ab67b22477e"},
+ {file = "protobuf-5.29.2-cp38-cp38-win32.whl", hash = "sha256:e621a98c0201a7c8afe89d9646859859be97cb22b8bf1d8eacfd90d5bda2eb19"},
+ {file = "protobuf-5.29.2-cp38-cp38-win_amd64.whl", hash = "sha256:13d6d617a2a9e0e82a88113d7191a1baa1e42c2cc6f5f1398d3b054c8e7e714a"},
+ {file = "protobuf-5.29.2-cp39-cp39-win32.whl", hash = "sha256:36000f97ea1e76e8398a3f02936aac2a5d2b111aae9920ec1b769fc4a222c4d9"},
+ {file = "protobuf-5.29.2-cp39-cp39-win_amd64.whl", hash = "sha256:2d2e674c58a06311c8e99e74be43e7f3a8d1e2b2fdf845eaa347fbd866f23355"},
+ {file = "protobuf-5.29.2-py3-none-any.whl", hash = "sha256:fde4554c0e578a5a0bcc9a276339594848d1e89f9ea47b4427c80e5d72f90181"},
+ {file = "protobuf-5.29.2.tar.gz", hash = "sha256:b2cc8e8bb7c9326996f0e160137b0861f1a82162502658df2951209d0cb0309e"},
]
[[package]]
@@ -1689,13 +1688,13 @@ files = [
[[package]]
name = "pymdown-extensions"
-version = "10.8.1"
+version = "10.13"
description = "Extension pack for Python Markdown."
optional = false
python-versions = ">=3.8"
files = [
- {file = "pymdown_extensions-10.8.1-py3-none-any.whl", hash = "sha256:f938326115884f48c6059c67377c46cf631c733ef3629b6eed1349989d1b30cb"},
- {file = "pymdown_extensions-10.8.1.tar.gz", hash = "sha256:3ab1db5c9e21728dabf75192d71471f8e50f216627e9a1fa9535ecb0231b9940"},
+ {file = "pymdown_extensions-10.13-py3-none-any.whl", hash = "sha256:80bc33d715eec68e683e04298946d47d78c7739e79d808203df278ee8ef89428"},
+ {file = "pymdown_extensions-10.13.tar.gz", hash = "sha256:e0b351494dc0d8d14a1f52b39b1499a00ef1566b4ba23dc74f1eba75c736f5dd"},
]
[package.dependencies]
@@ -1829,15 +1828,29 @@ files = [
[package.dependencies]
six = ">=1.5"
+[[package]]
+name = "python-dotenv"
+version = "1.0.1"
+description = "Read key-value pairs from a .env file and set them as environment variables"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"},
+ {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"},
+]
+
+[package.extras]
+cli = ["click (>=5.0)"]
+
[[package]]
name = "pytkdocs"
-version = "0.16.1"
+version = "0.16.2"
description = "Load Python objects documentation."
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "pytkdocs-0.16.1-py3-none-any.whl", hash = "sha256:a8c3f46ecef0b92864cc598e9101e9c4cf832ebbf228f50c84aa5dd850aac379"},
- {file = "pytkdocs-0.16.1.tar.gz", hash = "sha256:e2ccf6dfe9dbbceb09818673f040f1a7c32ed0bffb2d709b06be6453c4026045"},
+ {file = "pytkdocs-0.16.2-py3-none-any.whl", hash = "sha256:36450316d004f6399402d044f122f28f88ff4a069899d10de3d28ad6b4ba5799"},
+ {file = "pytkdocs-0.16.2.tar.gz", hash = "sha256:e75538a34932996b8803fbad4e4f6851fc0e9fd9aea86fc6602d6582c12098f3"},
]
[package.extras]
@@ -1845,62 +1858,64 @@ numpy-style = ["docstring_parser (>=0.7)"]
[[package]]
name = "pyyaml"
-version = "6.0.1"
+version = "6.0.2"
description = "YAML parser and emitter for Python"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.8"
files = [
- {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"},
- {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"},
- {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"},
- {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"},
- {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"},
- {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"},
- {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
- {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
- {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
- {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"},
- {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
- {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
- {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
- {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"},
- {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
- {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
- {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
- {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
- {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"},
- {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
- {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
- {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
- {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"},
- {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"},
- {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"},
- {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"},
- {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"},
- {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"},
- {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"},
- {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"},
- {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"},
- {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"},
- {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"},
- {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"},
- {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"},
- {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"},
- {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"},
- {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"},
- {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"},
- {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"},
- {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"},
- {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"},
- {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"},
- {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"},
- {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"},
- {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"},
- {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"},
- {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"},
- {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"},
- {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
- {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
+ {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"},
+ {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"},
+ {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"},
+ {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"},
+ {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"},
+ {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"},
+ {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"},
+ {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"},
+ {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"},
+ {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"},
+ {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"},
+ {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"},
+ {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"},
+ {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"},
+ {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"},
+ {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"},
+ {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"},
+ {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"},
+ {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"},
+ {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"},
+ {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"},
+ {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"},
+ {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"},
+ {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"},
+ {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"},
+ {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"},
+ {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"},
+ {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"},
+ {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"},
+ {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"},
+ {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"},
+ {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"},
+ {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"},
+ {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"},
+ {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"},
+ {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"},
+ {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"},
+ {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"},
+ {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"},
+ {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"},
+ {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"},
+ {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"},
+ {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"},
+ {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"},
+ {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"},
+ {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"},
+ {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"},
+ {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"},
+ {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"},
+ {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"},
+ {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"},
+ {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"},
+ {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"},
]
[[package]]
@@ -1957,13 +1972,13 @@ idna2008 = ["idna"]
[[package]]
name = "six"
-version = "1.16.0"
+version = "1.17.0"
description = "Python 2 and 3 compatibility utilities"
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
files = [
- {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
- {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
+ {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"},
+ {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"},
]
[[package]]
@@ -2129,43 +2144,41 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
[[package]]
name = "watchdog"
-version = "4.0.1"
+version = "6.0.0"
description = "Filesystem events monitoring"
optional = false
-python-versions = ">=3.8"
+python-versions = ">=3.9"
files = [
- {file = "watchdog-4.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:da2dfdaa8006eb6a71051795856bedd97e5b03e57da96f98e375682c48850645"},
- {file = "watchdog-4.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e93f451f2dfa433d97765ca2634628b789b49ba8b504fdde5837cdcf25fdb53b"},
- {file = "watchdog-4.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ef0107bbb6a55f5be727cfc2ef945d5676b97bffb8425650dadbb184be9f9a2b"},
- {file = "watchdog-4.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:17e32f147d8bf9657e0922c0940bcde863b894cd871dbb694beb6704cfbd2fb5"},
- {file = "watchdog-4.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:03e70d2df2258fb6cb0e95bbdbe06c16e608af94a3ffbd2b90c3f1e83eb10767"},
- {file = "watchdog-4.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:123587af84260c991dc5f62a6e7ef3d1c57dfddc99faacee508c71d287248459"},
- {file = "watchdog-4.0.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:093b23e6906a8b97051191a4a0c73a77ecc958121d42346274c6af6520dec175"},
- {file = "watchdog-4.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:611be3904f9843f0529c35a3ff3fd617449463cb4b73b1633950b3d97fa4bfb7"},
- {file = "watchdog-4.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:62c613ad689ddcb11707f030e722fa929f322ef7e4f18f5335d2b73c61a85c28"},
- {file = "watchdog-4.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:d4925e4bf7b9bddd1c3de13c9b8a2cdb89a468f640e66fbfabaf735bd85b3e35"},
- {file = "watchdog-4.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cad0bbd66cd59fc474b4a4376bc5ac3fc698723510cbb64091c2a793b18654db"},
- {file = "watchdog-4.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a3c2c317a8fb53e5b3d25790553796105501a235343f5d2bf23bb8649c2c8709"},
- {file = "watchdog-4.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c9904904b6564d4ee8a1ed820db76185a3c96e05560c776c79a6ce5ab71888ba"},
- {file = "watchdog-4.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:667f3c579e813fcbad1b784db7a1aaa96524bed53437e119f6a2f5de4db04235"},
- {file = "watchdog-4.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d10a681c9a1d5a77e75c48a3b8e1a9f2ae2928eda463e8d33660437705659682"},
- {file = "watchdog-4.0.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0144c0ea9997b92615af1d94afc0c217e07ce2c14912c7b1a5731776329fcfc7"},
- {file = "watchdog-4.0.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:998d2be6976a0ee3a81fb8e2777900c28641fb5bfbd0c84717d89bca0addcdc5"},
- {file = "watchdog-4.0.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e7921319fe4430b11278d924ef66d4daa469fafb1da679a2e48c935fa27af193"},
- {file = "watchdog-4.0.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:f0de0f284248ab40188f23380b03b59126d1479cd59940f2a34f8852db710625"},
- {file = "watchdog-4.0.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:bca36be5707e81b9e6ce3208d92d95540d4ca244c006b61511753583c81c70dd"},
- {file = "watchdog-4.0.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:ab998f567ebdf6b1da7dc1e5accfaa7c6992244629c0fdaef062f43249bd8dee"},
- {file = "watchdog-4.0.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:dddba7ca1c807045323b6af4ff80f5ddc4d654c8bce8317dde1bd96b128ed253"},
- {file = "watchdog-4.0.1-py3-none-manylinux2014_armv7l.whl", hash = "sha256:4513ec234c68b14d4161440e07f995f231be21a09329051e67a2118a7a612d2d"},
- {file = "watchdog-4.0.1-py3-none-manylinux2014_i686.whl", hash = "sha256:4107ac5ab936a63952dea2a46a734a23230aa2f6f9db1291bf171dac3ebd53c6"},
- {file = "watchdog-4.0.1-py3-none-manylinux2014_ppc64.whl", hash = "sha256:6e8c70d2cd745daec2a08734d9f63092b793ad97612470a0ee4cbb8f5f705c57"},
- {file = "watchdog-4.0.1-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:f27279d060e2ab24c0aa98363ff906d2386aa6c4dc2f1a374655d4e02a6c5e5e"},
- {file = "watchdog-4.0.1-py3-none-manylinux2014_s390x.whl", hash = "sha256:f8affdf3c0f0466e69f5b3917cdd042f89c8c63aebdb9f7c078996f607cdb0f5"},
- {file = "watchdog-4.0.1-py3-none-manylinux2014_x86_64.whl", hash = "sha256:ac7041b385f04c047fcc2951dc001671dee1b7e0615cde772e84b01fbf68ee84"},
- {file = "watchdog-4.0.1-py3-none-win32.whl", hash = "sha256:206afc3d964f9a233e6ad34618ec60b9837d0582b500b63687e34011e15bb429"},
- {file = "watchdog-4.0.1-py3-none-win_amd64.whl", hash = "sha256:7577b3c43e5909623149f76b099ac49a1a01ca4e167d1785c76eb52fa585745a"},
- {file = "watchdog-4.0.1-py3-none-win_ia64.whl", hash = "sha256:d7b9f5f3299e8dd230880b6c55504a1f69cf1e4316275d1b215ebdd8187ec88d"},
- {file = "watchdog-4.0.1.tar.gz", hash = "sha256:eebaacf674fa25511e8867028d281e602ee6500045b57f43b08778082f7f8b44"},
+ {file = "watchdog-6.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d1cdb490583ebd691c012b3d6dae011000fe42edb7a82ece80965b42abd61f26"},
+ {file = "watchdog-6.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc64ab3bdb6a04d69d4023b29422170b74681784ffb9463ed4870cf2f3e66112"},
+ {file = "watchdog-6.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c897ac1b55c5a1461e16dae288d22bb2e412ba9807df8397a635d88f671d36c3"},
+ {file = "watchdog-6.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c"},
+ {file = "watchdog-6.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2"},
+ {file = "watchdog-6.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c"},
+ {file = "watchdog-6.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bdd4e6f14b8b18c334febb9c4425a878a2ac20efd1e0b231978e7b150f92a948"},
+ {file = "watchdog-6.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860"},
+ {file = "watchdog-6.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0"},
+ {file = "watchdog-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c"},
+ {file = "watchdog-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134"},
+ {file = "watchdog-6.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b"},
+ {file = "watchdog-6.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e6f0e77c9417e7cd62af82529b10563db3423625c5fce018430b249bf977f9e8"},
+ {file = "watchdog-6.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:90c8e78f3b94014f7aaae121e6b909674df5b46ec24d6bebc45c44c56729af2a"},
+ {file = "watchdog-6.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e7631a77ffb1f7d2eefa4445ebbee491c720a5661ddf6df3498ebecae5ed375c"},
+ {file = "watchdog-6.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:c7ac31a19f4545dd92fc25d200694098f42c9a8e391bc00bdd362c5736dbf881"},
+ {file = "watchdog-6.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9513f27a1a582d9808cf21a07dae516f0fab1cf2d7683a742c498b93eedabb11"},
+ {file = "watchdog-6.0.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7a0e56874cfbc4b9b05c60c8a1926fedf56324bb08cfbc188969777940aef3aa"},
+ {file = "watchdog-6.0.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:e6439e374fc012255b4ec786ae3c4bc838cd7309a540e5fe0952d03687d8804e"},
+ {file = "watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13"},
+ {file = "watchdog-6.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379"},
+ {file = "watchdog-6.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e"},
+ {file = "watchdog-6.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f"},
+ {file = "watchdog-6.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26"},
+ {file = "watchdog-6.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c"},
+ {file = "watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2"},
+ {file = "watchdog-6.0.0-py3-none-win32.whl", hash = "sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a"},
+ {file = "watchdog-6.0.0-py3-none-win_amd64.whl", hash = "sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680"},
+ {file = "watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f"},
+ {file = "watchdog-6.0.0.tar.gz", hash = "sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282"},
]
[package.extras]
@@ -2251,13 +2264,13 @@ files = [
[[package]]
name = "win32-setctime"
-version = "1.1.0"
+version = "1.2.0"
description = "A small Python utility to set file creation time on Windows"
optional = false
python-versions = ">=3.5"
files = [
- {file = "win32_setctime-1.1.0-py3-none-any.whl", hash = "sha256:231db239e959c2fe7eb1d7dc129f11172354f98361c4fa2d6d2d7e278baa8aad"},
- {file = "win32_setctime-1.1.0.tar.gz", hash = "sha256:15cf5750465118d6929ae4de4eb46e8edae9a5634350c01ba582df868e932cb2"},
+ {file = "win32_setctime-1.2.0-py3-none-any.whl", hash = "sha256:95d644c4e708aba81dc3704a116d8cbc974d70b3bdb8be1d150e36be6e9d1390"},
+ {file = "win32_setctime-1.2.0.tar.gz", hash = "sha256:ae1fdf948f5640aae05c511ade119313fb6a30d7eabe25fef9764dca5873c4c0"},
]
[package.extras]
@@ -2265,81 +2278,76 @@ dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"]
[[package]]
name = "wrapt"
-version = "1.16.0"
+version = "1.17.0"
description = "Module for decorators, wrappers and monkey patching."
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.8"
files = [
- {file = "wrapt-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4"},
- {file = "wrapt-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020"},
- {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb2dee3874a500de01c93d5c71415fcaef1d858370d405824783e7a8ef5db440"},
- {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a88e6010048489cda82b1326889ec075a8c856c2e6a256072b28eaee3ccf487"},
- {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac83a914ebaf589b69f7d0a1277602ff494e21f4c2f743313414378f8f50a4cf"},
- {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:73aa7d98215d39b8455f103de64391cb79dfcad601701a3aa0dddacf74911d72"},
- {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:807cc8543a477ab7422f1120a217054f958a66ef7314f76dd9e77d3f02cdccd0"},
- {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bf5703fdeb350e36885f2875d853ce13172ae281c56e509f4e6eca049bdfb136"},
- {file = "wrapt-1.16.0-cp310-cp310-win32.whl", hash = "sha256:f6b2d0c6703c988d334f297aa5df18c45e97b0af3679bb75059e0e0bd8b1069d"},
- {file = "wrapt-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:decbfa2f618fa8ed81c95ee18a387ff973143c656ef800c9f24fb7e9c16054e2"},
- {file = "wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09"},
- {file = "wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d"},
- {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389"},
- {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060"},
- {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1"},
- {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3"},
- {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956"},
- {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d"},
- {file = "wrapt-1.16.0-cp311-cp311-win32.whl", hash = "sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362"},
- {file = "wrapt-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89"},
- {file = "wrapt-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b"},
- {file = "wrapt-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36"},
- {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73"},
- {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809"},
- {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b"},
- {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81"},
- {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9"},
- {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c"},
- {file = "wrapt-1.16.0-cp312-cp312-win32.whl", hash = "sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc"},
- {file = "wrapt-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8"},
- {file = "wrapt-1.16.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d462f28826f4657968ae51d2181a074dfe03c200d6131690b7d65d55b0f360f8"},
- {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a33a747400b94b6d6b8a165e4480264a64a78c8a4c734b62136062e9a248dd39"},
- {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3646eefa23daeba62643a58aac816945cadc0afaf21800a1421eeba5f6cfb9c"},
- {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ebf019be5c09d400cf7b024aa52b1f3aeebeff51550d007e92c3c1c4afc2a40"},
- {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc"},
- {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:1acd723ee2a8826f3d53910255643e33673e1d11db84ce5880675954183ec47e"},
- {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:bc57efac2da352a51cc4658878a68d2b1b67dbe9d33c36cb826ca449d80a8465"},
- {file = "wrapt-1.16.0-cp36-cp36m-win32.whl", hash = "sha256:da4813f751142436b075ed7aa012a8778aa43a99f7b36afe9b742d3ed8bdc95e"},
- {file = "wrapt-1.16.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6f6eac2360f2d543cc875a0e5efd413b6cbd483cb3ad7ebf888884a6e0d2e966"},
- {file = "wrapt-1.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a0ea261ce52b5952bf669684a251a66df239ec6d441ccb59ec7afa882265d593"},
- {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bd2d7ff69a2cac767fbf7a2b206add2e9a210e57947dd7ce03e25d03d2de292"},
- {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9159485323798c8dc530a224bd3ffcf76659319ccc7bbd52e01e73bd0241a0c5"},
- {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a86373cf37cd7764f2201b76496aba58a52e76dedfaa698ef9e9688bfd9e41cf"},
- {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:73870c364c11f03ed072dda68ff7aea6d2a3a5c3fe250d917a429c7432e15228"},
- {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b935ae30c6e7400022b50f8d359c03ed233d45b725cfdd299462f41ee5ffba6f"},
- {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:db98ad84a55eb09b3c32a96c576476777e87c520a34e2519d3e59c44710c002c"},
- {file = "wrapt-1.16.0-cp37-cp37m-win32.whl", hash = "sha256:9153ed35fc5e4fa3b2fe97bddaa7cbec0ed22412b85bcdaf54aeba92ea37428c"},
- {file = "wrapt-1.16.0-cp37-cp37m-win_amd64.whl", hash = "sha256:66dfbaa7cfa3eb707bbfcd46dab2bc6207b005cbc9caa2199bcbc81d95071a00"},
- {file = "wrapt-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1dd50a2696ff89f57bd8847647a1c363b687d3d796dc30d4dd4a9d1689a706f0"},
- {file = "wrapt-1.16.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:44a2754372e32ab315734c6c73b24351d06e77ffff6ae27d2ecf14cf3d229202"},
- {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e9723528b9f787dc59168369e42ae1c3b0d3fadb2f1a71de14531d321ee05b0"},
- {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbed418ba5c3dce92619656802cc5355cb679e58d0d89b50f116e4a9d5a9603e"},
- {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:941988b89b4fd6b41c3f0bfb20e92bd23746579736b7343283297c4c8cbae68f"},
- {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6a42cd0cfa8ffc1915aef79cb4284f6383d8a3e9dcca70c445dcfdd639d51267"},
- {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ca9b6085e4f866bd584fb135a041bfc32cab916e69f714a7d1d397f8c4891ca"},
- {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5e49454f19ef621089e204f862388d29e6e8d8b162efce05208913dde5b9ad6"},
- {file = "wrapt-1.16.0-cp38-cp38-win32.whl", hash = "sha256:c31f72b1b6624c9d863fc095da460802f43a7c6868c5dda140f51da24fd47d7b"},
- {file = "wrapt-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:490b0ee15c1a55be9c1bd8609b8cecd60e325f0575fc98f50058eae366e01f41"},
- {file = "wrapt-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9b201ae332c3637a42f02d1045e1d0cccfdc41f1f2f801dafbaa7e9b4797bfc2"},
- {file = "wrapt-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2076fad65c6736184e77d7d4729b63a6d1ae0b70da4868adeec40989858eb3fb"},
- {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5cd603b575ebceca7da5a3a251e69561bec509e0b46e4993e1cac402b7247b8"},
- {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b47cfad9e9bbbed2339081f4e346c93ecd7ab504299403320bf85f7f85c7d46c"},
- {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8212564d49c50eb4565e502814f694e240c55551a5f1bc841d4fcaabb0a9b8a"},
- {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5f15814a33e42b04e3de432e573aa557f9f0f56458745c2074952f564c50e664"},
- {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db2e408d983b0e61e238cf579c09ef7020560441906ca990fe8412153e3b291f"},
- {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:edfad1d29c73f9b863ebe7082ae9321374ccb10879eeabc84ba3b69f2579d537"},
- {file = "wrapt-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed867c42c268f876097248e05b6117a65bcd1e63b779e916fe2e33cd6fd0d3c3"},
- {file = "wrapt-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:eb1b046be06b0fce7249f1d025cd359b4b80fc1c3e24ad9eca33e0dcdb2e4a35"},
- {file = "wrapt-1.16.0-py3-none-any.whl", hash = "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1"},
- {file = "wrapt-1.16.0.tar.gz", hash = "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d"},
+ {file = "wrapt-1.17.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2a0c23b8319848426f305f9cb0c98a6e32ee68a36264f45948ccf8e7d2b941f8"},
+ {file = "wrapt-1.17.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1ca5f060e205f72bec57faae5bd817a1560fcfc4af03f414b08fa29106b7e2d"},
+ {file = "wrapt-1.17.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e185ec6060e301a7e5f8461c86fb3640a7beb1a0f0208ffde7a65ec4074931df"},
+ {file = "wrapt-1.17.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb90765dd91aed05b53cd7a87bd7f5c188fcd95960914bae0d32c5e7f899719d"},
+ {file = "wrapt-1.17.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:879591c2b5ab0a7184258274c42a126b74a2c3d5a329df16d69f9cee07bba6ea"},
+ {file = "wrapt-1.17.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fce6fee67c318fdfb7f285c29a82d84782ae2579c0e1b385b7f36c6e8074fffb"},
+ {file = "wrapt-1.17.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0698d3a86f68abc894d537887b9bbf84d29bcfbc759e23f4644be27acf6da301"},
+ {file = "wrapt-1.17.0-cp310-cp310-win32.whl", hash = "sha256:69d093792dc34a9c4c8a70e4973a3361c7a7578e9cd86961b2bbf38ca71e4e22"},
+ {file = "wrapt-1.17.0-cp310-cp310-win_amd64.whl", hash = "sha256:f28b29dc158ca5d6ac396c8e0a2ef45c4e97bb7e65522bfc04c989e6fe814575"},
+ {file = "wrapt-1.17.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:74bf625b1b4caaa7bad51d9003f8b07a468a704e0644a700e936c357c17dd45a"},
+ {file = "wrapt-1.17.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f2a28eb35cf99d5f5bd12f5dd44a0f41d206db226535b37b0c60e9da162c3ed"},
+ {file = "wrapt-1.17.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:81b1289e99cf4bad07c23393ab447e5e96db0ab50974a280f7954b071d41b489"},
+ {file = "wrapt-1.17.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f2939cd4a2a52ca32bc0b359015718472d7f6de870760342e7ba295be9ebaf9"},
+ {file = "wrapt-1.17.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6a9653131bda68a1f029c52157fd81e11f07d485df55410401f745007bd6d339"},
+ {file = "wrapt-1.17.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4e4b4385363de9052dac1a67bfb535c376f3d19c238b5f36bddc95efae15e12d"},
+ {file = "wrapt-1.17.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bdf62d25234290db1837875d4dceb2151e4ea7f9fff2ed41c0fde23ed542eb5b"},
+ {file = "wrapt-1.17.0-cp311-cp311-win32.whl", hash = "sha256:5d8fd17635b262448ab8f99230fe4dac991af1dabdbb92f7a70a6afac8a7e346"},
+ {file = "wrapt-1.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:92a3d214d5e53cb1db8b015f30d544bc9d3f7179a05feb8f16df713cecc2620a"},
+ {file = "wrapt-1.17.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:89fc28495896097622c3fc238915c79365dd0ede02f9a82ce436b13bd0ab7569"},
+ {file = "wrapt-1.17.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:875d240fdbdbe9e11f9831901fb8719da0bd4e6131f83aa9f69b96d18fae7504"},
+ {file = "wrapt-1.17.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5ed16d95fd142e9c72b6c10b06514ad30e846a0d0917ab406186541fe68b451"},
+ {file = "wrapt-1.17.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18b956061b8db634120b58f668592a772e87e2e78bc1f6a906cfcaa0cc7991c1"},
+ {file = "wrapt-1.17.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:daba396199399ccabafbfc509037ac635a6bc18510ad1add8fd16d4739cdd106"},
+ {file = "wrapt-1.17.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4d63f4d446e10ad19ed01188d6c1e1bb134cde8c18b0aa2acfd973d41fcc5ada"},
+ {file = "wrapt-1.17.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8a5e7cc39a45fc430af1aefc4d77ee6bad72c5bcdb1322cfde852c15192b8bd4"},
+ {file = "wrapt-1.17.0-cp312-cp312-win32.whl", hash = "sha256:0a0a1a1ec28b641f2a3a2c35cbe86c00051c04fffcfcc577ffcdd707df3f8635"},
+ {file = "wrapt-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:3c34f6896a01b84bab196f7119770fd8466c8ae3dfa73c59c0bb281e7b588ce7"},
+ {file = "wrapt-1.17.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:714c12485aa52efbc0fc0ade1e9ab3a70343db82627f90f2ecbc898fdf0bb181"},
+ {file = "wrapt-1.17.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da427d311782324a376cacb47c1a4adc43f99fd9d996ffc1b3e8529c4074d393"},
+ {file = "wrapt-1.17.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba1739fb38441a27a676f4de4123d3e858e494fac05868b7a281c0a383c098f4"},
+ {file = "wrapt-1.17.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e711fc1acc7468463bc084d1b68561e40d1eaa135d8c509a65dd534403d83d7b"},
+ {file = "wrapt-1.17.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:140ea00c87fafc42739bd74a94a5a9003f8e72c27c47cd4f61d8e05e6dec8721"},
+ {file = "wrapt-1.17.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:73a96fd11d2b2e77d623a7f26e004cc31f131a365add1ce1ce9a19e55a1eef90"},
+ {file = "wrapt-1.17.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0b48554952f0f387984da81ccfa73b62e52817a4386d070c75e4db7d43a28c4a"},
+ {file = "wrapt-1.17.0-cp313-cp313-win32.whl", hash = "sha256:498fec8da10e3e62edd1e7368f4b24aa362ac0ad931e678332d1b209aec93045"},
+ {file = "wrapt-1.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:fd136bb85f4568fffca995bd3c8d52080b1e5b225dbf1c2b17b66b4c5fa02838"},
+ {file = "wrapt-1.17.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:17fcf043d0b4724858f25b8826c36e08f9fb2e475410bece0ec44a22d533da9b"},
+ {file = "wrapt-1.17.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4a557d97f12813dc5e18dad9fa765ae44ddd56a672bb5de4825527c847d6379"},
+ {file = "wrapt-1.17.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0229b247b0fc7dee0d36176cbb79dbaf2a9eb7ecc50ec3121f40ef443155fb1d"},
+ {file = "wrapt-1.17.0-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8425cfce27b8b20c9b89d77fb50e368d8306a90bf2b6eef2cdf5cd5083adf83f"},
+ {file = "wrapt-1.17.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9c900108df470060174108012de06d45f514aa4ec21a191e7ab42988ff42a86c"},
+ {file = "wrapt-1.17.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:4e547b447073fc0dbfcbff15154c1be8823d10dab4ad401bdb1575e3fdedff1b"},
+ {file = "wrapt-1.17.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:914f66f3b6fc7b915d46c1cc424bc2441841083de01b90f9e81109c9759e43ab"},
+ {file = "wrapt-1.17.0-cp313-cp313t-win32.whl", hash = "sha256:a4192b45dff127c7d69b3bdfb4d3e47b64179a0b9900b6351859f3001397dabf"},
+ {file = "wrapt-1.17.0-cp313-cp313t-win_amd64.whl", hash = "sha256:4f643df3d4419ea3f856c5c3f40fec1d65ea2e89ec812c83f7767c8730f9827a"},
+ {file = "wrapt-1.17.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:69c40d4655e078ede067a7095544bcec5a963566e17503e75a3a3e0fe2803b13"},
+ {file = "wrapt-1.17.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f495b6754358979379f84534f8dd7a43ff8cff2558dcdea4a148a6e713a758f"},
+ {file = "wrapt-1.17.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:baa7ef4e0886a6f482e00d1d5bcd37c201b383f1d314643dfb0367169f94f04c"},
+ {file = "wrapt-1.17.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8fc931382e56627ec4acb01e09ce66e5c03c384ca52606111cee50d931a342d"},
+ {file = "wrapt-1.17.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:8f8909cdb9f1b237786c09a810e24ee5e15ef17019f7cecb207ce205b9b5fcce"},
+ {file = "wrapt-1.17.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ad47b095f0bdc5585bced35bd088cbfe4177236c7df9984b3cc46b391cc60627"},
+ {file = "wrapt-1.17.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:948a9bd0fb2c5120457b07e59c8d7210cbc8703243225dbd78f4dfc13c8d2d1f"},
+ {file = "wrapt-1.17.0-cp38-cp38-win32.whl", hash = "sha256:5ae271862b2142f4bc687bdbfcc942e2473a89999a54231aa1c2c676e28f29ea"},
+ {file = "wrapt-1.17.0-cp38-cp38-win_amd64.whl", hash = "sha256:f335579a1b485c834849e9075191c9898e0731af45705c2ebf70e0cd5d58beed"},
+ {file = "wrapt-1.17.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d751300b94e35b6016d4b1e7d0e7bbc3b5e1751e2405ef908316c2a9024008a1"},
+ {file = "wrapt-1.17.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7264cbb4a18dc4acfd73b63e4bcfec9c9802614572025bdd44d0721983fc1d9c"},
+ {file = "wrapt-1.17.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33539c6f5b96cf0b1105a0ff4cf5db9332e773bb521cc804a90e58dc49b10578"},
+ {file = "wrapt-1.17.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c30970bdee1cad6a8da2044febd824ef6dc4cc0b19e39af3085c763fdec7de33"},
+ {file = "wrapt-1.17.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:bc7f729a72b16ee21795a943f85c6244971724819819a41ddbaeb691b2dd85ad"},
+ {file = "wrapt-1.17.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:6ff02a91c4fc9b6a94e1c9c20f62ea06a7e375f42fe57587f004d1078ac86ca9"},
+ {file = "wrapt-1.17.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2dfb7cff84e72e7bf975b06b4989477873dcf160b2fd89959c629535df53d4e0"},
+ {file = "wrapt-1.17.0-cp39-cp39-win32.whl", hash = "sha256:2399408ac33ffd5b200480ee858baa58d77dd30e0dd0cab6a8a9547135f30a88"},
+ {file = "wrapt-1.17.0-cp39-cp39-win_amd64.whl", hash = "sha256:4f763a29ee6a20c529496a20a7bcb16a73de27f5da6a843249c7047daf135977"},
+ {file = "wrapt-1.17.0-py3-none-any.whl", hash = "sha256:d2c63b93548eda58abf5188e505ffed0229bf675f7c3090f8e36ad55b8cbc371"},
+ {file = "wrapt-1.17.0.tar.gz", hash = "sha256:16187aa2317c731170a88ef35e8937ae0f533c402872c1ee5e6d079fcf320801"},
]
[[package]]
@@ -2491,4 +2499,4 @@ cffi = ["cffi (>=1.11)"]
[metadata]
lock-version = "2.0"
python-versions = "^3.10"
-content-hash = "7193746daa73f589d96617384b1e9dc9cc3e52893cef0b80c33499f4cd644ea9"
+content-hash = "4ce070b9f91937ed235c7f5956c7ca78c7a5d7fc9236b689a1a9bc1e326651dd"
diff --git a/pyproject.toml b/pyproject.toml
index 991f28f5..0564cd92 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -84,7 +84,9 @@ mypy = "^1.7.0"
deprecated = "^1.2.14"
events = "^0.5"
numpy = "^1.26.2"
-jito-searcher-client = "0.1.4"
+# jito-searcher-client = "0.1.5"
+grpcio = "1.68.1"
+protobuf = "5.29.2"
[tool.poetry.dev-dependencies]
pytest = "^7.2.0"
@@ -97,6 +99,7 @@ mkdocs-material = "^8.1.8"
bump2version = "^1.0.1"
autopep8 = "^2.0.4"
mypy = "^1.7.0"
+python-dotenv = "^1.0.0"
[tool.poetry.group.dev.dependencies]
pytest = "^7.4.4"
diff --git a/src/driftpy/tx/jito_subscriber.py b/src/driftpy/tx/jito_subscriber.py
index cf5789c3..8d661876 100644
--- a/src/driftpy/tx/jito_subscriber.py
+++ b/src/driftpy/tx/jito_subscriber.py
@@ -1,25 +1,29 @@
+raise ImportError(
+ "The jito_subscriber module is deprecated and has been removed in driftpy."
+)
+
import asyncio
import random
-
from typing import Optional, Tuple, Union
-from solders.keypair import Keypair # type: ignore
-from solders.pubkey import Pubkey # type: ignore
-
-from solana.rpc.async_api import AsyncClient
-from solana.rpc.commitment import Confirmed
-
-from solders.system_program import TransferParams, transfer
-
-from jito_searcher_client.async_searcher import get_async_searcher_client # type: ignore
-from jito_searcher_client.generated.searcher_pb2_grpc import SearcherServiceStub # type: ignore
+from jito_searcher_client.async_searcher import (
+ get_async_searcher_client, # type: ignore
+)
from jito_searcher_client.generated.searcher_pb2 import (
- ConnectedLeadersResponse,
ConnectedLeadersRequest,
+ ConnectedLeadersResponse,
GetTipAccountsRequest,
GetTipAccountsResponse,
SubscribeBundleResultsRequest,
) # type: ignore
+from jito_searcher_client.generated.searcher_pb2_grpc import (
+ SearcherServiceStub, # type: ignore
+)
+from solana.rpc.async_api import AsyncClient
+from solana.rpc.commitment import Confirmed
+from solders.keypair import Keypair # type: ignore
+from solders.pubkey import Pubkey # type: ignore
+from solders.system_program import TransferParams, transfer
class JitoSubscriber:
diff --git a/src/driftpy/tx/jito_tx_sender.py b/src/driftpy/tx/jito_tx_sender.py
index 73e4fc3c..77e7df94 100644
--- a/src/driftpy/tx/jito_tx_sender.py
+++ b/src/driftpy/tx/jito_tx_sender.py
@@ -1,11 +1,22 @@
-import asyncio
+raise ImportError(
+ "The jito_tx_sender module is deprecated and has been removed in driftpy. "
+)
+import asyncio
from typing import Optional, Union
-from solana.transaction import Transaction
-from solana.rpc.types import TxOpts
+from jito_searcher_client.convert import (
+ tx_to_protobuf_packet,
+ versioned_tx_to_protobuf_packet,
+)
+from jito_searcher_client.generated.bundle_pb2 import Bundle
+from jito_searcher_client.generated.searcher_pb2 import (
+ SendBundleRequest,
+ SendBundleResponse,
+)
from solana.rpc.commitment import Commitment, Confirmed
-
+from solana.rpc.types import TxOpts
+from solana.transaction import Transaction
from solders.keypair import Keypair # type: ignore
from solders.transaction import VersionedTransaction # type: ignore
@@ -15,16 +26,6 @@
from driftpy.tx.jito_subscriber import JitoSubscriber
from driftpy.tx.types import TxSigAndSlot
-from jito_searcher_client.convert import (
- versioned_tx_to_protobuf_packet,
- tx_to_protobuf_packet,
-)
-from jito_searcher_client.generated.bundle_pb2 import Bundle
-from jito_searcher_client.generated.searcher_pb2 import (
- SendBundleRequest,
- SendBundleResponse,
-)
-
class JitoTxSender(FastTxSender):
def __init__(
From afe5da15257b905d9ce8c35a103f46783ce5c429 Mon Sep 17 00:00:00 2001
From: sina <20732540+SinaKhalili@users.noreply.github.com>
Date: Tue, 31 Dec 2024 04:51:12 -0800
Subject: [PATCH 03/15] Add grpc client
---
.../accounts/grpc/account_subscriber.py | 251 ++++++++++++++++++
src/driftpy/accounts/grpc/drift_client.py | 153 +++++++++++
src/driftpy/accounts/grpc/user.py | 12 +
3 files changed, 416 insertions(+)
create mode 100644 src/driftpy/accounts/grpc/account_subscriber.py
create mode 100644 src/driftpy/accounts/grpc/drift_client.py
create mode 100644 src/driftpy/accounts/grpc/user.py
diff --git a/src/driftpy/accounts/grpc/account_subscriber.py b/src/driftpy/accounts/grpc/account_subscriber.py
new file mode 100644
index 00000000..0d79ff76
--- /dev/null
+++ b/src/driftpy/accounts/grpc/account_subscriber.py
@@ -0,0 +1,251 @@
+import asyncio
+import time
+from typing import Callable, Optional, TypeVar
+
+import grpc.aio
+from anchorpy.program.core import Program
+from solana.rpc.commitment import Commitment
+from solders.pubkey import Pubkey
+
+from driftpy.accounts.grpc.geyser_codegen import geyser_pb2, geyser_pb2_grpc
+from driftpy.accounts.oracle import get_oracle_decode_fn
+from driftpy.accounts.types import DataAndSlot, FullOracleWrapper
+from driftpy.accounts.ws.account_subscriber import WebsocketAccountSubscriber
+from driftpy.constants.config import DRIFT_PROGRAM_ID, find_all_market_and_oracles
+from driftpy.types import GrpcConfig, OraclePriceData
+
+T = TypeVar("T")
+
+
+class TritonAuthMetadataPlugin(grpc.AuthMetadataPlugin):
+ def __init__(self, x_token: str):
+ self.x_token = x_token
+
+ def __call__(
+ self,
+ context: grpc.AuthMetadataContext,
+ callback: grpc.AuthMetadataPluginCallback,
+ ):
+ metadata = (("x-token", self.x_token),)
+ callback(metadata, None)
+
+
+class GrpcAccountSubscriber(WebsocketAccountSubscriber[T]):
+ def __init__(
+ self,
+ grpc_config: GrpcConfig,
+ account_name: str,
+ program: Program,
+ account_public_key: Pubkey,
+ commitment: Commitment = Commitment("confirmed"),
+ decode: Optional[Callable[[bytes], T]] = None,
+ initial_data: Optional[DataAndSlot[T]] = None,
+ ):
+ super().__init__(account_public_key, program, commitment, decode, initial_data)
+ self.client = self._create_grpc_client(grpc_config)
+ self.stream = None
+ self.listener_id = None
+ self.account_name = account_name
+ self.decode = (
+ decode if decode is not None else self.program.coder.accounts.decode
+ )
+
+ def _create_grpc_client(self, config: GrpcConfig) -> geyser_pb2_grpc.GeyserStub:
+ auth = TritonAuthMetadataPlugin(config.token)
+ ssl_creds = grpc.ssl_channel_credentials()
+ call_creds = grpc.metadata_call_credentials(auth)
+ combined_creds = grpc.composite_channel_credentials(ssl_creds, call_creds)
+
+ channel = grpc.aio.secure_channel(config.endpoint, credentials=combined_creds)
+ return geyser_pb2_grpc.GeyserStub(channel)
+
+ async def subscribe(self) -> Optional[asyncio.Task[None]]:
+ if self.listener_id is not None:
+ return
+
+ self.task = asyncio.create_task(self._subscribe_grpc())
+ return self.task
+
+ async def _subscribe_grpc(self):
+ """Internal method to handle the gRPC subscription"""
+ if self.data_and_slot is None:
+ await self.fetch()
+
+ try:
+ request_iterator = self._create_subscribe_request()
+ self.stream = self.client.Subscribe(request_iterator)
+ self.listener_id = 1
+
+ async for update in self.stream:
+ print(f"Got update for {self.account_name}", update)
+ try:
+ if update.HasField("ping") or update.HasField("pong"):
+ continue
+
+ if not update.HasField("account"):
+ print(f"No account for {self.account_name}")
+ continue
+
+ slot = int(update.account.slot)
+ account_info = {
+ "owner": Pubkey.from_bytes(update.account.account.owner),
+ "lamports": int(update.account.account.lamports),
+ "data": bytes(update.account.account.data),
+ "executable": update.account.account.executable,
+ "rent_epoch": int(update.account.account.rent_epoch),
+ }
+
+ if not account_info["data"]:
+ print(f"No data for {self.account_name}")
+ continue
+
+ decoded_data = (
+ self.decode(account_info["data"])
+ if self.decode
+ else account_info
+ )
+ self.update_data(DataAndSlot(slot, decoded_data))
+
+ except Exception as e:
+ print(f"Error processing account data for {self.account_name}: {e}")
+ break
+
+ except Exception as e:
+ print(f"Error in gRPC subscription for {self.account_name}: {e}")
+ if self.stream:
+ self.stream.cancel()
+ self.listener_id = None
+ raise e
+
+ async def _create_subscribe_request(self):
+ request = geyser_pb2.SubscribeRequest()
+ account_filter = geyser_pb2.SubscribeRequestFilterAccounts()
+ account_filter.account.append(str(self.pubkey))
+ account_filter.nonempty_txn_signature = True
+ request.accounts["account_monitor"].CopyFrom(account_filter)
+
+ request.commitment = geyser_pb2.CommitmentLevel.CONFIRMED
+ if self.commitment == Commitment("finalized"):
+ request.commitment = geyser_pb2.CommitmentLevel.FINALIZED
+ if self.commitment == Commitment("processed"):
+ request.commitment = geyser_pb2.CommitmentLevel.PROCESSED
+
+ yield request
+
+ while True:
+ await asyncio.sleep(30)
+ ping_request = geyser_pb2.SubscribeRequest()
+ ping_request.ping.id = int(time.time())
+ yield ping_request
+
+ async def unsubscribe(self) -> None:
+ if self.listener_id is not None:
+ try:
+ if self.stream:
+ await self.stream.cancel()
+ self.listener_id = None
+ except Exception as e:
+ print(f"Error unsubscribing from account {self.account_name}: {e}")
+ raise e
+
+ def update_data(self, new_data: Optional[DataAndSlot[T]]):
+ if new_data is None:
+ return
+
+ if self.data_and_slot is None or new_data.slot >= self.data_and_slot.slot:
+ self.data_and_slot = new_data
+ print("Good stuff!")
+
+
+async def start_subscribers(
+ full_oracle_wrappers: list[FullOracleWrapper],
+ rpc_fqdn: str,
+ x_token: str,
+ program: Program,
+):
+ tasks = []
+ subscribers = []
+
+ for oracle in full_oracle_wrappers:
+ subscriber = GrpcAccountSubscriber[OraclePriceData](
+ GrpcConfig(
+ endpoint=rpc_fqdn, token=x_token, commitment=Commitment("confirmed")
+ ),
+ str(oracle.pubkey),
+ program,
+ oracle.pubkey,
+ decode=get_oracle_decode_fn(oracle.oracle_source),
+ initial_data=oracle.oracle_price_data_and_slot,
+ )
+ subscribers.append(subscriber)
+ task = await subscriber.subscribe()
+ tasks.append(task)
+
+ asyncio.gather(*tasks)
+ return subscribers
+
+
+async def main():
+ import os
+ from pathlib import Path
+
+ import dotenv
+ from anchorpy.program.core import Program
+ from anchorpy.provider import Provider, Wallet
+ from anchorpy_core.idl import Idl
+ from solana.rpc.async_api import AsyncClient
+ from solders.keypair import Keypair
+
+ import driftpy
+
+ dotenv.load_dotenv()
+
+ rpc_fqdn = os.environ.get("RPC_FQDN")
+ x_token = os.environ.get("X_TOKEN")
+ pk = os.environ.get("PUBKEY")
+ private_key = os.environ.get("PRIVATE_KEY")
+ rpc_url = os.environ.get("RPC_TRITON")
+
+ if not rpc_fqdn or not x_token or not pk or not private_key:
+ raise ValueError("RPC_FDQN, X_TOKEN, PUBKEY, and PRIVATE_KEY must be set")
+
+ file = Path(str(next(iter(driftpy.__path__))) + "/idl/drift.json")
+ idl = Idl.from_json(file.read_text())
+ program_id = DRIFT_PROGRAM_ID
+
+ connection = AsyncClient(rpc_url)
+
+ wallet = Keypair.from_base58_string(private_key)
+ wallet = Wallet(wallet)
+ from driftpy.drift_client import DEFAULT_TX_OPTIONS
+
+ opts = DEFAULT_TX_OPTIONS
+ provider = Provider(connection, wallet, opts)
+
+ program = Program(idl, program_id, provider)
+
+ (
+ perp_ds,
+ spot_ds,
+ full_oracle_wrappers,
+ ) = await find_all_market_and_oracles(program)
+
+ full_oracle_wrappers = full_oracle_wrappers
+
+ subscribers = await start_subscribers(
+ full_oracle_wrappers, rpc_fqdn, x_token, program
+ )
+
+ print("All subscribers started")
+
+ # Keep the program running
+ try:
+ await asyncio.Event().wait() # This will never complete
+ except KeyboardInterrupt:
+ # Handle cleanup
+ for subscriber in subscribers:
+ await subscriber.unsubscribe()
+
+
+if __name__ == "__main__":
+ asyncio.run(main())
diff --git a/src/driftpy/accounts/grpc/drift_client.py b/src/driftpy/accounts/grpc/drift_client.py
new file mode 100644
index 00000000..a4c38bfd
--- /dev/null
+++ b/src/driftpy/accounts/grpc/drift_client.py
@@ -0,0 +1,153 @@
+from typing import Sequence
+
+from anchorpy.program.core import Program
+from solana.rpc.commitment import Commitment
+from solders.pubkey import Pubkey
+
+from driftpy.accounts.grpc.account_subscriber import GrpcAccountSubscriber, GrpcConfig
+from driftpy.accounts.oracle import get_oracle_decode_fn
+from driftpy.accounts.types import FullOracleWrapper
+from driftpy.accounts.ws.drift_client import WebsocketDriftClientAccountSubscriber
+from driftpy.addresses import (
+ get_perp_market_public_key,
+ get_spot_market_public_key,
+ get_state_public_key,
+)
+from driftpy.constants.config import find_all_market_and_oracles
+from driftpy.oracles.oracle_id import get_oracle_id
+from driftpy.types import (
+ OraclePriceData,
+ PerpMarketAccount,
+ SpotMarketAccount,
+ StateAccount,
+)
+
+
+class GrpcDriftClientAccountSubscriber(WebsocketDriftClientAccountSubscriber):
+ def __init__(
+ self,
+ program: Program,
+ grpc_config: GrpcConfig,
+ perp_market_indexes: Sequence[int],
+ spot_market_indexes: Sequence[int],
+ full_oracle_wrappers: Sequence[FullOracleWrapper],
+ should_find_all_markets_and_oracles: bool,
+ commitment: Commitment = Commitment("confirmed"),
+ ):
+ super().__init__(
+ program,
+ perp_market_indexes,
+ spot_market_indexes,
+ full_oracle_wrappers,
+ should_find_all_markets_and_oracles,
+ commitment,
+ )
+ self.grpc_config = grpc_config
+
+ async def subscribe_to_spot_market(self, market_index: int):
+ if market_index in self.spot_market_subscribers:
+ return
+
+ spot_market_public_key = get_spot_market_public_key(
+ self.program.program_id, market_index
+ )
+ spot_market_subscriber = GrpcAccountSubscriber[SpotMarketAccount](
+ self.grpc_config,
+ f"spot_market_{market_index}",
+ self.program,
+ spot_market_public_key,
+ self.commitment,
+ )
+ await spot_market_subscriber.subscribe()
+ self.spot_market_subscribers[market_index] = spot_market_subscriber
+
+ async def subscribe_to_perp_market(self, market_index: int):
+ if market_index in self.perp_market_subscribers:
+ return
+
+ perp_market_public_key = get_perp_market_public_key(
+ self.program.program_id, market_index
+ )
+ perp_market_subscriber = GrpcAccountSubscriber[PerpMarketAccount](
+ self.grpc_config,
+ f"perp_market_{market_index}",
+ self.program,
+ perp_market_public_key,
+ self.commitment,
+ )
+ await perp_market_subscriber.subscribe()
+ self.perp_market_subscribers[market_index] = perp_market_subscriber
+
+ async def subscribe_to_oracle(self, full_oracle_wrapper: FullOracleWrapper):
+ if full_oracle_wrapper.pubkey == Pubkey.default():
+ return
+
+ oracle_id = get_oracle_id(
+ full_oracle_wrapper.pubkey,
+ full_oracle_wrapper.oracle_source,
+ )
+ if oracle_id in self.oracle_subscribers:
+ return
+
+ oracle_subscriber = GrpcAccountSubscriber[OraclePriceData](
+ self.grpc_config,
+ f"oracle_{oracle_id}",
+ self.program,
+ full_oracle_wrapper.pubkey,
+ self.commitment,
+ decode=get_oracle_decode_fn(full_oracle_wrapper.oracle_source),
+ initial_data=full_oracle_wrapper.oracle_price_data_and_slot,
+ )
+
+ await oracle_subscriber.subscribe()
+ self.oracle_subscribers[oracle_id] = oracle_subscriber
+
+ async def subscribe(self):
+ if self.is_subscribed():
+ return
+
+ state_public_key = get_state_public_key(self.program.program_id)
+ self.state_subscriber = GrpcAccountSubscriber[StateAccount](
+ self.grpc_config,
+ "state",
+ self.program,
+ state_public_key,
+ self.commitment,
+ )
+ await self.state_subscriber.subscribe()
+
+ if self.should_find_all_markets_and_oracles:
+ (
+ perp_ds,
+ spot_ds,
+ full_oracle_wrappers,
+ ) = await find_all_market_and_oracles(self.program)
+
+ self.perp_market_indexes = [
+ data_and_slot.data.market_index for data_and_slot in perp_ds
+ ]
+ self.spot_market_indexes = [
+ data_and_slot.data.market_index for data_and_slot in spot_ds
+ ]
+ self.full_oracle_wrappers = full_oracle_wrappers
+
+ for full_oracle_wrapper in self.full_oracle_wrappers:
+ await self.subscribe_to_oracle(full_oracle_wrapper)
+
+ for market_index in self.perp_market_indexes:
+ await self.subscribe_to_perp_market(market_index)
+
+ for market_index in self.spot_market_indexes:
+ await self.subscribe_to_spot_market(market_index)
+ else:
+ for market_index in self.perp_market_indexes:
+ await self.subscribe_to_perp_market(market_index)
+
+ for market_index in self.spot_market_indexes:
+ await self.subscribe_to_spot_market(market_index)
+
+ for full_oracle_wrapper in self.full_oracle_wrappers:
+ await self.subscribe_to_oracle(full_oracle_wrapper)
+
+ await self._set_perp_oracle_map()
+ await self._set_spot_oracle_map()
diff --git a/src/driftpy/accounts/grpc/user.py b/src/driftpy/accounts/grpc/user.py
new file mode 100644
index 00000000..6d6b3bee
--- /dev/null
+++ b/src/driftpy/accounts/grpc/user.py
@@ -0,0 +1,12 @@
+from typing import Optional
+
+from driftpy.accounts.grpc.account_subscriber import GrpcAccountSubscriber
+from driftpy.accounts.types import DataAndSlot, UserAccountSubscriber
+from driftpy.types import UserAccount
+
+
+class GrpcUserAccountSubscriber(
+ GrpcAccountSubscriber[UserAccount], UserAccountSubscriber
+):
+ def get_user_account_and_slot(self) -> Optional[DataAndSlot[UserAccount]]:
+ return self.data_and_slot
From 5c5fc8a9ad846d53af542f75874a432abde0f06a Mon Sep 17 00:00:00 2001
From: sina <20732540+SinaKhalili@users.noreply.github.com>
Date: Thu, 2 Jan 2025 00:33:59 -0800
Subject: [PATCH 04/15] Add example: initializing GRPC
---
examples/grpc_client.py | 90 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 90 insertions(+)
create mode 100644 examples/grpc_client.py
diff --git a/examples/grpc_client.py b/examples/grpc_client.py
new file mode 100644
index 00000000..9c02dbf2
--- /dev/null
+++ b/examples/grpc_client.py
@@ -0,0 +1,90 @@
+import asyncio
+import os
+
+from anchorpy.provider import Provider, Wallet
+from dotenv import load_dotenv
+from solana.rpc.async_api import AsyncClient
+from solana.rpc.commitment import Commitment
+from solders.keypair import Keypair
+
+from driftpy.drift_client import AccountSubscriptionConfig, DriftClient
+from driftpy.types import GrpcConfig
+
+load_dotenv()
+
+RED = "\033[91m"
+GREEN = "\033[92m"
+RESET = "\033[0m"
+
+CLEAR_SCREEN = "\033c"
+
+
+async def watch_drift_markets():
+ rpc_fqdn = os.environ.get("RPC_FQDN")
+ x_token = os.environ.get("X_TOKEN")
+ private_key = os.environ.get("PRIVATE_KEY")
+ rpc_url = os.environ.get("RPC_TRITON")
+
+ if not (rpc_fqdn and x_token and private_key and rpc_url):
+ raise ValueError("RPC_FQDN, X_TOKEN, PRIVATE_KEY, and RPC_TRITON must be set")
+
+ wallet = Wallet(Keypair.from_base58_string(private_key))
+ connection = AsyncClient(rpc_url)
+ provider = Provider(connection, wallet)
+
+ drift_client = DriftClient(
+ provider.connection,
+ provider.wallet,
+ "mainnet",
+ account_subscription=AccountSubscriptionConfig(
+ "grpc",
+ grpc_config=GrpcConfig(
+ endpoint=rpc_fqdn,
+ token=x_token,
+ commitment=Commitment("confirmed"),
+ ),
+ ),
+ )
+
+ await drift_client.subscribe()
+ print("Subscribed via gRPC. Listening for market updates...")
+
+ previous_prices = {}
+
+ while True:
+ print(CLEAR_SCREEN, end="")
+
+ perp_markets = drift_client.get_perp_market_accounts()
+
+ if not perp_markets:
+ print(f"{RED}No perp markets found (yet){RESET}")
+ else:
+ print("Drift Perp Markets (gRPC subscription)\n")
+ perp_markets.sort(key=lambda x: x.market_index)
+ for market in perp_markets[:20]:
+ market_index = market.market_index
+ last_price = market.amm.historical_oracle_data.last_oracle_price / 1e6
+
+ if market_index in previous_prices:
+ old_price = previous_prices[market_index]
+ if last_price > old_price:
+ color = GREEN
+ elif last_price < old_price:
+ color = RED
+ else:
+ color = RESET
+ else:
+ color = RESET
+
+ print(
+ f"Market Index: {market_index} | "
+ f"Price: {color}${last_price:.4f}{RESET}"
+ )
+
+ previous_prices[market_index] = last_price
+
+ await asyncio.sleep(1)
+
+
+if __name__ == "__main__":
+ asyncio.run(watch_drift_markets())
From 9137c37c3b06d6db594bf83f285b5dd6a5bc662c Mon Sep 17 00:00:00 2001
From: sina <20732540+SinaKhalili@users.noreply.github.com>
Date: Thu, 2 Jan 2025 00:34:21 -0800
Subject: [PATCH 05/15] Add grpc to account_subscription
---
src/driftpy/account_subscription_config.py | 31 +++++++++++++++++++++-
1 file changed, 30 insertions(+), 1 deletion(-)
diff --git a/src/driftpy/account_subscription_config.py b/src/driftpy/account_subscription_config.py
index 4114ca08..2eca382e 100644
--- a/src/driftpy/account_subscription_config.py
+++ b/src/driftpy/account_subscription_config.py
@@ -13,6 +13,9 @@
DemoDriftClientAccountSubscriber,
DemoUserAccountSubscriber,
)
+from driftpy.accounts.grpc.account_subscriber import GrpcConfig
+from driftpy.accounts.grpc.drift_client import GrpcDriftClientAccountSubscriber
+from driftpy.accounts.grpc.user import GrpcUserAccountSubscriber
from driftpy.accounts.polling import (
PollingDriftClientAccountSubscriber,
PollingUserAccountSubscriber,
@@ -32,13 +35,17 @@ def default():
def __init__(
self,
- account_subscription_type: Literal["polling", "websocket", "cached", "demo"],
+ account_subscription_type: Literal[
+ "polling", "websocket", "cached", "demo", "grpc"
+ ],
bulk_account_loader: Optional[BulkAccountLoader] = None,
commitment: Commitment = Commitment("confirmed"),
+ grpc_config: Optional[GrpcConfig] = None,
):
self.type = account_subscription_type
self.commitment = commitment
self.bulk_account_loader = None
+ self.grpc_config = grpc_config
if self.type != "polling":
return
@@ -117,6 +124,18 @@ def get_drift_client_subscriber(
oracle_infos,
self.commitment,
)
+ case "grpc":
+ if self.grpc_config is None:
+ raise ValueError("A grpc config is required for grpc subscription")
+ return GrpcDriftClientAccountSubscriber(
+ program,
+ self.grpc_config,
+ perp_market_indexes,
+ spot_market_indexes,
+ cast(list[FullOracleWrapper], oracle_infos),
+ should_find_all_markets_and_oracles,
+ self.commitment,
+ )
def get_user_client_subscriber(self, program: Program, user_pubkey: Pubkey):
match self.type:
@@ -138,3 +157,13 @@ def get_user_client_subscriber(self, program: Program, user_pubkey: Pubkey):
)
case "demo":
return DemoUserAccountSubscriber(user_pubkey, program, self.commitment)
+ case "grpc":
+ if self.grpc_config is None:
+ raise ValueError("A grpc config is required for grpc subscription")
+ return GrpcUserAccountSubscriber(
+ grpc_config=self.grpc_config,
+ account_name="user",
+ account_public_key=user_pubkey,
+ program=program,
+ commitment=self.commitment,
+ )
From f5d72c7875771cc4b7bfe904437e5cced4606991 Mon Sep 17 00:00:00 2001
From: sina <20732540+SinaKhalili@users.noreply.github.com>
Date: Thu, 2 Jan 2025 00:35:09 -0800
Subject: [PATCH 06/15] Drift user: refactor
---
src/driftpy/drift_user.py | 26 ++++++++++++++++----------
1 file changed, 16 insertions(+), 10 deletions(-)
diff --git a/src/driftpy/drift_user.py b/src/driftpy/drift_user.py
index 6f36ca38..1f705d1c 100644
--- a/src/driftpy/drift_user.py
+++ b/src/driftpy/drift_user.py
@@ -6,16 +6,20 @@
from driftpy.account_subscription_config import AccountSubscriptionConfig
from driftpy.accounts.oracle import *
from driftpy.math.amm import calculate_market_open_bid_ask
-from driftpy.math.fuel import calculate_insurance_fuel_bonus
-from driftpy.math.fuel import calculate_perp_fuel_bonus
-from driftpy.math.fuel import calculate_spot_fuel_bonus
+from driftpy.math.fuel import (
+ calculate_insurance_fuel_bonus,
+ calculate_perp_fuel_bonus,
+ calculate_spot_fuel_bonus,
+)
from driftpy.math.margin import *
from driftpy.math.oracles import calculate_live_oracle_twap
from driftpy.math.perp_position import *
from driftpy.math.spot_balance import get_strict_token_value
from driftpy.math.spot_market import *
-from driftpy.math.spot_position import get_worst_case_token_amounts
-from driftpy.math.spot_position import is_spot_position_available
+from driftpy.math.spot_position import (
+ get_worst_case_token_amounts,
+ is_spot_position_available,
+)
from driftpy.oracles.strict_oracle_price import StrictOraclePrice
from driftpy.types import OraclePriceData
@@ -27,9 +31,7 @@ def __init__(
self,
drift_client,
user_public_key: Pubkey,
- account_subscription: Optional[
- AccountSubscriptionConfig
- ] = AccountSubscriptionConfig.default(),
+ account_subscription: AccountSubscriptionConfig = AccountSubscriptionConfig.default(),
):
"""Initialize the user object
@@ -52,19 +54,23 @@ def __init__(
)
async def subscribe(self):
+ if self.account_subscriber is None:
+ raise ValueError("No account subscriber found")
await self.account_subscriber.subscribe()
def unsubscribe(self):
+ if self.account_subscriber is None:
+ raise ValueError("No account subscriber found")
self.account_subscriber.unsubscribe()
def get_oracle_data_for_spot_market(
self, market_index: int
- ) -> Optional[OraclePriceData]:
+ ) -> OraclePriceData | None:
return self.drift_client.get_oracle_price_data_for_spot_market(market_index)
def get_oracle_data_for_perp_market(
self, market_index: int
- ) -> Optional[OraclePriceData]:
+ ) -> OraclePriceData | None:
return self.drift_client.get_oracle_price_data_for_perp_market(market_index)
def get_perp_market_account(self, market_index: int) -> PerpMarketAccount:
From 1eaa75f9f830518c9ac2d2d051e2c08db11a3171 Mon Sep 17 00:00:00 2001
From: sina <20732540+SinaKhalili@users.noreply.github.com>
Date: Thu, 2 Jan 2025 00:35:20 -0800
Subject: [PATCH 07/15] GRPC add unsubscribe
---
src/driftpy/accounts/grpc/drift_client.py | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/src/driftpy/accounts/grpc/drift_client.py b/src/driftpy/accounts/grpc/drift_client.py
index a4c38bfd..7b4535c8 100644
--- a/src/driftpy/accounts/grpc/drift_client.py
+++ b/src/driftpy/accounts/grpc/drift_client.py
@@ -151,3 +151,18 @@ async def subscribe(self):
await self._set_perp_oracle_map()
await self._set_spot_oracle_map()
+ await self.fetch()
+
+ async def unsubscribe(self):
+ if self.is_subscribed():
+ await self.state_subscriber.unsubscribe()
+ if self.spot_market_map and self.perp_market_map:
+ await self.spot_market_map.unsubscribe()
+ await self.perp_market_map.unsubscribe()
+ else:
+ for spot_market_subscriber in self.spot_market_subscribers.values():
+ await spot_market_subscriber.unsubscribe()
+ for perp_market_subscriber in self.perp_market_subscribers.values():
+ await perp_market_subscriber.unsubscribe()
+ for oracle_subscriber in self.oracle_subscribers.values():
+ await oracle_subscriber.unsubscribe()
From 66844d5cdda3cf9b1b1394a769378522ec77ee71 Mon Sep 17 00:00:00 2001
From: sina <20732540+SinaKhalili@users.noreply.github.com>
Date: Thu, 2 Jan 2025 00:35:45 -0800
Subject: [PATCH 08/15] GRPC remove logging
---
.../accounts/grpc/account_subscriber.py | 106 +-----------------
1 file changed, 5 insertions(+), 101 deletions(-)
diff --git a/src/driftpy/accounts/grpc/account_subscriber.py b/src/driftpy/accounts/grpc/account_subscriber.py
index 0d79ff76..b0575f38 100644
--- a/src/driftpy/accounts/grpc/account_subscriber.py
+++ b/src/driftpy/accounts/grpc/account_subscriber.py
@@ -8,11 +8,9 @@
from solders.pubkey import Pubkey
from driftpy.accounts.grpc.geyser_codegen import geyser_pb2, geyser_pb2_grpc
-from driftpy.accounts.oracle import get_oracle_decode_fn
-from driftpy.accounts.types import DataAndSlot, FullOracleWrapper
+from driftpy.accounts.types import DataAndSlot
from driftpy.accounts.ws.account_subscriber import WebsocketAccountSubscriber
-from driftpy.constants.config import DRIFT_PROGRAM_ID, find_all_market_and_oracles
-from driftpy.types import GrpcConfig, OraclePriceData
+from driftpy.types import GrpcConfig
T = TypeVar("T")
@@ -74,10 +72,11 @@ async def _subscribe_grpc(self):
try:
request_iterator = self._create_subscribe_request()
self.stream = self.client.Subscribe(request_iterator)
+ await self.stream.wait_for_connection()
+
self.listener_id = 1
async for update in self.stream:
- print(f"Got update for {self.account_name}", update)
try:
if update.HasField("ping") or update.HasField("pong"):
continue
@@ -142,7 +141,7 @@ async def unsubscribe(self) -> None:
if self.listener_id is not None:
try:
if self.stream:
- await self.stream.cancel()
+ self.stream.cancel()
self.listener_id = None
except Exception as e:
print(f"Error unsubscribing from account {self.account_name}: {e}")
@@ -154,98 +153,3 @@ def update_data(self, new_data: Optional[DataAndSlot[T]]):
if self.data_and_slot is None or new_data.slot >= self.data_and_slot.slot:
self.data_and_slot = new_data
- print("Good stuff!")
-
-
-async def start_subscribers(
- full_oracle_wrappers: list[FullOracleWrapper],
- rpc_fqdn: str,
- x_token: str,
- program: Program,
-):
- tasks = []
- subscribers = []
-
- for oracle in full_oracle_wrappers:
- subscriber = GrpcAccountSubscriber[OraclePriceData](
- GrpcConfig(
- endpoint=rpc_fqdn, token=x_token, commitment=Commitment("confirmed")
- ),
- str(oracle.pubkey),
- program,
- oracle.pubkey,
- decode=get_oracle_decode_fn(oracle.oracle_source),
- initial_data=oracle.oracle_price_data_and_slot,
- )
- subscribers.append(subscriber)
- task = await subscriber.subscribe()
- tasks.append(task)
-
- asyncio.gather(*tasks)
- return subscribers
-
-
-async def main():
- import os
- from pathlib import Path
-
- import dotenv
- from anchorpy.program.core import Program
- from anchorpy.provider import Provider, Wallet
- from anchorpy_core.idl import Idl
- from solana.rpc.async_api import AsyncClient
- from solders.keypair import Keypair
-
- import driftpy
-
- dotenv.load_dotenv()
-
- rpc_fqdn = os.environ.get("RPC_FQDN")
- x_token = os.environ.get("X_TOKEN")
- pk = os.environ.get("PUBKEY")
- private_key = os.environ.get("PRIVATE_KEY")
- rpc_url = os.environ.get("RPC_TRITON")
-
- if not rpc_fqdn or not x_token or not pk or not private_key:
- raise ValueError("RPC_FDQN, X_TOKEN, PUBKEY, and PRIVATE_KEY must be set")
-
- file = Path(str(next(iter(driftpy.__path__))) + "/idl/drift.json")
- idl = Idl.from_json(file.read_text())
- program_id = DRIFT_PROGRAM_ID
-
- connection = AsyncClient(rpc_url)
-
- wallet = Keypair.from_base58_string(private_key)
- wallet = Wallet(wallet)
- from driftpy.drift_client import DEFAULT_TX_OPTIONS
-
- opts = DEFAULT_TX_OPTIONS
- provider = Provider(connection, wallet, opts)
-
- program = Program(idl, program_id, provider)
-
- (
- perp_ds,
- spot_ds,
- full_oracle_wrappers,
- ) = await find_all_market_and_oracles(program)
-
- full_oracle_wrappers = full_oracle_wrappers
-
- subscribers = await start_subscribers(
- full_oracle_wrappers, rpc_fqdn, x_token, program
- )
-
- print("All subscribers started")
-
- # Keep the program running
- try:
- await asyncio.Event().wait() # This will never complete
- except KeyboardInterrupt:
- # Handle cleanup
- for subscriber in subscribers:
- await subscriber.unsubscribe()
-
-
-if __name__ == "__main__":
- asyncio.run(main())
From ab8453cdd9f829e57edec385156bda14f58bef27 Mon Sep 17 00:00:00 2001
From: sina <20732540+SinaKhalili@users.noreply.github.com>
Date: Thu, 2 Jan 2025 00:36:25 -0800
Subject: [PATCH 09/15] Update WS for typing
---
src/driftpy/accounts/ws/account_subscriber.py | 30 ++++++++-----------
1 file changed, 13 insertions(+), 17 deletions(-)
diff --git a/src/driftpy/accounts/ws/account_subscriber.py b/src/driftpy/accounts/ws/account_subscriber.py
index 1f04cb12..3c0a6de0 100644
--- a/src/driftpy/accounts/ws/account_subscriber.py
+++ b/src/driftpy/accounts/ws/account_subscriber.py
@@ -1,23 +1,19 @@
import asyncio
-from typing import Optional
+from typing import Callable, Generic, Optional, TypeVar, cast
-from anchorpy import Program
-from solders.pubkey import Pubkey
+import websockets
+import websockets.exceptions # force eager imports
+from anchorpy.program.core import Program
from solana.rpc.commitment import Commitment
+from solana.rpc.websocket_api import SolanaWsClientProtocol, connect
+from solders.pubkey import Pubkey
-from driftpy.accounts import get_account_data_and_slot
from driftpy.accounts import (
- UserAccountSubscriber,
DataAndSlot,
+ UserAccountSubscriber,
UserStatsAccountSubscriber,
+ get_account_data_and_slot,
)
-
-import websockets
-import websockets.exceptions # force eager imports
-from solana.rpc.websocket_api import connect
-
-from typing import cast, Generic, TypeVar, Callable
-
from driftpy.types import get_ws_url
T = TypeVar("T")
@@ -30,7 +26,7 @@ def __init__(
self,
pubkey: Pubkey,
program: Program,
- commitment: Commitment = "confirmed",
+ commitment: Commitment = Commitment("confirmed"),
decode: Optional[Callable[[bytes], T]] = None,
initial_data: Optional[DataAndSlot] = None,
):
@@ -42,7 +38,7 @@ def __init__(
self.decode = (
decode if decode is not None else self.program.coder.accounts.decode
)
- self.ws = None
+ self.ws: Optional[SolanaWsClientProtocol] = None
async def subscribe(self):
if self.data_and_slot is None:
@@ -60,8 +56,8 @@ async def subscribe_ws(self):
async for ws in connect(ws_endpoint):
try:
- self.ws = ws
- await ws.account_subscribe(
+ self.ws = cast(SolanaWsClientProtocol, ws)
+ await self.ws.account_subscribe(
self.pubkey,
commitment=self.commitment,
encoding="base64",
@@ -82,7 +78,7 @@ async def subscribe_ws(self):
except Exception:
print("Error processing account data")
break
- await ws.account_unsubscribe(subscription_id)
+ await self.ws.account_unsubscribe(subscription_id)
except websockets.exceptions.ConnectionClosed:
print("Websocket closed, reconnecting...")
continue
From 7bf940bad30b5e799c401a7d3987fbd55f2d795b Mon Sep 17 00:00:00 2001
From: sina <20732540+SinaKhalili@users.noreply.github.com>
Date: Thu, 2 Jan 2025 00:37:35 -0800
Subject: [PATCH 10/15] Update function get_data_and_slots
---
src/driftpy/accounts/polling/drift_client.py | 4 +-
src/driftpy/constants/config.py | 261 ++++++++++---------
2 files changed, 135 insertions(+), 130 deletions(-)
diff --git a/src/driftpy/accounts/polling/drift_client.py b/src/driftpy/accounts/polling/drift_client.py
index 9199a1b4..d377863a 100644
--- a/src/driftpy/accounts/polling/drift_client.py
+++ b/src/driftpy/accounts/polling/drift_client.py
@@ -12,7 +12,7 @@
get_spot_market_public_key,
get_state_public_key,
)
-from driftpy.constants.config import find_all_market_and_oracles
+from driftpy.constants.config import find_all_market_and_oracles_no_data_and_slots
from driftpy.oracles.oracle_id import get_oracle_id
from driftpy.types import (
OracleInfo,
@@ -64,7 +64,7 @@ async def subscribe(self):
perp_market_indexes,
spot_market_indexes,
oracle_infos,
- ) = await find_all_market_and_oracles(self.program)
+ ) = await find_all_market_and_oracles_no_data_and_slots(self.program)
self.perp_market_indexes = perp_market_indexes
self.spot_market_indexes = spot_market_indexes
self.oracle_infos = oracle_infos
diff --git a/src/driftpy/constants/config.py b/src/driftpy/constants/config.py
index ce02d0bc..7d3fa967 100644
--- a/src/driftpy/constants/config.py
+++ b/src/driftpy/constants/config.py
@@ -4,7 +4,7 @@
from typing import Literal, Optional, Sequence, Tuple, Union
import jsonrpcclient
-from anchorpy import Program
+from anchorpy.program.core import Program
from solders.pubkey import Pubkey
from driftpy.accounts.oracle import decode_oracle
@@ -84,142 +84,147 @@ class Config:
}
-async def find_all_market_and_oracles(
- program: Program, data_and_slots: bool = False
+async def find_all_market_and_oracles_no_data_and_slots(
+ program: Program,
) -> Tuple[
- Union[list[int], list[DataAndSlot[PerpMarketAccount]]],
- Union[list[int], list[DataAndSlot[SpotMarketAccount]]],
- Union[list[OracleInfo], list[FullOracleWrapper]],
+ list[int],
+ list[int],
+ list[OracleInfo],
]:
- if not data_and_slots:
- perp_market_indexes = []
- spot_market_indexes = []
- oracle_infos = {}
-
- perp_markets = await program.account["PerpMarket"].all()
- for perp_market in perp_markets:
- perp_market_indexes.append(perp_market.account.market_index)
- oracle = perp_market.account.amm.oracle
- oracle_source = perp_market.account.amm.oracle_source
- oracle_infos[str(oracle)] = OracleInfo(oracle, oracle_source)
-
- spot_markets = await program.account["SpotMarket"].all()
- for spot_market in spot_markets:
- spot_market_indexes.append(spot_market.account.market_index)
- oracle = spot_market.account.oracle
- oracle_source = spot_market.account.oracle_source
- oracle_infos[str(oracle)] = OracleInfo(oracle, oracle_source)
-
- return perp_market_indexes, spot_market_indexes, oracle_infos.values()
- else:
- perp_markets = []
- spot_markets = []
- oracle_infos = {}
-
- perp_filters = [{"memcmp": {"offset": 0, "bytes": "2pTyMkwXuti"}}]
- spot_filters = [{"memcmp": {"offset": 0, "bytes": "HqqNdyfVbzv"}}]
-
- perp_request = jsonrpcclient.request(
- "getProgramAccounts",
- (
- str(program.program_id),
- {"filters": perp_filters, "encoding": "base64", "withContext": True},
- ),
- )
-
- post = program.provider.connection._provider.session.post(
- program.provider.connection._provider.endpoint_uri,
- json=perp_request,
- headers={"content-encoding": "gzip"},
- )
- resp = await asyncio.wait_for(post, timeout=10)
- parsed_resp = jsonrpcclient.parse(resp.json())
-
- if isinstance(parsed_resp, jsonrpcclient.Error):
- raise ValueError(f"Error fetching perp markets: {parsed_resp.message}")
-
- if not isinstance(parsed_resp, jsonrpcclient.Ok):
- raise ValueError(f"Error fetching perp markets - not ok: {parsed_resp}")
-
- perp_slot = int(parsed_resp.result["context"]["slot"])
- perp_markets: list[PerpMarketAccount] = []
- for account in parsed_resp.result["value"]:
- perp_market = decode_account(account["account"]["data"][0], program)
- perp_markets.append(perp_market)
-
- perp_ds: list[DataAndSlot] = [
- DataAndSlot(perp_slot, perp_market) for perp_market in perp_markets
- ]
-
- spot_request = jsonrpcclient.request(
- "getProgramAccounts",
- (
- str(program.program_id),
- {"filters": spot_filters, "encoding": "base64", "withContext": True},
- ),
- )
-
- post = program.provider.connection._provider.session.post(
- program.provider.connection._provider.endpoint_uri,
- json=spot_request,
- headers={"content-encoding": "gzip"},
- )
- resp = await asyncio.wait_for(post, timeout=10)
- parsed_resp = jsonrpcclient.parse(resp.json())
-
- if isinstance(parsed_resp, jsonrpcclient.Error):
- raise ValueError(f"Error fetching spot markets: {parsed_resp.message}")
- if not isinstance(parsed_resp, jsonrpcclient.Ok):
- raise ValueError(f"Error fetching spot markets - not ok: {parsed_resp}")
-
- spot_slot = int(parsed_resp.result["context"]["slot"])
+ perp_market_indexes = []
+ spot_market_indexes = []
+ oracle_infos: dict[str, OracleInfo] = {}
- spot_markets: list[SpotMarketAccount] = []
- for account in parsed_resp.result["value"]:
- spot_market = decode_account(account["account"]["data"][0], program)
- spot_markets.append(spot_market)
+ perp_markets = await program.account["PerpMarket"].all()
+ for perp_market in perp_markets:
+ perp_market_indexes.append(perp_market.account.market_index)
+ oracle = perp_market.account.amm.oracle
+ oracle_source = perp_market.account.amm.oracle_source
+ oracle_infos[str(oracle)] = OracleInfo(oracle, oracle_source)
- spot_ds: list[DataAndSlot] = [
- DataAndSlot(spot_slot, spot_market) for spot_market in spot_markets
- ]
+ spot_markets = await program.account["SpotMarket"].all()
+ for spot_market in spot_markets:
+ spot_market_indexes.append(spot_market.account.market_index)
+ oracle = spot_market.account.oracle
+ oracle_source = spot_market.account.oracle_source
+ oracle_infos[str(oracle)] = OracleInfo(oracle, oracle_source)
- oracle_infos.update(
- {market.amm.oracle: market.amm.oracle_source for market in perp_markets}
- )
- oracle_infos.update(
- {market.oracle: market.oracle_source for market in spot_markets}
- )
+ return perp_market_indexes, spot_market_indexes, list(oracle_infos.values())
- oracle_keys = list(oracle_infos.keys())
- oracle_ais = await program.provider.connection.get_multiple_accounts(
- oracle_keys
+async def find_all_market_and_oracles(
+ program: Program,
+) -> Tuple[
+ list[DataAndSlot[PerpMarketAccount]],
+ list[DataAndSlot[SpotMarketAccount]],
+ list[FullOracleWrapper],
+]:
+ perp_markets = []
+ spot_markets = []
+ oracle_infos = {}
+
+ perp_filters = [{"memcmp": {"offset": 0, "bytes": "2pTyMkwXuti"}}]
+ spot_filters = [{"memcmp": {"offset": 0, "bytes": "HqqNdyfVbzv"}}]
+
+ perp_request = jsonrpcclient.request(
+ "getProgramAccounts",
+ (
+ str(program.program_id),
+ {"filters": perp_filters, "encoding": "base64", "withContext": True},
+ ),
+ )
+
+ post = program.provider.connection._provider.session.post(
+ program.provider.connection._provider.endpoint_uri,
+ json=perp_request,
+ headers={"content-encoding": "gzip"},
+ )
+ resp = await asyncio.wait_for(post, timeout=10)
+ parsed_resp = jsonrpcclient.parse(resp.json())
+
+ if isinstance(parsed_resp, jsonrpcclient.Error):
+ raise ValueError(f"Error fetching perp markets: {parsed_resp.message}")
+
+ if not isinstance(parsed_resp, jsonrpcclient.Ok):
+ raise ValueError(f"Error fetching perp markets - not ok: {parsed_resp}")
+
+ perp_slot = int(parsed_resp.result["context"]["slot"])
+ perp_markets: list[PerpMarketAccount] = []
+ for account in parsed_resp.result["value"]:
+ perp_market = decode_account(account["account"]["data"][0], program)
+ perp_markets.append(perp_market)
+
+ perp_ds: list[DataAndSlot] = [
+ DataAndSlot(perp_slot, perp_market) for perp_market in perp_markets
+ ]
+
+ spot_request = jsonrpcclient.request(
+ "getProgramAccounts",
+ (
+ str(program.program_id),
+ {"filters": spot_filters, "encoding": "base64", "withContext": True},
+ ),
+ )
+
+ post = program.provider.connection._provider.session.post(
+ program.provider.connection._provider.endpoint_uri,
+ json=spot_request,
+ headers={"content-encoding": "gzip"},
+ )
+ resp = await asyncio.wait_for(post, timeout=10)
+ parsed_resp = jsonrpcclient.parse(resp.json())
+
+ if isinstance(parsed_resp, jsonrpcclient.Error):
+ raise ValueError(f"Error fetching spot markets: {parsed_resp.message}")
+ if not isinstance(parsed_resp, jsonrpcclient.Ok):
+ raise ValueError(f"Error fetching spot markets - not ok: {parsed_resp}")
+
+ spot_slot = int(parsed_resp.result["context"]["slot"])
+
+ spot_markets: list[SpotMarketAccount] = []
+ for account in parsed_resp.result["value"]:
+ spot_market = decode_account(account["account"]["data"][0], program)
+ spot_markets.append(spot_market)
+
+ spot_ds: list[DataAndSlot] = [
+ DataAndSlot(spot_slot, spot_market) for spot_market in spot_markets
+ ]
+
+ oracle_infos.update(
+ {market.amm.oracle: market.amm.oracle_source for market in perp_markets}
+ )
+ oracle_infos.update(
+ {market.oracle: market.oracle_source for market in spot_markets}
+ )
+
+ oracle_keys = list(oracle_infos.keys())
+
+ oracle_ais = await program.provider.connection.get_multiple_accounts(oracle_keys)
+
+ oracle_slot = oracle_ais.context.slot
+
+ oracle_price_datas = [
+ decode_oracle(account.data, oracle_infos[oracle_keys[i]])
+ for i, account in enumerate(oracle_ais.value)
+ if account is not None
+ ]
+
+ oracle_ds: list[DataAndSlot] = [
+ DataAndSlot(oracle_slot, oracle_price_data)
+ for oracle_price_data in oracle_price_datas
+ ]
+
+ full_oracle_wrappers: list[FullOracleWrapper] = [
+ FullOracleWrapper(
+ pubkey=oracle_keys[i],
+ oracle_source=oracle_infos[oracle_keys[i]],
+ oracle_price_data_and_slot=oracle_ds[i],
)
+ for i in range(len(oracle_keys))
+ if oracle_ais.value[i] is not None
+ ]
- oracle_slot = oracle_ais.context.slot
-
- oracle_price_datas = [
- decode_oracle(account.data, oracle_infos[oracle_keys[i]])
- for i, account in enumerate(oracle_ais.value)
- if account is not None
- ]
-
- oracle_ds: list[DataAndSlot] = [
- DataAndSlot(oracle_slot, oracle_price_data)
- for oracle_price_data in oracle_price_datas
- ]
-
- full_oracle_wrappers: list[FullOracleWrapper] = [
- FullOracleWrapper(
- pubkey=oracle_keys[i],
- oracle_source=oracle_infos[oracle_keys[i]],
- oracle_price_data_and_slot=oracle_ds[i],
- )
- for i in range(len(oracle_keys))
- if oracle_ais.value[i] is not None
- ]
-
- return perp_ds, spot_ds, full_oracle_wrappers
+ return perp_ds, spot_ds, full_oracle_wrappers
def decode_account(decoded_data: bytes | str, program):
From 386292c10100d6eae020d301580344aeaa6bfe74 Mon Sep 17 00:00:00 2001
From: sina <20732540+SinaKhalili@users.noreply.github.com>
Date: Thu, 2 Jan 2025 00:38:23 -0800
Subject: [PATCH 11/15] Refactor: formatting
---
src/driftpy/accounts/ws/drift_client.py | 34 ++++++++++++++++++-------
src/driftpy/accounts/ws/user_stats.py | 5 ++--
src/driftpy/user_map/user_map_config.py | 6 +++--
3 files changed, 31 insertions(+), 14 deletions(-)
diff --git a/src/driftpy/accounts/ws/drift_client.py b/src/driftpy/accounts/ws/drift_client.py
index fa64d09e..91647a8e 100644
--- a/src/driftpy/accounts/ws/drift_client.py
+++ b/src/driftpy/accounts/ws/drift_client.py
@@ -1,7 +1,7 @@
import asyncio
from typing import Optional, Sequence, Union
-from anchorpy import Program
+from anchorpy.program.core import Program
from solana.rpc.commitment import Commitment
from driftpy.accounts.oracle import get_oracle_decode_fn
@@ -11,7 +11,12 @@
FullOracleWrapper,
)
from driftpy.accounts.ws.account_subscriber import WebsocketAccountSubscriber
-from driftpy.addresses import *
+from driftpy.addresses import (
+ Pubkey,
+ get_perp_market_public_key,
+ get_spot_market_public_key,
+ get_state_public_key,
+)
from driftpy.constants.config import find_all_market_and_oracles
from driftpy.constants.perp_markets import mainnet_perp_market_configs
from driftpy.market_map.market_map import MarketMap
@@ -35,7 +40,7 @@ def __init__(
spot_market_indexes: Sequence[int],
full_oracle_wrappers: Sequence[FullOracleWrapper],
should_find_all_markets_and_oracles: bool,
- commitment: Commitment = "confirmed",
+ commitment: Commitment = Commitment("confirmed"),
):
self.program = program
self.commitment = commitment
@@ -71,7 +76,8 @@ async def subscribe(self):
perp_ds,
spot_ds,
full_oracle_wrappers,
- ) = await find_all_market_and_oracles(self.program, data_and_slots=True)
+ ) = await find_all_market_and_oracles(self.program)
+
self.perp_market_indexes = [
data_and_slot.data.market_index for data_and_slot in perp_ds
]
@@ -82,14 +88,14 @@ async def subscribe(self):
spot_market_config = MarketMapConfig(
self.program,
- MarketType.Spot(),
+ MarketType.Spot(), # type: ignore
WebsocketConfig(),
self.program.provider.connection,
)
perp_market_config = MarketMapConfig(
self.program,
- MarketType.Perp(),
+ MarketType.Perp(), # type: ignore
WebsocketConfig(),
self.program.provider.connection,
)
@@ -183,8 +189,16 @@ async def subscribe_to_oracle(self, full_oracle_wrapper: FullOracleWrapper):
await oracle_subscriber.subscribe()
self.oracle_subscribers[oracle_id] = oracle_subscriber
- async def subscribe_to_oracle_info(self, oracle_info: OracleInfo):
- oracle_id = get_oracle_id(oracle_info.pubkey, oracle_info.source)
+ async def subscribe_to_oracle_info(
+ self, oracle_info: OracleInfo | FullOracleWrapper
+ ):
+ source = None
+ if isinstance(oracle_info, FullOracleWrapper):
+ source = oracle_info.oracle_source
+ else:
+ source = oracle_info.source
+
+ oracle_id = get_oracle_id(oracle_info.pubkey, source)
if oracle_info.pubkey == Pubkey.default():
return
@@ -195,7 +209,7 @@ async def subscribe_to_oracle_info(self, oracle_info: OracleInfo):
oracle_info.pubkey,
self.program,
self.commitment,
- get_oracle_decode_fn(oracle_info.source),
+ get_oracle_decode_fn(source),
)
await oracle_subscriber.subscribe()
@@ -234,6 +248,8 @@ async def add_oracle(self, oracle_info: OracleInfo):
return await self.subscribe_to_oracle_info(oracle_info)
def get_state_account_and_slot(self) -> Optional[DataAndSlot[StateAccount]]:
+ if not self.state_subscriber:
+ raise ValueError("State subscriber not found")
return self.state_subscriber.data_and_slot
def get_perp_market_and_slot(
diff --git a/src/driftpy/accounts/ws/user_stats.py b/src/driftpy/accounts/ws/user_stats.py
index 2e569377..4069e719 100644
--- a/src/driftpy/accounts/ws/user_stats.py
+++ b/src/driftpy/accounts/ws/user_stats.py
@@ -1,10 +1,9 @@
from typing import Optional
from driftpy.accounts import DataAndSlot
-from driftpy.types import UserStatsAccount
-
-from driftpy.accounts.ws.account_subscriber import WebsocketAccountSubscriber
from driftpy.accounts.types import UserStatsAccountSubscriber
+from driftpy.accounts.ws.account_subscriber import WebsocketAccountSubscriber
+from driftpy.types import UserStatsAccount
class WebsocketUserStatsAccountSubscriber(
diff --git a/src/driftpy/user_map/user_map_config.py b/src/driftpy/user_map/user_map_config.py
index 58e22fdb..bf40b0c6 100644
--- a/src/driftpy/user_map/user_map_config.py
+++ b/src/driftpy/user_map/user_map_config.py
@@ -1,7 +1,9 @@
-from solana.rpc.async_api import AsyncClient
-from solana.rpc.commitment import Commitment
from dataclasses import dataclass
from typing import Optional, Union
+
+from solana.rpc.async_api import AsyncClient
+from solana.rpc.commitment import Commitment
+
from driftpy.drift_client import DriftClient
From a02a639ded8b09e6bd1466d3f78ddee9c1082ecc Mon Sep 17 00:00:00 2001
From: sina <20732540+SinaKhalili@users.noreply.github.com>
Date: Thu, 2 Jan 2025 00:38:59 -0800
Subject: [PATCH 12/15] Client: check for subscriber
---
src/driftpy/drift_client.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/driftpy/drift_client.py b/src/driftpy/drift_client.py
index 73910120..a92a430c 100644
--- a/src/driftpy/drift_client.py
+++ b/src/driftpy/drift_client.py
@@ -258,6 +258,8 @@ def __init__(
)
async def subscribe(self):
+ if self.account_subscriber is None:
+ raise ValueError("No account subscriber found")
await self.account_subscriber.subscribe()
if self.enforce_tx_sequencing:
await self.load_sequence_info()
@@ -300,6 +302,8 @@ async def add_user_stats(self, authority: Pubkey):
await self.user_stats[authority].fetch_accounts()
async def unsubscribe(self):
+ if self.account_subscriber is None:
+ raise ValueError("No account subscriber found")
await self.account_subscriber.unsubscribe()
def get_user(self, sub_account_id=None) -> DriftUser:
From ab61939d185d56f05c8de3c53c3914cfbf4254f6 Mon Sep 17 00:00:00 2001
From: sina <20732540+SinaKhalili@users.noreply.github.com>
Date: Thu, 2 Jan 2025 00:39:09 -0800
Subject: [PATCH 13/15] GRPC user stats
---
src/driftpy/accounts/grpc/user_stats.py | 14 ++++++++++++++
1 file changed, 14 insertions(+)
create mode 100644 src/driftpy/accounts/grpc/user_stats.py
diff --git a/src/driftpy/accounts/grpc/user_stats.py b/src/driftpy/accounts/grpc/user_stats.py
new file mode 100644
index 00000000..20d41570
--- /dev/null
+++ b/src/driftpy/accounts/grpc/user_stats.py
@@ -0,0 +1,14 @@
+from typing import Optional
+
+from driftpy.accounts.grpc.account_subscriber import GrpcAccountSubscriber
+from driftpy.accounts.types import DataAndSlot, UserStatsAccountSubscriber
+from driftpy.types import UserStatsAccount
+
+
+class GrpcUserStatsAccountSubscriber(
+ GrpcAccountSubscriber[UserStatsAccount], UserStatsAccountSubscriber
+):
+ def get_user_stats_account_and_slot(
+ self,
+ ) -> Optional[DataAndSlot[UserStatsAccount]]:
+ return self.data_and_slot
From 9b30bb2401a99430c264209f88f5fed82786eb13 Mon Sep 17 00:00:00 2001
From: sina <20732540+SinaKhalili@users.noreply.github.com>
Date: Thu, 2 Jan 2025 00:50:36 -0800
Subject: [PATCH 14/15] Update pyproject
---
pyproject.toml | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/pyproject.toml b/pyproject.toml
index 0564cd92..f13ad95a 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -100,6 +100,8 @@ bump2version = "^1.0.1"
autopep8 = "^2.0.4"
mypy = "^1.7.0"
python-dotenv = "^1.0.0"
+ruff = "^0.8.4"
+
[tool.poetry.group.dev.dependencies]
pytest = "^7.4.4"
@@ -114,7 +116,7 @@ build-backend = "poetry.core.masonry.api"
asyncio_mode = "strict"
[tool.ruff]
-exclude = [".git", "__pycache__", "docs/source/conf.py", "old", "build", "dist"]
+exclude = [".git", "__pycache__", "docs/source/conf.py", "old", "build", "dist", "**/geyser_codegen/**"]
[tool.ruff.pycodestyle]
max-line-length = 88
From a5d36316c16e2d642a7dcf6e16674247dcb89e76 Mon Sep 17 00:00:00 2001
From: sina <20732540+SinaKhalili@users.noreply.github.com>
Date: Thu, 2 Jan 2025 00:59:55 -0800
Subject: [PATCH 15/15] Update poetry lockfile
---
poetry.lock | 29 ++++++++++++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/poetry.lock b/poetry.lock
index 67675ebd..a3ae958f 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1970,6 +1970,33 @@ idna = {version = "*", optional = true, markers = "extra == \"idna2008\""}
[package.extras]
idna2008 = ["idna"]
+[[package]]
+name = "ruff"
+version = "0.8.4"
+description = "An extremely fast Python linter and code formatter, written in Rust."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "ruff-0.8.4-py3-none-linux_armv6l.whl", hash = "sha256:58072f0c06080276804c6a4e21a9045a706584a958e644353603d36ca1eb8a60"},
+ {file = "ruff-0.8.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ffb60904651c00a1e0b8df594591770018a0f04587f7deeb3838344fe3adabac"},
+ {file = "ruff-0.8.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:6ddf5d654ac0d44389f6bf05cee4caeefc3132a64b58ea46738111d687352296"},
+ {file = "ruff-0.8.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e248b1f0fa2749edd3350a2a342b67b43a2627434c059a063418e3d375cfe643"},
+ {file = "ruff-0.8.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bf197b98ed86e417412ee3b6c893f44c8864f816451441483253d5ff22c0e81e"},
+ {file = "ruff-0.8.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c41319b85faa3aadd4d30cb1cffdd9ac6b89704ff79f7664b853785b48eccdf3"},
+ {file = "ruff-0.8.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:9f8402b7c4f96463f135e936d9ab77b65711fcd5d72e5d67597b543bbb43cf3f"},
+ {file = "ruff-0.8.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4e56b3baa9c23d324ead112a4fdf20db9a3f8f29eeabff1355114dd96014604"},
+ {file = "ruff-0.8.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:736272574e97157f7edbbb43b1d046125fce9e7d8d583d5d65d0c9bf2c15addf"},
+ {file = "ruff-0.8.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5fe710ab6061592521f902fca7ebcb9fabd27bc7c57c764298b1c1f15fff720"},
+ {file = "ruff-0.8.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:13e9ec6d6b55f6da412d59953d65d66e760d583dd3c1c72bf1f26435b5bfdbae"},
+ {file = "ruff-0.8.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:97d9aefef725348ad77d6db98b726cfdb075a40b936c7984088804dfd38268a7"},
+ {file = "ruff-0.8.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:ab78e33325a6f5374e04c2ab924a3367d69a0da36f8c9cb6b894a62017506111"},
+ {file = "ruff-0.8.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:8ef06f66f4a05c3ddbc9121a8b0cecccd92c5bf3dd43b5472ffe40b8ca10f0f8"},
+ {file = "ruff-0.8.4-py3-none-win32.whl", hash = "sha256:552fb6d861320958ca5e15f28b20a3d071aa83b93caee33a87b471f99a6c0835"},
+ {file = "ruff-0.8.4-py3-none-win_amd64.whl", hash = "sha256:f21a1143776f8656d7f364bd264a9d60f01b7f52243fbe90e7670c0dfe0cf65d"},
+ {file = "ruff-0.8.4-py3-none-win_arm64.whl", hash = "sha256:9183dd615d8df50defa8b1d9a074053891ba39025cf5ae88e8bcb52edcc4bf08"},
+ {file = "ruff-0.8.4.tar.gz", hash = "sha256:0d5f89f254836799af1615798caa5f80b7f935d7a670fad66c5007928e57ace8"},
+]
+
[[package]]
name = "six"
version = "1.17.0"
@@ -2499,4 +2526,4 @@ cffi = ["cffi (>=1.11)"]
[metadata]
lock-version = "2.0"
python-versions = "^3.10"
-content-hash = "4ce070b9f91937ed235c7f5956c7ca78c7a5d7fc9236b689a1a9bc1e326651dd"
+content-hash = "e375aa4100bd07523d0272705c587d76ab359a845f9457a518f38d14c8a30cf9"