Initial commit
This commit is contained in:
		
						commit
						4788326c4e
					
				
							
								
								
									
										28
									
								
								cic_tools/eth/checksum.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								cic_tools/eth/checksum.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
			
		||||
# third-party imports
 | 
			
		||||
import sha3
 | 
			
		||||
from hexathon import (
 | 
			
		||||
        strip_0x,
 | 
			
		||||
        uniform,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def to_checksum(address_hex):
 | 
			
		||||
    
 | 
			
		||||
        address_hex = strip_0x(address_hex)
 | 
			
		||||
        address_hex = uniform(address_hex)
 | 
			
		||||
        h = sha3.keccak_256()
 | 
			
		||||
        h.update(address_hex.encode('utf-8'))
 | 
			
		||||
        z = h.digest()
 | 
			
		||||
 | 
			
		||||
        checksum_address_hex = '0x'
 | 
			
		||||
 | 
			
		||||
        for (i, c) in enumerate(address_hex):
 | 
			
		||||
            if c in '1234567890':
 | 
			
		||||
                checksum_address_hex += c
 | 
			
		||||
            elif c in 'abcdef':
 | 
			
		||||
                if z[int(i / 2)] & (0x80 >> ((i % 2) * 4)) > 1:
 | 
			
		||||
                    checksum_address_hex += c.upper()
 | 
			
		||||
                else:
 | 
			
		||||
                    checksum_address_hex += c
 | 
			
		||||
 | 
			
		||||
        return checksum_address_hex
 | 
			
		||||
							
								
								
									
										31
									
								
								cic_tools/eth/connection.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								cic_tools/eth/connection.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
			
		||||
import logging
 | 
			
		||||
import json
 | 
			
		||||
from urllib.request import (
 | 
			
		||||
        Request,
 | 
			
		||||
        urlopen,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
from .error import DefaultErrorParser
 | 
			
		||||
from .method import jsonrpc_result
 | 
			
		||||
 | 
			
		||||
error_parser = DefaultErrorParser()
 | 
			
		||||
logg = logging.getLogger(__name__)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class HTTPConnection:
 | 
			
		||||
 | 
			
		||||
    def __init__(self, url):
 | 
			
		||||
        self.url = url
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def do(self, o, error_parser=error_parser):
 | 
			
		||||
        req = Request(
 | 
			
		||||
                self.url,
 | 
			
		||||
                method='POST',
 | 
			
		||||
                )
 | 
			
		||||
        req.add_header('Content-Type', 'application/json')
 | 
			
		||||
        data = json.dumps(o)
 | 
			
		||||
        logg.debug('(HTTP) send {}'.format(data))
 | 
			
		||||
        res = urlopen(req, data=data.encode('utf-8'))
 | 
			
		||||
        o = json.load(res)
 | 
			
		||||
        return jsonrpc_result(o, error_parser)
 | 
			
		||||
							
								
								
									
										2
									
								
								cic_tools/eth/constant.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								cic_tools/eth/constant.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
			
		||||
zero_address = '0x{:040x}'.format(0)
 | 
			
		||||
zero_content = '0x{:064x}'.format(0)
 | 
			
		||||
							
								
								
									
										8
									
								
								cic_tools/eth/error.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								cic_tools/eth/error.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
class EthException(Exception):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DefaultErrorParser:
 | 
			
		||||
 | 
			
		||||
    def translate(self, error):
 | 
			
		||||
        return EthException('default parser code {}'.format(error))
 | 
			
		||||
							
								
								
									
										7
									
								
								cic_tools/eth/hash.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								cic_tools/eth/hash.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
			
		||||
import sha3
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def keccak256_hex(s):
 | 
			
		||||
    h = sha3.keccak_256()
 | 
			
		||||
    h.update(s.encode('utf-8'))
 | 
			
		||||
    return h.digest().hex()
 | 
			
		||||
							
								
								
									
										61
									
								
								cic_tools/eth/method.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								cic_tools/eth/method.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,61 @@
 | 
			
		||||
import sha3
 | 
			
		||||
import uuid
 | 
			
		||||
 | 
			
		||||
from hexathon import add_0x
 | 
			
		||||
from eth_abi import encode_single
 | 
			
		||||
 | 
			
		||||
from .hash import keccak256_hex
 | 
			
		||||
from .constant import zero_address
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# TODO: move to cic-contracts
 | 
			
		||||
erc20_balance_signature = keccak256_hex('balanceOf(address)')[:8]
 | 
			
		||||
erc20_decimals_signature = keccak256_hex('decimals()')[:8]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def jsonrpc_template():
 | 
			
		||||
    return {
 | 
			
		||||
        'jsonrpc': '2.0',
 | 
			
		||||
        'id': str(uuid.uuid4()),
 | 
			
		||||
        'method': None,
 | 
			
		||||
        'params': [],
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def erc20_balance(contract_address, address, sender_address=zero_address):
 | 
			
		||||
    o = jsonrpc_template()
 | 
			
		||||
    o['method'] = 'eth_call'
 | 
			
		||||
    data = erc20_balance_signature
 | 
			
		||||
    data += encode_single('address', address).hex()
 | 
			
		||||
    data = add_0x(data)
 | 
			
		||||
    a = call(contract_address, data=data)
 | 
			
		||||
    o['params'].append(a)
 | 
			
		||||
    o['params'].append('latest')
 | 
			
		||||
    return o
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def erc20_decimals(contract_address, sender_address=zero_address):
 | 
			
		||||
    o = jsonrpc_template()
 | 
			
		||||
    o['method'] = 'eth_call'
 | 
			
		||||
    arg = add_0x(erc20_decimals_signature)
 | 
			
		||||
    #o['params'].append(arg)
 | 
			
		||||
    a = call(contract_address, arg)
 | 
			
		||||
    o['params'].append(a)
 | 
			
		||||
    o['params'].append('latest')
 | 
			
		||||
    return o
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def call(contract_address, data, sender_address=zero_address):
 | 
			
		||||
    return {
 | 
			
		||||
        'from': sender_address,
 | 
			
		||||
        'to': contract_address,
 | 
			
		||||
        'data': data,
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def jsonrpc_result(o, ep):
 | 
			
		||||
    if o.get('error') != None:
 | 
			
		||||
        raise ep.translate(o)
 | 
			
		||||
    return o['result']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										0
									
								
								cic_tools/eth/runnable/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								cic_tools/eth/runnable/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										99
									
								
								cic_tools/eth/runnable/balance.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								cic_tools/eth/runnable/balance.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,99 @@
 | 
			
		||||
#!python3
 | 
			
		||||
 | 
			
		||||
"""Token balance query script
 | 
			
		||||
 | 
			
		||||
.. moduleauthor:: Louis Holbrook <dev@holbrook.no>
 | 
			
		||||
.. pgp:: 0826EDA1702D1E87C6E2875121D2E7BB88C2A746 
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
# SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
# standard imports
 | 
			
		||||
import os
 | 
			
		||||
import json
 | 
			
		||||
import argparse
 | 
			
		||||
import logging
 | 
			
		||||
 | 
			
		||||
# third-party imports
 | 
			
		||||
from hexathon import (
 | 
			
		||||
        add_0x,
 | 
			
		||||
        strip_0x,
 | 
			
		||||
        even,
 | 
			
		||||
        )
 | 
			
		||||
import sha3
 | 
			
		||||
from eth_abi import encode_single
 | 
			
		||||
 | 
			
		||||
# local imports
 | 
			
		||||
from cic_tools.eth.checksum import to_checksum
 | 
			
		||||
from cic_tools.eth.method import (
 | 
			
		||||
        jsonrpc_template,
 | 
			
		||||
        erc20_balance,
 | 
			
		||||
        erc20_decimals,
 | 
			
		||||
        jsonrpc_result,
 | 
			
		||||
        )
 | 
			
		||||
from cic_tools.eth.connection import HTTPConnection
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
logging.basicConfig(level=logging.WARNING)
 | 
			
		||||
logg = logging.getLogger()
 | 
			
		||||
 | 
			
		||||
default_abi_dir = os.environ.get('ETH_ABI_DIR', '/usr/share/local/cic/solidity/abi')
 | 
			
		||||
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('-t', '--token-address', dest='t', type=str, help='Token address. If not set, will return gas balance')
 | 
			
		||||
argparser.add_argument('-u', '--unsafe', dest='u', action='store_true', help='Auto-convert address to checksum adddress')
 | 
			
		||||
argparser.add_argument('--abi-dir', dest='abi_dir', type=str, default=default_abi_dir, help='Directory containing bytecode and abi (default {})'.format(default_abi_dir))
 | 
			
		||||
argparser.add_argument('-v', action='store_true', help='Be verbose')
 | 
			
		||||
argparser.add_argument('account', type=str, help='Account address')
 | 
			
		||||
args = argparser.parse_args()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if args.v:
 | 
			
		||||
    logg.setLevel(logging.DEBUG)
 | 
			
		||||
 | 
			
		||||
conn = HTTPConnection(args.p)
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
#    w3 = web3.Web3(web3.Web3.HTTPProvider(args.p))
 | 
			
		||||
# REPLACE WITH URLLIB
 | 
			
		||||
  
 | 
			
		||||
    account = to_checksum(args.account)
 | 
			
		||||
    if not args.u and account != add_0x(args.account):
 | 
			
		||||
        raise ValueError('invalid checksum address')
 | 
			
		||||
    
 | 
			
		||||
    r = None
 | 
			
		||||
    decimals = 18
 | 
			
		||||
    if args.t != None:
 | 
			
		||||
        # determine decimals
 | 
			
		||||
        decimals_o = erc20_decimals(args.t)
 | 
			
		||||
        r = conn.do(decimals_o)
 | 
			
		||||
        decimals = int(strip_0x(r), 16)
 | 
			
		||||
 | 
			
		||||
        # get balance
 | 
			
		||||
        balance_o = erc20_balance(args.t, account)
 | 
			
		||||
        r = conn.do(balance_o)
 | 
			
		||||
 | 
			
		||||
    else:
 | 
			
		||||
        o = jsonrpc_template()
 | 
			
		||||
        o['method'] = 'eth_getBalance'
 | 
			
		||||
        o['params'].append(account)
 | 
			
		||||
        r = conn.do(o)
 | 
			
		||||
   
 | 
			
		||||
    hx = strip_0x(r)
 | 
			
		||||
    balance = int(hx, 16)
 | 
			
		||||
    logg.debug('balance {} = {} decimals {}'.format(even(hx), balance, decimals))
 | 
			
		||||
 | 
			
		||||
    balance_str = str(balance)
 | 
			
		||||
    balance_len = len(balance_str)
 | 
			
		||||
    if balance_len < 19:
 | 
			
		||||
        print('0.{}'.format(balance_str.zfill(decimals)))
 | 
			
		||||
    else:
 | 
			
		||||
        offset = balance_len-decimals
 | 
			
		||||
        print('{}.{}'.format(balance_str[:offset],balance_str[offset:]))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    main()
 | 
			
		||||
							
								
								
									
										8
									
								
								cic_tools/eth/runnable/checksum.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								cic_tools/eth/runnable/checksum.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
# standard imports
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
# local imports
 | 
			
		||||
from cic_tools.eth.checksum import to_checksum
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
print(to_checksum(sys.argv[1]))
 | 
			
		||||
							
								
								
									
										13
									
								
								requirements.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								requirements.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
			
		||||
cryptocurrency-cli-tools==0.0.4
 | 
			
		||||
giftable-erc20-token==0.0.7b6
 | 
			
		||||
eth-accounts-index==0.0.10a6
 | 
			
		||||
erc20-single-shot-faucet==0.2.0a5
 | 
			
		||||
erc20-approval-escrow==0.3.0a4
 | 
			
		||||
cic-eth==0.10.0a21+build.e4161b3e
 | 
			
		||||
vobject==0.9.6.1
 | 
			
		||||
faker==4.17.1
 | 
			
		||||
eth-address-index==0.1.0a5
 | 
			
		||||
crypto-dev-signer==0.4.13rc2
 | 
			
		||||
pysha3==1.0.2
 | 
			
		||||
hexathon==0.0.1a2
 | 
			
		||||
eth-abi==2.1.1
 | 
			
		||||
							
								
								
									
										36
									
								
								setup.cfg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								setup.cfg
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,36 @@
 | 
			
		||||
[metadata]
 | 
			
		||||
name = cic-tools
 | 
			
		||||
version = 0.0.1a1
 | 
			
		||||
description = Executable tools for CIC network
 | 
			
		||||
author = Louis Holbrook
 | 
			
		||||
author_email = dev@holbrook.no
 | 
			
		||||
url = https://gitlab.com/grassrootseconomics/cic-tools
 | 
			
		||||
keywords =
 | 
			
		||||
	cic
 | 
			
		||||
	cryptocurrency
 | 
			
		||||
	ethereum
 | 
			
		||||
	solidarity
 | 
			
		||||
	mutual_credit
 | 
			
		||||
classifiers =
 | 
			
		||||
	Programming Language :: Python :: 3
 | 
			
		||||
	Operating System :: OS Independent
 | 
			
		||||
	Development Status :: 3 - Alpha
 | 
			
		||||
	Environment :: Console
 | 
			
		||||
	Intended Audience :: Developers
 | 
			
		||||
	License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
 | 
			
		||||
	Topic :: Internet
 | 
			
		||||
#	Topic :: Blockchain :: EVM
 | 
			
		||||
license = GPL3
 | 
			
		||||
licence_files =
 | 
			
		||||
	LICENSE.txt
 | 
			
		||||
 | 
			
		||||
[options]
 | 
			
		||||
python_requires = >= 3.6
 | 
			
		||||
packages = 
 | 
			
		||||
	cic_tools.eth
 | 
			
		||||
	cic_tools.eth.runnable
 | 
			
		||||
 | 
			
		||||
[options.entry_points]
 | 
			
		||||
console_scripts =
 | 
			
		||||
	eth-balance = cic_tools.eth.runnable.balance:main
 | 
			
		||||
	eth-checksum = cic_tools.eth.runnable.checksum:main
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user