--prod option for moonworm

pull/93/head
Yhtyyar Sahatov 2022-09-12 17:23:28 +03:00
rodzic 19a3aed0d9
commit 4c62d2a4bc
4 zmienionych plików z 112 dodań i 9 usunięć

Wyświetl plik

@ -101,7 +101,7 @@ def handle_brownie_generate(args: argparse.Namespace):
build = json.load(ifp)
abi = build["abi"]
interface = generate_brownie_interface(abi, args.name)
interface = generate_brownie_interface(abi, build, args.name, prod=args.prod)
write_file(interface, os.path.join(args.outdir, args.name + ".py"))
@ -381,6 +381,11 @@ def generate_argument_parser() -> argparse.ArgumentParser:
required=True,
help=f"Path to brownie project directory",
)
generate_brownie_parser.add_argument(
"--prod",
action="store_true",
help="Generate shippable python interface, in which abi and bytecode will be included inside generated file",
)
generate_brownie_parser.set_defaults(func=handle_brownie_generate)
generate_parser = subcommands.add_parser(

Wyświetl plik

@ -1,4 +1,5 @@
import copy
from distutils.command.build import build
import logging
import os
from typing import Any, Dict, List, Optional
@ -12,12 +13,17 @@ from .basic import format_code, function_spec, get_constructor, make_annotation
BROWNIE_INTERFACE_TEMPLATE_PATH = os.path.join(
os.path.dirname(__file__), "brownie_contract.py.template"
)
BROWNIE_INTERFACE_PROD_TEMPLATE_PATH = os.path.join(
os.path.dirname(__file__), "brownie_contract_prod.py.template"
)
try:
with open(BROWNIE_INTERFACE_TEMPLATE_PATH, "r") as ifp:
BROWNIE_INTERFACE_TEMPLATE = ifp.read()
with open(BROWNIE_INTERFACE_PROD_TEMPLATE_PATH, "r") as ifp:
BROWNIE_INTERFACE_PROD_TEMPLATE = ifp.read()
except Exception as e:
logging.warn(
f"WARNING: Could not load cli template from {BROWNIE_INTERFACE_TEMPLATE_PATH}:"
f"WARNING: Could not load cli template from ({BROWNIE_INTERFACE_TEMPLATE_PATH})/({BROWNIE_INTERFACE_PROD_TEMPLATE_PATH}):"
)
logging.warn(e)
@ -887,7 +893,12 @@ def generate_brownie_cli(
def generate_brownie_interface(
abi: List[Dict[str, Any]], contract_name: str, cli: bool = True, format: bool = True
abi: List[Dict[str, Any]],
contract_build: Dict[str, Any],
contract_name: str,
cli: bool = True,
format: bool = True,
prod: bool = False,
) -> str:
contract_class = generate_brownie_contract_class(abi, contract_name)
module_body = [contract_class]
@ -897,11 +908,22 @@ def generate_brownie_interface(
module_body.extend(contract_cli_functions)
contract_body = cst.Module(body=module_body).code
content = BROWNIE_INTERFACE_TEMPLATE.format(
contract_body=contract_body,
moonworm_version=MOONWORM_VERSION,
)
if prod:
content = BROWNIE_INTERFACE_PROD_TEMPLATE.format(
contract_abi=abi,
contract_build={
"bytecode": contract_build["bytecode"],
"abi": contract_build["abi"],
"contractName": contract_build["contractName"],
},
contract_body=contract_body,
moonworm_version=MOONWORM_VERSION,
)
else:
content = BROWNIE_INTERFACE_TEMPLATE.format(
contract_body=contract_body,
moonworm_version=MOONWORM_VERSION,
)
if format:
content = format_code(content)

Wyświetl plik

@ -66,4 +66,4 @@ def contract_from_build(abi_name: str) -> ContractContainer:
return ContractContainer(PROJECT, build)
{contract_body}
{contract_body}

Wyświetl plik

@ -0,0 +1,76 @@
# Code generated by moonworm : https://github.com/bugout-dev/moonworm
# Moonworm version : {moonworm_version}
import argparse
import json
import os
from pathlib import Path
from typing import Any, Dict, List, Optional, Union
from brownie import Contract, network, project
from brownie.network.contract import ContractContainer, ContractConstructor, TransactionReceiptType, ContractNotFound, _ContractBase
from eth_typing.evm import ChecksumAddress
CONTRACT_BUILD = {contract_build}
def get_abi_json(*args) -> List[Dict[str, Any]]:
return CONTRACT_BUILD["abi"]
# This is workaround to deploy new contract which has only bytecode and abi in brownie
class CustomContract(Contract):
@classmethod
def from_build_object(cls, build: Dict[str, Any]):
self = cls.__new__(cls)
self.bytecode = build["bytecode"]
_ContractBase.__init__(self, None, build, {{}}) # type: ignore
self.deploy = ContractConstructor(self, self._name)
self.addres = None
return self
def _add_from_tx(self, tx: TransactionReceiptType) -> None:
tx._confirmed.wait()
if tx.status and tx.contract_address is not None:
self.address = tx.contract_address
self.tx = tx
self._owner = tx.sender
try:
self.at(tx.contract_address, tx.sender, tx)
except ContractNotFound:
# if the contract self-destructed during deployment
pass
def at(
self,
address: str,
owner: Any = None,
tx: Optional[TransactionReceiptType] = None,
persist: bool = True,
) -> Contract:
contract = Contract.from_abi(self._name, self.address, self.abi)
contract.tx = self.tx
return contract
def contract_from_build(*args) -> CustomContract:
return CustomContract.from_build_object(CONTRACT_BUILD)
def boolean_argument_type(raw_value: str) -> bool:
TRUE_VALUES = ["1", "t", "y", "true", "yes"]
FALSE_VALUES = ["0", "f", "n", "false", "no"]
if raw_value.lower() in TRUE_VALUES:
return True
elif raw_value.lower() in FALSE_VALUES:
return False
raise ValueError(
f"Invalid boolean argument: {{raw_value}}. Value must be one of: {{','.join(TRUE_VALUES + FALSE_VALUES)}}"
)
def bytes_argument_type(raw_value: str) -> str:
return raw_value
{contract_body}