2
2
import json
3
3
import time
4
4
from enum import Enum
5
- from typing import Any , Dict , List , Optional , Union , Tuple
5
+ from typing import Any , Dict , List , Optional , Tuple , Union
6
6
7
7
import cbor2
8
8
import requests
@@ -88,7 +88,31 @@ def _request(self, method: OgmiosQueryType, args: JSON) -> Any:
88
88
)
89
89
return json .loads (response )["result" ]
90
90
91
- def _check_chain_tip_and_update (self ):
91
+ def _query_current_protocol_params (self ) -> JSON :
92
+ args = {"query" : "currentProtocolParameters" }
93
+ return self ._request (OgmiosQueryType .Query , args )
94
+
95
+ def _query_genesis_config (self ) -> JSON :
96
+ args = {"query" : "genesisConfig" }
97
+ return self ._request (OgmiosQueryType .Query , args )
98
+
99
+ def _query_current_epoch (self ) -> int :
100
+ args = {"query" : "currentEpoch" }
101
+ return self ._request (OgmiosQueryType .Query , args )
102
+
103
+ def _query_chain_tip (self ) -> JSON :
104
+ args = {"query" : "chainTip" }
105
+ return self ._request (OgmiosQueryType .Query , args )
106
+
107
+ def _query_utxos_by_address (self , address : str ) -> List [List [JSON ]]:
108
+ args = {"query" : {"utxo" : [address ]}}
109
+ return self ._request (OgmiosQueryType .Query , args )
110
+
111
+ def _query_utxos_by_tx_id (self , tx_id : str , index : int ) -> List [List [JSON ]]:
112
+ args = {"query" : {"utxo" : [{"txId" : tx_id , "index" : index }]}}
113
+ return self ._request (OgmiosQueryType .Query , args )
114
+
115
+ def _is_chain_tip_updated (self ):
92
116
slot = self .last_block_slot
93
117
if self ._last_known_block_slot != slot :
94
118
self ._last_known_block_slot = slot
@@ -104,84 +128,84 @@ def _fraction_parser(fraction: str) -> float:
104
128
@property
105
129
def protocol_param (self ) -> ProtocolParameters :
106
130
"""Get current protocol parameters"""
107
- args = {"query" : "currentProtocolParameters" }
108
- if not self ._protocol_param or self ._check_chain_tip_and_update ():
109
- result = self ._request (OgmiosQueryType .Query , args )
110
- param = ProtocolParameters (
111
- min_fee_constant = result ["minFeeConstant" ],
112
- min_fee_coefficient = result ["minFeeCoefficient" ],
113
- max_block_size = result ["maxBlockBodySize" ],
114
- max_tx_size = result ["maxTxSize" ],
115
- max_block_header_size = result ["maxBlockHeaderSize" ],
116
- key_deposit = result ["stakeKeyDeposit" ],
117
- pool_deposit = result ["poolDeposit" ],
118
- pool_influence = self ._fraction_parser (result ["poolInfluence" ]),
119
- monetary_expansion = self ._fraction_parser (result ["monetaryExpansion" ]),
120
- treasury_expansion = self ._fraction_parser (result ["treasuryExpansion" ]),
121
- decentralization_param = self ._fraction_parser (
122
- result .get ("decentralizationParameter" , "0/1" )
123
- ),
124
- extra_entropy = result .get ("extraEntropy" , "" ),
125
- protocol_major_version = result ["protocolVersion" ]["major" ],
126
- protocol_minor_version = result ["protocolVersion" ]["minor" ],
127
- min_pool_cost = result ["minPoolCost" ],
128
- price_mem = self ._fraction_parser (result ["prices" ]["memory" ]),
129
- price_step = self ._fraction_parser (result ["prices" ]["steps" ]),
130
- max_tx_ex_mem = result ["maxExecutionUnitsPerTransaction" ]["memory" ],
131
- max_tx_ex_steps = result ["maxExecutionUnitsPerTransaction" ]["steps" ],
132
- max_block_ex_mem = result ["maxExecutionUnitsPerBlock" ]["memory" ],
133
- max_block_ex_steps = result ["maxExecutionUnitsPerBlock" ]["steps" ],
134
- max_val_size = result ["maxValueSize" ],
135
- collateral_percent = result ["collateralPercentage" ],
136
- max_collateral_inputs = result ["maxCollateralInputs" ],
137
- coins_per_utxo_word = result .get (
138
- "coinsPerUtxoWord" , ALONZO_COINS_PER_UTXO_WORD
139
- ),
140
- coins_per_utxo_byte = result .get ("coinsPerUtxoByte" , 0 ),
141
- cost_models = result .get ("costModels" , {}),
142
- )
131
+ if not self ._protocol_param or self ._is_chain_tip_updated ():
132
+ self ._protocol_param = self ._fetch_protocol_param ()
133
+ return self ._protocol_param
143
134
144
- if "plutus:v1" in param .cost_models :
145
- param .cost_models ["PlutusV1" ] = param .cost_models .pop ("plutus:v1" )
146
- if "plutus:v2" in param .cost_models :
147
- param .cost_models ["PlutusV2" ] = param .cost_models .pop ("plutus:v2" )
135
+ def _fetch_protocol_param (self ) -> ProtocolParameters :
136
+ result = self ._query_current_protocol_params ()
137
+ param = ProtocolParameters (
138
+ min_fee_constant = result ["minFeeConstant" ],
139
+ min_fee_coefficient = result ["minFeeCoefficient" ],
140
+ max_block_size = result ["maxBlockBodySize" ],
141
+ max_tx_size = result ["maxTxSize" ],
142
+ max_block_header_size = result ["maxBlockHeaderSize" ],
143
+ key_deposit = result ["stakeKeyDeposit" ],
144
+ pool_deposit = result ["poolDeposit" ],
145
+ pool_influence = self ._fraction_parser (result ["poolInfluence" ]),
146
+ monetary_expansion = self ._fraction_parser (result ["monetaryExpansion" ]),
147
+ treasury_expansion = self ._fraction_parser (result ["treasuryExpansion" ]),
148
+ decentralization_param = self ._fraction_parser (
149
+ result .get ("decentralizationParameter" , "0/1" )
150
+ ),
151
+ extra_entropy = result .get ("extraEntropy" , "" ),
152
+ protocol_major_version = result ["protocolVersion" ]["major" ],
153
+ protocol_minor_version = result ["protocolVersion" ]["minor" ],
154
+ min_pool_cost = result ["minPoolCost" ],
155
+ price_mem = self ._fraction_parser (result ["prices" ]["memory" ]),
156
+ price_step = self ._fraction_parser (result ["prices" ]["steps" ]),
157
+ max_tx_ex_mem = result ["maxExecutionUnitsPerTransaction" ]["memory" ],
158
+ max_tx_ex_steps = result ["maxExecutionUnitsPerTransaction" ]["steps" ],
159
+ max_block_ex_mem = result ["maxExecutionUnitsPerBlock" ]["memory" ],
160
+ max_block_ex_steps = result ["maxExecutionUnitsPerBlock" ]["steps" ],
161
+ max_val_size = result ["maxValueSize" ],
162
+ collateral_percent = result ["collateralPercentage" ],
163
+ max_collateral_inputs = result ["maxCollateralInputs" ],
164
+ coins_per_utxo_word = result .get (
165
+ "coinsPerUtxoWord" , ALONZO_COINS_PER_UTXO_WORD
166
+ ),
167
+ coins_per_utxo_byte = result .get ("coinsPerUtxoByte" , 0 ),
168
+ cost_models = result .get ("costModels" , {}),
169
+ )
148
170
149
- args = {"query" : "genesisConfig" }
150
- result = self ._request (OgmiosQueryType .Query , args )
151
- param .min_utxo = result ["protocolParameters" ]["minUtxoValue" ]
171
+ if "plutus:v1" in param .cost_models :
172
+ param .cost_models ["PlutusV1" ] = param .cost_models .pop ("plutus:v1" )
173
+ if "plutus:v2" in param .cost_models :
174
+ param .cost_models ["PlutusV2" ] = param .cost_models .pop ("plutus:v2" )
152
175
153
- self ._protocol_param = param
154
- return self ._protocol_param
176
+ result = self ._query_genesis_config ()
177
+ param .min_utxo = result ["protocolParameters" ]["minUtxoValue" ]
178
+ return param
155
179
156
180
@property
157
181
def genesis_param (self ) -> GenesisParameters :
158
182
"""Get chain genesis parameters"""
159
- args = {"query" : "genesisConfig" }
160
- if not self ._genesis_param or self ._check_chain_tip_and_update ():
161
- result = self ._request (OgmiosQueryType .Query , args )
162
- system_start_unix = int (
163
- calendar .timegm (
164
- time .strptime (
165
- result ["systemStart" ].split ("." )[0 ], "%Y-%m-%dT%H:%M:%S"
166
- ),
167
- )
168
- )
169
- self ._genesis_param = GenesisParameters (
170
- active_slots_coefficient = self ._fraction_parser (
171
- result ["activeSlotsCoefficient" ]
172
- ),
173
- update_quorum = result ["updateQuorum" ],
174
- max_lovelace_supply = result ["maxLovelaceSupply" ],
175
- network_magic = result ["networkMagic" ],
176
- epoch_length = result ["epochLength" ],
177
- system_start = system_start_unix ,
178
- slots_per_kes_period = result ["slotsPerKesPeriod" ],
179
- slot_length = result ["slotLength" ],
180
- max_kes_evolutions = result ["maxKesEvolutions" ],
181
- security_param = result ["securityParameter" ],
182
- )
183
+ if not self ._genesis_param or self ._is_chain_tip_updated ():
184
+ self ._genesis_param = self ._fetch_genesis_param ()
183
185
return self ._genesis_param
184
186
187
+ def _fetch_genesis_param (self ) -> GenesisParameters :
188
+ result = self ._query_genesis_config ()
189
+ system_start_unix = int (
190
+ calendar .timegm (
191
+ time .strptime (result ["systemStart" ].split ("." )[0 ], "%Y-%m-%dT%H:%M:%S" ),
192
+ )
193
+ )
194
+ return GenesisParameters (
195
+ active_slots_coefficient = self ._fraction_parser (
196
+ result ["activeSlotsCoefficient" ]
197
+ ),
198
+ update_quorum = result ["updateQuorum" ],
199
+ max_lovelace_supply = result ["maxLovelaceSupply" ],
200
+ network_magic = result ["networkMagic" ],
201
+ epoch_length = result ["epochLength" ],
202
+ system_start = system_start_unix ,
203
+ slots_per_kes_period = result ["slotsPerKesPeriod" ],
204
+ slot_length = result ["slotLength" ],
205
+ max_kes_evolutions = result ["maxKesEvolutions" ],
206
+ security_param = result ["securityParameter" ],
207
+ )
208
+
185
209
@property
186
210
def network (self ) -> Network :
187
211
"""Get current network"""
@@ -190,37 +214,29 @@ def network(self) -> Network:
190
214
@property
191
215
def epoch (self ) -> int :
192
216
"""Current epoch number"""
193
- args = {"query" : "currentEpoch" }
194
- return self ._request (OgmiosQueryType .Query , args )
217
+ return self ._query_current_epoch ()
195
218
196
219
@property
197
220
def last_block_slot (self ) -> int :
198
221
"""Slot number of last block"""
199
- args = {"query" : "chainTip" }
200
- return self ._request (OgmiosQueryType .Query , args )["slot" ]
201
-
202
- def _extract_asset_info (self , asset_hash : str ) -> Tuple [str , ScriptHash , AssetName ]:
203
- policy_hex , asset_name_hex = asset_hash .split ("." )
204
- policy = ScriptHash .from_primitive (policy_hex )
205
- asset_name = AssetName .from_primitive (asset_name_hex )
222
+ result = self ._query_chain_tip ()
223
+ return result ["slot" ]
206
224
207
- return policy_hex , policy , asset_name
208
-
209
- def _check_utxo_unspent (self , tx_id : str , index : int ) -> bool :
210
- """Check whether an UTxO is unspent with Ogmios.
225
+ def utxos (self , address : str ) -> List [UTxO ]:
226
+ """Get all UTxOs associated with an address.
211
227
212
228
Args:
213
- tx_id (str): transaction id.
214
- index (int): transaction index.
215
- """
216
-
217
- args = {"query" : {"utxo" : [{"txId" : tx_id , "index" : index }]}}
218
- results = self ._request (OgmiosQueryType .Query , args )
229
+ address (str): An address encoded with bech32.
219
230
220
- if results :
221
- return True
231
+ Returns:
232
+ List[UTxO]: A list of UTxOs.
233
+ """
234
+ if self ._kupo_url :
235
+ utxos = self ._utxos_kupo (address )
222
236
else :
223
- return False
237
+ utxos = self ._utxos_ogmios (address )
238
+
239
+ return utxos
224
240
225
241
def _utxos_kupo (self , address : str ) -> List [UTxO ]:
226
242
"""Get all UTxOs associated with an address with Kupo.
@@ -234,7 +250,9 @@ def _utxos_kupo(self, address: str) -> List[UTxO]:
234
250
List[UTxO]: A list of UTxOs.
235
251
"""
236
252
if self ._kupo_url is None :
237
- raise AssertionError ("kupo_url object attribute has not been assigned properly." )
253
+ raise AssertionError (
254
+ "kupo_url object attribute has not been assigned properly."
255
+ )
238
256
239
257
address_url = self ._kupo_url + "/" + address
240
258
results = requests .get (address_url ).json ()
@@ -288,6 +306,23 @@ def _utxos_kupo(self, address: str) -> List[UTxO]:
288
306
289
307
return utxos
290
308
309
+ def _check_utxo_unspent (self , tx_id : str , index : int ) -> bool :
310
+ """Check whether an UTxO is unspent with Ogmios.
311
+
312
+ Args:
313
+ tx_id (str): transaction id.
314
+ index (int): transaction index.
315
+ """
316
+ results = self ._query_utxos_by_tx_id (tx_id , index )
317
+ return len (results ) > 0
318
+
319
+ def _extract_asset_info (self , asset_hash : str ) -> Tuple [str , ScriptHash , AssetName ]:
320
+ policy_hex , asset_name_hex = asset_hash .split ("." )
321
+ policy = ScriptHash .from_primitive (policy_hex )
322
+ asset_name = AssetName .from_primitive (asset_name_hex )
323
+
324
+ return policy_hex , policy , asset_name
325
+
291
326
def _utxos_ogmios (self , address : str ) -> List [UTxO ]:
292
327
"""Get all UTxOs associated with an address with Ogmios.
293
328
@@ -297,12 +332,9 @@ def _utxos_ogmios(self, address: str) -> List[UTxO]:
297
332
Returns:
298
333
List[UTxO]: A list of UTxOs.
299
334
"""
300
-
301
- args = {"query" : {"utxo" : [address ]}}
302
- results = self ._request (OgmiosQueryType .Query , args )
335
+ results = self ._query_utxos_by_address (address )
303
336
304
337
utxos = []
305
-
306
338
for result in results :
307
339
in_ref = result [0 ]
308
340
output = result [1 ]
@@ -360,22 +392,6 @@ def _utxos_ogmios(self, address: str) -> List[UTxO]:
360
392
361
393
return utxos
362
394
363
- def utxos (self , address : str ) -> List [UTxO ]:
364
- """Get all UTxOs associated with an address.
365
-
366
- Args:
367
- address (str): An address encoded with bech32.
368
-
369
- Returns:
370
- List[UTxO]: A list of UTxOs.
371
- """
372
- if self ._kupo_url :
373
- utxos = self ._utxos_kupo (address )
374
- else :
375
- utxos = self ._utxos_ogmios (address )
376
-
377
- return utxos
378
-
379
395
def submit_tx (self , cbor : Union [bytes , str ]):
380
396
"""Submit a transaction to the blockchain.
381
397
0 commit comments