strideutils 0.9.0__tar.gz → 0.9.2__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.9.0 → strideutils-0.9.2}/.bumpversion.cfg +1 -1
- {strideutils-0.9.0 → strideutils-0.9.2}/PKG-INFO +1 -1
- {strideutils-0.9.0 → strideutils-0.9.2}/pyproject.toml +1 -1
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/coingecko.py +0 -2
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/config_examples/strideutils_config.yaml.example +0 -22
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/exec_tx.py +17 -3
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/stride_config.py +1 -1
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils-stubs/stride_requests.pyi +1 -1
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils.egg-info/PKG-INFO +1 -1
- {strideutils-0.9.0 → strideutils-0.9.2}/tests/test_exec_tx.py +49 -3
- {strideutils-0.9.0 → strideutils-0.9.2}/.github/workflows/lint.yml +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/.github/workflows/publish.yml +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/.github/workflows/test.yml +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/.github/workflows/version.yaml +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/.gitignore +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/LICENSE +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/MANIFEST.in +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/Makefile +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/README.md +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/example-config.yaml +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/setup.cfg +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/Makefile +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/__init__.py +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/__init__.pyi +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/coingecko.pyi +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/config_examples/env.local.example +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/cryptography.py +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/cryptography.pyi +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/exec_tx.pyi +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/py.typed +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/redis_connector.py +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/redis_connector.pyi +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/run_safely.py +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/run_safely.pyi +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/sheets_connector.py +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/sheets_connector.pyi +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/slack_connector.py +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/slack_connector.pyi +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/stride_alerts.py +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/stride_alerts.pyi +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/stride_config.pyi +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/stride_requests.py +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/stride_requests.pyi +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/telegram_connector.py +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/telegram_connector.pyi +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/twilio_connector.py +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/twilio_connector.pyi +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/types.py +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils/types.pyi +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils-stubs/__init__.pyi +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils-stubs/coingecko.pyi +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils-stubs/cryptography.pyi +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils-stubs/exec_tx.pyi +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils-stubs/redis_connector.pyi +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils-stubs/run_safely.pyi +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils-stubs/sheets_connector.pyi +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils-stubs/slack_connector.pyi +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils-stubs/stride_alerts.pyi +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils-stubs/stride_config.pyi +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils-stubs/telegram_connector.pyi +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils-stubs/twilio_connector.pyi +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils-stubs/types.pyi +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils.egg-info/SOURCES.txt +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils.egg-info/dependency_links.txt +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils.egg-info/requires.txt +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/strideutils.egg-info/top_level.txt +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/tests/test_coingecko.py +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/tests/test_config.py +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/tests/test_encryption.py +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/tests/test_redis_connector.py +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/tests/test_sheets_connector.py +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/tests/test_slack_connector.py +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/tests/test_stride_requests.py +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/tests/test_telegram_connector.py +0 -0
- {strideutils-0.9.0 → strideutils-0.9.2}/tests/test_twilio_connector.py +0 -0
{strideutils-0.9.0 → strideutils-0.9.2}/strideutils/config_examples/strideutils_config.yaml.example
RENAMED
|
@@ -89,28 +89,6 @@ host_zones:
|
|
|
89
89
|
api_endpoint:
|
|
90
90
|
rpc_endpoint:
|
|
91
91
|
|
|
92
|
-
umee:
|
|
93
|
-
name: umeee
|
|
94
|
-
id: umee-1
|
|
95
|
-
denom: uumee
|
|
96
|
-
ticker: UMEE
|
|
97
|
-
denom_decimals: 6
|
|
98
|
-
denom_on_stride: ibc/1A2271226209D309902AFF4F21BD21237CB514DD24EA2EE0423BF74C6135D8B8
|
|
99
|
-
inflation_frequency_hours: -1 # Every block
|
|
100
|
-
api_endpoint:
|
|
101
|
-
rpc_endpoint:
|
|
102
|
-
|
|
103
|
-
comdex:
|
|
104
|
-
name: comdex
|
|
105
|
-
id: comdex-1
|
|
106
|
-
denom: ucmdx
|
|
107
|
-
ticker: CMDX
|
|
108
|
-
denom_decimals: 6
|
|
109
|
-
denom_on_stride: ibc/EB66980014602E6BD50A1CB9FFB8FA694DC3EC10A48D2C1C649D732954F88D4A
|
|
110
|
-
inflation_frequency_hours: -1 # Every block
|
|
111
|
-
api_endpoint:
|
|
112
|
-
rpc_endpoint:
|
|
113
|
-
|
|
114
92
|
sommelier:
|
|
115
93
|
name: sommelier
|
|
116
94
|
id: sommelier-3
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import os
|
|
3
|
+
import re
|
|
3
4
|
import subprocess
|
|
4
5
|
import time
|
|
5
6
|
from dataclasses import dataclass
|
|
@@ -11,6 +12,13 @@ from strideutils import stride_requests
|
|
|
11
12
|
from strideutils.stride_config import config
|
|
12
13
|
|
|
13
14
|
WALLET_SETUP_COMMAND = "echo {mnemonic} | {binary} keys add {account_name} --recover --keyring-backend=test"
|
|
15
|
+
_GAS_ESTIMATE_LINE = re.compile(r"gas estimate: \d+$")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _is_gas_estimate_only_stderr(stderr: str) -> bool:
|
|
19
|
+
"""True when stderr contains only the normal --gas auto estimate line(s)."""
|
|
20
|
+
lines = [line.strip() for line in stderr.splitlines() if line.strip()]
|
|
21
|
+
return bool(lines) and all(_GAS_ESTIMATE_LINE.fullmatch(line) for line in lines)
|
|
14
22
|
|
|
15
23
|
|
|
16
24
|
@dataclass
|
|
@@ -24,7 +32,11 @@ class TxResponse:
|
|
|
24
32
|
raw_log: Optional[str] = None
|
|
25
33
|
|
|
26
34
|
|
|
27
|
-
def restore_wallet(
|
|
35
|
+
def restore_wallet(
|
|
36
|
+
account_name: str = "wallet",
|
|
37
|
+
mnemonic_var: str = "MNEMONIC",
|
|
38
|
+
binary: str = "strided",
|
|
39
|
+
):
|
|
28
40
|
"""
|
|
29
41
|
Restores a wallet in the keyring, using the mnemonic under the specified environment variable
|
|
30
42
|
"""
|
|
@@ -47,8 +59,10 @@ def execute_tx(command: str, api_endpoint: str = config.stride.api_endpoint) ->
|
|
|
47
59
|
# Run the command in the shell and store the response
|
|
48
60
|
output = subprocess.run(command, shell=True, capture_output=True, text=True)
|
|
49
61
|
|
|
50
|
-
|
|
51
|
-
|
|
62
|
+
if not output.stdout:
|
|
63
|
+
return TxResponse(stdout={}, stderr=output.stderr, raw_log=output.stderr or "")
|
|
64
|
+
|
|
65
|
+
if output.stderr and not _is_gas_estimate_only_stderr(output.stderr):
|
|
52
66
|
return TxResponse(stdout={}, stderr=output.stderr, raw_log=output.stderr)
|
|
53
67
|
|
|
54
68
|
# Cast the stdout and build the response
|
|
@@ -114,7 +114,7 @@ def get_block_time(height: int, rpc_endpoint: str = ...) -> datetime.datetime: .
|
|
|
114
114
|
def get_icns_name(address: str) -> str: ...
|
|
115
115
|
def get_account_info(address: str, api_endpoint: str = ...): ...
|
|
116
116
|
def get_tx(hash: str, api_endpoint: str = ...) -> dict: ...
|
|
117
|
-
def get_txs(event_filters: list[str], api_endpoint: str = ..., limit=None) -> dict: ...
|
|
117
|
+
def get_txs(event_filters: list[str], api_endpoint: str = ..., limit=None, sdk50: bool = True) -> dict: ...
|
|
118
118
|
def get_tx_info(address: str, sequence: str | int, api_endpoint: str = ...) -> dict: ...
|
|
119
119
|
def generate_vesting_account(
|
|
120
120
|
start_time_in_local_tz: str,
|
|
@@ -54,7 +54,10 @@ MOCK_FAILED_TX_RESPONSE = MockTxResponse(
|
|
|
54
54
|
|
|
55
55
|
def test_execute_tx_success() -> None:
|
|
56
56
|
"""Test successful transaction execution."""
|
|
57
|
-
with
|
|
57
|
+
with (
|
|
58
|
+
patch("subprocess.run") as mock_run,
|
|
59
|
+
patch("strideutils.stride_requests.requests.get") as mock_get_tx,
|
|
60
|
+
):
|
|
58
61
|
# Mock subprocess.run
|
|
59
62
|
mock_process = MagicMock()
|
|
60
63
|
mock_process.stdout = json.dumps(MOCK_SUCCESS_STDOUT)
|
|
@@ -85,7 +88,10 @@ def test_execute_tx_success() -> None:
|
|
|
85
88
|
|
|
86
89
|
def test_execute_tx_failure() -> None:
|
|
87
90
|
"""Test failed transaction execution."""
|
|
88
|
-
with
|
|
91
|
+
with (
|
|
92
|
+
patch("subprocess.run") as mock_run,
|
|
93
|
+
patch("strideutils.stride_requests.requests.get") as mock_get_tx,
|
|
94
|
+
):
|
|
89
95
|
# Mock subprocess.run
|
|
90
96
|
mock_process = MagicMock()
|
|
91
97
|
mock_process.stdout = json.dumps(MOCK_SUCCESS_STDOUT)
|
|
@@ -105,6 +111,43 @@ def test_execute_tx_failure() -> None:
|
|
|
105
111
|
assert response.raw_log == "transaction failed"
|
|
106
112
|
|
|
107
113
|
|
|
114
|
+
def test_execute_tx_gas_estimate_stderr() -> None:
|
|
115
|
+
"""Test that --gas auto stderr does not block tx parsing."""
|
|
116
|
+
with (
|
|
117
|
+
patch("subprocess.run") as mock_run,
|
|
118
|
+
patch("strideutils.stride_requests.requests.get") as mock_get_tx,
|
|
119
|
+
):
|
|
120
|
+
mock_process = MagicMock()
|
|
121
|
+
mock_process.stdout = json.dumps(MOCK_SUCCESS_STDOUT)
|
|
122
|
+
mock_process.stderr = "gas estimate: 53873342\n"
|
|
123
|
+
mock_run.return_value = mock_process
|
|
124
|
+
|
|
125
|
+
mock_get_tx.return_value = MOCK_SUCCESS_TX_RESPONSE
|
|
126
|
+
|
|
127
|
+
response = execute_tx(MOCK_COMMAND, MOCK_API_ENDPOINT)
|
|
128
|
+
|
|
129
|
+
assert response.success is True
|
|
130
|
+
assert response.tx_hash == MOCK_TX_HASH
|
|
131
|
+
assert response.code == 0
|
|
132
|
+
assert response.raw_log == "transaction successful"
|
|
133
|
+
assert response.stderr == "gas estimate: 53873342\n"
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def test_execute_tx_gas_estimate_plus_real_error() -> None:
|
|
137
|
+
"""Test that gas estimate stderr plus a real error still fails."""
|
|
138
|
+
with patch("subprocess.run") as mock_run:
|
|
139
|
+
mock_process = MagicMock()
|
|
140
|
+
mock_process.stdout = json.dumps(MOCK_SUCCESS_STDOUT)
|
|
141
|
+
mock_process.stderr = "gas estimate: 53873342\ninsufficient fees"
|
|
142
|
+
mock_run.return_value = mock_process
|
|
143
|
+
|
|
144
|
+
response = execute_tx(MOCK_COMMAND, MOCK_API_ENDPOINT)
|
|
145
|
+
|
|
146
|
+
assert response.success is False
|
|
147
|
+
assert response.tx_hash == ""
|
|
148
|
+
assert response.raw_log == "gas estimate: 53873342\ninsufficient fees"
|
|
149
|
+
|
|
150
|
+
|
|
108
151
|
def test_execute_tx_subprocess_error() -> None:
|
|
109
152
|
"""Test handling of subprocess execution error."""
|
|
110
153
|
with patch("subprocess.run") as mock_run:
|
|
@@ -213,7 +256,10 @@ def test_execute_tx_auto_append_flags() -> None:
|
|
|
213
256
|
test_cases: List[Tuple[str, str]] = [
|
|
214
257
|
("base command", "base command -y --output json"),
|
|
215
258
|
("base command -y", "base command -y --output json"),
|
|
216
|
-
(
|
|
259
|
+
(
|
|
260
|
+
"base command --output json",
|
|
261
|
+
"base command --output json -y --output json",
|
|
262
|
+
),
|
|
217
263
|
]
|
|
218
264
|
|
|
219
265
|
for input_cmd, expected_cmd in test_cases:
|
|
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
|
|
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
|
|
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
|