Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions mining/run_receive_signals_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import waitress

from miner_config import MinerConfig
from vali_objects.enums.execution_type_enum import ExecutionType
from vali_objects.vali_config import TradePair, ValiConfig
from vali_objects.enums.order_type_enum import OrderType
from vali_objects.utils.vali_bkp_utils import ValiBkpUtils
Expand All @@ -33,6 +34,9 @@ def handle_data():
# Check if 'Authorization' header is provided
data = request.json

if data is None:
return jsonify({"error": "Invalid message"}), 401

print("received data:", data)

if "api_key" in data:
Expand All @@ -57,9 +61,18 @@ def handle_data():
else:
raise Exception("trade_pair must be a string or a dict")

signal = Signal(trade_pair=TradePair.from_trade_pair_id(signal_trade_pair_str),
leverage=float(data["leverage"]),
order_type=OrderType.from_string(data["order_type"].upper()))
trade_pair = TradePair.from_trade_pair_id(signal_trade_pair_str)
if trade_pair is None:
return jsonify({"error": "Invalid trade pair"}), 401

signal = Signal(
trade_pair=trade_pair,
order_type=OrderType.from_string(data["order_type"].upper()),
leverage=float(data["leverage"]),
execution_type=data.get("execution_type", "MARKET").upper(),
limit_price=float(data["limit_price"]) if "limit_price" in data else None,
cancel_order_uuid=data["cancel_order_uuid"] if "cancel_order_uuid" in data else None
)
# make miner received signals dir if doesnt exist
ValiBkpUtils.make_dir(MinerConfig.get_miner_received_signals_dir())
# store miner signal
Expand All @@ -83,4 +96,4 @@ def handle_data():

if __name__ == "__main__":
waitress.serve(app, host="0.0.0.0", port=8088, connection_limit=1000)
print('Successfully started run_receive_signals_server.')
print('Successfully started run_receive_signals_server.')
9 changes: 7 additions & 2 deletions mining/sample_signal_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
import requests
import json

from vali_objects.enums.execution_type_enum import ExecutionType
from vali_objects.enums.order_type_enum import OrderType
from vali_objects.vali_config import TradePair, TradePairCategory


class CustomEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, TradePair) or isinstance(obj, OrderType):
if isinstance(obj, TradePair) or isinstance(obj, OrderType) or isinstance(obj, ExecutionType):
return obj.__json__() # Use the to_dict method to serialize TradePair

if isinstance(obj, TradePairCategory):
Expand Down Expand Up @@ -40,6 +41,10 @@ def default(self, obj):
'trade_pair': TradePair.FTSE,
'order_type': OrderType.LONG,
'leverage': .05,
# 'execution_type': ExecutionType.MARKET,
# 'execution_type': ExecutionType.LIMIT_CANCEL,
# 'limit_price': 0.1,
# 'cancel_order_uuid': "order-uuid",
'api_key': 'xxxx'
}

Expand All @@ -61,4 +66,4 @@ def default(self, obj):
print(response.json()) # Print the response data
else:
print(response.__dict__)
print("POST request failed with status code:", response.status_code)
print("POST request failed with status code:", response.status_code)
237 changes: 155 additions & 82 deletions neurons/validator.py

Large diffs are not rendered by default.

10 changes: 6 additions & 4 deletions ptn_api/api_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from vali_objects.utils.vali_bkp_utils import ValiBkpUtils


def start_rest_server(shared_queue, host="127.0.0.1", port=48888, refresh_interval=15, position_manager=None, contract_manager=None):
def start_rest_server(shared_queue, host="127.0.0.1", port=48888, refresh_interval=15, position_manager=None, contract_manager=None, limit_order_manager=None):
"""Starts the REST API server in a separate process."""
try:

Expand All @@ -26,7 +26,8 @@ def start_rest_server(shared_queue, host="127.0.0.1", port=48888, refresh_interv
port=port,
refresh_interval=refresh_interval,
position_manager=position_manager,
contract_manager=contract_manager
contract_manager=contract_manager,
limit_order_manager=limit_order_manager
)
rest_server.run()
except Exception as e:
Expand Down Expand Up @@ -63,7 +64,7 @@ class APIManager:

def __init__(self, shared_queue, refresh_interval=15,
rest_host="127.0.0.1", rest_port=48888,
ws_host="localhost", ws_port=8765, position_manager=None, contract_manager=None):
ws_host="localhost", ws_port=8765, position_manager=None, contract_manager=None, limit_order_manager=None):
"""Initialize API management with shared queue and server configurations.

Args:
Expand All @@ -89,6 +90,7 @@ def __init__(self, shared_queue, refresh_interval=15,
self.ws_port = ws_port
self.position_manager = position_manager
self.contract_manager = contract_manager
self.limit_order_manager = limit_order_manager

# Get default API keys file path
self.api_keys_file = ValiBkpUtils.get_api_keys_file_path()
Expand All @@ -113,7 +115,7 @@ def run(self):
# Start REST server process with host/port configuration
rest_process = Process(
target=start_rest_server,
args=(self.shared_queue, self.rest_host, self.rest_port, self.refresh_interval, self.position_manager, self.contract_manager),
args=(self.shared_queue, self.rest_host, self.rest_port, self.refresh_interval, self.position_manager, self.contract_manager, self.limit_order_manager),
name="RestServer"
)
rest_process.start()
Expand Down
26 changes: 25 additions & 1 deletion ptn_api/rest_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ class PTNRestServer(APIKeyMixin):
"""Handles REST API requests with Flask and Waitress."""

def __init__(self, api_keys_file, shared_queue=None, host="127.0.0.1",
port=48888, refresh_interval=15, metrics_interval_minutes=5, position_manager=None, contract_manager=None):
port=48888, refresh_interval=15, metrics_interval_minutes=5, position_manager=None, contract_manager=None, limit_order_manager=None):
"""Initialize the REST server with API key handling and routing.

Args:
Expand All @@ -249,6 +249,7 @@ def __init__(self, api_keys_file, shared_queue=None, host="127.0.0.1",
self.position_manager: PositionManager = position_manager
self.contract_manager = contract_manager
self.nonce_manager = NonceManager()
self.limit_order_manager = limit_order_manager
self.data_path = ValiConfig.BASE_DIR
self.host = host
self.port = port
Expand Down Expand Up @@ -537,6 +538,29 @@ def get_eliminations():
else:
return jsonify(data)

@self.app.route("/limit-orders/<minerid>", methods=["GET"])
def get_limit_orders_unique(minerid):
api_key = self._get_api_key_safe()

if not self.is_valid_api_key(api_key):
return jsonify({'error': 'Unauthorized access'}), 401

api_key_tier = self.get_api_key_tier(api_key)
if api_key_tier == 100 and self.limit_order_manager:
orders_data = self.limit_order_manager.to_dashboard_dict(minerid)
if not orders_data:
return jsonify({'error': f'No limit orders found for miner {minerid}'}), 404
else:
try:
orders_data = ValiBkpUtils.get_limit_orders(minerid, running_unit_tests=False)
if not orders_data:
return jsonify({'error': f'No limit orders found for miner {minerid}'}), 404
except Exception as e:
bt.logging.error(f"Error retrieving limit orders for {minerid}: {e}")
return jsonify({'error': 'Error retrieving limit orders'}), 500

return jsonify(orders_data)

@self.app.route("/collateral/deposit", methods=["POST"])
def deposit_collateral():
"""Process collateral deposit with encoded extrinsic."""
Expand Down
7 changes: 6 additions & 1 deletion restore_validator_from_backup.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from time_util.time_util import TimeUtil
from vali_objects.position import Position
from vali_objects.utils.elimination_manager import EliminationManager
from vali_objects.utils.limit_order_manager import LimitOrderManager
from vali_objects.utils.position_manager import PositionManager
from vali_objects.utils.challengeperiod_manager import ChallengePeriodManager
from vali_objects.utils.vali_bkp_utils import ValiBkpUtils
Expand Down Expand Up @@ -87,6 +88,7 @@ def regenerate_miner_positions(perform_backup=True, backup_from_data_dir=False,
elimination_manager=elimination_manager)
challengeperiod_manager = ChallengePeriodManager(metagraph=None, position_manager=position_manager)
perf_ledger_manager = PerfLedgerManager(None)
limit_order_manager = LimitOrderManager(position_manager, None)

if DEBUG:
position_manager.pre_run_setup()
Expand Down Expand Up @@ -180,8 +182,11 @@ def regenerate_miner_positions(perform_backup=True, backup_from_data_dir=False,
## Now sync challenge period with the disk
challengeperiod = data.get('challengeperiod', {})
challengeperiod_manager.sync_challenge_period_data(challengeperiod)

challengeperiod_manager._write_challengeperiod_from_memory_to_disk()

limit_orders = data.get('limit_orders', {})
limit_order_manager.sync_limit_orders(limit_orders)

return True

if __name__ == "__main__":
Expand Down
36 changes: 27 additions & 9 deletions runnable/generate_request_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from time_util.time_util import TimeUtil
from vali_objects.utils.challengeperiod_manager import ChallengePeriodManager
from vali_objects.utils.elimination_manager import EliminationManager
from vali_objects.utils.limit_order_manager import LimitOrderManager
from vali_objects.utils.plagiarism_detector import PlagiarismDetector
from vali_objects.vali_config import ValiConfig
from vali_objects.decoders.generalized_json_decoder import GeneralizedJSONDecoder
Expand All @@ -25,13 +26,14 @@
assert sorted(PERCENT_NEW_POSITIONS_TIERS, reverse=True) == PERCENT_NEW_POSITIONS_TIERS, 'needs to be sorted for efficient pruning'

class RequestCoreManager:
def __init__(self, position_manager, subtensor_weight_setter, plagiarism_detector):
def __init__(self, position_manager, subtensor_weight_setter, plagiarism_detector, limit_order_manager):
self.position_manager = position_manager
self.perf_ledger_manager = position_manager.perf_ledger_manager
self.elimination_manager = position_manager.elimination_manager
self.challengeperiod_manager = position_manager.challengeperiod_manager
self.subtensor_weight_setter = subtensor_weight_setter
self.plagiarism_detector = plagiarism_detector
self.limit_order_manager = limit_order_manager

def hash_string_to_int(self, s: str) -> int:
# Create a SHA-256 hash object
Expand Down Expand Up @@ -148,9 +150,16 @@ def upload_checkpoint_to_gcloud(self, final_dict):
blob.upload_from_string(zip_buffer)
print(f'Uploaded {blob_name} to {bucket_name}')

def create_and_upload_production_files(self, eliminations, ord_dict_hotkey_position_map, time_now,
youngest_order_processed_ms, oldest_order_processed_ms,
challengeperiod_dict):
def create_and_upload_production_files(
self,
eliminations,
ord_dict_hotkey_position_map,
time_now,
youngest_order_processed_ms,
oldest_order_processed_ms,
challengeperiod_dict,
limit_orders_dict
):

perf_ledgers = self.perf_ledger_manager.get_perf_ledgers(portfolio_only=False)
final_dict = {
Expand All @@ -162,7 +171,8 @@ def create_and_upload_production_files(self, eliminations, ord_dict_hotkey_posit
'youngest_order_processed_ms': youngest_order_processed_ms,
'oldest_order_processed_ms': oldest_order_processed_ms,
'positions': ord_dict_hotkey_position_map,
'perf_ledgers': perf_ledgers
'perf_ledgers': perf_ledgers,
'limit_orders': limit_orders_dict
}

vcp_output_file_path = ValiBkpUtils.get_vcp_output_path()
Expand Down Expand Up @@ -255,11 +265,18 @@ def generate_request_core(self, get_dash_data_hotkey: str | None = None, write_a
assert n_orders_original == n_positions_new, f"n_orders_original: {n_orders_original}, n_positions_new: {n_positions_new}"

challengeperiod_dict = self.challengeperiod_manager.to_checkpoint_dict()
limit_orders_dict = self.limit_order_manager.limit_orders

if write_and_upload_production_files:
self.create_and_upload_production_files(eliminations, ord_dict_hotkey_position_map, time_now_ms,
youngest_order_processed_ms, oldest_order_processed_ms,
challengeperiod_dict)
self.create_and_upload_production_files(
eliminations,
ord_dict_hotkey_position_map,
time_now_ms,
youngest_order_processed_ms,
oldest_order_processed_ms,
challengeperiod_dict,
limit_orders_dict
)

checkpoint_dict = {
'challengeperiod': challengeperiod_dict,
Expand All @@ -286,6 +303,7 @@ def generate_request_core(self, get_dash_data_hotkey: str | None = None, write_a
position_manager=position_manager,
)
plagiarism_detector = PlagiarismDetector(None, None, position_manager=position_manager)
limit_order_manager = LimitOrderManager(position_manager, None)

rcm = RequestCoreManager(position_manager, subtensor_weight_setter, plagiarism_detector)
rcm = RequestCoreManager(position_manager, subtensor_weight_setter, plagiarism_detector, limit_order_manager)
rcm.generate_request_core(write_and_upload_production_files=True)
Loading
Loading