chainlib/chainlib/eth/gas.py

139 lines
4.0 KiB
Python
Raw Normal View History

2021-04-04 14:55:27 +02:00
# standard imports
import logging
2021-02-09 09:42:46 +01:00
# third-party imports
from hexathon import (
add_0x,
strip_0x,
)
from crypto_dev_signer.eth.transaction import EIP155Transaction
# local imports
from chainlib.hash import keccak256_hex_to_hex
2021-04-04 14:55:27 +02:00
from chainlib.jsonrpc import jsonrpc_template
from chainlib.eth.tx import (
TxFactory,
TxFormat,
raw,
)
from chainlib.eth.constant import (
MINIMUM_FEE_UNITS,
)
2021-02-09 09:42:46 +01:00
2021-04-04 14:55:27 +02:00
logg = logging.getLogger(__name__)
2021-02-09 09:42:46 +01:00
def price():
o = jsonrpc_template()
o['method'] = 'eth_gasPrice'
return o
def balance(address):
o = jsonrpc_template()
o['method'] = 'eth_getBalance'
o['params'].append(address)
2021-04-04 14:55:27 +02:00
o['params'].append('latest')
2021-02-09 09:42:46 +01:00
return o
2021-04-04 14:55:27 +02:00
class Gas(TxFactory):
2021-02-09 09:42:46 +01:00
2021-04-04 14:55:27 +02:00
def create(self, sender_address, recipient_address, value, tx_format=TxFormat.JSONRPC):
tx = self.template(sender_address, recipient_address, use_nonce=True)
tx['value'] = value
2021-02-09 09:42:46 +01:00
txe = EIP155Transaction(tx, tx['nonce'], tx['chainId'])
2021-04-04 14:55:27 +02:00
tx_raw = self.signer.sign_transaction_to_rlp(txe)
2021-02-09 09:42:46 +01:00
tx_raw_hex = add_0x(tx_raw.hex())
tx_hash_hex = add_0x(keccak256_hex_to_hex(tx_raw_hex))
o = None
2021-04-04 14:55:27 +02:00
if tx_format == TxFormat.JSONRPC:
o = raw(tx_raw_hex)
elif tx_format == TxFormat.RLP_SIGNED:
o = tx_raw_hex
2021-02-09 09:42:46 +01:00
return (tx_hash_hex, o)
2021-04-04 14:55:27 +02:00
class RPCGasOracle:
2021-02-09 09:42:46 +01:00
def __init__(self, conn, code_callback=None, min_price=1):
2021-02-09 09:42:46 +01:00
self.conn = conn
2021-04-04 14:55:27 +02:00
self.code_callback = code_callback
self.min_price = min_price
2021-02-09 09:42:46 +01:00
2021-04-04 14:55:27 +02:00
def get_gas(self, code=None):
2021-04-13 06:50:33 +02:00
gas_price = 0
if self.conn != None:
o = price()
r = self.conn.do(o)
n = strip_0x(r)
gas_price = int(n, 16)
2021-04-04 14:55:27 +02:00
fee_units = MINIMUM_FEE_UNITS
if self.code_callback != None:
fee_units = self.code_callback(code)
2021-04-13 06:50:33 +02:00
if gas_price < self.min_price:
logg.debug('adjusting price {} to set minimum {}'.format(gas_price, self.min_price))
gas_price = self.min_price
return (gas_price, fee_units)
class RPCPureGasOracle(RPCGasOracle):
def __init__(self, conn, code_callback=None):
super(RPCPureGasOracle, self).__init__(conn, code_callback=code_callback, min_price=0)
2021-04-04 14:55:27 +02:00
class OverrideGasOracle(RPCGasOracle):
2021-04-04 14:55:27 +02:00
def __init__(self, price=None, limit=None, conn=None, code_callback=None):
self.conn = None
self.code_callback = None
self.limit = limit
self.price = price
2021-04-14 14:45:37 +02:00
price_conn = None
if self.limit == None or self.price == None:
2021-04-13 06:50:33 +02:00
if self.price == None:
price_conn = conn
logg.debug('override gas oracle with rpc fallback; price {} limit {}'.format(self.price, self.limit))
2021-04-14 14:45:37 +02:00
super(OverrideGasOracle, self).__init__(price_conn, code_callback)
2021-04-04 14:55:27 +02:00
def get_gas(self, code=None):
r = None
fee_units = None
fee_price = None
2021-04-13 06:50:33 +02:00
rpc_results = super(OverrideGasOracle, self).get_gas(code)
2021-04-04 14:55:27 +02:00
if self.limit != None:
fee_units = self.limit
if self.price != None:
fee_price = self.price
if fee_price == None:
if rpc_results != None:
fee_price = rpc_results[0]
logg.debug('override gas oracle without explicit price, setting from rpc {}'.format(fee_price))
else:
fee_price = MINIMUM_FEE_PRICE
logg.debug('override gas oracle without explicit price, setting default {}'.format(fee_price))
if fee_units == None:
if rpc_results != None:
fee_units = rpc_results[1]
2021-04-13 06:50:33 +02:00
logg.debug('override gas oracle without explicit limit, setting from rpc {}'.format(fee_units))
2021-04-04 14:55:27 +02:00
else:
fee_units = MINIMUM_FEE_UNITS
2021-04-13 06:50:33 +02:00
logg.debug('override gas oracle without explicit limit, setting default {}'.format(fee_units))
2021-04-04 14:55:27 +02:00
return (fee_price, fee_units)
DefaultGasOracle = RPCGasOracle