Implement remaining cli tools on chainlib cli util

This commit is contained in:
nolash
2021-07-29 20:25:10 +02:00
parent 3d71df49b8
commit e007d0754e
12 changed files with 216 additions and 382 deletions

View File

@@ -198,6 +198,11 @@ class ERC20(TxFactory):
return abi_decode_single(ABIContractType.UINT256, v)
@classmethod
def parse_balance_of(self, v):
return self.parse_balance(v)
@classmethod
def parse_total_supply(self, v):
return abi_decode_single(ABIContractType.UINT256, v)

View File

@@ -16,17 +16,17 @@ import json
import argparse
import logging
# third-party imports
# external imports
from hexathon import (
add_0x,
strip_0x,
even,
)
import sha3
from eth_abi import encode_single
# external imports
from chainlib.eth.address import to_checksum
import chainlib.eth.cli
from chainlib.eth.address import to_checksum_address
from chainlib.eth.connection import EthHTTPConnection
from chainlib.eth.gas import (
OverrideGasOracle,
@@ -40,46 +40,29 @@ from eth_erc20 import ERC20
logging.basicConfig(level=logging.WARNING)
logg = logging.getLogger()
default_eth_provider = os.environ.get('RPC_PROVIDER')
if default_eth_provider == None:
default_eth_provider = os.environ.get('ETH_PROVIDER', 'http://localhost:8545')
argparser = argparse.ArgumentParser()
argparser.add_argument('-p', '--provider', dest='p', default=default_eth_provider, type=str, help='Web3 provider url (http only)')
argparser.add_argument('-a', '--token-address', dest='a', required=True, type=str, help='Token address. If not set, will return gas balance')
argparser.add_argument('-f', '--format', dest='f', type=str, default='terminal', help='Output format [terminal (default), raw, brief]')
argparser.add_argument('-i', '--chain-spec', dest='i', type=str, default='evm:ethereum:1', help='Chain specification string')
argparser.add_argument('-u', '--unsafe', dest='u', action='store_true', help='Auto-convert address to checksum adddress')
argparser.add_argument('--seq', action='store_true', help='Use sequential rpc ids')
argparser.add_argument('-v', action='store_true', help='Be verbose')
argparser.add_argument('-vv', action='store_true', help='Be more verbose')
argparser.add_argument('address', type=str, help='Account address')
arg_flags = chainlib.eth.cli.argflag_std_read | chainlib.eth.cli.Flag.EXEC
argparser = chainlib.eth.cli.ArgumentParser(arg_flags)
argparser.add_positional('address', type=str, help='Ethereum address of recipient')
args = argparser.parse_args()
config = chainlib.eth.cli.Config.from_args(args, arg_flags)
wallet = chainlib.eth.cli.Wallet()
wallet.from_config(config)
holder_address = args.address
if wallet.get_signer_address() == None and holder_address != None:
holder_address = wallet.from_address(holder_address)
if args.vv:
logg.setLevel(logging.DEBUG)
elif args.v:
logg.setLevel(logging.INFO)
rpc = chainlib.eth.cli.Rpc()
conn = rpc.connect_by_config(config)
conn = EthHTTPConnection(args.p)
gas_oracle = OverrideGasOracle(conn)
chain_spec = ChainSpec.from_chain_str(config.get('CHAIN_SPEC'))
address = to_checksum(args.address)
if not args.u and address != add_0x(args.address):
raise ValueError('invalid checksum address')
token_address = args.a
fmt = args.f
chain_spec = ChainSpec.from_chain_str(args.i)
token_address = config.get('_EXEC_ADDRESS')
def main():
r = None
decimals = 18
g = ERC20(chain_spec=chain_spec)
# determine decimals
decimals_o = g.decimals(token_address)
r = conn.do(decimals_o)
@@ -96,9 +79,8 @@ def main():
token_symbol = g.parse_symbol(r)
logg.info('symbol {}'.format(token_symbol))
# get balance
balance_o = g.balance(token_address, address)
balance_o = g.balance(token_address, holder_address)
r = conn.do(balance_o)
hx = strip_0x(r)
@@ -107,9 +89,7 @@ def main():
balance_str = str(balance_value)
balance_len = len(balance_str)
if fmt == 'terminal':
sys.stdout.write('{} ({}): '.format(token_name, token_symbol))
if fmt == 'raw':
if config.get('_RAW'):
print(balance_str)
else:
if balance_len < decimals + 1:

View File

@@ -16,7 +16,7 @@ import json
import argparse
import logging
# third-party imports
# external imports
from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer
from crypto_dev_signer.keystore.dict import DictKeystore
from hexathon import (
@@ -37,6 +37,8 @@ from chainlib.eth.gas import (
)
from chainlib.chain import ChainSpec
from chainlib.eth.runnable.util import decode_for_puny_humans
from chainlib.eth.address import to_checksum_address
import chainlib.eth.cli
# local imports
from eth_erc20 import ERC20
@@ -44,124 +46,70 @@ from eth_erc20 import ERC20
logging.basicConfig(level=logging.WARNING)
logg = logging.getLogger()
logging.getLogger('web3').setLevel(logging.WARNING)
logging.getLogger('urllib3').setLevel(logging.WARNING)
default_eth_provider = os.environ.get('RPC_PROVIDER')
if default_eth_provider == None:
default_eth_provider = os.environ.get('ETH_PROVIDER', 'http://localhost:8545')
argparser = argparse.ArgumentParser()
argparser.add_argument('-p', '--provider', dest='p', default=default_eth_provider, type=str, help='Web3 provider url (http only)')
argparser.add_argument('-w', action='store_true', help='Wait for the last transaction to be confirmed')
argparser.add_argument('-ww', action='store_true', help='Wait for every transaction to be confirmed')
argparser.add_argument('-i', '--chain-spec', dest='i', type=str, default='evm:ethereum:1', help='Chain specification string')
argparser.add_argument('-a', '--token-address', required='True', dest='a', type=str, help='Token address')
argparser.add_argument('-y', '--key-file', dest='y', type=str, help='Ethereum keystore file to use for signing')
argparser.add_argument('--env-prefix', default=os.environ.get('CONFINI_ENV_PREFIX'), dest='env_prefix', type=str, help='environment prefix for variables to overwrite configuration')
argparser.add_argument('-u', '--unsafe', dest='u', action='store_true', help='Auto-convert address to checksum adddress')
argparser.add_argument('-s', '--send', dest='s', action='store_true', help='Send to network')
argparser.add_argument('--nonce', type=int, help='Override nonce')
argparser.add_argument('--gas-price', dest='gas_price', type=int, help='Override gas price')
argparser.add_argument('--gas-limit', dest='gas_limit', type=int, help='Override gas limit')
argparser.add_argument('--seq', action='store_true', help='Use sequential rpc ids')
argparser.add_argument('-v', action='store_true', help='Be verbose')
argparser.add_argument('-vv', action='store_true', help='Be more verbose')
argparser.add_argument('recipient', type=str, help='Recipient account address')
argparser.add_argument('amount', type=int, help='Amount of tokens to mint and gift')
arg_flags = chainlib.eth.cli.argflag_std_write | chainlib.eth.cli.Flag.EXEC | chainlib.eth.cli.Flag.WALLET
argparser = chainlib.eth.cli.ArgumentParser(arg_flags)
argparser.add_positional('amount', type=int, help='Token amount to send')
args = argparser.parse_args()
extra_args = {
'amount': None,
}
config = chainlib.eth.cli.Config.from_args(args, arg_flags, extra_args=extra_args, default_fee_limit=100000)
if args.vv:
logg.setLevel(logging.DEBUG)
elif args.v:
logg.setLevel(logging.INFO)
block_all = args.ww
block_all = args.ww
block_last = args.w or block_all
passphrase_env = 'ETH_PASSPHRASE'
if args.env_prefix != None:
passphrase_env = args.env_prefix + '_' + passphrase_env
passphrase = os.environ.get(passphrase_env)
logg.error('pass {}'.format(passphrase_env))
if passphrase == None:
logg.warning('no passphrase given')
passphrase=''
wallet = chainlib.eth.cli.Wallet()
wallet.from_config(config)
signer_address = None
keystore = DictKeystore()
if args.y != None:
logg.debug('loading keystore file {}'.format(args.y))
signer_address = keystore.import_keystore_file(args.y, password=passphrase)
logg.debug('now have key for signer address {}'.format(signer_address))
signer = EIP155Signer(keystore)
rpc = chainlib.eth.cli.Rpc(wallet=wallet)
conn = rpc.connect_by_config(config)
rpc_id_generator = None
if args.seq:
rpc_id_generator = IntSequenceGenerator()
chain_spec = ChainSpec.from_chain_str(config.get('CHAIN_SPEC'))
auth = None
#if os.environ.get('RPC_AUTHENTICATION') == 'custom_token':
value = config.get('_AMOUNT')
if os.environ.get('RPC_AUTHENTICATION') == 'basic':
from chainlib.auth import BasicAuth
#auth = CustomHeaderTokenAuth('x-api-key', os.environ['RPC_AUTHENTICATION_STRING'])
auth = BasicAuth(os.environ['RPC_USERNAME'], os.environ['RPC_PASSWORD'])
conn = EthHTTPConnection(args.p)
nonce_oracle = None
if args.nonce != None:
nonce_oracle = OverrideNonceOracle(signer_address, args.nonce, id_generator=rpc_id_generator)
else:
nonce_oracle = RPCNonceOracle(signer_address, conn, id_generator=rpc_id_generator)
#def _max_gas(code=None):
# return 8000000
gas_oracle = None
if args.gas_price != None or args.gas_limit != None:
gas_oracle = OverrideGasOracle(price=args.gas_price, limit=args.gas_limit, id_generator=rpc_id_generator, conn=conn)
else:
gas_oracle = RPCGasOracle(conn, code_callback=ERC20.gas, id_generator=rpc_id_generator)
chain_spec = ChainSpec.from_chain_str(args.i)
chain_id = chain_spec.network_id()
value = args.amount
send = args.s
g = ERC20(chain_spec, signer=signer, gas_oracle=gas_oracle, nonce_oracle=nonce_oracle)
send = config.true('_RPC_SEND')
def balance(token_address, address, id_generator=None):
o = g.balance(token_address, address, id_generator=id_generator)
def balance(generator, token_address, address, id_generator=None):
o = generator.balance(token_address, address, id_generator=id_generator)
r = conn.do(o)
hx = strip_0x(r)
return int(hx, 16)
token_balance = generator.parse_balance(r)
return token_balance
def main():
recipient = args.recipient
if not args.u and recipient != add_0x(args.recipient):
raise ValueError('invalid checksum address')
signer = rpc.get_signer()
signer_address = rpc.get_sender_address()
gas_oracle = rpc.get_gas_oracle()
nonce_oracle = rpc.get_nonce_oracle()
g = ERC20(chain_spec, signer=signer, gas_oracle=gas_oracle, nonce_oracle=nonce_oracle)
recipient = to_checksum_address(config.get('_RECIPIENT'))
if not config.true('_UNSAFE') and recipient != add_0x(config.get('_RECIPIENT')):
raise ValueError('invalid checksum address for recipient')
token_address = to_checksum_address(config.get('_EXEC_ADDRESS'))
if not config.true('_UNSAFE') and token_address != add_0x(config.get('_EXEC_ADDRESS')):
raise ValueError('invalid checksum address for contract')
if logg.isEnabledFor(logging.DEBUG):
sender_balance = balance(args.a, signer_address, id_generator=rpc_id_generator)
recipient_balance = balance(args.a, recipient, id_generator=rpc_id_generator)
logg.debug('sender {} balance after: {}'.format(signer_address, sender_balance))
logg.debug('recipient {} balance after: {}'.format(recipient, recipient_balance))
sender_balance = balance(g, token_address, signer_address, id_generator=rpc.id_generator)
recipient_balance = balance(g, token_address, recipient, id_generator=rpc.id_generator)
logg.debug('sender {} balance before: {}'.format(signer_address, sender_balance))
logg.debug('recipient {} balance before: {}'.format(recipient, recipient_balance))
(tx_hash_hex, o) = g.transfer(args.a, signer_address, recipient, value, id_generator=rpc_id_generator)
(tx_hash_hex, o) = g.transfer(token_address, signer_address, recipient, value, id_generator=rpc.id_generator)
if send:
conn.do(o)
if block_last:
r = conn.wait(tx_hash_hex)
if logg.isEnabledFor(logging.DEBUG):
sender_balance = balance(args.a, signer_address, id_generator=rpc_id_generator)
recipient_balance = balance(args.a, recipient, id_generator=rpc_id_generator)
sender_balance = balance(g, token_address, signer_address, id_generator=rpc.id_generator)
recipient_balance = balance(g, token_address, recipient, id_generator=rpc.id_generator)
logg.debug('sender {} balance after: {}'.format(signer_address, sender_balance))
logg.debug('recipient {} balance after: {}'.format(recipient, recipient_balance))
if r['status'] == 0:
@@ -170,12 +118,7 @@ def main():
print(tx_hash_hex)
else:
if logg.isEnabledFor(logging.INFO):
io_str = io.StringIO()
decode_for_puny_humans(o['params'][0], chain_spec, io_str)
print(io_str.getvalue())
else:
print(o['params'][0])
print(o['params'][0])
if __name__ == '__main__':