strideutils 0.4.4__tar.gz → 0.5.0__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.
Files changed (34) hide show
  1. {strideutils-0.4.4 → strideutils-0.5.0}/PKG-INFO +12 -4
  2. {strideutils-0.4.4 → strideutils-0.5.0}/README.md +10 -3
  3. {strideutils-0.4.4 → strideutils-0.5.0}/pyproject.toml +2 -1
  4. {strideutils-0.4.4 → strideutils-0.5.0}/strideutils/coingecko.py +5 -11
  5. strideutils-0.5.0/strideutils/config_examples/env.local.example +24 -0
  6. {strideutils-0.4.4 → strideutils-0.5.0}/strideutils/exec_tx.py +4 -2
  7. {strideutils-0.4.4 → strideutils-0.5.0}/strideutils/slack_connector.py +21 -0
  8. {strideutils-0.4.4 → strideutils-0.5.0}/strideutils/stride_config.py +8 -13
  9. {strideutils-0.4.4 → strideutils-0.5.0}/strideutils/stride_requests.py +27 -41
  10. {strideutils-0.4.4 → strideutils-0.5.0}/strideutils/stride_upstash.py +47 -3
  11. strideutils-0.4.4/strideutils/config_examples/strideutils_secrets.yaml.example +0 -28
  12. {strideutils-0.4.4 → strideutils-0.5.0}/strideutils/Makefile +0 -0
  13. {strideutils-0.4.4 → strideutils-0.5.0}/strideutils/__init__.py +0 -0
  14. {strideutils-0.4.4 → strideutils-0.5.0}/strideutils/config_examples/strideutils_config.yaml.example +0 -0
  15. {strideutils-0.4.4 → strideutils-0.5.0}/strideutils/cryptography.py +0 -0
  16. {strideutils-0.4.4 → strideutils-0.5.0}/strideutils/invariant_helpers.py +0 -0
  17. {strideutils-0.4.4 → strideutils-0.5.0}/strideutils/run_safely.py +0 -0
  18. {strideutils-0.4.4 → strideutils-0.5.0}/strideutils/sheets_connector.py +0 -0
  19. {strideutils-0.4.4 → strideutils-0.5.0}/strideutils/stride_alerts.py +0 -0
  20. {strideutils-0.4.4 → strideutils-0.5.0}/strideutils/twilio_connector.py +0 -0
  21. {strideutils-0.4.4 → strideutils-0.5.0}/strideutils/types.py +0 -0
  22. {strideutils-0.4.4 → strideutils-0.5.0}/strideutils-stubs/__init__.pyi +0 -0
  23. {strideutils-0.4.4 → strideutils-0.5.0}/strideutils-stubs/coingecko.pyi +0 -0
  24. {strideutils-0.4.4 → strideutils-0.5.0}/strideutils-stubs/cryptography.pyi +0 -0
  25. {strideutils-0.4.4 → strideutils-0.5.0}/strideutils-stubs/exec_tx.pyi +0 -0
  26. {strideutils-0.4.4 → strideutils-0.5.0}/strideutils-stubs/invariant_helpers.pyi +0 -0
  27. {strideutils-0.4.4 → strideutils-0.5.0}/strideutils-stubs/run_safely.pyi +0 -0
  28. {strideutils-0.4.4 → strideutils-0.5.0}/strideutils-stubs/sheets_connector.pyi +0 -0
  29. {strideutils-0.4.4 → strideutils-0.5.0}/strideutils-stubs/slack_connector.pyi +0 -0
  30. {strideutils-0.4.4 → strideutils-0.5.0}/strideutils-stubs/stride_alerts.pyi +0 -0
  31. {strideutils-0.4.4 → strideutils-0.5.0}/strideutils-stubs/stride_config.pyi +0 -0
  32. {strideutils-0.4.4 → strideutils-0.5.0}/strideutils-stubs/stride_requests.pyi +0 -0
  33. {strideutils-0.4.4 → strideutils-0.5.0}/strideutils-stubs/stride_upstash.pyi +0 -0
  34. {strideutils-0.4.4 → strideutils-0.5.0}/strideutils-stubs/twilio_connector.pyi +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: strideutils
3
- Version: 0.4.4
3
+ Version: 0.5.0
4
4
  Summary:
5
5
  Author: Your Name
6
6
  Author-email: you@example.com
@@ -18,6 +18,7 @@ Requires-Dist: gspread (>=6.0.2)
18
18
  Requires-Dist: pandas (>=2.1.1)
19
19
  Requires-Dist: pycryptodome (>=3.20.0)
20
20
  Requires-Dist: python-dateutil (>=2.8.2)
21
+ Requires-Dist: python-dotenv (==1.0.1)
21
22
  Requires-Dist: pytz (>=2023.3)
22
23
  Requires-Dist: pyyaml (>=6.0.1)
23
24
  Requires-Dist: redis (>=4.5.4)
@@ -49,12 +50,11 @@ Strideutils requires three different environment variables that can be added to
49
50
 
50
51
  ```
51
52
  export STRIDEUTILS_CONFIG_PATH=
52
- export STRIDEUTILS_SECRETS_PATH=
53
- export ENV=DEV
53
+ export STRIDEUTILS_ENV_PATH=
54
54
  ```
55
55
 
56
56
  Examples of these files are included under strideutils/config_examples.
57
- Stride Labs employees can find config.yaml in launchpad and strideutils_secrets.yamls in lastpass.
57
+ Stride Labs employees can find config.yaml in launchpad and .env.local in lastpass. We recommend you place .env.local in your launchpad repo.
58
58
 
59
59
  Any configuration or secrets that aren't consumed don't need to be set. However if one is accessed but unset, an error will be thrown for easier debugging.
60
60
 
@@ -77,6 +77,14 @@ import sys
77
77
  sys.path = ['/path/to/strideutils/'] + sys.path
78
78
  ```
79
79
 
80
+ Alternatively, you can install strideutils through local mode. However, please be warned that this will make your local Python environment _always_ use your local strideutils. This might lead to unexpected behavior if you local changes.
81
+
82
+ To install in local mode, run the following:
83
+
84
+ ```
85
+ pip3 install -e /Users/username/Documents/strideutils
86
+ ```
87
+
80
88
  Confirm the location of where it's being imported from by printing the module.
81
89
  After making changes to strideutils, reload it before testing your application.
82
90
 
@@ -20,12 +20,11 @@ Strideutils requires three different environment variables that can be added to
20
20
 
21
21
  ```
22
22
  export STRIDEUTILS_CONFIG_PATH=
23
- export STRIDEUTILS_SECRETS_PATH=
24
- export ENV=DEV
23
+ export STRIDEUTILS_ENV_PATH=
25
24
  ```
26
25
 
27
26
  Examples of these files are included under strideutils/config_examples.
28
- Stride Labs employees can find config.yaml in launchpad and strideutils_secrets.yamls in lastpass.
27
+ Stride Labs employees can find config.yaml in launchpad and .env.local in lastpass. We recommend you place .env.local in your launchpad repo.
29
28
 
30
29
  Any configuration or secrets that aren't consumed don't need to be set. However if one is accessed but unset, an error will be thrown for easier debugging.
31
30
 
@@ -48,6 +47,14 @@ import sys
48
47
  sys.path = ['/path/to/strideutils/'] + sys.path
49
48
  ```
50
49
 
50
+ Alternatively, you can install strideutils through local mode. However, please be warned that this will make your local Python environment _always_ use your local strideutils. This might lead to unexpected behavior if you local changes.
51
+
52
+ To install in local mode, run the following:
53
+
54
+ ```
55
+ pip3 install -e /Users/username/Documents/strideutils
56
+ ```
57
+
51
58
  Confirm the location of where it's being imported from by printing the module.
52
59
  After making changes to strideutils, reload it before testing your application.
53
60
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "strideutils"
3
- version = "0.4.4"
3
+ version = "0.5.0"
4
4
  description = ""
5
5
  authors = ["Your Name <you@example.com>"]
6
6
  readme = "README.md"
@@ -21,6 +21,7 @@ slack-sdk = ">=3.23.0"
21
21
  pandas = ">=2.1.1"
22
22
  twilio = ">=8.10.0"
23
23
  tabulate = ">=0.9.0"
24
+ python-dotenv = "==1.0.1"
24
25
  pyyaml = ">=6.0.1"
25
26
  python-dateutil = ">=2.8.2"
26
27
  pycryptodome = ">=3.20.0"
@@ -79,11 +79,8 @@ def get_token_price_history(token: str, num_days=90, use_key=False, memo={}) ->
79
79
  price_key = (token, num_days)
80
80
  if price_key not in memo:
81
81
  tstr = get_coingecko_name(config.get_chain(ticker=token))
82
- rurl = (
83
- f"https://api.coingecko.com/api/v3/coins/{tstr}/market_chart?vs_currency=usd&days={num_days}" # noqa:E231
84
- )
82
+ rurl = f"{COINGECKO_ENDPOINT}api/v3/coins/{tstr}/market_chart?vs_currency=usd&days={num_days}" # noqa:E231
85
83
  rel_headers = {"x-cg-pro-api-key": config.COINGECKO_API_TOKEN} if use_key else None
86
-
87
84
  r = requests.get(
88
85
  rurl,
89
86
  headers=rel_headers,
@@ -98,7 +95,7 @@ def get_token_price_history(token: str, num_days=90, use_key=False, memo={}) ->
98
95
  return memo[token]
99
96
 
100
97
 
101
- def get_token_volume_history(token: str, num_days=90, use_key=False, memo={}) -> pd.Series:
98
+ def get_token_volume_history(token: str, num_days=90, use_key=True, memo={}) -> pd.Series:
102
99
  """
103
100
  returns a Pandas Series with token volume data going back num_days
104
101
  e.g. get_token_volume_history('uatom', 30) returns a Series with 30 days of ATOM volume data
@@ -107,11 +104,8 @@ def get_token_volume_history(token: str, num_days=90, use_key=False, memo={}) ->
107
104
  volume_key = (token, num_days)
108
105
  if volume_key not in memo:
109
106
  tstr = get_coingecko_name(config.get_chain(ticker=token))
110
- rurl = (
111
- f"https://api.coingecko.com/api/v3/coins/{tstr}/market_chart?vs_currency=usd&days={num_days}" # noqa:E231
112
- )
107
+ rurl = f"{COINGECKO_ENDPOINT}api/v3/coins/{tstr}/market_chart?vs_currency=usd&days={num_days}" # noqa:E231
113
108
  rel_headers = {"x-cg-pro-api-key": config.COINGECKO_API_TOKEN} if use_key else None
114
-
115
109
  r = requests.get(
116
110
  rurl,
117
111
  headers=rel_headers,
@@ -126,7 +120,7 @@ def get_token_volume_history(token: str, num_days=90, use_key=False, memo={}) ->
126
120
  return memo[token]
127
121
 
128
122
 
129
- def get_dataframe_of_prices(token_list: List[str], num_days: int = 90) -> pd.DataFrame:
123
+ def get_dataframe_of_prices(token_list: List[str], num_days: int = 90, use_key: bool = True) -> pd.DataFrame:
130
124
  """
131
125
  returns a Pandas DataFrame with token price data going back num_days, for the given tokens
132
126
  e.g. get_dataframe_of_prices(["ATOM", "OSMO", "STRD"], 30) returns a DataFrame of 30 days of price data
@@ -134,7 +128,7 @@ def get_dataframe_of_prices(token_list: List[str], num_days: int = 90) -> pd.Dat
134
128
  # gather the dataframe
135
129
  df = {}
136
130
  for token in token_list:
137
- df[token] = get_token_price_history(token, num_days)["price"]
131
+ df[token] = get_token_price_history(token, num_days, use_key=use_key)["price"]
138
132
  df = pd.DataFrame(df)
139
133
  # resample based on how much data we're gathering
140
134
  if num_days > 90:
@@ -0,0 +1,24 @@
1
+ ENV=DEV
2
+ CONFIGURE_STRIDEUTILS_LOGS=true
3
+
4
+ # Slack
5
+ SLACK_CHANNELS={"test": "U33D4351C2V"}
6
+
7
+ # API Tokens
8
+ NUMIA_API_TOKEN=token
9
+ COINGECKO_API_TOKEN=cgtoken
10
+
11
+ # Upstash
12
+ UPSTASH_PUBLIC_PASSWORD=password
13
+
14
+ # Twilio
15
+ TWILIO_ALERTS_NUMBER=+11111111111
16
+
17
+ # Slashbot twitter
18
+ TWITTER_CONSUMER_KEY=consumerkey
19
+
20
+ # Epoch Summary
21
+ EPOCH_SUMMARY_SLACK_BEARER_TOKEN=token
22
+
23
+ # Google Sheets
24
+ PUBLICSHEETS_AUTH={}
@@ -18,14 +18,16 @@ class TxResponse:
18
18
  raw_log: Optional[str] = None
19
19
 
20
20
 
21
- def execute_tx(command: str, api_endpoint: str = config.stride.api_endpoint) -> TxResponse:
21
+ def execute_tx(command: str, api_endpoint: str = config.stride.api_endpoint, verbose=False) -> TxResponse:
22
22
  """
23
23
  Execute a tx and query the tx hash
24
24
  """
25
25
  output = subprocess.run(command, shell=True, capture_output=True)
26
26
  standard_out = re.sub(r'\x1b\[[0-9;]*[mGKH]', '', output.stdout.decode('utf-8'))
27
27
  error_out = re.sub(r'\x1b\[[0-9;]*[mGKH]', '', output.stderr.decode('utf-8'))
28
-
28
+ if verbose:
29
+ print("Standard Out: ", standard_out)
30
+ print("Error Out: ", error_out)
29
31
  tx_hash = ""
30
32
  for output_line in standard_out.split('\n'):
31
33
  if 'txhash' in output_line:
@@ -1,4 +1,5 @@
1
1
  import os
2
+ import traceback
2
3
  from typing import List, Optional, Union
3
4
 
4
5
  from slack_sdk import WebClient
@@ -51,3 +52,23 @@ def post_msg(
51
52
  print("Error sending message: ", e)
52
53
  raise
53
54
  return thread_ts
55
+
56
+
57
+ def upload_file(file_name: str, content: str) -> str:
58
+ '''
59
+ This uploads a file called "file_name" with the string contents "content"
60
+
61
+ This will return a link that can be used to embed a file in slack.
62
+ For example:
63
+ url = upload_file("test.txt", "Hello World")
64
+ post_msg(f"<{url}|This is a file>", channel="#alerts-debug")
65
+ '''
66
+ client = WebClient(token=config.STRIDEBOT_API_TOKEN)
67
+ try:
68
+ slack_file = client.files_upload_v2(filename=file_name, content=content)
69
+ except Exception as e:
70
+ print(f"Error uploading file to slack: {e}")
71
+ traceback.print_exc()
72
+ raise ValueError(f"Error uploading file to slack: {e}")
73
+ file_link = slack_file['file']['permalink']
74
+ return file_link
@@ -8,6 +8,7 @@ from dataclasses import dataclass, field, fields
8
8
  from typing import Any, List, Optional, Union
9
9
 
10
10
  import yaml
11
+ from dotenv import load_dotenv
11
12
 
12
13
  MISSING_CONFIG_MSG = "Configuration or environment variable '{x}' is not set or unknown"
13
14
 
@@ -191,6 +192,8 @@ class Config(ConfigObj):
191
192
  UPSTASH_STRIDE_FRONTEND_PASSWORD: str = ""
192
193
  UPSTASH_STRIDE_BACKEND_PASSWORD: str = ""
193
194
  UPSTASH_STRIDE_DYDX_PUBLIC_PASSWORD: str = ""
195
+ UPSTASH_STRIDE_DYDX_AIRDROP_PASSWORD: str = ""
196
+ UPSTASH_STRIDE_MILESTONES_PASSWORD: str = ""
194
197
 
195
198
  # Stride internal secrets
196
199
  SLACK_BEARER_TOKEN: str = ""
@@ -317,7 +320,6 @@ def _load_raw_config() -> dict[str, Any]:
317
320
  'Shell var STRIDEUTILS_CONFIG_PATH is missing or the file does not exist in the default location.'
318
321
  'The default file and location is config/config.yaml in the current working directory'
319
322
  )
320
-
321
323
  with open(strideutils_config_path, 'r') as config_file:
322
324
  raw_config = yaml.load(config_file, Loader)
323
325
 
@@ -327,20 +329,13 @@ def _load_raw_config() -> dict[str, Any]:
327
329
  def _load_raw_secrets() -> dict[str, Optional[str]]:
328
330
  """
329
331
  Loads the secret variables into a dictionary
330
- If this is running locally in dev mode, secrets are grabbed from the path defined by STRIDEUTILS_SECRETS_PATH
332
+ If this is running locally in dev mode, secrets are grabbed from the path defined by STRIDEUTILS_ENV_PATH
331
333
  Otherwise, their loaded as environment variables
332
334
  """
333
- if ENV == "PROD":
334
- return {secret.name: os.environ.get(secret.name) for secret in fields(Config) if os.environ.get(secret.name)}
335
-
336
- if not (strideutils_secrets_path := os.environ.get('STRIDEUTILS_SECRETS_PATH')):
337
- raise ValueError(MISSING_CONFIG_MSG.format(x='STRIDEUTILS_SECRETS_PATH'))
338
-
339
- with open(strideutils_secrets_path, 'r') as f:
340
- raw_secrets = yaml.load(f, Loader)
341
- raw_secrets.update({'ENV': ENV})
342
-
343
- return raw_secrets
335
+ strideutils_env_path = os.environ.get('STRIDEUTILS_ENV_PATH', '.env.local')
336
+ if os.path.exists(strideutils_env_path):
337
+ load_dotenv(strideutils_env_path)
338
+ return {secret.name: os.environ.get(secret.name) for secret in fields(Config) if os.environ.get(secret.name)}
344
339
 
345
340
 
346
341
  def _parse_raw_configs(raw_config: dict[str, Any], raw_secrets: dict[str, Optional[str]]) -> Config:
@@ -916,36 +916,6 @@ def get_sttoken_apr(token: str) -> Optional[float]:
916
916
  return float(cast(str, apr))
917
917
 
918
918
 
919
- def get_delegated_tokens_on_address(
920
- delegator_address: str,
921
- api_endpoint: str = config.stride.api_endpoint,
922
- ) -> Dict[str, int]:
923
- """
924
- Returns a dict mapping from "validator_address" to "num tokens delegated", given a delegator address
925
-
926
- Raw response example (stake_endpoint)
927
- {
928
- "delegation_responses": [
929
- {"delegation": {
930
- "delegator_address": "cosmos10...28",
931
- "validator_address": "cosmosvaloper1p..r2qs",
932
- "shares":"1.180957009445999997"},
933
- "balance":{"denom":"uatom","amount":"1"}
934
- }, ...],
935
- "pagination": {...}
936
- }
937
-
938
- Returns
939
- e.g. {'valoper1': 10, 'valoper2': 20}
940
- """
941
- stake_endpoint = f"{api_endpoint}/{ACCOUNT_DELEGATIONS_QUERY.format(delegator_address=delegator_address)}"
942
- host_zone_balance = query_list_with_pagination(stake_endpoint, rel_key="delegation_responses")
943
- stake_amounts: Dict[str, int] = {}
944
- for hzb in host_zone_balance:
945
- stake_amounts[hzb["delegation"]["validator_address"]] = int(hzb["balance"]["amount"])
946
- return stake_amounts
947
-
948
-
949
919
  def get_unbonding_tokens_on_address(
950
920
  delegator_address: str,
951
921
  api_endpoint: str = config.stride.api_endpoint,
@@ -1003,18 +973,20 @@ def get_delegations(delegator_address: str, api_endpoint: str = config.stride.ap
1003
973
  return delegations_by_validator
1004
974
 
1005
975
 
1006
- def get_host_zone_delegations(host_zone_id: str, include_ground_truth: bool = True) -> pd.DataFrame:
976
+ def _parse_validator_dict(raw_validators: List[dict[str, Any]]) -> pd.DataFrame:
1007
977
  """
1008
- Given a host zone id, returns a Dataframe of validator delegations.
978
+ Given the output of a host_zone's "validator" field,
979
+ this will parse the data into a Pandas DataFrame.
1009
980
 
1010
- If `include_ground_truth=True`, then will also return the "true" delegations
1011
- on the host zone delegaiton account.
981
+ Will also cast the relevant columns to ints and floats.
1012
982
  """
1013
- int_cols = [
983
+ int_fields = [
1014
984
  "weight",
1015
985
  "delegation",
1016
- "slash_query_progress_tracker",
1017
986
  "slash_query_checkpoint",
987
+ "slash_query_progress_tracker",
988
+ ]
989
+ float_cols = [
1018
990
  "shares_to_tokens_rate",
1019
991
  ]
1020
992
  output_cols = [
@@ -1027,12 +999,26 @@ def get_host_zone_delegations(host_zone_id: str, include_ground_truth: bool = Tr
1027
999
  "shares_to_tokens_rate",
1028
1000
  ]
1029
1001
 
1030
- # Query the validator delegations on the host zone
1031
- host_zone = get_host_zone(host_zone_id)
1032
- validator_df = pd.DataFrame(host_zone["validators"])
1033
- validator_df[int_cols] = validator_df[int_cols].map(lambda i: int(float(i))) # type: ignore
1034
- validator_df = validator_df[output_cols]
1002
+ def parse_validator(field_name: str, field_value: Any) -> Any:
1003
+ if field_name in int_fields:
1004
+ return int(field_value)
1005
+ if field_name in float_cols:
1006
+ return float(field_value)
1007
+ return field_value
1008
+
1009
+ cast_validators = [{k: parse_validator(k, v) for k, v in val_dict.items()} for val_dict in raw_validators]
1010
+ return pd.DataFrame(cast_validators, dtype=object)[output_cols]
1011
+
1035
1012
 
1013
+ def get_host_zone_delegations(host_zone_id: str, include_ground_truth: bool = True) -> pd.DataFrame:
1014
+ """
1015
+ Given a host zone id, returns a Dataframe of validator delegations.
1016
+
1017
+ If `include_ground_truth=True`, then will also return the "true" delegations
1018
+ on the host zone delegaiton account.
1019
+ """
1020
+ host_zone = get_host_zone(host_zone_id)
1021
+ validator_df = _parse_validator_dict(host_zone["validators"])
1036
1022
  # If the ground truth isn't requested, return as is
1037
1023
  if not include_ground_truth:
1038
1024
  return validator_df
@@ -1,4 +1,4 @@
1
- from typing import Dict, Optional
1
+ from typing import Dict, List, Optional
2
2
 
3
3
  import redis
4
4
 
@@ -43,7 +43,20 @@ def get_redis_db(redis_db_name: str) -> redis.Redis:
43
43
  password=config.UPSTASH_STRIDE_DYDX_PUBLIC_PASSWORD,
44
44
  ssl=True,
45
45
  )
46
-
46
+ elif redis_db_name == 'dydx_airdrop':
47
+ r = redis.Redis(
48
+ host='pleasant-pipefish-54904.upstash.io',
49
+ port=6379,
50
+ password=config.UPSTASH_STRIDE_DYDX_AIRDROP_PASSWORD,
51
+ ssl=True,
52
+ )
53
+ elif redis_db_name == "milestones":
54
+ r = redis.Redis(
55
+ host='adapting-snail-56076.upstash.io',
56
+ port=6379,
57
+ password=config.UPSTASH_STRIDE_MILESTONES_PASSWORD,
58
+ ssl=True,
59
+ )
47
60
  else:
48
61
  raise ValueError(f'Invalid Redis DB: {redis_db_name}')
49
62
 
@@ -64,6 +77,35 @@ def get(redis_key: str, db_name='frontend') -> Optional[str]:
64
77
  return value.decode('utf-8') if value is not None else None
65
78
 
66
79
 
80
+ def get_multiple_keys(redis_keys: List[str], db_name='frontend') -> List[Optional[str]]:
81
+ """
82
+ This function will read multiple keys in at once.
83
+ Value will be "None" if the key does not exist.
84
+
85
+ Pulls from the specified redis db.
86
+ """
87
+ db = get_redis_db(db_name)
88
+ values = db.mget(redis_keys)
89
+
90
+ return [value.decode('utf-8') if value is not None else None for value in values]
91
+
92
+
93
+ def get_all_keys(db_name='dydx_airdrop') -> List[str]:
94
+ """
95
+ This function will return all keys in the redis db specified.
96
+ """
97
+ db = get_redis_db(db_name)
98
+
99
+ out = []
100
+
101
+ cursor = '0'
102
+ while cursor != 0:
103
+ cursor, keys = db.scan(cursor, count=1000)
104
+ if keys:
105
+ out.extend(keys)
106
+ return [key.decode('utf-8') for key in out]
107
+
108
+
67
109
  def set(redis_key: str, redis_val: str, db_name='frontend'):
68
110
  """
69
111
  This function will set the given key to value in the redis_db specified.
@@ -79,5 +121,7 @@ def set_keys(dict_to_upload: Dict[str, str], db_name='frontend', prefix=''):
79
121
  Will append "prefix" to all keys in the dict.
80
122
  """
81
123
  db = get_redis_db(db_name)
124
+ pipe = db.pipeline()
82
125
  for k, v in dict_to_upload.items():
83
- db.set(prefix + k, v)
126
+ pipe.set(prefix + k, v)
127
+ pipe.execute()
@@ -1,28 +0,0 @@
1
- # Twilio
2
- TWILIO_ALERTS_NUMBER: +18663326515
3
- TWILIO_ACCOUNT_ID:
4
- TWILIO_API_TOKEN:
5
- PHONE_NUMBERS: {}
6
-
7
- # Slack
8
- STRIDEBOT_API_TOKEN:
9
-
10
- # GSHEETS
11
- PUBLICSHEETS_AUTH:
12
-
13
- # Coingecko
14
- COINGECKO_API_TOKEN:
15
-
16
- # Stride Internal secrets
17
- SLACK_BEARER_TOKEN:
18
- SLACK_SUCCESS_CHANNEL_ID:
19
- SLACK_INVARIANT_FAILURE_CHANNEL_ID:
20
- SLACK_PACKET_FAILURE_CHANNEL_ID:
21
- NUMIA_API_TOKEN:
22
- UPSTASH_PUBLIC_PASSWORD:
23
- UPSTASH_STRIDE_FRONTEND_PASSWORD:
24
- UPSTASH_STRIDE_BACKEND_PASSWORD:
25
-
26
- # AWS
27
- AWS_ACCESS_KEY_ID:
28
- AWS_SECRET_ACCESS_KEY: