Skip to content

Commit

Permalink
feat: implement cip-1559 changes
Browse files Browse the repository at this point in the history
  • Loading branch information
darwintree committed Sep 24, 2024
1 parent da6e597 commit 91bb2d3
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 77 deletions.
30 changes: 29 additions & 1 deletion conflux_web3/_utils/method_formatters.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ def from_hex_to_drip(val: Any):
RPC.cfx_getSkippedBlocksByEpoch: apply_formatter_at_index(to_hex_if_integer, 0),
RPC.cfx_getBlockByHashWithPivotAssumption: apply_formatter_at_index(to_hex_if_integer, 2),
RPC.cfx_getEpochReceipts: apply_formatter_at_index(to_hex_if_integer, 0),
RPC.cfx_feeHistory: compose(
apply_formatter_at_index(to_hex_if_integer, 0),
apply_formatter_at_index(to_hex_if_integer, 1),
),

RPC.cfx_getCode: apply_formatter_at_index(to_hex_if_integer, 1),
RPC.cfx_getStorageAt: apply_formatter_at_index(to_hex_if_integer, 2),
Expand Down Expand Up @@ -229,6 +233,7 @@ def from_hex_to_drip(val: Any):
log_entry_formatter = apply_formatters_to_dict(LOG_ENTRY_FORMATTERS)

RECEIPT_FORMATTERS = {
"type": to_integer_if_hex,
"transactionHash": to_hash32,
"index": to_integer_if_hex,
"blockHash": apply_formatter_if(is_not_null, to_hash32),
Expand All @@ -247,11 +252,17 @@ def from_hex_to_drip(val: Any):
"outcomeStatus": to_integer_if_hex,
"logsBloom": to_hexbytes(256), # type: ignore
"logs": apply_list_to_array_formatter(log_entry_formatter),
"burntGasFee": from_hex_to_drip,
"effectiveGasPrice": from_hex_to_drip,
}
# receipt_formatter = apply_formatters_to_dict(RECEIPT_FORMATTERS)

ACCESS_LIST_ENTRY_FORMATTERS = {
"address": from_trust_to_base32,
}

TRANSACTION_DATA_FORMATTERS = {
"type": to_integer_if_hex,
"blockHash": apply_formatter_if(is_not_null, to_hash32),
"chainId": apply_formatter_if(is_not_null, to_integer_if_hex),
"contractCreated": apply_formatter_if(is_not_null, from_trust_to_base32),
Expand All @@ -270,6 +281,10 @@ def from_hex_to_drip(val: Any):
"transactionIndex": apply_formatter_if(is_not_null, to_integer_if_hex),
"v": apply_formatter_if(is_not_null, to_integer_if_hex),
"value": from_hex_to_drip,
"maxFeePerGas": apply_formatter_if(is_not_null, from_hex_to_drip),
"maxPriorityFeePerGas": apply_formatter_if(is_not_null, from_hex_to_drip),
"accessList": apply_formatter_if(is_not_null, apply_list_to_array_formatter(apply_formatters_to_dict(ACCESS_LIST_ENTRY_FORMATTERS))),
"yParity": apply_formatter_if(is_not_null, to_integer_if_hex),
}
transaction_data_formatter = apply_formatters_to_dict(TRANSACTION_DATA_FORMATTERS)

Expand Down Expand Up @@ -311,7 +326,8 @@ def from_hex_to_drip(val: Any):
),
(is_array_of_strings, apply_list_to_array_formatter(to_hash32)),
)
)
),
"baseFeePerGas": apply_formatter_if(is_not_null, from_hex_to_drip),
}
block_formatter = apply_formatters_to_dict(BLOCK_FORMATTERS)

Expand Down Expand Up @@ -395,6 +411,7 @@ def fixed64_to_float(val: str) -> float:
"powBaseReward": from_hex_to_drip,
"interestRate": to_integer_if_hex,
"storagePointProp": to_integer_if_hex,
"baseFeeShareProp": to_integer_if_hex,
}

SUPPLY_INFO_FORMATTERS = {
Expand All @@ -419,6 +436,14 @@ def fixed64_to_float(val: str) -> float:
)
}

FEE_HISTORY_FORMATTERS = {
"baseFeePerGas": apply_list_to_array_formatter(from_hex_to_drip),
# "gasUsedRatio": lambda x: x, # do nothing
"oldestEpoch": to_integer_if_hex,
"reward": apply_list_to_array_formatter(apply_list_to_array_formatter(from_hex_to_drip)),
}


SIMPLE_RESULT_FORMATTER_MAPPING: Dict[Type[Any], Callable[..., Any]] = {
int: to_integer_if_hex,
Drip: from_hex_to_drip,
Expand Down Expand Up @@ -449,6 +474,7 @@ def create_dict_result_formatter(typed_dict_class: Type[TypedDict]) -> Callable[
RPC.cfx_estimateGasAndCollateral: apply_formatters_to_dict(ESTIMATE_FORMATTERS),
RPC.cfx_getConfirmationRiskByHash: fixed64_to_float,
RPC.cfx_gasPrice: from_hex_to_drip,
RPC.cfx_maxPriorityFeePerGas: from_hex_to_drip,
RPC.cfx_getBalance: from_hex_to_drip,
RPC.cfx_getStakingBalance: from_hex_to_drip,
RPC.cfx_getNextNonce: to_integer_if_hex,
Expand All @@ -463,6 +489,7 @@ def create_dict_result_formatter(typed_dict_class: Type[TypedDict]) -> Callable[
is_not_null,
apply_formatters_to_dict(RECEIPT_FORMATTERS),
))),
RPC.cfx_feeHistory: apply_formatters_to_dict(FEE_HISTORY_FORMATTERS),

RPC.cfx_getLogs: filter_result_formatter,
RPC.cfx_getFilterLogs: filter_result_formatter,
Expand Down Expand Up @@ -501,6 +528,7 @@ def create_dict_result_formatter(typed_dict_class: Type[TypedDict]) -> Callable[
),
RPC.cfx_getSupplyInfo: apply_formatters_to_dict(SUPPLY_INFO_FORMATTERS),
RPC.cfx_getCollateralInfo: create_dict_result_formatter(CollateralInfo),
RPC.cfx_getFeeBurnt: from_hex_to_drip,

RPC.cfx_getAccountPendingInfo: apply_formatters_to_dict(PENDING_INFO_FORMATTERS),
RPC.cfx_getAccountPendingTransactions: apply_formatters_to_dict(PENDING_TRANSACTIONS_INFO_FORMATTERS),
Expand Down
3 changes: 3 additions & 0 deletions conflux_web3/_utils/rpc_abi.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ class RPC:
cfx_getBlockRewardInfo = RPCEndpoint("cfx_getBlockRewardInfo")
cfx_getBlocksByEpoch = RPCEndpoint("cfx_getBlocksByEpoch")
cfx_getEpochReceipts = RPCEndpoint("cfx_getEpochReceipts")
cfx_maxPriorityFeePerGas = RPCEndpoint("cfx_maxPriorityFeePerGas")
cfx_feeHistory = RPCEndpoint("cfx_feeHistory")
cfx_getFeeBurnt = RPCEndpoint("cfx_getFeeBurnt")

cfx_getCode = RPCEndpoint("cfx_getCode")
cfx_getCollateralForStorage = RPCEndpoint("cfx_getCollateralForStorage")
Expand Down
25 changes: 25 additions & 0 deletions conflux_web3/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
)
from conflux_web3.types import (
EstimateResult,
FeeHistory,
TxReceipt,
TxData,
NodeStatus,
Expand Down Expand Up @@ -396,6 +397,18 @@ def default_account_munger(
RPC.cfx_checkBalanceAgainstTransaction
)

_max_priority_fee_per_gas: ConfluxMethod[Callable[[], Drip]] = ConfluxMethod(
RPC.cfx_maxPriorityFeePerGas
)

_fee_history: ConfluxMethod[Callable[[int, EpochNumberParam, Sequence[float]], FeeHistory]] = ConfluxMethod(
RPC.cfx_feeHistory
)

_get_fee_burnt: ConfluxMethod[Callable[[], Drip]] = ConfluxMethod(
RPC.cfx_getFeeBurnt
)

_get_logs: ConfluxMethod[Callable[[FilterParams], List[LogReceipt]]] = ConfluxMethod(
RPC.cfx_getLogs
)
Expand Down Expand Up @@ -1668,3 +1681,15 @@ def uninstall_filter(self, filter_id: _FilterId) -> bool:

def get_admin(self, address: AddressParam, block_identifier: Optional[EpochNumberParam] = None) -> Union[None, Base32Address]:
return self._get_admin(address, block_identifier)

def fee_history(self, epoch_count: int, block_identifier: EpochNumberParam, reward_percentiles: Sequence[float]) -> FeeHistory:
return self._fee_history(epoch_count, block_identifier, reward_percentiles)

def get_fee_burnt(self) -> Drip:
return self._get_fee_burnt()

@property
def max_priority_fee_per_gas(self) -> Drip:
return self._max_priority_fee_per_gas()


132 changes: 63 additions & 69 deletions conflux_web3/types/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ class EventData(TransactionEventData, total=False):
TxReceipt = TypedDict(
"TxReceipt",
{
"type": int,
"transactionHash": Hash32,
"index": int,
"blockHash": Hash32,
Expand All @@ -220,13 +221,16 @@ class EventData(TransactionEventData, total=False):
"logsBloom": HexBytes,
"logs": List[TransactionLogReceipt],
"txExecErrorMsg": Union[str, None],
"effectiveGasPrice": Drip,
"burntGasFee": Drip,
},
)
"""
Transaction receipt as a dict
Parameters
----------
| "type": int,
| "transactionHash": Hash32,
| "index": int,
| "blockHash": Hash32,
Expand All @@ -245,16 +249,25 @@ class EventData(TransactionEventData, total=False):
| "logsBloom": HexBytes,
| "logs": List[TransactionLogReceipt],
| "txExecErrorMsg": Union[str, None]
| "effectiveGasPrice": Drip,
| "burntGasFee": Drip,
"""

class TxReceiptWithSpace(TxReceipt):
space: Literal["native", "evm"]

class AccessListEntry(TypedDict):
address: Base32Address
storageKeys: Sequence[HexStr]

AccessList = NewType("AccessList", Sequence[AccessListEntry])


# syntax b/c "from" keyword not allowed w/ class construction
TxData = TypedDict(
"TxData",
LegacyTxData = TypedDict(
"LegacyTxData",
{
"type": int,
"blockHash": Union[None, Hash32],
"chainId": int,
"contractCreated": Union[None, Base32Address],
Expand All @@ -276,30 +289,37 @@ class TxReceiptWithSpace(TxReceipt):
},
total=False,
)
"""
Transaction data as a dict

Parameters
----------
| "blockHash": Union[None, Hash32],
| "chainId": int,
| "contractCreated": Union[None, Base32Address],
| "data": HexBytes,
| "epochHeight": int,
| "from": Base32Address,
| "gas": int,
| "gasPrice": Drip,
| "hash": Hash32,
| "nonce": Nonce,
| "r": HexBytes,
| "s": HexBytes,
| "status": Union[None, int],
| "storageLimit": Storage,
| "to": Union[None, Base32Address],
| "transactionIndex": Union[None, int],
| "v": int,
| "value": Drip,
"""
class TxData(LegacyTxData, total=False):
"""
Transaction data as a dict
Parameters
----------
| "type": int,
| "blockHash": Union[None, Hash32],
| "chainId": int,
| "contractCreated": Union[None, Base32Address],
| "data": HexBytes,
| "epochHeight": int,
| "from": Base32Address,
| "gas": int,
| "gasPrice": Drip,
| "hash": Hash32,
| "nonce": Nonce,
| "r": HexBytes,
| "s": HexBytes,
| "status": Union[None, int],
| "storageLimit": Storage,
| "to": Union[None, Base32Address],
| "transactionIndex": Union[None, int],
| "v": int,
| "value": Drip,
"""
maxFeePerGas: Optional[Drip]
maxPriorityFeePerGas: Optional[Drip]
accessList: Optional[AccessList]
yParity: Optional[int]

class BlockData(TypedDict):
"""
Expand Down Expand Up @@ -354,6 +374,7 @@ class BlockData(TypedDict):
custom: Sequence[HexBytes]
posReference: Hash32
transactions: Sequence[Union[Hash32, TxData]]
baseFeePerGas: Drip


Middleware = Callable[[Callable[[RPCEndpoint, Any], RPCResponse], "Web3"], Any]
Expand Down Expand Up @@ -505,10 +526,12 @@ class DAOVoteInfo(TypedDict):
| powBaseReward: Drip
| interestRate: int
| storagePointProp: int
| baseFeeShareProp: int
"""
powBaseReward: Drip
interestRate: int
storagePointProp: int
baseFeeShareProp: int

class SupplyInfo(TypedDict):
"""
Expand Down Expand Up @@ -590,47 +613,18 @@ class CollateralInfo(TypedDict):

_FilterId = Union[LogFilterId, BlockFilterId, TxFilterId, str]

__all__ = [
"TxDict",
"TxParam",
"HexAddress",
"Drip",
"CFX",
"GDrip",
"AddressParam",
"Storage",
"EpochNumberParam",
"EpochLiteral",
"EpochNumber",
"NodeStatus",
"EstimateResult",
"FilterParams",
"TransactionLogReceipt",
"LogReceipt",
"TransactionEventData",
"EventData",
"TxReceipt",
"TxReceiptWithSpace"
"TxData",
"BlockData",
"MiddlewareOnion",
"StorageRoot",
"SponsorInfo",
"AccountInfo",
"DepositInfo",
"VoteInfo",
"BlockRewardInfo",
"PoSEconomicsInfo",
"PoSAccountRewardsInfo",
"PoSEpochRewardInfo",
"DAOVoteInfo",
"SupplyInfo",
"PendingInfo",
"PendingTransactionsInfo",
"TransactionPaymentInfo",
"CollateralInfo",
"LogFilterId",
"BlockFilterId",
"TxFilterId",
"_FilterId",
]
class FeeHistory(TypedDict):
"""
Fee history information
Parameters
----------
| baseFeePerGas: Sequence[Drip] - List of base fee per gas values for each epoch
| gasUsedRatio: Sequence[float] - List of gas used ratios for each epoch pivot block
| oldestEpoch: int - The oldest epoch number in the returned range
| reward: Sequence[Sequence[Drip]] - List of effective priority fee per gas values for each epoch
"""
baseFeePerGas: Sequence[Drip]
gasUsedRatio: Sequence[float]
oldestEpoch: int
reward: Sequence[Sequence[Drip]]
15 changes: 9 additions & 6 deletions tests/_test_helpers/type_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,16 @@ def isinstance(val: Any, field_type: Type[Any]) -> bool:

@staticmethod
def assert_instance(val: Any, field_type: Type[Any]) -> Literal[True]:
from pydantic import BaseModel, ValidationError

if is_typeddict(field_type):
annotations = field_type.__annotations__
for key, sub_field_type in annotations.items():
if key not in val:
raise TypeError(f"missed key for typed_dict: {key} not in {val}")
if not TypeValidator.isinstance(val[key], sub_field_type):
raise TypeError(f"unexpected value type for typed_dict field: {val[key]} should be type {sub_field_type}")
class PydanticModel(BaseModel, arbitrary_types_allowed=True):
__annotations__ = field_type.__annotations__

try:
PydanticModel(**val)
except ValidationError as e:
raise TypeError(f"Validation error for typed_dict: {e}")
return True
if get_origin(field_type) is Union:
for t in get_args(field_type):
Expand Down
Loading

0 comments on commit 91bb2d3

Please sign in to comment.