11import calendar
22import json
33import time
4- from typing import Dict , List , Union
4+ from enum import Enum
5+ from typing import Any , Dict , List , Optional , Union , Tuple
56
67import cbor2
78import requests
3233__all__ = ["OgmiosChainContext" ]
3334
3435
36+ JSON = Dict [str , Any ]
37+
38+
39+ class OgmiosQueryType (str , Enum ):
40+ Query = "Query"
41+ SubmitTx = "SubmitTx"
42+ EvaluateTx = "EvaluateTx"
43+
44+
3545class OgmiosChainContext (ChainContext ):
46+ _ws_url : str
47+ _network : Network
48+ _service_name : str
49+ _kupo_url : Optional [str ]
50+ _last_known_block_slot : int
51+ _genesis_param : Optional [GenesisParameters ]
52+ _protocol_param : Optional [ProtocolParameters ]
53+
3654 def __init__ (
3755 self ,
3856 ws_url : str ,
@@ -48,15 +66,15 @@ def __init__(
4866 self ._genesis_param = None
4967 self ._protocol_param = None
5068
51- def _request (self , method : str , args : dict ) -> Union [ dict , int ] :
69+ def _request (self , method : OgmiosQueryType , args : JSON ) -> Any :
5270 ws = websocket .WebSocket ()
5371 ws .connect (self ._ws_url )
5472 request = json .dumps (
5573 {
5674 "type" : "jsonwsp/request" ,
5775 "version" : "1.0" ,
5876 "servicename" : self ._service_name ,
59- "methodname" : method ,
77+ "methodname" : method . value ,
6078 "args" : args ,
6179 },
6280 separators = ("," , ":" ),
@@ -86,10 +104,9 @@ def _fraction_parser(fraction: str) -> float:
86104 @property
87105 def protocol_param (self ) -> ProtocolParameters :
88106 """Get current protocol parameters"""
89- method = "Query"
90107 args = {"query" : "currentProtocolParameters" }
91108 if not self ._protocol_param or self ._check_chain_tip_and_update ():
92- result = self ._request (method , args )
109+ result = self ._request (OgmiosQueryType . Query , args )
93110 param = ProtocolParameters (
94111 min_fee_constant = result ["minFeeConstant" ],
95112 min_fee_coefficient = result ["minFeeCoefficient" ],
@@ -130,7 +147,7 @@ def protocol_param(self) -> ProtocolParameters:
130147 param .cost_models ["PlutusV2" ] = param .cost_models .pop ("plutus:v2" )
131148
132149 args = {"query" : "genesisConfig" }
133- result = self ._request (method , args )
150+ result = self ._request (OgmiosQueryType . Query , args )
134151 param .min_utxo = result ["protocolParameters" ]["minUtxoValue" ]
135152
136153 self ._protocol_param = param
@@ -139,10 +156,9 @@ def protocol_param(self) -> ProtocolParameters:
139156 @property
140157 def genesis_param (self ) -> GenesisParameters :
141158 """Get chain genesis parameters"""
142- method = "Query"
143159 args = {"query" : "genesisConfig" }
144160 if not self ._genesis_param or self ._check_chain_tip_and_update ():
145- result = self ._request (method , args )
161+ result = self ._request (OgmiosQueryType . Query , args )
146162 system_start_unix = int (
147163 calendar .timegm (
148164 time .strptime (
@@ -174,23 +190,21 @@ def network(self) -> Network:
174190 @property
175191 def epoch (self ) -> int :
176192 """Current epoch number"""
177- method = "Query"
178193 args = {"query" : "currentEpoch" }
179- return self ._request (method , args )
194+ return self ._request (OgmiosQueryType . Query , args )
180195
181196 @property
182197 def last_block_slot (self ) -> int :
183198 """Slot number of last block"""
184- method = "Query"
185199 args = {"query" : "chainTip" }
186- return self ._request (method , args )["slot" ]
200+ return self ._request (OgmiosQueryType . Query , args )["slot" ]
187201
188- def _extract_asset_info (self , asset_hash : str ):
202+ def _extract_asset_info (self , asset_hash : str ) -> Tuple [ str , ScriptHash , AssetName ] :
189203 policy_hex , asset_name_hex = asset_hash .split ("." )
190204 policy = ScriptHash .from_primitive (policy_hex )
191- asset_name_hex = AssetName .from_primitive (asset_name_hex )
205+ asset_name = AssetName .from_primitive (asset_name_hex )
192206
193- return policy_hex , policy , asset_name_hex
207+ return policy_hex , policy , asset_name
194208
195209 def _check_utxo_unspent (self , tx_id : str , index : int ) -> bool :
196210 """Check whether an UTxO is unspent with Ogmios.
@@ -200,9 +214,8 @@ def _check_utxo_unspent(self, tx_id: str, index: int) -> bool:
200214 index (int): transaction index.
201215 """
202216
203- method = "Query"
204217 args = {"query" : {"utxo" : [{"txId" : tx_id , "index" : index }]}}
205- results = self ._request (method , args )
218+ results = self ._request (OgmiosQueryType . Query , args )
206219
207220 if results :
208221 return True
@@ -220,6 +233,9 @@ def _utxos_kupo(self, address: str) -> List[UTxO]:
220233 Returns:
221234 List[UTxO]: A list of UTxOs.
222235 """
236+ if self ._kupo_url is None :
237+ raise AssertionError ("kupo_url object attribute has not been assigned properly." )
238+
223239 address_url = self ._kupo_url + "/" + address
224240 results = requests .get (address_url ).json ()
225241
@@ -282,9 +298,8 @@ def _utxos_ogmios(self, address: str) -> List[UTxO]:
282298 List[UTxO]: A list of UTxOs.
283299 """
284300
285- method = "Query"
286301 args = {"query" : {"utxo" : [address ]}}
287- results = self ._request (method , args )
302+ results = self ._request (OgmiosQueryType . Query , args )
288303
289304 utxos = []
290305
@@ -374,9 +389,8 @@ def submit_tx(self, cbor: Union[bytes, str]):
374389 if isinstance (cbor , bytes ):
375390 cbor = cbor .hex ()
376391
377- method = "SubmitTx"
378392 args = {"submit" : cbor }
379- result = self ._request (method , args )
393+ result = self ._request (OgmiosQueryType . SubmitTx , args )
380394 if "SubmitFail" in result :
381395 raise TransactionFailedException (result ["SubmitFail" ])
382396
@@ -395,9 +409,8 @@ def evaluate_tx(self, cbor: Union[bytes, str]) -> Dict[str, ExecutionUnits]:
395409 if isinstance (cbor , bytes ):
396410 cbor = cbor .hex ()
397411
398- method = "EvaluateTx"
399412 args = {"evaluate" : cbor }
400- result = self ._request (method , args )
413+ result = self ._request (OgmiosQueryType . EvaluateTx , args )
401414 if "EvaluationResult" not in result :
402415 raise TransactionFailedException (result )
403416 else :
0 commit comments