Compare commits

...

7 Commits

Author SHA1 Message Date
lash
dbce42888c Implement for chainlib 0.4.x 2022-11-06 10:29:58 +00:00
lash
067cc1bb30 Update giftable token on chainlib 0.3.x 2022-11-03 19:26:03 +00:00
lash
78e3637289 Bump minor version 2022-05-15 07:08:33 +00:00
lash
aec45d7f09 Implement CLI tools on chainlib 0.3.0 structure 2022-05-13 07:43:46 +00:00
lash
48156eb7ba Upgrade chainlib 2022-05-09 20:14:34 +00:00
lash
70663293af Correct chainlib-eth range 2022-04-20 22:05:50 +00:00
lash
8f8d96dfef Upgrade deps 2022-04-20 21:42:30 +00:00
14 changed files with 293 additions and 163 deletions

View File

@@ -1,3 +1,10 @@
* 0.4.1
- Implement chainlib 0.4.x for giftable token
- Fix broken inputs in erc20 cli tools
* 0.4.0
- Implement chainlib 0.3.0
* 0.3.1
- Upgrade chainlib to 0.2.0
* 0.1.10
- Apply transfer ownership protection in GiftableToken contract
* 0.1.9

3
python/README.test Normal file
View File

@@ -0,0 +1,3 @@
On arch, Python.h is in non-standard location, which may cause pip install -r test_requirements to fail.
If so, set env CFLAGS=`pkg-config --cflags python3`

View File

@@ -26,6 +26,15 @@ import sha3
# external imports
import chainlib.eth.cli
from chainlib.eth.cli.arg import (
Arg,
ArgFlag,
process_args,
)
from chainlib.eth.cli.config import (
Config,
process_config,
)
from chainlib.eth.address import to_checksum_address
from chainlib.eth.connection import EthHTTPConnection
from chainlib.eth.gas import (
@@ -33,35 +42,55 @@ from chainlib.eth.gas import (
balance,
)
from chainlib.chain import ChainSpec
from chainlib.eth.cli.log import process_log
from chainlib.eth.settings import process_settings
from chainlib.settings import ChainSettings
# local imports
from eth_erc20 import ERC20
logging.basicConfig(level=logging.WARNING)
def process_config_local(config, arg, args, flags):
recipient = None
address = config.get('_POSARG')
if address:
recipient = add_0x(address)
else:
recipient = stdin_arg()
config.add(recipient, '_RECIPIENT', False)
return config
logg = logging.getLogger()
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')
arg_flags = ArgFlag()
arg = Arg(arg_flags)
flags = arg_flags.STD_READ | arg_flags.EXEC
argparser = chainlib.eth.cli.ArgumentParser()
argparser = process_args(argparser, arg, flags)
argparser.add_argument('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)
logg = process_log(args, logg)
rpc = chainlib.eth.cli.Rpc()
conn = rpc.connect_by_config(config)
config = Config()
config = process_config(config, arg, args, flags, positional_name='address')
config = process_config_local(config, arg, args, flags)
logg.debug('config loaded:\n{}'.format(config))
chain_spec = ChainSpec.from_chain_str(config.get('CHAIN_SPEC'))
token_address = config.get('_EXEC_ADDRESS')
settings = ChainSettings()
settings = process_settings(settings, config)
logg.debug('settings loaded:\n{}'.format(settings))
def main():
g = ERC20(chain_spec=chain_spec, gas_oracle=rpc.get_gas_oracle())
token_address = settings.get('EXEC')
conn = settings.get('CONN')
g = ERC20(
chain_spec=settings.get('CHAIN_SPEC'),
gas_oracle=settings.get('GAS_ORACLE'),
)
# determine decimals
decimals_o = g.decimals(token_address)
@@ -80,7 +109,7 @@ def main():
logg.info('symbol {}'.format(token_symbol))
# get balance
balance_o = g.balance(token_address, holder_address)
balance_o = g.balance(token_address, settings.get('RECIPIENT'))
r = conn.do(balance_o)
hx = strip_0x(r)

View File

@@ -26,6 +26,16 @@ import sha3
# external imports
import chainlib.eth.cli
from chainlib.eth.cli.arg import (
Arg,
ArgFlag,
process_args,
stdin_arg,
)
from chainlib.eth.cli.config import (
Config,
process_config,
)
from chainlib.eth.address import to_checksum_address
from chainlib.eth.connection import EthHTTPConnection
from chainlib.eth.gas import (
@@ -33,77 +43,105 @@ from chainlib.eth.gas import (
balance,
)
from chainlib.chain import ChainSpec
from chainlib.eth.settings import process_settings
from chainlib.settings import ChainSettings
from chainlib.eth.cli.log import process_log
# local imports
from eth_erc20 import ERC20
logging.basicConfig(level=logging.WARNING)
logg = logging.getLogger()
arg_flags = chainlib.eth.cli.argflag_std_read | chainlib.eth.cli.Flag.EXEC
argparser = chainlib.eth.cli.ArgumentParser(arg_flags)
argparser.add_positional('item', required=False)
def process_config_local(config, arg, args, flags):
contract = None
try:
contract = config.get('_EXEC_ADDRESS')
except KeyError:
pass
if contract == None:
address = config.get('_POSARG')
if address:
contract = add_0x(address)
else:
contract = stdin_arg()
config.add(contract, '_CONTRACT', False)
return config
arg_flags = ArgFlag()
arg = Arg(arg_flags)
flags = arg_flags.STD_READ | arg_flags.EXEC | arg_flags.TAB
argparser = chainlib.eth.cli.ArgumentParser()
argparser = process_args(argparser, arg, flags)
argparser.add_argument('contract_address', type=str, help='Token contract address (may also be specified by -e)')
args = argparser.parse_args()
config = chainlib.eth.cli.Config.from_args(args, arg_flags)
rpc = chainlib.eth.cli.Rpc()
conn = rpc.connect_by_config(config)
logg = process_log(args, logg)
chain_spec = ChainSpec.from_chain_str(config.get('CHAIN_SPEC'))
config = Config()
config = process_config(config, arg, args, flags, positional_name='contract_address')
config = process_config_local(config, arg, args, flags)
logg.debug('config loaded:\n{}'.format(config))
token_address = config.get('_EXEC_ADDRESS')
settings = ChainSettings()
settings = process_settings(settings, config)
logg.debug('settings loaded:\n{}'.format(settings))
def main():
g = ERC20(chain_spec=chain_spec, gas_oracle=rpc.get_gas_oracle())
token_address = config.get('_CONTRACT')
conn = settings.get('CONN')
g = ERC20(
chain_spec=settings.get('CHAIN_SPEC'),
gas_oracle=settings.get('GAS_ORACLE'),
)
if not args.item or args.item == 'name':
outkeys = config.get('_OUTARG')
if not outkeys or 'address' in outkeys:
name_o = g.name(token_address)
r = conn.do(name_o)
token_name = g.parse_name(r)
s = ''
if not args.item or not args.raw:
if not config.true('_RAW'):
s = 'Name: '
s += token_name
print(s)
if args.item == 'name':
sys.exit(0)
if not args.item or args.item == 'symbol':
if not outkeys or 'symbol' in outkeys:
symbol_o = g.symbol(token_address)
r = conn.do(symbol_o)
token_symbol = g.parse_symbol(r)
s = ''
if not args.item or not args.raw:
if not config.true('_RAW'):
s = 'Symbol: '
s += token_symbol
print(s)
if args.item == 'symbol':
sys.exit(0)
if not args.item or args.item == 'decimals':
if not outkeys or 'decimals' in outkeys:
decimals_o = g.decimals(token_address)
r = conn.do(decimals_o)
decimals = int(strip_0x(r), 16)
s = ''
if not args.item or not args.raw:
if not config.true('_RAW'):
s = 'Decimals: '
s += str(decimals)
print(s)
if args.item == 'decimals':
sys.exit(0)
if not args.item or args.item == 'supply':
if not outkeys or 'supply' in outkeys:
supply_o = g.total_supply(token_address)
r = conn.do(supply_o)
supply = int(strip_0x(r), 16)
s = ''
if not args.item or not args.raw:
if not config.true('_RAW'):
s = 'Supply: '
s += str(supply)
print(s)
if args.item == 'supply':
sys.exit(0)
if __name__ == '__main__':

View File

@@ -21,44 +21,53 @@ from hexathon import (
add_0x,
strip_0x,
)
from chainlib.eth.connection import EthHTTPConnection
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
from chainlib.eth.cli.log import process_log
from chainlib.eth.settings import process_settings
from chainlib.settings import ChainSettings
from chainlib.eth.cli.arg import (
Arg,
ArgFlag,
process_args,
)
from chainlib.eth.cli.config import (
Config,
process_config,
)
# local imports
from eth_erc20 import ERC20
logging.basicConfig(level=logging.WARNING)
logg = logging.getLogger()
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')
def process_config_local(config, arg, args, flags):
config.add(config.get('_POSARG'), '_VALUE', False)
return config
arg_flags = ArgFlag()
arg = Arg(arg_flags)
flags = arg_flags.STD_WRITE | arg_flags.EXEC | arg_flags.WALLET
argparser = chainlib.eth.cli.ArgumentParser()
argparser = process_args(argparser, arg, flags)
argparser.add_argument('value', type=str, help='Token value 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)
block_all = args.ww
block_last = args.w or block_all
logg = process_log(args, logg)
wallet = chainlib.eth.cli.Wallet()
wallet.from_config(config)
config = Config()
config = process_config(config, arg, args, flags, positional_name='value')
config = process_config_local(config, arg, args, flags)
logg.debug('config loaded:\n{}'.format(config))
rpc = chainlib.eth.cli.Rpc(wallet=wallet)
conn = rpc.connect_by_config(config)
chain_spec = ChainSpec.from_chain_str(config.get('CHAIN_SPEC'))
value = config.get('_AMOUNT')
send = config.true('_RPC_SEND')
settings = ChainSettings()
settings = process_settings(settings, config)
logg.debug('settings loaded:\n{}'.format(settings))
def balance(generator, token_address, address, id_generator=None):
def balance(conn, generator, token_address, address, id_generator=None):
o = generator.balance(token_address, address, id_generator=id_generator)
r = conn.do(o)
token_balance = generator.parse_balance(r)
@@ -66,37 +75,32 @@ def balance(generator, token_address, address, id_generator=None):
def main():
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')
token_address = settings.get('EXEC')
signer_address = settings.get('SENDER_ADDRESS')
recipient = settings.get('RECIPIENT')
value = settings.get('VALUE')
conn = settings.get('CONN')
g = ERC20(
settings.get('CHAIN_SPEC'),
signer=settings.get('SIGNER'),
gas_oracle=settings.get('GAS_ORACLE'),
nonce_oracle=settings.get('NONCE_ORACLE'),
)
if logg.isEnabledFor(logging.DEBUG):
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)
sender_balance = balance(conn, g, token_address, signer_address, id_generator=settings.get('RPC_ID_GENERATOR'))
recipient_balance = balance(conn, g, token_address, recipient, id_generator=settings.get('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(token_address, signer_address, recipient, value, id_generator=rpc.id_generator)
(tx_hash_hex, o) = g.transfer(token_address, signer_address, recipient, value, id_generator=settings.get('RPC_ID_GENERATOR'))
if send:
if settings.get('RPC_SEND'):
conn.do(o)
if block_last:
if settings.get('WAIT'):
r = conn.wait(tx_hash_hex)
if logg.isEnabledFor(logging.DEBUG):
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)
sender_balance = balance(conn, g, token_address, signer_address, id_generator=settings.get('RPC_ID_GENERATOR'))
recipient_balance = balance(conn, g, token_address, recipient, id_generator=settings.get('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:

File diff suppressed because one or more lines are too long

View File

@@ -94,4 +94,6 @@ class GiftableToken(TxFactory):
tx = self.template(sender_address, contract_address, use_nonce=True)
tx = self.set_code(tx, data)
tx = self.finalize(tx, tx_format)
return tx
return tx

View File

@@ -1,3 +1,5 @@
#!python3
"""Deploys giftable token
.. moduleauthor:: Louis Holbrook <dev@holbrook.no>
@@ -18,56 +20,76 @@ from enum import Enum
# external imports
import chainlib.eth.cli
from chainlib.chain import ChainSpec
from chainlib.eth.connection import EthHTTPConnection
from chainlib.eth.tx import receipt
from chainlib.settings import ChainSettings
from chainlib.eth.cli.log import process_log
from chainlib.eth.settings import process_settings
from chainlib.eth.cli.arg import (
Arg,
ArgFlag,
process_args,
)
from chainlib.eth.cli.config import (
Config,
process_config,
)
# local imports
from giftable_erc20_token import GiftableToken
logging.basicConfig(level=logging.WARNING)
logg = logging.getLogger()
arg_flags = chainlib.eth.cli.argflag_std_write
argparser = chainlib.eth.cli.ArgumentParser(arg_flags)
def process_config_local(config, arg, args, flags):
config.add(args.token_name, '_TOKEN_NAME', False)
config.add(args.token_symbol, '_TOKEN_SYMBOL', False)
config.add(args.token_decimals, '_TOKEN_DECIMALS', False)
return config
arg_flags = ArgFlag()
arg = Arg(arg_flags)
flags = arg_flags.STD_WRITE | arg_flags.WALLET
argparser = chainlib.eth.cli.ArgumentParser()
argparser = process_args(argparser, 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.add_argument('--decimals', dest='token_decimals', default=18, type=int, help='Token decimals')
args = argparser.parse_args()
extra_args = {
'token_name': None,
'token_symbol': None,
'token_decimals': None,
}
config = chainlib.eth.cli.Config.from_args(args, arg_flags, extra_args=extra_args, default_fee_limit=GiftableToken.gas())
logg = process_log(args, logg)
wallet = chainlib.eth.cli.Wallet()
wallet.from_config(config)
config = Config()
config = process_config(config, arg, args, flags)
config = process_config_local(config, arg, args, flags)
logg.debug('config loaded:\n{}'.format(config))
rpc = chainlib.eth.cli.Rpc(wallet=wallet)
conn = rpc.connect_by_config(config)
chain_spec = ChainSpec.from_chain_str(config.get('CHAIN_SPEC'))
settings = ChainSettings()
settings = process_settings(settings, config)
logg.debug('settings loaded:\n{}'.format(settings))
def main():
signer = rpc.get_signer()
signer_address = rpc.get_sender_address()
signer_address = settings.get('SENDER_ADDRESS')
token_name = config.get('_TOKEN_NAME')
token_symbol = config.get('_TOKEN_SYMBOL')
token_decimals = config.get('_TOKEN_DECIMALS')
c = GiftableToken(
settings.get('CHAIN_SPEC'),
signer=settings.get('SIGNER'),
gas_oracle=settings.get('GAS_ORACLE'),
nonce_oracle=settings.get('NONCE_ORACLE'),
)
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)
(tx_hash_hex, o) = c.constructor(signer_address, token_name, token_symbol, token_decimals)
if config.get('_RPC_SEND'):
(tx_hash_hex, o) = c.constructor(
signer_address,
config.get('_TOKEN_NAME'),
config.get('_TOKEN_SYMBOL'),
config.get('_TOKEN_DECIMALS'),
)
if settings.get('RPC_SEND'):
conn.do(o)
if config.get('_WAIT'):
if settings.get('WAIT'):
r = conn.wait(tx_hash_hex)
if r['status'] == 0:
sys.stderr.write('EVM revert while deploying contract. Wish I had more to tell you')

View File

@@ -17,10 +17,21 @@ import time
# external imports
import chainlib.eth.cli
from chainlib.eth.connection import EthHTTPConnection
from chainlib.chain import ChainSpec
from chainlib.eth.tx import receipt
from chainlib.settings import ChainSettings
from chainlib.eth.cli.log import process_log
from chainlib.eth.settings import process_settings
from chainlib.eth.address import to_checksum_address
from chainlib.eth.cli.arg import (
Arg,
ArgFlag,
process_args,
)
from chainlib.eth.cli.config import (
Config,
process_config,
)
from hexathon import (
strip_0x,
add_0x,
@@ -29,37 +40,41 @@ from hexathon import (
# local imports
from giftable_erc20_token import GiftableToken
logging.basicConfig(level=logging.WARNING)
logg = logging.getLogger()
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)
def process_config_local(config, arg, args, flags):
config.add(args.rm, '_RM', False)
config.add(add_0x(args.minter_address[0]), '_MINTER_ADDRESS', False)
return config
arg_flags = ArgFlag()
arg = Arg(arg_flags)
flags = arg_flags.STD_WRITE | arg_flags.EXEC | arg_flags.WALLET
argparser = chainlib.eth.cli.ArgumentParser()
argparser = process_args(argparser, arg, flags)
argparser.add_argument('--rm', action='store_true', help='Remove entry')
argparser.add_positional('minter_address', type=str, help='Address to add or remove as minter')
argparser.add_argument('minter_address', type=str, help='Address to add or remove as minter')
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())
wallet = chainlib.eth.cli.Wallet()
wallet.from_config(config)
logg = process_log(args, logg)
rpc = chainlib.eth.cli.Rpc(wallet=wallet)
conn = rpc.connect_by_config(config)
config = Config()
config = process_config(config, arg, args, flags)
config = process_config_local(config, arg, args, flags)
logg.debug('config loaded:\n{}'.format(config))
chain_spec = ChainSpec.from_chain_str(config.get('CHAIN_SPEC'))
settings = ChainSettings()
settings = process_settings(settings, config)
logg.debug('settings loaded:\n{}'.format(settings))
def main():
signer = rpc.get_signer()
signer_address = rpc.get_sender_address()
signer_address = settings.get('SENDER_ADDRESS')
gas_oracle = rpc.get_gas_oracle()
nonce_oracle = rpc.get_nonce_oracle()
recipient_address_input = config.get('_RECIPIENT')
recipient_address_input = settings.get('RECIPIENT')
if recipient_address_input == None:
recipient_address_input = signer_address
@@ -67,20 +82,30 @@ def main():
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)
if config.get('_RM'):
(tx_hash_hex, o) = c.remove_minter(token_address, signer_address, minter_address)
else:
(tx_hash_hex, o) = c.add_minter(token_address, signer_address, minter_address)
c = GiftableToken(
settings.get('CHAIN_SPEC'),
signer=settings.get('SIGNER'),
gas_oracle=settings.get('GAS_ORACLE'),
nonce_oracle=settings.get('NONCE_ORACLE'),
)
if config.get('_RPC_SEND'):
if config.get('_RM'):
(tx_hash_hex, o) = c.remove_minter(
settings.get('EXEC'),
signer_address,
minter_address,
)
else:
(tx_hash_hex, o) = c.add_minter(
settings.get('EXEC'),
signer_address,
minter_address,
)
if settings.get('RPC_SEND'):
conn.do(o)
if config.get('_WAIT'):
if settings.get('WAIT'):
r = conn.wait(tx_hash_hex)
if r['status'] == 0:
sys.stderr.write('EVM revert. Wish I had more to tell you')

View File

@@ -1,3 +1,3 @@
confini>=0.5.7,<0.7.0
chainlib-eth>=0.0.27,<=0.1.0
potaahto~=0.1.0
confini~=0.6.1
chainlib-eth~=0.4.2
potaahto~=0.1.1

View File

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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long