strideutils 0.3.5__tar.gz → 0.3.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {strideutils-0.3.5 → strideutils-0.3.7}/PKG-INFO +2 -4
- {strideutils-0.3.5 → strideutils-0.3.7}/pyproject.toml +2 -2
- {strideutils-0.3.5 → strideutils-0.3.7}/strideutils/stride_requests.py +101 -44
- {strideutils-0.3.5 → strideutils-0.3.7}/README.md +0 -0
- {strideutils-0.3.5 → strideutils-0.3.7}/strideutils/Makefile +0 -0
- {strideutils-0.3.5 → strideutils-0.3.7}/strideutils/__init__.py +0 -0
- {strideutils-0.3.5 → strideutils-0.3.7}/strideutils/coingecko.py +0 -0
- {strideutils-0.3.5 → strideutils-0.3.7}/strideutils/config_examples/strideutils_config.yaml.example +0 -0
- {strideutils-0.3.5 → strideutils-0.3.7}/strideutils/config_examples/strideutils_secrets.yaml.example +0 -0
- {strideutils-0.3.5 → strideutils-0.3.7}/strideutils/cryptography.py +0 -0
- {strideutils-0.3.5 → strideutils-0.3.7}/strideutils/exec_tx.py +0 -0
- {strideutils-0.3.5 → strideutils-0.3.7}/strideutils/invariant_helpers.py +0 -0
- {strideutils-0.3.5 → strideutils-0.3.7}/strideutils/run_safely.py +0 -0
- {strideutils-0.3.5 → strideutils-0.3.7}/strideutils/sheets_connector.py +0 -0
- {strideutils-0.3.5 → strideutils-0.3.7}/strideutils/slack_connector.py +0 -0
- {strideutils-0.3.5 → strideutils-0.3.7}/strideutils/stride_alerts.py +0 -0
- {strideutils-0.3.5 → strideutils-0.3.7}/strideutils/stride_config.py +0 -0
- {strideutils-0.3.5 → strideutils-0.3.7}/strideutils/stride_upstash.py +0 -0
- {strideutils-0.3.5 → strideutils-0.3.7}/strideutils/twilio_connector.py +0 -0
- {strideutils-0.3.5 → strideutils-0.3.7}/strideutils/types.py +0 -0
- {strideutils-0.3.5 → strideutils-0.3.7}/strideutils-stubs/__init__.pyi +0 -0
- {strideutils-0.3.5 → strideutils-0.3.7}/strideutils-stubs/coingecko.pyi +0 -0
- {strideutils-0.3.5 → strideutils-0.3.7}/strideutils-stubs/cryptography.pyi +0 -0
- {strideutils-0.3.5 → strideutils-0.3.7}/strideutils-stubs/exec_tx.pyi +0 -0
- {strideutils-0.3.5 → strideutils-0.3.7}/strideutils-stubs/invariant_helpers.pyi +0 -0
- {strideutils-0.3.5 → strideutils-0.3.7}/strideutils-stubs/run_safely.pyi +0 -0
- {strideutils-0.3.5 → strideutils-0.3.7}/strideutils-stubs/sheets_connector.pyi +0 -0
- {strideutils-0.3.5 → strideutils-0.3.7}/strideutils-stubs/slack_connector.pyi +0 -0
- {strideutils-0.3.5 → strideutils-0.3.7}/strideutils-stubs/stride_alerts.pyi +0 -0
- {strideutils-0.3.5 → strideutils-0.3.7}/strideutils-stubs/stride_config.pyi +0 -0
- {strideutils-0.3.5 → strideutils-0.3.7}/strideutils-stubs/stride_requests.pyi +0 -0
- {strideutils-0.3.5 → strideutils-0.3.7}/strideutils-stubs/stride_upstash.pyi +0 -0
- {strideutils-0.3.5 → strideutils-0.3.7}/strideutils-stubs/twilio_connector.pyi +0 -0
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: strideutils
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.7
|
|
4
4
|
Summary:
|
|
5
5
|
Author: Your Name
|
|
6
6
|
Author-email: you@example.com
|
|
7
|
-
Requires-Python: >=3.
|
|
7
|
+
Requires-Python: >=3.11
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
10
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
11
9
|
Classifier: Programming Language :: Python :: 3.11
|
|
12
10
|
Classifier: Programming Language :: Python :: 3.12
|
|
13
11
|
Requires-Dist: bech32 (>=1.2.0)
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "strideutils"
|
|
3
|
-
version = "0.3.
|
|
3
|
+
version = "0.3.7"
|
|
4
4
|
description = ""
|
|
5
5
|
authors = ["Your Name <you@example.com>"]
|
|
6
6
|
readme = "README.md"
|
|
7
7
|
include = ["strideutils", "strideutils-stubs"]
|
|
8
8
|
|
|
9
9
|
[tool.poetry.dependencies]
|
|
10
|
-
python = ">=3.
|
|
10
|
+
python = ">=3.11"
|
|
11
11
|
google-api-python-client = ">=2.100.0"
|
|
12
12
|
google-auth-httplib2 = ">=0.1.1"
|
|
13
13
|
google-auth-oauthlib = ">=1.1.0"
|
|
@@ -7,7 +7,6 @@ from functools import lru_cache
|
|
|
7
7
|
from typing import Any, Dict, List, Optional, Tuple, Union, cast
|
|
8
8
|
|
|
9
9
|
import bech32
|
|
10
|
-
import dateutil.parser
|
|
11
10
|
import pandas as pd
|
|
12
11
|
import pytz
|
|
13
12
|
import requests
|
|
@@ -327,6 +326,61 @@ def get_unbonding_records(
|
|
|
327
326
|
return host_zone_unbondings
|
|
328
327
|
|
|
329
328
|
|
|
329
|
+
def get_unbonding_queue_records(chain_id: str, block_height: int = 0) -> List[Dict[str, Any]]:
|
|
330
|
+
"""
|
|
331
|
+
Queries all the unbonding records that are ready to initiate an unbonding
|
|
332
|
+
This is identified by records in status UNBONDING_QUEUE with a non-zero unbonding amount
|
|
333
|
+
"""
|
|
334
|
+
unbonding_records = get_unbonding_records(
|
|
335
|
+
chain_id=chain_id,
|
|
336
|
+
block_height=block_height,
|
|
337
|
+
status=types.UnbondingRecordStatus.UNBONDING_QUEUE,
|
|
338
|
+
)
|
|
339
|
+
return [ur for ur in unbonding_records if int(ur["native_token_amount"]) > 0]
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
def get_unbonded_records(
|
|
343
|
+
chain_id: str,
|
|
344
|
+
block_height: int = 0,
|
|
345
|
+
filter_unbonded_last_epoch: bool = False,
|
|
346
|
+
) -> List[Dict[str, Any]]:
|
|
347
|
+
"""
|
|
348
|
+
Queries the list of all unbonding records records that have finished unbonding
|
|
349
|
+
This is identified by records in status EXIT_TRANSFER_QUEUE with an unbonding time
|
|
350
|
+
in the past
|
|
351
|
+
Optionally filter to records that just unbonded last epoch
|
|
352
|
+
"""
|
|
353
|
+
unbonding_records = get_unbonding_records(
|
|
354
|
+
chain_id=chain_id,
|
|
355
|
+
block_height=block_height,
|
|
356
|
+
status=types.UnbondingRecordStatus.EXIT_TRANSFER_QUEUE,
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
# If we're fetching an older block, use that block's time as the "current time"
|
|
360
|
+
current_time = int(datetime.datetime.now().timestamp() * 1e9)
|
|
361
|
+
if block_height != 0:
|
|
362
|
+
current_time = int(get_block_time(block_height).timestamp() * 1e9)
|
|
363
|
+
|
|
364
|
+
# Filter to the records that have finished unbonding, and optionally also
|
|
365
|
+
# filter to records that just finished during the last epoch
|
|
366
|
+
day = 24 * 60 * 60 * 1e9
|
|
367
|
+
filtered_unbonding_records = []
|
|
368
|
+
for unbonding_record in unbonding_records:
|
|
369
|
+
unbonding_time = int(unbonding_record["unbonding_time"])
|
|
370
|
+
|
|
371
|
+
# Ignore records that haven't finished unbonding yet
|
|
372
|
+
if unbonding_time > current_time:
|
|
373
|
+
continue
|
|
374
|
+
|
|
375
|
+
# If filtering from last epoch, ignore records that unbonded over a day ago
|
|
376
|
+
if filter_unbonded_last_epoch and (current_time - unbonding_time) > day:
|
|
377
|
+
continue
|
|
378
|
+
|
|
379
|
+
filtered_unbonding_records.append(unbonding_record)
|
|
380
|
+
|
|
381
|
+
return filtered_unbonding_records
|
|
382
|
+
|
|
383
|
+
|
|
330
384
|
def get_lsm_deposit_records(chain_id: str) -> List[Dict[str, Any]]:
|
|
331
385
|
"""
|
|
332
386
|
Queries all the LSM deposit records
|
|
@@ -630,7 +684,7 @@ def get_block_time(height: int, rpc_endpoint: str = config.stride.rpc_endpoint)
|
|
|
630
684
|
url = f"{rpc_endpoint}/block?height={height}"
|
|
631
685
|
resp = request(url)
|
|
632
686
|
block_time = resp["result"]["block"]["header"]["time"]
|
|
633
|
-
block_datetime =
|
|
687
|
+
block_datetime = datetime.datetime.fromisoformat(block_time)
|
|
634
688
|
return block_datetime
|
|
635
689
|
|
|
636
690
|
|
|
@@ -757,64 +811,67 @@ def generate_vesting_account(
|
|
|
757
811
|
|
|
758
812
|
|
|
759
813
|
def get_block_height_in_past(
|
|
760
|
-
|
|
761
|
-
|
|
814
|
+
target_time: Optional[datetime.datetime] = None,
|
|
815
|
+
target_time_offset: Optional[datetime.timedelta] = None,
|
|
816
|
+
error_tolerance: datetime.timedelta = datetime.timedelta(minutes=5),
|
|
762
817
|
seconds_per_block: int = 6,
|
|
763
|
-
prev_time: Optional[str] = None,
|
|
764
|
-
verbose: bool = False,
|
|
765
818
|
rpc_endpoint: str = config.stride.rpc_endpoint,
|
|
766
819
|
) -> int:
|
|
767
820
|
"""
|
|
768
821
|
Gets the block height at a specified time by binary searching at different heights
|
|
769
822
|
|
|
770
823
|
Args:
|
|
771
|
-
|
|
772
|
-
|
|
824
|
+
target_time (datetime): the target time to search for
|
|
825
|
+
(e.g. search for the block at time 2024-01-01 01:00:00 UTC)
|
|
826
|
+
target_time_offset (timedelta): the target time to search for,
|
|
827
|
+
defined as an offset from the current time
|
|
828
|
+
(e.g. search for the block 24 hours ago)
|
|
829
|
+
error_tolerance (timedelta): max time delta before the height is considered found
|
|
773
830
|
seconds_per_block: block time to use for the estimation start
|
|
774
|
-
prev_time: Optional time to start the search at (instead of using time_in_past)
|
|
775
831
|
|
|
776
832
|
Returns:
|
|
777
833
|
The block height at the specified time
|
|
778
834
|
"""
|
|
835
|
+
# Get the current time and latest block height
|
|
836
|
+
current_time = datetime.datetime.now(tz=datetime.timezone.utc)
|
|
779
837
|
latest_block = get_latest_block(rpc_endpoint=rpc_endpoint)
|
|
780
838
|
|
|
781
|
-
#
|
|
782
|
-
|
|
783
|
-
if
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
num_days_back = ts / (60 * 60 * 24)
|
|
788
|
-
time_in_past = datetime.timedelta(seconds=ts)
|
|
839
|
+
# Depending on whether the target time or target_time_offset was used,
|
|
840
|
+
# calculate the parameter that was not provided
|
|
841
|
+
if target_time and not target_time_offset:
|
|
842
|
+
target_time_offset = current_time - target_time
|
|
843
|
+
elif target_time_offset and not target_time:
|
|
844
|
+
target_time = current_time - target_time_offset
|
|
789
845
|
else:
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
846
|
+
raise ValueError("Either target time or target time offset must be specified (but not both)")
|
|
847
|
+
|
|
848
|
+
# Using the target offset, determine the block delta to start our search, based
|
|
849
|
+
# on the estimated block time
|
|
850
|
+
blocks_in_past = int(target_time_offset.total_seconds() / seconds_per_block)
|
|
851
|
+
estimated_height = latest_block - blocks_in_past
|
|
852
|
+
|
|
853
|
+
# Continually loop over the following until we find a block that lines up with
|
|
854
|
+
# our target time (within our margin of error)
|
|
855
|
+
# - Guess a height
|
|
856
|
+
# - Find the time at that height
|
|
857
|
+
# - Check if the time is close enough to our target
|
|
858
|
+
# - Refine our block height guess and repeat
|
|
859
|
+
while True:
|
|
860
|
+
estimated_time = get_block_time(estimated_height, rpc_endpoint=rpc_endpoint)
|
|
861
|
+
|
|
862
|
+
time_error = target_time.timestamp() - estimated_time.timestamp()
|
|
863
|
+
if abs(time_error) < error_tolerance.total_seconds():
|
|
864
|
+
return estimated_height
|
|
865
|
+
|
|
866
|
+
blocks_correction = int(time_error / seconds_per_block)
|
|
867
|
+
estimated_height += blocks_correction
|
|
868
|
+
|
|
869
|
+
|
|
870
|
+
def get_block_height_one_day_ago() -> int:
|
|
814
871
|
"""
|
|
815
872
|
Get the block height from 1 day ago
|
|
816
873
|
"""
|
|
817
|
-
return get_block_height_in_past(datetime.timedelta(hours=24)
|
|
874
|
+
return get_block_height_in_past(target_time_offset=datetime.timedelta(hours=24))
|
|
818
875
|
|
|
819
876
|
|
|
820
877
|
def get_sttoken_apr(token: str) -> Optional[float]:
|
|
@@ -1030,7 +1087,7 @@ def get_stride_epoch_start_time() -> datetime.datetime:
|
|
|
1030
1087
|
Returns the epoch start time for the current "stride" epoch
|
|
1031
1088
|
"""
|
|
1032
1089
|
stride_epoch = get_stride_epoch()
|
|
1033
|
-
return
|
|
1090
|
+
return datetime.datetime.fromisoformat(stride_epoch["current_epoch_start_time"])
|
|
1034
1091
|
|
|
1035
1092
|
|
|
1036
1093
|
def get_day_epoch_start_time() -> datetime.datetime:
|
|
@@ -1038,7 +1095,7 @@ def get_day_epoch_start_time() -> datetime.datetime:
|
|
|
1038
1095
|
Returns the epoch start time for the current "day" epoch
|
|
1039
1096
|
"""
|
|
1040
1097
|
day_epoch = get_day_epoch()
|
|
1041
|
-
return
|
|
1098
|
+
return datetime.datetime.fromisoformat(day_epoch["current_epoch_start_time"])
|
|
1042
1099
|
|
|
1043
1100
|
|
|
1044
1101
|
def get_stride_epoch_start_height() -> int:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{strideutils-0.3.5 → strideutils-0.3.7}/strideutils/config_examples/strideutils_config.yaml.example
RENAMED
|
File without changes
|
{strideutils-0.3.5 → strideutils-0.3.7}/strideutils/config_examples/strideutils_secrets.yaml.example
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|