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
Signed by: lash
GPG Key ID: 21D2E7BB88C2A746
12 changed files with 216 additions and 382 deletions

View File

@ -1 +1 @@
include **/data/ERC20.json **/data/GiftableToken.json **/data/GiftableToken.bin requirements.txt test_requirements.txt include **/data/ERC20.json **/data/GiftableToken.json **/data/GiftableToken.bin *requirements.txt

View File

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

View File

@ -16,17 +16,17 @@ import json
import argparse import argparse
import logging import logging
# third-party imports # external imports
from hexathon import ( from hexathon import (
add_0x, add_0x,
strip_0x, strip_0x,
even, even,
) )
import sha3 import sha3
from eth_abi import encode_single
# external imports # 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.connection import EthHTTPConnection
from chainlib.eth.gas import ( from chainlib.eth.gas import (
OverrideGasOracle, OverrideGasOracle,
@ -40,46 +40,29 @@ from eth_erc20 import ERC20
logging.basicConfig(level=logging.WARNING) logging.basicConfig(level=logging.WARNING)
logg = logging.getLogger() logg = logging.getLogger()
default_eth_provider = os.environ.get('RPC_PROVIDER') arg_flags = chainlib.eth.cli.argflag_std_read | chainlib.eth.cli.Flag.EXEC
if default_eth_provider == None: argparser = chainlib.eth.cli.ArgumentParser(arg_flags)
default_eth_provider = os.environ.get('ETH_PROVIDER', 'http://localhost:8545') argparser.add_positional('address', type=str, help='Ethereum address of recipient')
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')
args = argparser.parse_args() 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: rpc = chainlib.eth.cli.Rpc()
logg.setLevel(logging.DEBUG) conn = rpc.connect_by_config(config)
elif args.v:
logg.setLevel(logging.INFO)
conn = EthHTTPConnection(args.p) chain_spec = ChainSpec.from_chain_str(config.get('CHAIN_SPEC'))
gas_oracle = OverrideGasOracle(conn)
address = to_checksum(args.address) token_address = config.get('_EXEC_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)
def main(): def main():
r = None
decimals = 18
g = ERC20(chain_spec=chain_spec) g = ERC20(chain_spec=chain_spec)
# determine decimals # determine decimals
decimals_o = g.decimals(token_address) decimals_o = g.decimals(token_address)
r = conn.do(decimals_o) r = conn.do(decimals_o)
@ -96,9 +79,8 @@ def main():
token_symbol = g.parse_symbol(r) token_symbol = g.parse_symbol(r)
logg.info('symbol {}'.format(token_symbol)) logg.info('symbol {}'.format(token_symbol))
# get balance # get balance
balance_o = g.balance(token_address, address) balance_o = g.balance(token_address, holder_address)
r = conn.do(balance_o) r = conn.do(balance_o)
hx = strip_0x(r) hx = strip_0x(r)
@ -107,9 +89,7 @@ def main():
balance_str = str(balance_value) balance_str = str(balance_value)
balance_len = len(balance_str) balance_len = len(balance_str)
if fmt == 'terminal': if config.get('_RAW'):
sys.stdout.write('{} ({}): '.format(token_name, token_symbol))
if fmt == 'raw':
print(balance_str) print(balance_str)
else: else:
if balance_len < decimals + 1: if balance_len < decimals + 1:

View File

@ -16,7 +16,7 @@ import json
import argparse import argparse
import logging import logging
# third-party imports # external imports
from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer
from crypto_dev_signer.keystore.dict import DictKeystore from crypto_dev_signer.keystore.dict import DictKeystore
from hexathon import ( from hexathon import (
@ -37,6 +37,8 @@ from chainlib.eth.gas import (
) )
from chainlib.chain import ChainSpec from chainlib.chain import ChainSpec
from chainlib.eth.runnable.util import decode_for_puny_humans from chainlib.eth.runnable.util import decode_for_puny_humans
from chainlib.eth.address import to_checksum_address
import chainlib.eth.cli
# local imports # local imports
from eth_erc20 import ERC20 from eth_erc20 import ERC20
@ -44,124 +46,70 @@ from eth_erc20 import ERC20
logging.basicConfig(level=logging.WARNING) logging.basicConfig(level=logging.WARNING)
logg = logging.getLogger() logg = logging.getLogger()
logging.getLogger('web3').setLevel(logging.WARNING) arg_flags = chainlib.eth.cli.argflag_std_write | chainlib.eth.cli.Flag.EXEC | chainlib.eth.cli.Flag.WALLET
logging.getLogger('urllib3').setLevel(logging.WARNING) argparser = chainlib.eth.cli.ArgumentParser(arg_flags)
argparser.add_positional('amount', type=int, help='Token amount to send')
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')
args = argparser.parse_args() args = argparser.parse_args()
extra_args = {
'amount': None,
if args.vv: }
logg.setLevel(logging.DEBUG) config = chainlib.eth.cli.Config.from_args(args, arg_flags, extra_args=extra_args, default_fee_limit=100000)
elif args.v:
logg.setLevel(logging.INFO)
block_all = args.ww block_all = args.ww
block_last = args.w or block_all block_last = args.w or block_all
passphrase_env = 'ETH_PASSPHRASE' wallet = chainlib.eth.cli.Wallet()
if args.env_prefix != None: wallet.from_config(config)
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=''
signer_address = None rpc = chainlib.eth.cli.Rpc(wallet=wallet)
keystore = DictKeystore() conn = rpc.connect_by_config(config)
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_id_generator = None chain_spec = ChainSpec.from_chain_str(config.get('CHAIN_SPEC'))
if args.seq:
rpc_id_generator = IntSequenceGenerator()
auth = None value = config.get('_AMOUNT')
#if os.environ.get('RPC_AUTHENTICATION') == 'custom_token':
if os.environ.get('RPC_AUTHENTICATION') == 'basic': send = config.true('_RPC_SEND')
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)
def balance(token_address, address, id_generator=None): def balance(generator, token_address, address, id_generator=None):
o = g.balance(token_address, address, id_generator=id_generator) o = generator.balance(token_address, address, id_generator=id_generator)
r = conn.do(o) r = conn.do(o)
hx = strip_0x(r) token_balance = generator.parse_balance(r)
return int(hx, 16) return token_balance
def main(): def main():
recipient = args.recipient signer = rpc.get_signer()
if not args.u and recipient != add_0x(args.recipient): signer_address = rpc.get_sender_address()
raise ValueError('invalid checksum 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): if logg.isEnabledFor(logging.DEBUG):
sender_balance = balance(args.a, signer_address, id_generator=rpc_id_generator) sender_balance = balance(g, token_address, signer_address, id_generator=rpc.id_generator)
recipient_balance = balance(args.a, recipient, 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('sender {} balance before: {}'.format(signer_address, sender_balance))
logg.debug('recipient {} balance after: {}'.format(recipient, recipient_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: if send:
conn.do(o) conn.do(o)
if block_last: if block_last:
r = conn.wait(tx_hash_hex) r = conn.wait(tx_hash_hex)
if logg.isEnabledFor(logging.DEBUG): if logg.isEnabledFor(logging.DEBUG):
sender_balance = balance(args.a, signer_address, id_generator=rpc_id_generator) sender_balance = balance(g, token_address, signer_address, id_generator=rpc.id_generator)
recipient_balance = balance(args.a, recipient, 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('sender {} balance after: {}'.format(signer_address, sender_balance))
logg.debug('recipient {} balance after: {}'.format(recipient, recipient_balance)) logg.debug('recipient {} balance after: {}'.format(recipient, recipient_balance))
if r['status'] == 0: if r['status'] == 0:
@ -169,11 +117,6 @@ def main():
sys.exit(1) sys.exit(1)
print(tx_hash_hex) 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: else:
print(o['params'][0]) print(o['params'][0])

File diff suppressed because one or more lines are too long

View File

@ -38,7 +38,7 @@ class GiftableToken(TxFactory):
@staticmethod @staticmethod
def gas(code=None): def gas(code=None):
return 1500000 return 2000000
@staticmethod @staticmethod
@ -71,6 +71,18 @@ class GiftableToken(TxFactory):
return tx return tx
def remove_minter(self, contract_address, sender_address, address, tx_format=TxFormat.JSONRPC):
enc = ABIContractEncoder()
enc.method('removeMinter')
enc.typ(ABIContractType.ADDRESS)
enc.address(address)
data = enc.get()
tx = self.template(sender_address, contract_address, use_nonce=True)
tx = self.set_code(tx, data)
tx = self.finalize(tx, tx_format)
return tx
def mint_to(self, contract_address, sender_address, address, value, tx_format=TxFormat.JSONRPC): def mint_to(self, contract_address, sender_address, address, value, tx_format=TxFormat.JSONRPC):
enc = ABIContractEncoder() enc = ABIContractEncoder()
enc.method('mintTo') enc.method('mintTo')

View File

@ -17,17 +17,8 @@ import time
from enum import Enum from enum import Enum
# external imports # external imports
from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer import chainlib.eth.cli
from crypto_dev_signer.keystore.dict import DictKeystore
from chainlib.chain import ChainSpec from chainlib.chain import ChainSpec
from chainlib.eth.nonce import (
RPCNonceOracle,
OverrideNonceOracle,
)
from chainlib.eth.gas import (
RPCGasOracle,
OverrideGasOracle,
)
from chainlib.eth.connection import EthHTTPConnection from chainlib.eth.connection import EthHTTPConnection
from chainlib.eth.tx import receipt from chainlib.eth.tx import receipt
@ -37,83 +28,47 @@ from giftable_erc20_token import GiftableToken
logging.basicConfig(level=logging.WARNING) logging.basicConfig(level=logging.WARNING)
logg = logging.getLogger() logg = logging.getLogger()
script_dir = os.path.dirname(__file__) arg_flags = chainlib.eth.cli.argflag_std_write
data_dir = os.path.join(script_dir, '..', 'data') argparser = chainlib.eth.cli.ArgumentParser(arg_flags)
argparser.add_argument('--name', dest='token_name', required=True, type=str, help='Token name')
argparser.add_argument('--symbol', dest='token_symbol', required=True, type=str, help='Token symbol')
argparser = argparse.ArgumentParser() argparser.add_argument('--decimals', dest='token_decimals', default=18, type=int, help='Token decimals')
argparser.add_argument('-p', '--provider', dest='p', default='http://localhost:8545', 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('-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('--name', default='Giftable Token', type=str, help='Token name')
argparser.add_argument('--symbol', default='GFT', type=str, help='Token symbol')
argparser.add_argument('--decimals', default=18, type=int, help='Token decimals')
argparser.add_argument('-d', action='store_true', help='Dump RPC calls to terminal and do not send')
argparser.add_argument('--gas-price', type=int, dest='gas_price', help='Override gas price')
argparser.add_argument('--nonce', type=int, help='Override transaction nonce')
argparser.add_argument('-v', action='store_true', help='Be verbose')
argparser.add_argument('-vv', action='store_true', help='Be more verbose')
args = argparser.parse_args() args = argparser.parse_args()
if args.vv: extra_args = {
logg.setLevel(logging.DEBUG) 'token_name': None,
elif args.v: 'token_symbol': None,
logg.setLevel(logging.INFO) 'token_decimals': None,
}
config = chainlib.eth.cli.Config.from_args(args, arg_flags, extra_args=extra_args, default_fee_limit=GiftableToken.gas())
block_all = args.ww wallet = chainlib.eth.cli.Wallet()
block_last = args.w or block_all wallet.from_config(config)
passphrase_env = 'ETH_PASSPHRASE' rpc = chainlib.eth.cli.Rpc(wallet=wallet)
if args.env_prefix != None: conn = rpc.connect_by_config(config)
passphrase_env = args.env_prefix + '_' + passphrase_env
passphrase = os.environ.get(passphrase_env)
if passphrase == None:
logg.warning('no passphrase given')
passphrase=''
signer_address = None chain_spec = ChainSpec.from_chain_str(config.get('CHAIN_SPEC'))
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)
chain_spec = ChainSpec.from_chain_str(args.i)
rpc = EthHTTPConnection(args.p)
nonce_oracle = None
if args.nonce != None:
nonce_oracle = OverrideNonceOracle(signer_address, args.nonce)
else:
nonce_oracle = RPCNonceOracle(signer_address, rpc)
gas_oracle = None
if args.gas_price !=None:
gas_oracle = OverrideGasOracle(price=args.gas_price, conn=rpc, code_callback=GiftableToken.gas)
else:
gas_oracle = RPCGasOracle(rpc, code_callback=GiftableToken.gas)
dummy = args.d
token_name = args.name
token_symbol = args.symbol
token_decimals = args.decimals
def main(): def main():
signer = rpc.get_signer()
signer_address = rpc.get_sender_address()
token_name = config.get('_TOKEN_NAME')
token_symbol = config.get('_TOKEN_SYMBOL')
token_decimals = config.get('_TOKEN_DECIMALS')
gas_oracle = rpc.get_gas_oracle()
nonce_oracle = rpc.get_nonce_oracle()
c = GiftableToken(chain_spec, signer=signer, gas_oracle=gas_oracle, nonce_oracle=nonce_oracle) c = GiftableToken(chain_spec, signer=signer, gas_oracle=gas_oracle, nonce_oracle=nonce_oracle)
(tx_hash_hex, o) = c.constructor(signer_address, token_name, token_symbol, token_decimals) (tx_hash_hex, o) = c.constructor(signer_address, token_name, token_symbol, token_decimals)
if dummy: if config.get('_RPC_SEND'):
print(tx_hash_hex) conn.do(o)
print(o) if config.get('_WAIT'):
else: r = conn.wait(tx_hash_hex)
rpc.do(o)
if block_last:
r = rpc.wait(tx_hash_hex)
if r['status'] == 0: if r['status'] == 0:
sys.stderr.write('EVM revert while deploying contract. Wish I had more to tell you') sys.stderr.write('EVM revert while deploying contract. Wish I had more to tell you')
sys.exit(1) sys.exit(1)
@ -123,6 +78,8 @@ def main():
print(address) print(address)
else: else:
print(tx_hash_hex) print(tx_hash_hex)
else:
print(o)
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -15,20 +15,16 @@ import argparse
import logging import logging
import time import time
# third-party imports # external imports
from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer import chainlib.eth.cli
from crypto_dev_signer.keystore.dict import DictKeystore
from chainlib.eth.tx import receipt from chainlib.eth.tx import receipt
from chainlib.chain import ChainSpec from chainlib.chain import ChainSpec
from chainlib.eth.nonce import (
RPCNonceOracle,
OverrideNonceOracle,
)
from chainlib.eth.gas import (
RPCGasOracle,
OverrideGasOracle,
)
from chainlib.eth.connection import EthHTTPConnection from chainlib.eth.connection import EthHTTPConnection
from chainlib.eth.address import to_checksum_address
from hexathon import (
strip_0x,
add_0x,
)
# local imports # local imports
from giftable_erc20_token import GiftableToken from giftable_erc20_token import GiftableToken
@ -36,85 +32,50 @@ from giftable_erc20_token import GiftableToken
logging.basicConfig(level=logging.WARNING) logging.basicConfig(level=logging.WARNING)
logg = logging.getLogger() logg = logging.getLogger()
script_dir = os.path.dirname(__file__) arg_flags = chainlib.eth.cli.argflag_std_write | chainlib.eth.cli.Flag.EXEC | chainlib.eth.cli.Flag.WALLET
data_dir = os.path.join(script_dir, '..', 'data') argparser = chainlib.eth.cli.ArgumentParser(arg_flags)
argparser.add_positional('amount', type=int, help='Token amount to gift')
argparser = argparse.ArgumentParser()
argparser.add_argument('-p', '--provider', dest='p', default='http://localhost:8545', type=str, help='Web3 provider url (http only)')
argparser.add_argument('-e', action='store_true', help='Treat all transactions as essential')
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='Giftable token address')
argparser.add_argument('-y', '--key-file', dest='y', type=str, help='Ethereum keystore file to use for signing')
argparser.add_argument('-v', action='store_true', help='Be verbose')
argparser.add_argument('-vv', action='store_true', help='Be more verbose')
argparser.add_argument('-d', action='store_true', help='Dump RPC calls to terminal and do not send')
argparser.add_argument('--gas-price', type=int, dest='gas_price', help='Override gas price')
argparser.add_argument('--nonce', type=int, help='Override transaction nonce')
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('--recipient', type=str, help='Recipient account address. If not set, tokens will be gifted to the keystore account')
argparser.add_argument('value', type=int, help='Value of tokens to mint and gift')
args = argparser.parse_args() 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=GiftableToken.gas())
if args.vv: wallet = chainlib.eth.cli.Wallet()
logg.setLevel(logging.DEBUG) wallet.from_config(config)
elif args.v:
logg.setLevel(logging.INFO)
block_all = args.ww rpc = chainlib.eth.cli.Rpc(wallet=wallet)
block_last = args.w or block_all conn = rpc.connect_by_config(config)
passphrase_env = 'ETH_PASSPHRASE' chain_spec = ChainSpec.from_chain_str(config.get('CHAIN_SPEC'))
if args.env_prefix != None:
passphrase_env = args.env_prefix + '_' + passphrase_env
passphrase = os.environ.get(passphrase_env)
if passphrase == None:
logg.warning('no passphrase given')
passphrase=''
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)
chain_spec = ChainSpec.from_chain_str(args.i)
rpc = EthHTTPConnection(args.p)
nonce_oracle = None
if args.nonce != None:
nonce_oracle = OverrideNonceOracle(signer_address, args.nonce)
else:
nonce_oracle = RPCNonceOracle(signer_address, rpc)
gas_oracle = None
if args.gas_price !=None:
gas_oracle = OverrideGasOracle(price=args.gas_price, conn=rpc, code_callback=GiftableToken.gas)
else:
gas_oracle = RPCGasOracle(rpc, code_callback=GiftableToken.gas)
dummy = args.d
token_address = args.a
recipient_address = args.recipient
if recipient_address == None:
recipient_address = signer_address
token_value = args.value
def main(): def main():
signer = rpc.get_signer()
signer_address = rpc.get_sender_address()
gas_oracle = rpc.get_gas_oracle()
nonce_oracle = rpc.get_nonce_oracle()
recipient_address_input = config.get('_RECIPIENT')
if recipient_address_input == None:
recipient_address_input = signer_address
recipient_address = add_0x(to_checksum_address(recipient_address_input))
if not config.true('_UNSAFE') and recipient_address != add_0x(recipient_address_input):
raise ValueError('invalid checksum address for recipient')
token_address = add_0x(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')
token_value = config.get('_AMOUNT')
c = GiftableToken(chain_spec, signer=signer, gas_oracle=gas_oracle, nonce_oracle=nonce_oracle) c = GiftableToken(chain_spec, signer=signer, gas_oracle=gas_oracle, nonce_oracle=nonce_oracle)
(tx_hash_hex, o) = c.mint_to(token_address, signer_address, recipient_address, token_value) (tx_hash_hex, o) = c.mint_to(token_address, signer_address, recipient_address, token_value)
if dummy: if config.get('_RPC_SEND'):
print(tx_hash_hex) conn.do(o)
print(o) if config.get('_WAIT'):
else: r = conn.wait(tx_hash_hex)
rpc.do(o)
if block_last:
r = rpc.wait(tx_hash_hex)
if r['status'] == 0: if r['status'] == 0:
sys.stderr.write('EVM revert. Wish I had more to tell you') sys.stderr.write('EVM revert. Wish I had more to tell you')
sys.exit(1) sys.exit(1)
@ -122,6 +83,8 @@ def main():
logg.info('mint to {} tx {}'.format(recipient_address, tx_hash_hex)) logg.info('mint to {} tx {}'.format(recipient_address, tx_hash_hex))
print(tx_hash_hex) print(tx_hash_hex)
else:
print(o)
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -16,19 +16,15 @@ import logging
import time import time
# external imports # external imports
import chainlib.eth.cli
from chainlib.eth.connection import EthHTTPConnection from chainlib.eth.connection import EthHTTPConnection
from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer
from crypto_dev_signer.keystore.dict import DictKeystore
from chainlib.eth.nonce import (
RPCNonceOracle,
OverrideNonceOracle,
)
from chainlib.eth.gas import (
RPCGasOracle,
OverrideGasOracle,
)
from chainlib.chain import ChainSpec from chainlib.chain import ChainSpec
from chainlib.eth.tx import receipt from chainlib.eth.tx import receipt
from chainlib.eth.address import to_checksum_address
from hexathon import (
strip_0x,
add_0x,
)
# local imports # local imports
from giftable_erc20_token import GiftableToken from giftable_erc20_token import GiftableToken
@ -36,80 +32,56 @@ from giftable_erc20_token import GiftableToken
logging.basicConfig(level=logging.WARNING) logging.basicConfig(level=logging.WARNING)
logg = logging.getLogger() logg = logging.getLogger()
script_dir = os.path.dirname(__file__) arg_flags = chainlib.eth.cli.argflag_std_write | chainlib.eth.cli.Flag.EXEC | chainlib.eth.cli.Flag.WALLET
data_dir = os.path.join(script_dir, '..', 'data') argparser = chainlib.eth.cli.ArgumentParser(arg_flags)
argparser.add_argument('--rm', action='store_true', help='Remove entry')
argparser = argparse.ArgumentParser() argparser.add_positional('minter_address', type=str, help='Address to add or remove as minter')
argparser.add_argument('-p', '--provider', dest='p', default='http://localhost:8545', 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='Giftable token address')
argparser.add_argument('-y', '--key-file', dest='y', type=str, help='Ethereum keystore file to use for signing')
argparser.add_argument('-v', action='store_true', help='Be verbose')
argparser.add_argument('-vv', action='store_true', help='Be more verbose')
argparser.add_argument('-d', action='store_true', help='Dump RPC calls to terminal and do not send')
argparser.add_argument('--gas-price', type=int, dest='gas_price', help='Override gas price')
argparser.add_argument('--nonce', type=int, help='Override transaction nonce')
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('minter_address', type=str, help='Minter address to add')
args = argparser.parse_args() args = argparser.parse_args()
extra_args = {
'rm': None,
'minter_address': None,
}
config = chainlib.eth.cli.Config.from_args(args, arg_flags, extra_args=extra_args, default_fee_limit=GiftableToken.gas())
if args.vv: wallet = chainlib.eth.cli.Wallet()
logg.setLevel(logging.DEBUG) wallet.from_config(config)
elif args.v:
logg.setLevel(logging.INFO)
block_all = args.ww rpc = chainlib.eth.cli.Rpc(wallet=wallet)
block_last = args.w or block_all conn = rpc.connect_by_config(config)
passphrase_env = 'ETH_PASSPHRASE' chain_spec = ChainSpec.from_chain_str(config.get('CHAIN_SPEC'))
if args.env_prefix != None:
passphrase_env = args.env_prefix + '_' + passphrase_env
passphrase = os.environ.get(passphrase_env)
if passphrase == None:
logg.warning('no passphrase given')
passphrase=''
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)
chain_spec = ChainSpec.from_chain_str(args.i)
rpc = EthHTTPConnection(args.p)
nonce_oracle = None
if args.nonce != None:
nonce_oracle = OverrideNonceOracle(signer_address, args.nonce)
else:
nonce_oracle = RPCNonceOracle(signer_address, rpc)
gas_oracle = None
if args.gas_price !=None:
gas_oracle = OverrideGasOracle(price=args.gas_price, conn=rpc, code_callback=GiftableToken.gas)
else:
gas_oracle = RPCGasOracle(rpc, code_callback=GiftableToken.gas)
dummy = args.d
token_address = args.a
minter_address = args.minter_address
def main(): def main():
signer = rpc.get_signer()
signer_address = rpc.get_sender_address()
gas_oracle = rpc.get_gas_oracle()
nonce_oracle = rpc.get_nonce_oracle()
recipient_address_input = config.get('_RECIPIENT')
if recipient_address_input == None:
recipient_address_input = signer_address
recipient_address = add_0x(to_checksum_address(recipient_address_input))
if not config.true('_UNSAFE') and recipient_address != add_0x(recipient_address_input):
raise ValueError('invalid checksum address for recipient')
token_address = add_0x(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')
minter_address = config.get('_MINTER_ADDRESS')
c = GiftableToken(chain_spec, signer=signer, gas_oracle=gas_oracle, nonce_oracle=nonce_oracle) c = GiftableToken(chain_spec, signer=signer, gas_oracle=gas_oracle, nonce_oracle=nonce_oracle)
(tx_hash_hex, o) = c.add_minter(token_address, signer_address, minter_address) if config.get('_RM'):
if dummy: (tx_hash_hex, o) = c.remove_minter(token_address, signer_address, minter_address)
print(tx_hash_hex)
print(o)
else: else:
rpc.do(o) (tx_hash_hex, o) = c.add_minter(token_address, signer_address, minter_address)
if block_last:
r = rpc.wait(tx_hash_hex) if config.get('_RPC_SEND'):
conn.do(o)
if config.get('_WAIT'):
r = conn.wait(tx_hash_hex)
if r['status'] == 0: if r['status'] == 0:
sys.stderr.write('EVM revert. Wish I had more to tell you') sys.stderr.write('EVM revert. Wish I had more to tell you')
sys.exit(1) sys.exit(1)
@ -117,6 +89,8 @@ def main():
logg.info('add minter {} to {} tx {}'.format(minter_address, token_address, tx_hash_hex)) logg.info('add minter {} to {} tx {}'.format(minter_address, token_address, tx_hash_hex))
print(tx_hash_hex) print(tx_hash_hex)
else:
print(o)
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -1,4 +1,4 @@
confini~=0.3.6rc3 confini>=0.3.6rc3,<0.5.0
crypto-dev-signer~=0.4.14b6 crypto-dev-signer>=0.4.14b7,<=0.4.14
chainlib-eth~=0.0.5a1 chainlib-eth>=0.0.7a4,<=0.1.0
potaahto~=0.0.1a2 potaahto~=0.0.1a2

View File

@ -1,6 +1,6 @@
[metadata] [metadata]
name = eth-erc20 name = eth-erc20
version = 0.0.10a2 version = 0.1.1a1
description = ERC20 interface and simple contract with deployment script that lets any address mint and gift itself tokens. description = ERC20 interface and simple contract with deployment script that lets any address mint and gift itself tokens.
author = Louis Holbrook author = Louis Holbrook
author_email = dev@holbrook.no author_email = dev@holbrook.no

File diff suppressed because one or more lines are too long