Compare commits
41 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
772781c1b8 | ||
|
bf166af544 | ||
|
43f3aff255 | ||
|
586eccfba0 | ||
|
dfe18a4238 | ||
|
3f24ab93fc | ||
|
7ed616a13d | ||
|
f22115ff8c | ||
|
7ea2b43d60 | ||
|
7dc62676ba | ||
|
e03c5b8035 | ||
|
6ad0edd8a8 | ||
|
e053098652 | ||
|
e621913f74 | ||
|
3c55bc9ac2 | ||
|
65b10ea306 | ||
|
e723f26267 | ||
|
9470b81fad | ||
|
2d06d60eed | ||
|
33d9877bac | ||
|
05d3357318 | ||
|
85e5359e7c | ||
|
72f3b8d346 | ||
|
21ebdeae77 | ||
|
628028e4ce | ||
|
7604b48e12 | ||
|
d70dfc3f03 | ||
|
c060222638 | ||
|
e16cc956e0 | ||
|
9012b9884a | ||
|
a1896b40c1 | ||
|
2f90eb632f | ||
|
7b7496a374 | ||
|
23f977482c | ||
|
20dfb641ff | ||
|
972535f1f9 | ||
|
a2168a50e3 | ||
|
9548ed5d1b | ||
|
e499770d6d | ||
|
e49fae9717 | ||
|
84c4a82abb |
11
CHANGELOG
11
CHANGELOG
@ -1,3 +1,14 @@
|
||||
- 0.3.1
|
||||
* Fix missing application of status on tx result
|
||||
- 0.3.0
|
||||
* Implement chainlib with new arg and config handling
|
||||
* Implement cli tools on settings module
|
||||
- 0.2.0
|
||||
* Implement chainlib generic tx, block and tx result objects
|
||||
- 0.1.3
|
||||
* Add block author field
|
||||
- 0.1.2
|
||||
* Upgrade chainlib dep
|
||||
- 0.1.1
|
||||
* Add fee_limit, fee_price alias to Tx object
|
||||
- 0.1.0:
|
||||
|
@ -1,4 +1,7 @@
|
||||
import sys
|
||||
# standard imports
|
||||
import logging
|
||||
import datetime
|
||||
|
||||
# external imports
|
||||
from chainlib.jsonrpc import JSONRPCRequest
|
||||
from chainlib.block import Block as BaseBlock
|
||||
@ -6,10 +9,14 @@ from hexathon import (
|
||||
add_0x,
|
||||
strip_0x,
|
||||
compact,
|
||||
to_int as hex_to_int,
|
||||
)
|
||||
|
||||
# local imports
|
||||
from chainlib.eth.tx import Tx
|
||||
from .src import Src
|
||||
|
||||
logg = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def block_latest(id_generator=None):
|
||||
@ -76,7 +83,7 @@ def syncing(id_generator=None):
|
||||
return j.finalize(o)
|
||||
|
||||
|
||||
class Block(BaseBlock):
|
||||
class Block(BaseBlock, Src):
|
||||
"""Encapsulates an Ethereum block
|
||||
|
||||
:param src: Block representation data
|
||||
@ -86,21 +93,32 @@ class Block(BaseBlock):
|
||||
|
||||
tx_generator = Tx
|
||||
|
||||
def __init__(self, src):
|
||||
self.hash = src['hash']
|
||||
def __init__(self, src=None):
|
||||
super(Block, self).__init__(src=src)
|
||||
|
||||
self.set_hash(self.src['hash'])
|
||||
try:
|
||||
self.number = int(strip_0x(src['number']), 16)
|
||||
self.number = int(strip_0x(self.src['number']), 16)
|
||||
except TypeError:
|
||||
self.number = int(src['number'])
|
||||
self.txs = src['transactions']
|
||||
self.block_src = src
|
||||
self.number = int(self.src['number'])
|
||||
self.txs = self.src['transactions']
|
||||
self.block_src = self.src
|
||||
try:
|
||||
self.timestamp = int(strip_0x(src['timestamp']), 16)
|
||||
self.timestamp = int(strip_0x(self.src['timestamp']), 16)
|
||||
except TypeError:
|
||||
self.timestamp = int(src['timestamp'])
|
||||
self.timestamp = int(self.src['timestamp'])
|
||||
|
||||
try:
|
||||
self.author = self.src['author']
|
||||
except KeyError:
|
||||
self.author = self.src['miner']
|
||||
|
||||
self.fee_limit = self.src['gas_limit']
|
||||
self.fee_cost = self.src['gas_used']
|
||||
self.parent_hash = self.src['parent_hash']
|
||||
|
||||
|
||||
def get_tx(self, tx_hash):
|
||||
def tx_index_by_hash(self, tx_hash):
|
||||
i = 0
|
||||
idx = -1
|
||||
tx_hash = add_0x(tx_hash)
|
||||
@ -118,3 +136,28 @@ class Block(BaseBlock):
|
||||
raise AttributeError('tx {} not found in block {}'.format(tx_hash, self.hash))
|
||||
return idx
|
||||
|
||||
|
||||
def to_human(self):
|
||||
s = """hash: {}
|
||||
number: {}
|
||||
parent: {}
|
||||
timestamp: {}
|
||||
time: {}
|
||||
author: {}
|
||||
gas_limit: {}
|
||||
gas_used: {}
|
||||
txs: {}
|
||||
""".format(
|
||||
self.hash,
|
||||
self.number,
|
||||
self.parent_hash,
|
||||
self.timestamp,
|
||||
datetime.datetime.fromtimestamp(self.timestamp),
|
||||
self.author,
|
||||
hex_to_int(self.fee_limit),
|
||||
hex_to_int(self.fee_cost),
|
||||
len(self.txs),
|
||||
)
|
||||
|
||||
return s
|
||||
|
||||
|
@ -1,10 +1,6 @@
|
||||
# external imports
|
||||
from chainlib.cli import (
|
||||
ArgumentParser,
|
||||
argflag_std_read,
|
||||
argflag_std_write,
|
||||
argflag_std_base,
|
||||
argflag_std_base_read,
|
||||
flag_reset as argflag_reset,
|
||||
Flag,
|
||||
from chainlib.cli.arg import (
|
||||
ArgumentParser,
|
||||
Arg,
|
||||
ArgFlag,
|
||||
process_args,
|
||||
)
|
||||
|
@ -2,7 +2,11 @@
|
||||
import os
|
||||
|
||||
# external imports
|
||||
from chainlib.cli import Config as BaseConfig
|
||||
from chainlib.cli.config import (
|
||||
Config as BaseConfig,
|
||||
process_config as base_process_config,
|
||||
)
|
||||
|
||||
|
||||
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
data_dir = os.path.join(script_dir, '..')
|
||||
@ -14,14 +18,12 @@ class Config(BaseConfig):
|
||||
default_base_config_dir = os.path.join(data_dir, 'data', 'config')
|
||||
default_fee_limit = 21000
|
||||
|
||||
@classmethod
|
||||
def from_args(cls, args, arg_flags=0x0f, env=os.environ, extra_args={}, base_config_dir=None, default_config_dir=None, user_config_dir=None, default_fee_limit=None, logger=None, load_callback=None):
|
||||
super(Config, cls).override_defaults(base_dir=cls.default_base_config_dir)
|
||||
if default_fee_limit == None:
|
||||
default_fee_limit = cls.default_fee_limit
|
||||
config = BaseConfig.from_args(args, arg_flags=arg_flags, env=env, extra_args=extra_args, base_config_dir=base_config_dir, default_config_dir=default_config_dir, user_config_dir=user_config_dir, default_fee_limit=default_fee_limit, logger=logger, load_callback=load_callback)
|
||||
|
||||
if not config.get('RPC_DIALECT'):
|
||||
def process_config(config, arg, args, flags):
|
||||
config = base_process_config(config, arg, args, flags)
|
||||
if arg.match('provider', flags):
|
||||
|
||||
if not bool(config.get('RPC_DIALECT')):
|
||||
config.add('default', 'RPC_DIALECT', exists_ok=True)
|
||||
elif config.get('RPC_DIALECT') not in [
|
||||
'openethereum',
|
||||
@ -29,5 +31,4 @@ class Config(BaseConfig):
|
||||
]:
|
||||
raise ValueError('unknown rpc dialect {}'.format(config.get('RPC_DIALECT')))
|
||||
|
||||
return config
|
||||
|
||||
return config
|
||||
|
1
chainlib/eth/cli/log.py
Normal file
1
chainlib/eth/cli/log.py
Normal file
@ -0,0 +1 @@
|
||||
from chainlib.cli.log import process_log
|
@ -15,6 +15,3 @@ class Wallet(BaseWallet):
|
||||
"""
|
||||
def __init__(self, checksummer=AddressChecksum):
|
||||
super(Wallet, self).__init__(EIP155Signer, checksummer=checksummer, keystore=DictKeystore())
|
||||
|
||||
|
||||
|
||||
|
@ -6,6 +6,7 @@ import logging
|
||||
# external imports
|
||||
from hexathon import (
|
||||
strip_0x,
|
||||
add_0x,
|
||||
pad,
|
||||
)
|
||||
|
||||
@ -502,6 +503,8 @@ def code(address, block_spec=BlockSpec.LATEST, id_generator=None):
|
||||
block_height = 'pending'
|
||||
else:
|
||||
block_height = int(block_spec)
|
||||
block_height = block_height.to_bytes(8, byteorder='big')
|
||||
block_height = add_0x(block_height.hex())
|
||||
j = JSONRPCRequest(id_generator)
|
||||
o = j.template()
|
||||
o['method'] = 'eth_getCode'
|
||||
|
@ -5,10 +5,19 @@ credentials =
|
||||
dialect = default
|
||||
scheme = http
|
||||
verify = 1
|
||||
timeout = 10.0
|
||||
proxy =
|
||||
|
||||
[chain]
|
||||
spec = evm:berlin:1:ethereum
|
||||
min_fee = 21000
|
||||
max_fee = 8000000
|
||||
|
||||
[wallet]
|
||||
key_file =
|
||||
passphrase =
|
||||
|
||||
[state]
|
||||
path =
|
||||
runtime_path =
|
||||
backend =
|
||||
|
@ -10,51 +10,73 @@ from hexathon import (
|
||||
strip_0x,
|
||||
even,
|
||||
)
|
||||
|
||||
# local imports
|
||||
import chainlib.eth.cli
|
||||
from chainlib.eth.address import AddressChecksum
|
||||
from chainlib.settings import ChainSettings
|
||||
from chainlib.chain import ChainSpec
|
||||
from funga.eth.signer import EIP155Signer
|
||||
from chainlib.jsonrpc import (
|
||||
jsonrpc_result,
|
||||
IntSequenceGenerator,
|
||||
)
|
||||
|
||||
# local 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.cli.log import process_log
|
||||
from chainlib.eth.address import AddressChecksum
|
||||
from chainlib.eth.connection import EthHTTPConnection
|
||||
from chainlib.eth.gas import (
|
||||
OverrideGasOracle,
|
||||
balance,
|
||||
)
|
||||
from chainlib.chain import ChainSpec
|
||||
from funga.eth.signer import EIP155Signer
|
||||
from chainlib.eth.settings import process_settings
|
||||
|
||||
|
||||
logging.basicConfig(level=logging.WARNING)
|
||||
logg = logging.getLogger()
|
||||
|
||||
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
#config_dir = os.path.join(script_dir, '..', 'data', 'config')
|
||||
|
||||
arg_flags = chainlib.eth.cli.argflag_std_read
|
||||
argparser = chainlib.eth.cli.ArgumentParser(arg_flags)
|
||||
argparser.add_positional('address', type=str, help='Ethereum address of recipient')
|
||||
|
||||
def process_config_local(config, arg, args, flags):
|
||||
config.add(args.address, '_RECIPIENT', False)
|
||||
return config
|
||||
|
||||
|
||||
arg_flags = ArgFlag()
|
||||
arg = Arg(arg_flags)
|
||||
flags = arg_flags.STD_READ
|
||||
|
||||
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)
|
||||
logg.debug('flags {} {} {}'.format(flags, arg_flags.SEQ, flags & arg_flags.SEQ))
|
||||
|
||||
rpc = chainlib.eth.cli.Rpc()
|
||||
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))
|
||||
|
||||
settings = ChainSettings()
|
||||
settings = process_settings(settings, config)
|
||||
|
||||
chain_spec = ChainSpec.from_chain_str(config.get('CHAIN_SPEC'))
|
||||
|
||||
def main():
|
||||
r = None
|
||||
decimals = 18
|
||||
|
||||
o = balance(holder_address, id_generator=rpc.id_generator)
|
||||
r = conn.do(o)
|
||||
o = balance(settings.get('RECIPIENT'), id_generator=settings.get('RPC_ID_GENERATOR'))
|
||||
r = settings.get('CONN').do(o)
|
||||
|
||||
hx = strip_0x(r)
|
||||
balance_value = int(hx, 16)
|
||||
|
168
chainlib/eth/runnable/block.py
Normal file
168
chainlib/eth/runnable/block.py
Normal file
@ -0,0 +1,168 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# standard imports
|
||||
import sys
|
||||
import os
|
||||
import json
|
||||
import argparse
|
||||
import logging
|
||||
import enum
|
||||
import select
|
||||
|
||||
# external imports
|
||||
from potaahto.symbols import snake_and_camel
|
||||
from hexathon import (
|
||||
add_0x,
|
||||
strip_0x,
|
||||
)
|
||||
import sha3
|
||||
from chainlib.jsonrpc import (
|
||||
JSONRPCRequest,
|
||||
jsonrpc_result,
|
||||
IntSequenceGenerator,
|
||||
)
|
||||
from chainlib.chain import ChainSpec
|
||||
from chainlib.status import Status
|
||||
from chainlib.settings import ChainSettings
|
||||
|
||||
# local imports
|
||||
from chainlib.eth.connection import EthHTTPConnection
|
||||
from chainlib.eth.tx import (
|
||||
Tx,
|
||||
pack,
|
||||
)
|
||||
from chainlib.eth.address import (
|
||||
to_checksum_address,
|
||||
is_checksum_address,
|
||||
)
|
||||
from chainlib.eth.block import (
|
||||
Block,
|
||||
block_by_hash,
|
||||
block_by_number,
|
||||
)
|
||||
from chainlib.eth.runnable.util import decode_for_puny_humans
|
||||
from chainlib.eth.jsonrpc import to_blockheight_param
|
||||
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.cli.log import process_log
|
||||
from chainlib.eth.settings import process_settings
|
||||
|
||||
logg = logging.getLogger()
|
||||
|
||||
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
config_dir = os.path.join(script_dir, '..', 'data', 'config')
|
||||
|
||||
def process_config_local(config, arg, args, flags):
|
||||
config.add(args.block, '_BLOCK', False)
|
||||
return config
|
||||
|
||||
|
||||
def process_settings_local(settings, config):
|
||||
block_identifier = config.get('_BLOCK')
|
||||
maybe_hex = None
|
||||
is_number = False
|
||||
try:
|
||||
maybe_hex = strip_0x(block_identifier)
|
||||
except ValueError:
|
||||
is_number = True
|
||||
|
||||
if maybe_hex != None:
|
||||
if len(maybe_hex) != 64:
|
||||
is_number = True
|
||||
else:
|
||||
is_number = True
|
||||
|
||||
r = None
|
||||
if not is_number:
|
||||
config.add(block_identifier, '_HASH', False)
|
||||
else:
|
||||
settings.set('_BLOCK', int(block_identifier))
|
||||
|
||||
return process_settings(settings, config)
|
||||
|
||||
|
||||
argparser = chainlib.eth.cli.ArgumentParser()
|
||||
arg_flags = ArgFlag()
|
||||
arg = Arg(arg_flags)
|
||||
flags = arg_flags.STD_BASE_READ
|
||||
flags = arg_flags.less(flags, arg_flags.CHAIN_SPEC)
|
||||
argparser = process_args(argparser, arg, flags)
|
||||
argparser.add_argument('block', nargs='?', type=str, help='Block hash or number to retrieve')
|
||||
args = argparser.parse_args()
|
||||
|
||||
logg = process_log(args, logg)
|
||||
|
||||
config = Config()
|
||||
config = process_config(config, arg, args, flags)
|
||||
config = process_config_local(config, arg, args, flags)
|
||||
logg.debug('config loaded:\n{}'.format(config))
|
||||
|
||||
settings = ChainSettings()
|
||||
settings = process_settings_local(settings, config)
|
||||
logg.debug('settings loaded:\n{}'.format(settings))
|
||||
|
||||
|
||||
|
||||
def get_block(settings):
|
||||
hsh = settings.get('HASH')[0]
|
||||
r = None
|
||||
if hsh == None:
|
||||
r = get_block_number(
|
||||
settings.get('CONN'),
|
||||
settings.get('_BLOCK'),
|
||||
settings.get('RPC_ID_GENERATOR'),
|
||||
)
|
||||
else:
|
||||
r = get_block_hash(
|
||||
settings.get('CONN'),
|
||||
hsh,
|
||||
settings.get('RPC_ID_GENERATOR'),
|
||||
)
|
||||
|
||||
return block_process(r)
|
||||
|
||||
|
||||
def get_block_number(conn, block_number, id_generator):
|
||||
o = block_by_number(block_number, include_tx=False)
|
||||
block_src = conn.do(o)
|
||||
if block_src == None:
|
||||
logg.error('Block number {} not found'.format(block_number))
|
||||
sys.exit(1)
|
||||
return block_src
|
||||
|
||||
|
||||
def get_block_hash(conn, block_hash, id_generator):
|
||||
block_hash = add_0x(block_hash)
|
||||
o = block_by_hash(block_hash, include_tx=False)
|
||||
block_src = conn.do(o)
|
||||
if block_src == None:
|
||||
logg.error('Block hash {} not found'.format(block_hash))
|
||||
sys.exit(1)
|
||||
return block_src
|
||||
|
||||
|
||||
def block_process(block_src):
|
||||
return Block(block_src)
|
||||
|
||||
|
||||
def main():
|
||||
r = get_block(settings)
|
||||
|
||||
if not config.true('_RAW'):
|
||||
r = r.to_human()
|
||||
else:
|
||||
r = repr(r)
|
||||
if r != None:
|
||||
print(r)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
@ -8,43 +8,70 @@ import json
|
||||
import logging
|
||||
import select
|
||||
|
||||
# local imports
|
||||
import chainlib.eth.cli
|
||||
from chainlib.eth.address import AddressChecksum
|
||||
from chainlib.eth.connection import EthHTTPConnection
|
||||
from chainlib.eth.tx import count
|
||||
# external imports
|
||||
from chainlib.settings import ChainSettings
|
||||
from chainlib.chain import ChainSpec
|
||||
from chainlib.jsonrpc import IntSequenceGenerator
|
||||
from funga.eth.keystore.dict import DictKeystore
|
||||
from funga.eth.signer import EIP155Signer
|
||||
from hexathon import add_0x
|
||||
|
||||
logging.basicConfig(level=logging.WARNING)
|
||||
# local 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.cli.log import process_log
|
||||
from chainlib.eth.address import AddressChecksum
|
||||
from chainlib.eth.connection import EthHTTPConnection
|
||||
from chainlib.eth.tx import count
|
||||
from chainlib.eth.settings import process_settings
|
||||
|
||||
logg = logging.getLogger()
|
||||
|
||||
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
config_dir = os.path.join(script_dir, '..', 'data', 'config')
|
||||
|
||||
arg_flags = chainlib.eth.cli.argflag_std_base_read | chainlib.eth.cli.Flag.WALLET
|
||||
argparser = chainlib.eth.cli.ArgumentParser(arg_flags)
|
||||
argparser.add_positional('address', type=str, help='Ethereum address of recipient')
|
||||
|
||||
def process_config_local(config, arg, args, flags):
|
||||
config.add(args.address, '_RECIPIENT', False)
|
||||
return config
|
||||
|
||||
argparser = chainlib.eth.cli.ArgumentParser()
|
||||
arg_flags = ArgFlag()
|
||||
arg = Arg(arg_flags)
|
||||
flags = arg_flags.STD_BASE_READ | arg_flags.WALLET | arg_flags.UNSAFE
|
||||
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, default_config_dir=config_dir)
|
||||
|
||||
holder_address = args.address
|
||||
wallet = chainlib.eth.cli.Wallet()
|
||||
wallet.from_config(config)
|
||||
if wallet.get_signer_address() == None and holder_address != None:
|
||||
wallet.from_address(holder_address)
|
||||
logg = process_log(args, logg)
|
||||
logg.debug('flags {} {} {}'.format(flags, arg_flags.SEQ, flags & arg_flags.SEQ))
|
||||
|
||||
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))
|
||||
|
||||
settings = ChainSettings()
|
||||
settings = process_settings(settings, config)
|
||||
logg.debug('settings loaded:\n{}'.format(settings))
|
||||
|
||||
|
||||
def main():
|
||||
# TODO: should tolerate if address not prefixed with 0x
|
||||
o = count(add_0x(holder_address), id_generator=rpc.id_generator)
|
||||
r = conn.do(o)
|
||||
o = count(
|
||||
settings.get('RECIPIENT'),
|
||||
id_generator=settings.get('RPC_ID_GENERATOR'),
|
||||
)
|
||||
r = settings.get('CONN').do(o)
|
||||
count_result = None
|
||||
try:
|
||||
count_result = int(r, 16)
|
||||
|
@ -11,10 +11,24 @@ import select
|
||||
# external imports
|
||||
import chainlib.eth.cli
|
||||
from chainlib.eth.tx import unpack
|
||||
from chainlib.settings import ChainSettings
|
||||
from chainlib.chain import ChainSpec
|
||||
|
||||
# local imports
|
||||
import chainlib.eth.cli
|
||||
from chainlib.eth.runnable.util import decode_for_puny_humans
|
||||
from chainlib.eth.cli.arg import (
|
||||
Arg,
|
||||
ArgFlag,
|
||||
process_args,
|
||||
)
|
||||
from chainlib.eth.cli.config import (
|
||||
Config,
|
||||
process_config,
|
||||
)
|
||||
from chainlib.eth.cli.log import process_log
|
||||
from chainlib.eth.settings import process_settings
|
||||
|
||||
|
||||
logging.basicConfig(level=logging.WARNING)
|
||||
logg = logging.getLogger()
|
||||
@ -22,16 +36,39 @@ logg = logging.getLogger()
|
||||
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
config_dir = os.path.join(script_dir, '..', 'data', 'config')
|
||||
|
||||
arg_flags = chainlib.eth.cli.Flag.VERBOSE | chainlib.eth.cli.Flag.CHAIN_SPEC | chainlib.eth.cli.Flag.ENV_PREFIX | chainlib.eth.cli.Flag.RAW
|
||||
argparser = chainlib.eth.cli.ArgumentParser(arg_flags)
|
||||
argparser.add_positional('tx_data', type=str, help='Transaction data to decode')
|
||||
args = argparser.parse_args()
|
||||
config = chainlib.eth.cli.Config.from_args(args, arg_flags, default_config_dir=config_dir)
|
||||
|
||||
chain_spec = ChainSpec.from_chain_str(config.get('CHAIN_SPEC'))
|
||||
def process_config_local(config, arg, args, flags):
|
||||
config.add(args.tx_data, '_TX_DATA', False)
|
||||
return config
|
||||
|
||||
|
||||
arg_flags = ArgFlag()
|
||||
arg = Arg(arg_flags)
|
||||
flags = arg_flags.VERBOSE | arg_flags.CHAIN_SPEC | arg_flags.RAW | arg_flags.ENV | arg_flags.SEQ
|
||||
|
||||
argparser = chainlib.eth.cli.ArgumentParser()
|
||||
argparser = process_args(argparser, arg, flags)
|
||||
argparser.add_argument('tx_data', type=str, help='Transaction data to decode')
|
||||
args = argparser.parse_args()
|
||||
|
||||
logg = process_log(args, logg)
|
||||
|
||||
config = Config()
|
||||
config = process_config(config, arg, args, flags)
|
||||
config = process_config_local(config, arg, args, flags)
|
||||
logg.debug('config loaded:\n{}'.format(config))
|
||||
|
||||
settings = ChainSettings()
|
||||
settings = process_settings(settings, config)
|
||||
logg.debug('settings loaded:\n{}'.format(settings))
|
||||
|
||||
|
||||
def main():
|
||||
decode_for_puny_humans(args.tx_data, chain_spec, sys.stdout)
|
||||
decode_for_puny_humans(
|
||||
config.get('_TX_DATA'),
|
||||
settings.get('CHAIN_SPEC'),
|
||||
sys.stdout,
|
||||
)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
@ -21,6 +21,16 @@ from hexathon import (
|
||||
|
||||
# local 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.cli.log import process_log
|
||||
from chainlib.eth.cli.encode import CLIEncoder
|
||||
from chainlib.eth.constant import ZERO_ADDRESS
|
||||
from chainlib.eth.address import to_checksum
|
||||
@ -47,22 +57,28 @@ script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
config_dir = os.path.join(script_dir, '..', 'data', 'config')
|
||||
|
||||
|
||||
arg_flags = chainlib.eth.cli.argflag_std_write | chainlib.eth.cli.Flag.EXEC | chainlib.eth.cli.Flag.FEE | chainlib.eth.cli.Flag.FMT_HUMAN | chainlib.eth.cli.Flag.FMT_WIRE | chainlib.eth.cli.Flag.FMT_RPC
|
||||
arg_flags = flag_reset(arg_flags, chainlib.cli.Flag.NO_TARGET)
|
||||
argparser = chainlib.eth.cli.ArgumentParser(arg_flags)
|
||||
def process_config_local(config, arg, args, flags):
|
||||
config.add(args.signature, '_SIGNATURE', False)
|
||||
config.add(args.contract_args, '_CONTRACT_ARGS', False)
|
||||
return config
|
||||
|
||||
arg_flags = ArgFlag()
|
||||
arg = Arg(arg_flags)
|
||||
flags = arg_flags.STD_WRITE | arg_flags.EXEC | arg_flags.FEE | arg_flags.FMT_HUMAN | arg_flags.FMT_WIRE | arg_flags.FMT_RPC
|
||||
|
||||
argparser = chainlib.eth.cli.ArgumentParser()
|
||||
argparser = process_args(argparser, arg, flags)
|
||||
argparser.add_argument('--mode', type=str, choices=['tx', 'call', 'arg'], help='Mode of operation')
|
||||
argparser.add_argument('--signature', type=str, help='Method signature to encode')
|
||||
argparser.add_argument('contract_args', type=str, nargs='*', help='arguments to encode')
|
||||
args = argparser.parse_args()
|
||||
extra_args = {
|
||||
'signature': None,
|
||||
'contract_args': None,
|
||||
}
|
||||
config = chainlib.eth.cli.Config.from_args(args, arg_flags, extra_args=extra_args, default_config_dir=config_dir)
|
||||
logg.debug('config loaded:\n{}'.format(config))
|
||||
|
||||
block_all = args.ww
|
||||
block_last = args.w or block_all
|
||||
logg = process_log(args, logg)
|
||||
|
||||
config = Config()
|
||||
config = process_config(config, arg, args, flags)
|
||||
config = process_config_local(config, arg, args, flags)
|
||||
logg.debug('config loaded:\n{}'.format(config))
|
||||
|
||||
wallet = chainlib.eth.cli.Wallet(EIP155Signer)
|
||||
wallet.from_config(config)
|
||||
|
@ -14,56 +14,68 @@ from hexathon import (
|
||||
add_0x,
|
||||
strip_0x,
|
||||
)
|
||||
|
||||
# local imports
|
||||
from chainlib.eth.address import to_checksum_address
|
||||
from chainlib.eth.connection import EthHTTPConnection
|
||||
from chainlib.settings import ChainSettings
|
||||
from chainlib.jsonrpc import (
|
||||
JSONRPCRequest,
|
||||
IntSequenceGenerator,
|
||||
)
|
||||
from chainlib.chain import ChainSpec
|
||||
|
||||
# local imports
|
||||
from chainlib.eth.address import to_checksum_address
|
||||
from chainlib.eth.connection import EthHTTPConnection
|
||||
from chainlib.eth.gas import Gas
|
||||
from chainlib.eth.gas import balance as gas_balance
|
||||
from chainlib.chain import ChainSpec
|
||||
from chainlib.eth.runnable.util import decode_for_puny_humans
|
||||
from chainlib.eth.address import (
|
||||
is_same_address,
|
||||
is_checksum_address,
|
||||
)
|
||||
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.cli.log import process_log
|
||||
from chainlib.eth.settings import process_settings
|
||||
|
||||
logging.basicConfig(level=logging.WARNING)
|
||||
logg = logging.getLogger()
|
||||
|
||||
arg_flags = chainlib.eth.cli.argflag_std_write | chainlib.eth.cli.Flag.WALLET
|
||||
argparser = chainlib.eth.cli.ArgumentParser(arg_flags)
|
||||
|
||||
def process_config_local(config, arg, args, flags):
|
||||
config.add(args.data, '_DATA', False)
|
||||
config.add(args.amount, '_VALUE', 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('--data', type=str, help='Transaction data')
|
||||
argparser.add_positional('amount', type=int, help='Token amount to send')
|
||||
argparser.add_argument('amount', type=str, help='Token amount to send')
|
||||
args = argparser.parse_args()
|
||||
extra_args = {
|
||||
'data': None,
|
||||
'amount': None,
|
||||
}
|
||||
#config = chainlib.eth.cli.Config.from_args(args, arg_flags, extra_args=extra_args, default_config_dir=config_dir)
|
||||
config = chainlib.eth.cli.Config.from_args(args, arg_flags, extra_args=extra_args)
|
||||
|
||||
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)
|
||||
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(address, id_generator):
|
||||
def balance(conn, address, id_generator):
|
||||
o = gas_balance(address, id_generator=id_generator)
|
||||
r = conn.do(o)
|
||||
try:
|
||||
@ -75,47 +87,71 @@ def balance(address, id_generator):
|
||||
|
||||
|
||||
def main():
|
||||
signer = rpc.get_signer()
|
||||
signer_address = rpc.get_sender_address()
|
||||
|
||||
g = Gas(chain_spec, signer=signer, gas_oracle=rpc.get_gas_oracle(), nonce_oracle=rpc.get_nonce_oracle())
|
||||
g = Gas(
|
||||
settings.get('CHAIN_SPEC'),
|
||||
signer=settings.get('SIGNER'),
|
||||
gas_oracle=settings.get('GAS_ORACLE'),
|
||||
nonce_oracle=settings.get('NONCE_ORACLE'),
|
||||
)
|
||||
|
||||
recipient = to_checksum_address(config.get('_RECIPIENT'))
|
||||
if not config.true('_UNSAFE') and not is_checksum_address(recipient):
|
||||
raise ValueError('invalid checksum address')
|
||||
|
||||
logg.info('gas transfer from {} to {} value {}'.format(signer_address, recipient, value))
|
||||
if logg.isEnabledFor(logging.DEBUG):
|
||||
try:
|
||||
sender_balance = balance(add_0x(signer_address), rpc.id_generator)
|
||||
recipient_balance = balance(add_0x(recipient), rpc.id_generator)
|
||||
logg.debug('sender {}Â balance before: {}'.format(signer_address, sender_balance))
|
||||
logg.debug('recipient {}Â balance before: {}'.format(recipient, recipient_balance))
|
||||
sender_balance = balance(
|
||||
settings.get('CONN'),
|
||||
settings.get('SENDER_ADDRESS'),
|
||||
settings.get('RPC_ID_GENERATOR'),
|
||||
)
|
||||
recipient_balance = balance(
|
||||
settings.get('CONN'),
|
||||
settings.get('RECIPIENT'),
|
||||
settings.get('RPC_ID_GENERATOR'),
|
||||
)
|
||||
logg.debug('sender {}Â balance before: {}'.format(settings.get('SENDER_ADDRESS'), sender_balance))
|
||||
logg.debug('recipient {}Â balance before: {}'.format(settings.get('RECIPIENT'), recipient_balance))
|
||||
except urllib.error.URLError:
|
||||
pass
|
||||
|
||||
(tx_hash_hex, o) = g.create(signer_address, add_0x(recipient), value, data=config.get('_DATA'), id_generator=rpc.id_generator)
|
||||
(tx_hash_hex, o) = g.create(
|
||||
settings.get('SENDER_ADDRESS'),
|
||||
settings.get('RECIPIENT'),
|
||||
settings.get('VALUE'),
|
||||
data=config.get('_DATA'),
|
||||
id_generator=settings.get('RPC_ID_GENERATOR'),
|
||||
)
|
||||
|
||||
logg.info('gas transfer from {} to {} value {} hash {}'.format(settings.get('SENDER_ADDRESS'), settings.get('RECIPIENT'), settings.get('VALUE'), tx_hash_hex))
|
||||
|
||||
if send:
|
||||
conn.do(o)
|
||||
if block_last:
|
||||
r = conn.wait(tx_hash_hex)
|
||||
if settings.get('RPC_SEND'):
|
||||
settings.get('CONN').do(o)
|
||||
if config.true('_WAIT'):
|
||||
r = settings.get('CONN').wait(tx_hash_hex)
|
||||
if logg.isEnabledFor(logging.DEBUG):
|
||||
sender_balance = balance(add_0x(signer_address), rpc.id_generator)
|
||||
recipient_balance = balance(add_0x(recipient), 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(
|
||||
settings.get('CONN'),
|
||||
settings.get('SENDER_ADDRESS'),
|
||||
settings.get('RPC_ID_GENERATOR'),
|
||||
)
|
||||
recipient_balance = balance(
|
||||
settings.get('CONN'),
|
||||
settings.get('RECIPIENT'),
|
||||
settings.get('RPC_ID_GENERATOR'),
|
||||
)
|
||||
logg.debug('sender {}Â balance before: {}'.format(settings.get('SENDER_ADDRESS'), sender_balance))
|
||||
logg.debug('recipient {}Â balance before: {}'.format(settings.get('RECIPIENT'), recipient_balance))
|
||||
if r['status'] == 0:
|
||||
logg.critical('VM revert for {}. Wish I could tell you more'.format(tx_hash_hex))
|
||||
sys.exit(1)
|
||||
print(tx_hash_hex)
|
||||
else:
|
||||
#if logg.isEnabledFor(logging.INFO):
|
||||
if config.true('_RAW'):
|
||||
print(o['params'][0])
|
||||
else:
|
||||
io_str = io.StringIO()
|
||||
decode_for_puny_humans(o['params'][0], chain_spec, io_str)
|
||||
decode_for_puny_humans(o['params'][0], settings.get('CHAIN_SPEC'), io_str)
|
||||
print(io_str.getvalue())
|
||||
|
||||
|
||||
|
@ -23,12 +23,15 @@ from chainlib.jsonrpc import (
|
||||
)
|
||||
from chainlib.chain import ChainSpec
|
||||
from chainlib.status import Status
|
||||
from chainlib.settings import ChainSettings
|
||||
|
||||
# local imports
|
||||
from chainlib.eth.connection import EthHTTPConnection
|
||||
from chainlib.eth.tx import (
|
||||
Tx,
|
||||
pack,
|
||||
transaction,
|
||||
receipt,
|
||||
)
|
||||
from chainlib.eth.address import (
|
||||
to_checksum_address,
|
||||
@ -41,35 +44,67 @@ from chainlib.eth.block import (
|
||||
from chainlib.eth.runnable.util import decode_for_puny_humans
|
||||
from chainlib.eth.jsonrpc import to_blockheight_param
|
||||
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.contract import code
|
||||
from chainlib.eth.cli.log import process_log
|
||||
from chainlib.eth.settings import process_settings
|
||||
|
||||
|
||||
logging.basicConfig(level=logging.WARNING, format='%(asctime)s %(levelname)s %(filename)s:%(lineno)d %(message)s')
|
||||
logg = logging.getLogger()
|
||||
|
||||
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
config_dir = os.path.join(script_dir, '..', 'data', 'config')
|
||||
|
||||
arg_flags = chainlib.eth.cli.argflag_std_base_read
|
||||
arg_flags = chainlib.eth.cli.argflag_reset(arg_flags, chainlib.eth.cli.Flag.CHAIN_SPEC)
|
||||
argparser = chainlib.eth.cli.ArgumentParser(arg_flags)
|
||||
argparser.add_positional('item', type=str, help='Address or transaction to retrieve data for')
|
||||
|
||||
def process_config_local(config, arg, args, flags):
|
||||
config.add(args.item, '_ITEM', False)
|
||||
return config
|
||||
|
||||
|
||||
def process_settings_local(settings, config):
|
||||
item = config.get('_ITEM')
|
||||
item = strip_0x(item)
|
||||
|
||||
if len(item) == 40:
|
||||
config.add(item, '_RECIPIENT', False)
|
||||
elif len(item) == 64:
|
||||
config.add(item, '_HASH', False)
|
||||
|
||||
return process_settings(settings, config)
|
||||
|
||||
|
||||
arg_flags = ArgFlag()
|
||||
arg = Arg(arg_flags)
|
||||
flags = arg_flags.STD_BASE_READ | arg_flags.TARGET
|
||||
flags = arg_flags.less(flags, arg_flags.CHAIN_SPEC)
|
||||
|
||||
argparser = chainlib.eth.cli.ArgumentParser()
|
||||
argparser = process_args(argparser, arg, flags)
|
||||
argparser.add_argument('item', type=str, help='Address or transaction to retrieve data for')
|
||||
args = argparser.parse_args()
|
||||
config = chainlib.eth.cli.Config.from_args(args, arg_flags, default_config_dir=config_dir)
|
||||
|
||||
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)
|
||||
config = process_config_local(config, arg, args, flags)
|
||||
logg.debug('config loaded:\n{}'.format(config))
|
||||
|
||||
item = add_0x(args.item)
|
||||
settings = ChainSettings()
|
||||
settings = process_settings_local(settings, config)
|
||||
logg.debug('settings loaded:\n{}'.format(settings))
|
||||
|
||||
|
||||
def get_transaction(conn, tx_hash, id_generator):
|
||||
tx_hash = add_0x(tx_hash)
|
||||
j = JSONRPCRequest(id_generator=id_generator)
|
||||
o = j.template()
|
||||
o['method'] = 'eth_getTransactionByHash'
|
||||
o['params'].append(tx_hash)
|
||||
o = j.finalize(o)
|
||||
def get_transaction(conn, chain_spec, tx_hash, id_generator):
|
||||
o = transaction(tx_hash, id_generator=id_generator)
|
||||
tx_src = conn.do(o)
|
||||
if tx_src == None:
|
||||
logg.error('Transaction {} not found'.format(tx_hash))
|
||||
@ -83,12 +118,8 @@ def get_transaction(conn, tx_hash, id_generator):
|
||||
status = -1
|
||||
rcpt = None
|
||||
|
||||
o = j.template()
|
||||
o['method'] = 'eth_getTransactionReceipt'
|
||||
o['params'].append(tx_hash)
|
||||
o = j.finalize(o)
|
||||
o = receipt(tx_hash, id_generator=id_generator)
|
||||
rcpt = conn.do(o)
|
||||
#status = int(strip_0x(rcpt['status']), 16)
|
||||
|
||||
if tx == None:
|
||||
tx = Tx(tx_src)
|
||||
@ -105,17 +136,10 @@ def get_transaction(conn, tx_hash, id_generator):
|
||||
|
||||
|
||||
def get_address(conn, address, id_generator, height):
|
||||
address = add_0x(address)
|
||||
j = JSONRPCRequest(id_generator=id_generator)
|
||||
o = j.template()
|
||||
o['method'] = 'eth_getCode'
|
||||
o['params'].append(address)
|
||||
height = to_blockheight_param(height)
|
||||
o['params'].append(height)
|
||||
o = j.finalize(o)
|
||||
code = conn.do(o)
|
||||
o = code(address, height, id_generator=id_generator)
|
||||
r = conn.do(o)
|
||||
|
||||
content = strip_0x(code, allow_empty=True)
|
||||
content = strip_0x(r, allow_empty=True)
|
||||
if len(content) == 0:
|
||||
return None
|
||||
|
||||
@ -123,18 +147,24 @@ def get_address(conn, address, id_generator, height):
|
||||
|
||||
|
||||
def main():
|
||||
address = item
|
||||
r = None
|
||||
if len(address) > 42:
|
||||
r = get_transaction(conn, address, rpc.id_generator)
|
||||
if settings.get('HASH') != None:
|
||||
hsh = settings.get('HASH')[0]
|
||||
r = get_transaction(
|
||||
settings.get('CONN'),
|
||||
settings.get('CHAIN_SPEC'),
|
||||
hsh,
|
||||
settings.get('RPC_ID_GENERATOR'),
|
||||
)
|
||||
if not config.true('_RAW'):
|
||||
r = r.to_human()
|
||||
else:
|
||||
if config.get('_UNSAFE'):
|
||||
address = to_checksum_address(address)
|
||||
elif not is_checksum_address(address):
|
||||
raise ValueError('invalid checksum address: {}'.format(address))
|
||||
r = get_address(conn, address, rpc.id_generator, config.get('_HEIGHT'))
|
||||
r = get_address(
|
||||
settings.get('CONN'),
|
||||
settings.get('RECIPIENT'),
|
||||
settings.get('RPC_ID_GENERATOR'),
|
||||
settings.get('HEIGHT'),
|
||||
)
|
||||
if r != None:
|
||||
print(r)
|
||||
|
||||
|
@ -17,6 +17,7 @@ from hexathon import (
|
||||
)
|
||||
import sha3
|
||||
from funga.eth.signer import EIP155Signer
|
||||
from chainlib.settings import ChainSettings
|
||||
|
||||
# local imports
|
||||
from chainlib.eth.address import AddressChecksum
|
||||
@ -35,10 +36,20 @@ from chainlib.eth.gas import (
|
||||
price,
|
||||
)
|
||||
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.cli.log import process_log
|
||||
from chainlib.eth.settings import process_settings
|
||||
|
||||
BLOCK_SAMPLES = 10
|
||||
|
||||
logging.basicConfig(level=logging.WARNING)
|
||||
logg = logging.getLogger()
|
||||
|
||||
script_dir = os.path.dirname(os.path |