|
3 | 3 |
|
4 | 4 | from web3 import Web3 |
5 | 5 | from web3.datastructures import AttributeDict |
6 | | -from web3.contract import Contract |
| 6 | +from web3.contract import Contract, ContractFunction |
7 | 7 | from thirdweb.common.error import NoSignerException |
8 | 8 | from web3._utils.events import EventLogErrorFlags |
9 | 9 | from thirdweb.common.sign import EIP712Domain, sign_typed_data_internal |
@@ -95,6 +95,53 @@ def get_events(self, event: str, receipt: TxReceipt) -> Tuple[AttributeDict]: |
95 | 95 | .processReceipt(receipt, errors=EventLogErrorFlags.Discard) |
96 | 96 | ) |
97 | 97 |
|
| 98 | + def call(self, fn: str, *args) -> Any: |
| 99 | + func = cast(ContractFunction, getattr(self.get_contract_interface().functions, fn, None)) |
| 100 | + if func is None: |
| 101 | + raise Exception( |
| 102 | + f"Function {fn} not found on contract {self._contract_abi.contract_address}. " |
| 103 | + + "Check your dashboard for the list of available functions." |
| 104 | + ) |
| 105 | + |
| 106 | + # We need this to set params properly on func + throws good errors |
| 107 | + func.args = args |
| 108 | + func.kwargs = {} |
| 109 | + func._set_function_info() |
| 110 | + |
| 111 | + if len(func.abi["inputs"]) != len(args): |
| 112 | + signature = ( |
| 113 | + "(" |
| 114 | + + ", ".join( |
| 115 | + [(i["name"] + ": " + i["type"]) for i in func.abi["inputs"]] |
| 116 | + ) |
| 117 | + + ")" |
| 118 | + ) |
| 119 | + raise Exception( |
| 120 | + f"Function {fn} expects {len(func.arguments)} arguments, " |
| 121 | + f"but {len(args)} were provided.\nExpected function signature: {signature}" |
| 122 | + ) |
| 123 | + |
| 124 | + if func.abi["stateMutability"] == "view" or func.abi["stateMutability"] == "pure": |
| 125 | + return func(*args).call() |
| 126 | + else: |
| 127 | + provider = self.get_provider() |
| 128 | + signer = self.get_signer() |
| 129 | + |
| 130 | + if signer is None: |
| 131 | + raise NoSignerException |
| 132 | + |
| 133 | + nonce = provider.eth.get_transaction_count(signer.address) # type: ignore |
| 134 | + |
| 135 | + tx = func(*args).buildTransaction( |
| 136 | + TxParams(gas_price=provider.eth.gas_price).as_dict() |
| 137 | + ) |
| 138 | + tx["nonce"] = nonce |
| 139 | + |
| 140 | + signed_tx = signer.sign_transaction(tx) # type: ignore |
| 141 | + tx_hash = provider.eth.send_raw_transaction(signed_tx.rawTransaction) |
| 142 | + |
| 143 | + return provider.eth.wait_for_transaction_receipt(tx_hash) |
| 144 | + |
98 | 145 | def send_transaction(self, fn: str, args: List[Any], overrides: TxParams = None) -> TxReceipt: |
99 | 146 | """ |
100 | 147 | Send and execute a transaction and return the receipt. |
|
0 commit comments