EthTx - Ethereum transactions decoder

Overview

EthTx - Ethereum transactions decoder

Python Black OpenSource Apache

Installation

pip install ethtx

Requirements

The package needs a few external resources, defined in EthTxConfig object:

  1. Geth node - required to have access to the raw Ethereum data; it must be a full archive node with the debug option ON
  2. MongoDB database - required to store smart contracts' ABI and semantics used in the decoding process; it can be a Mongo Atlas or local instance
  3. Etherscan API key - required to get the source code and ABI for smart contracts used in transaction

Getting started

from ethtx import EthTx, EthTxConfig
from ethtx.models.decoded_model import DecodedTransaction


ethtx_config = EthTxConfig(
    mongo_connection_string= ##MongoDB connection string,
    mongo_database= ##MongoDB database,
    etherscan_api_key= ##Etherscan API key,
    web3nodes={
        "mainnet": ##Geth archive node URL,
    },
    default_chain="mainnet",
    etherscan_urls={
        "mainnet": "https://api.etherscan.io/api",
    },
)

ethtx = EthTx.initialize(ethtx_config)
transaction: DecodedTransaction = ethtx.decoders.decode_transaction('0x50051e0a6f216ab9484c2080001c7e12d5138250acee1f4b7c725b8fb6bb922d')

Features

EthTx most important functions:

  1. raw node data access:
ethtx = EthTx.initialize(ethtx_config)
web3provider = ethtx.providers.web3provider

from ethtx.models.w3_model import W3Transaction, W3Block, W3Receipt, W3CallTree

# read raw transaction data directly from the node
w3transaction: W3Transaction = web3provider.get_transaction('0x50051e0a6f216ab9484c2080001c7e12d5138250acee1f4b7c725b8fb6bb922d')
w3block: W3Block = web3provider.get_block(w3transaction.blockNumber)
w3receipt: W3Receipt = web3provider.get_receipt(w3transaction.hash.hex())
w3calls: W3CallTree = web3provider.get_calls(w3transaction.hash.hex()
  1. ABI decoding:
from ethtx.models.objects_model import Transaction, Event, Call
from ethtx.models.decoded_model import DecodedEvent, DecodedCall, DecodedTransfer, DecodedBalance

# read the raw transaction from the node
transaction: Transaction = web3provider.get_full_transaction('0x50051e0a6f216ab9484c2080001c7e12d5138250acee1f4b7c725b8fb6bb922d')

# decode transaction components
abi_decoded_events: List[Event] = ethtx.decoders.abi_decoder.decode_events(transaction.events, transaction.metadata)
abi_decoded_calls: DecodedCall = ethtx.decoders.abi_decoder.decode_calls(transaction.root_call, transaction.metadata)
abi_decoded_transfers: List[DecodedTransfer] = ethtx.decoders.abi_decoder.decode_transfers(abi_decoded_calls, abi_decoded_events)
abi_decoded_balances: List[DecodedBalance] = ethtx.decoders.abi_decoder.decode_balances(abi_decoded_transfers)

# decode a single event
raw_event: Event = transaction.events[3]
abi_decoded_event: DecodedEvent = ethtx.decoders.abi_decoder.decode_event(raw_event, transaction.metadata)

# decode a single call
raw_call: Call = transaction.root_call.subcalls[3].subcalls[2]
abi_decoded_call: DecodedCall = ethtx.decoders.abi_decoder.decode_call(raw_call, transaction.metadata)
  1. Semantic decoding:
from ethtx.models.decoded_model import DecodedTransactionMetadata

# get proxies used in the transaction
proxies = ethtx.decoders.get_proxies(transaction.root_call)

# semantically decode transaction components
decoded_metadata: DecodedTransactionMetadata = ethtx.decoders.semantic_decoder.decode_metadata(block.metadata, transaction.metadata)
decoded_events: List[DecodedEvent] = ethtx.decoders.semantic_decoder.decode_events(abi_decoded_events, decoded_metadata, token_proxies)
decoded_calls: Call = ethtx.decoders.semantic_decoder.decode_calls(abi_decoded_calls, decoded_metadata, proxies)
decoded_transfers: List[DecodedTransfer] = ethtx.decoders.semantic_decoder.decode_transfers(abi_decoded_transfers)
decoded_balances: List[DecodedBalance] = ethtx.decoders.semantic_decoder.decode_balances(abi_decoded_balances)

# semantically decode a single event
decoded_event: DecodedEvent = ethtx.decoders.semantic_decoder.decode_event(abi_decoded_events[0], decoded_metadata, proxies)
# semantically decode a single call
decoded_call: Call = ethtx.decoders.semantic_decoder.decode_call(abi_decoded_calls.subcalls[2].subcalls[0], decoded_metadata, proxies)
Comments
  • No module named 'ethtx.semantics'

    No module named 'ethtx.semantics'

    Windows 10. Python version 3.10.4. Latest version for ethtx is installed with pip install ethtx.

    I created a file test.py with the following content:

    from ethtx import EthTx, EthTxConfig
    from ethtx.models.decoded_model import DecodedTransaction
    
    ethtx_config = EthTxConfig(
        etherscan_api_key="my etherscan API key",  ##Etherscan API key,
        web3nodes={
            "mainnet": {
                "hook": "my Infura url",  # multiple nodes supported, separate them with comma
                "poa": False  # represented by bool value
            }
        },
        default_chain="mainnet",
        etherscan_urls={"mainnet": "https://api.etherscan.io/api" }
    )
    
    ethtx = EthTx.initialize(ethtx_config)
    transaction: DecodedTransaction = ethtx.decoders.decode_transaction(
        '0x50051e0a6f216ab9484c2080001c7e12d5138250acee1f4b7c725b8fb6bb922d')
    

    Once I try to execute the file with py test.py, I get the following error:

    Traceback (most recent call last):
      File "C:\Users\Utente\Desktop\ethtx\test.py", line 1, in <module>
        from ethtx import EthTx, EthTxConfig
      File "C:\Users\Utente\AppData\Local\Programs\Python\Python310\lib\site-packages\ethtx\__init__.py", line 13, in <module>
        from .ethtx import EthTx, EthTxConfig
      File "C:\Users\Utente\AppData\Local\Programs\Python\Python310\lib\site-packages\ethtx\ethtx.py", line 18, in <module>
        from .decoders.abi.decoder import ABIDecoder
      File "C:\Users\Utente\AppData\Local\Programs\Python\Python310\lib\site-packages\ethtx\decoders\abi\decoder.py", line 32, in <module>
        from .abc import IABIDecoder
      File "C:\Users\Utente\AppData\Local\Programs\Python\Python310\lib\site-packages\ethtx\decoders\abi\abc.py", line 25, in <module>
        from ethtx.providers.semantic_providers import SemanticsRepository
      File "C:\Users\Utente\AppData\Local\Programs\Python\Python310\lib\site-packages\ethtx\providers\semantic_providers\__init__.py", line 15, in <module>
        from .repository import SemanticsRepository
      File "C:\Users\Utente\AppData\Local\Programs\Python\Python310\lib\site-packages\ethtx\providers\semantic_providers\repository.py", line 30, in <module>
        from ethtx.semantics.protocols_router import amend_contract_semantics
      File "C:\Users\Utente\AppData\Local\Programs\Python\Python310\lib\site-packages\ethtx\semantics\protocols_router.py", line 21, in <module>
        def amend_contract_semantics(semantics: ContractSemantics, router_=Router()):
      File "C:\Users\Utente\AppData\Local\Programs\Python\Python310\lib\site-packages\ethtx\semantics\router.py", line 30, in __new__
        return cls._get_semantics()
      File "C:\Users\Utente\AppData\Local\Programs\Python\Python310\lib\site-packages\ethtx\semantics\router.py", line 52, in _get_semantics
        imported_module = importlib.import_module(
      File "C:\Users\Utente\AppData\Local\Programs\Python\Python310\lib\importlib\__init__.py", line 126, in import_module
        return _bootstrap._gcd_import(name[level:], package, level)
    ModuleNotFoundError: No module named 'ethtx.semanticsC:\\Users\\Utente\\AppData\\Local\\Programs\\Python\\Python310\\lib\\site-packages\\ethtx\\semantics\\base'
    

    What's the issue? Thanks for the help.

    opened by yuripaoloni 10
  • from_address is none

    from_address is none

    When I run get start script,I get error: Traceback (most recent call last): File "Code/python/Blockchain/eth_trans_decode.py", line 23, in transaction: DecodedTransaction = ethtx.decoders.decode_transaction( File "/opt/anaconda3/envs/py3.8/lib/python3.8/site-packages/ethtx/ethtx.py", line 67, in decode_transaction return self._decoder_service.decode_transaction(chain_id, tx_hash) File "/opt/anaconda3/envs/py3.8/lib/python3.8/site-packages/ethtx/decoders/decoder_service.py", line 47, in decode_transaction transaction = self.web3provider.get_full_transaction( File "/opt/anaconda3/envs/py3.8/lib/python3.8/site-packages/ethtx/providers/web3_provider.py", line 466, in get_full_transaction w3calltree = self.get_calls(tx_hash, chain_id) File "/opt/anaconda3/envs/py3.8/lib/python3.8/site-packages/ethtx/providers/web3_provider.py", line 255, in get_calls return self._create_call_from_debug_trace_tx( File "/opt/anaconda3/envs/py3.8/lib/python3.8/site-packages/ethtx/providers/web3_provider.py", line 490, in _create_call_from_debug_trace_tx main_parent = W3CallTree(tx_hash=tx_hash, chain_id=chain_id, **w3input) File "pydantic/main.py", line 406, in pydantic.main.BaseModel.init pydantic.error_wrappers.ValidationError: 2 validation errors for W3CallTree type field required (type=value_error.missing) from_address none is not an allowed value (type=type_error.none.not_allowed)

    When debug, I found from_address is set to none in ethtx/providers/web3_provider.py , 479 line.

    I have no idea why? And I print the debug_transaction response , it dose not contain from_address , either.

    bug 
    opened by wulasite 10
  • OverflowError: integer division result too large for a float in calls.py L194

    OverflowError: integer division result too large for a float in calls.py L194

    When I install and run starter demo, I put a tx hash : 0x4f378f91bf16a26cff104aea5eceaa66c72d128dade84ddb619d40426f9780a0 and got an error report like the output below:

    Traceback (most recent call last):
      File "/home/ubuntu/.local/lib/python3.8/site-packages/ethtx/decoders/abi/decoder.py", line 171, in _decode_transaction
        full_decoded_transaction.calls = self.decode_calls(
      File "/home/ubuntu/.local/lib/python3.8/site-packages/ethtx/decoders/abi/decoder.py", line 68, in decode_calls
        return ABICallsDecoder(
      File "/home/ubuntu/.local/lib/python3.8/site-packages/ethtx/decoders/abi/calls.py", line 55, in decode
        calls_tree = self._decode_nested_calls(
      File "/home/ubuntu/.local/lib/python3.8/site-packages/ethtx/decoders/abi/calls.py", line 237, in _decode_nested_calls
        self._decode_nested_calls(
      File "/home/ubuntu/.local/lib/python3.8/site-packages/ethtx/decoders/abi/calls.py", line 237, in _decode_nested_calls
        self._decode_nested_calls(
      File "/home/ubuntu/.local/lib/python3.8/site-packages/ethtx/decoders/abi/calls.py", line 237, in _decode_nested_calls
        self._decode_nested_calls(
      File "/home/ubuntu/.local/lib/python3.8/site-packages/ethtx/decoders/abi/calls.py", line 224, in _decode_nested_calls
        decoded = self.decode_call(
      File "/home/ubuntu/.local/lib/python3.8/site-packages/ethtx/decoders/abi/calls.py", line 194, in decode_call
        value=call.call_value / 10**18,
    OverflowError: integer division result too large for a float
    Traceback (most recent call last):
      File "ethtxdemo.py", line 18, in <module>
        transaction: DecodedTransaction = ethtx.decoders.decode_transaction('0x4f378f91bf16a26cff104aea5eceaa66c72d128dade84ddb619d40426f9780a0')
      File "/home/ubuntu/.local/lib/python3.8/site-packages/ethtx/ethtx.py", line 67, in decode_transaction
        return self._decoder_service.decode_transaction(chain_id, tx_hash)
      File "/home/ubuntu/.local/lib/python3.8/site-packages/ethtx/decoders/decoder_service.py", line 63, in decode_transaction
        abi_decoded_tx = self.abi_decoder.decode_transaction(
      File "/home/ubuntu/.local/lib/python3.8/site-packages/ethtx/decoders/abi/decoder.py", line 54, in decode_transaction
        full_decoded_transaction = self._decode_transaction(
      File "/home/ubuntu/.local/lib/python3.8/site-packages/ethtx/decoders/abi/decoder.py", line 180, in _decode_transaction
        raise e
      File "/home/ubuntu/.local/lib/python3.8/site-packages/ethtx/decoders/abi/decoder.py", line 171, in _decode_transaction
        full_decoded_transaction.calls = self.decode_calls(
      File "/home/ubuntu/.local/lib/python3.8/site-packages/ethtx/decoders/abi/decoder.py", line 68, in decode_calls
        return ABICallsDecoder(
      File "/home/ubuntu/.local/lib/python3.8/site-packages/ethtx/decoders/abi/calls.py", line 55, in decode
        calls_tree = self._decode_nested_calls(
      File "/home/ubuntu/.local/lib/python3.8/site-packages/ethtx/decoders/abi/calls.py", line 237, in _decode_nested_calls
        self._decode_nested_calls(
      File "/home/ubuntu/.local/lib/python3.8/site-packages/ethtx/decoders/abi/calls.py", line 237, in _decode_nested_calls
        self._decode_nested_calls(
      File "/home/ubuntu/.local/lib/python3.8/site-packages/ethtx/decoders/abi/calls.py", line 237, in _decode_nested_calls
        self._decode_nested_calls(
      File "/home/ubuntu/.local/lib/python3.8/site-packages/ethtx/decoders/abi/calls.py", line 224, in _decode_nested_calls
        decoded = self.decode_call(
      File "/home/ubuntu/.local/lib/python3.8/site-packages/ethtx/decoders/abi/calls.py", line 194, in decode_call
        value=call.call_value / 10**18,
    OverflowError: integer division result too large for a float
    

    I think maybe L194

    value=call.call_value / 10**18,
    

    could be replaced by

    value=Decimal(call.call_value) / 10**18,
    

    and a import should also be added.

    I will push a PR soon

    bug 
    opened by hitdavid 9
  • Getting started script not working

    Getting started script not working

    Just discovered this repo. Really interested to test it out.

    However, when I tried to run the 'Getting started1' script in README, I came across a few errors:

    Error 1:

    File "test.py", line 6
        mongo_database = "mongomock://localhost"
        ^
    SyntaxError: invalid syntax
    

    I got passed this by adding commas before each inline comment. Then I got another error:

    Error 2:

    Traceback (most recent call last):
      File "test.py", line 4, in <module>
        ethtx_config = EthTxConfig(
    TypeError: __init__() got an unexpected keyword argument 'mongo_database'
    

    I looked into ethtx.py and didn't see any mongo_database attribute. So I commented the mongo_database line out. Then I got another error:

    Error 3:

    Traceback (most recent call last):
      File "test.py", line 18, in <module>
        ethtx = EthTx.initialize(ethtx_config)
      File "/home/lsa/anaconda3/lib/python3.8/site-packages/ethtx/ethtx.py", line 122, in initialize
        repository = MongoSemanticsDatabase(db=mongo_client.get_database())
      File "/home/lsa/anaconda3/lib/python3.8/site-packages/mongomock/mongo_client.py", line 133, in get_database
        db = self.get_default_database(
      File "/home/lsa/anaconda3/lib/python3.8/site-packages/mongomock/mongo_client.py", line 151, in get_default_database
        raise ConfigurationError('No default database name defined or provided.')
    pymongo.errors.ConfigurationError: No default database name defined or provided.
    

    Can you advise if I am doing something incorrectly? Thanks.

    bug documentation 
    opened by 0x1355 5
  • Account balances not adding up for Eth for USDT transaction on UniswapV3

    Account balances not adding up for Eth for USDT transaction on UniswapV3

    So it seems that there is some bug with how multicalls are being handled.

    here https://etherscan.io/tx/0x093cdad6594e26543fdec775ddb99c6a761bace9512332a5aec50b38b39e92d9

    You see that I have received $126 USDT for .1 eth.

    However then the transaction is analyzed it does not seem to reflect that: https://ethtx.info/mainnet/0x093cdad6594e26543fdec775ddb99c6a761bace9512332a5aec50b38b39e92d9/

    Other tool seems to handle this better https://phalcon.blocksec.com/tx/eth/0x093cdad6594e26543fdec775ddb99c6a761bace9512332a5aec50b38b39e92d9.

    Anyone know if this is a bug... or am i just misinterpreting the result.

    bug 
    opened by lemiesz 4
  • gunicorn.errors.HaltServer: <HaltServer 'Worker failed to boot.' 3>

    gunicorn.errors.HaltServer:

    Version:0.3.1

    ethtx_ce_1       | [2021-10-15 13:09:57 +0000] [7] [INFO] Starting gunicorn 20.1.0
    ethtx_ce_1       | [2021-10-15 13:09:57 +0000] [7] [INFO] Listening at: http://0.0.0.0:5000 (7)
    ethtx_ce_1       | [2021-10-15 13:09:57 +0000] [7] [INFO] Using worker: sync
    ethtx_ce_1       | [2021-10-15 13:09:57 +0000] [14] [INFO] Booting worker with pid: 14
    ethtx_ce_1       | [2021-10-15 13:09:57 +0000] [15] [INFO] Booting worker with pid: 15
    ethtx_ce_1       | [2021-10-15 13:09:57 +0000] [16] [INFO] Booting worker with pid: 16
    ethtx_ce_1       | [2021-10-15 13:09:57 +0000] [17] [INFO] Booting worker with pid: 17
    ethtx_ce_1       | [2021-10-15 13:09:58 +0000] [14] [ERROR] Exception in worker process
    ethtx_ce_1       | Traceback (most recent call last):
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/arbiter.py", line 589, in spawn_worker
    ethtx_ce_1       |     worker.init_process()
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/workers/base.py", line 134, in init_process
    ethtx_ce_1       |     self.load_wsgi()
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/workers/base.py", line 146, in load_wsgi
    ethtx_ce_1       |     self.wsgi = self.app.wsgi()
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/app/base.py", line 67, in wsgi
    ethtx_ce_1       |     self.callable = self.load()
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/app/wsgiapp.py", line 58, in load
    ethtx_ce_1       |     return self.load_wsgiapp()
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/app/wsgiapp.py", line 48, in load_wsgiapp
    ethtx_ce_1       |     return util.import_app(self.app_uri)
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/util.py", line 359, in import_app
    ethtx_ce_1       |     mod = importlib.import_module(module)
    ethtx_ce_1       |   File "/usr/local/lib/python3.8/importlib/__init__.py", line 127, in import_module
    ethtx_ce_1       |     return _bootstrap._gcd_import(name[level:], package, level)
    ethtx_ce_1       |   File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
    ethtx_ce_1       |   File "<frozen importlib._bootstrap>", line 991, in _find_and_load
    ethtx_ce_1       |   File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
    ethtx_ce_1       |   File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
    ethtx_ce_1       |   File "<frozen importlib._bootstrap_external>", line 843, in exec_module
    ethtx_ce_1       |   File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
    ethtx_ce_1       |   File "/app/wsgi.py", line 23, in <module>
    ethtx_ce_1       |     ethtx_config = EthTxConfig(
    ethtx_ce_1       | TypeError: __init__() got an unexpected keyword argument 'mongo_database'
    ethtx_ce_1       | [2021-10-15 13:09:58 +0000] [14] [INFO] Worker exiting (pid: 14)
    ethtx_ce_1       | [2021-10-15 13:09:58 +0000] [15] [ERROR] Exception in worker process
    ethtx_ce_1       | Traceback (most recent call last):
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/arbiter.py", line 589, in spawn_worker
    ethtx_ce_1       |     worker.init_process()
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/workers/base.py", line 134, in init_process
    ethtx_ce_1       |     self.load_wsgi()
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/workers/base.py", line 146, in load_wsgi
    ethtx_ce_1       |     self.wsgi = self.app.wsgi()
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/app/base.py", line 67, in wsgi
    ethtx_ce_1       |     self.callable = self.load()
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/app/wsgiapp.py", line 58, in load
    ethtx_ce_1       |     return self.load_wsgiapp()
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/app/wsgiapp.py", line 48, in load_wsgiapp
    ethtx_ce_1       |     return util.import_app(self.app_uri)
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/util.py", line 359, in import_app
    ethtx_ce_1       |     mod = importlib.import_module(module)
    ethtx_ce_1       |   File "/usr/local/lib/python3.8/importlib/__init__.py", line 127, in import_module
    ethtx_ce_1       |     return _bootstrap._gcd_import(name[level:], package, level)
    ethtx_ce_1       |   File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
    ethtx_ce_1       |   File "<frozen importlib._bootstrap>", line 991, in _find_and_load
    ethtx_ce_1       |   File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
    ethtx_ce_1       |   File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
    ethtx_ce_1       |   File "<frozen importlib._bootstrap_external>", line 843, in exec_module
    ethtx_ce_1       |   File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
    ethtx_ce_1       |   File "/app/wsgi.py", line 23, in <module>
    ethtx_ce_1       |     ethtx_config = EthTxConfig(
    ethtx_ce_1       | TypeError: __init__() got an unexpected keyword argument 'mongo_database'
    ethtx_ce_1       | [2021-10-15 13:09:58 +0000] [15] [INFO] Worker exiting (pid: 15)
    ethtx_ce_1       | [2021-10-15 13:09:59 +0000] [7] [WARNING] Worker with pid 15 was terminated due to signal 15
    ethtx_ce_1       | [2021-10-15 13:09:59 +0000] [16] [ERROR] Exception in worker process
    ethtx_ce_1       | Traceback (most recent call last):
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/arbiter.py", line 589, in spawn_worker
    ethtx_ce_1       |     worker.init_process()
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/workers/base.py", line 134, in init_process
    ethtx_ce_1       |     self.load_wsgi()
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/workers/base.py", line 146, in load_wsgi
    ethtx_ce_1       |     self.wsgi = self.app.wsgi()
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/app/base.py", line 67, in wsgi
    ethtx_ce_1       |     self.callable = self.load()
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/app/wsgiapp.py", line 58, in load
    ethtx_ce_1       |     return self.load_wsgiapp()
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/app/wsgiapp.py", line 48, in load_wsgiapp
    ethtx_ce_1       |     return util.import_app(self.app_uri)
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/util.py", line 359, in import_app
    ethtx_ce_1       |     mod = importlib.import_module(module)
    ethtx_ce_1       |   File "/usr/local/lib/python3.8/importlib/__init__.py", line 127, in import_module
    ethtx_ce_1       |     return _bootstrap._gcd_import(name[level:], package, level)
    ethtx_ce_1       |   File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
    ethtx_ce_1       |   File "<frozen importlib._bootstrap>", line 991, in _find_and_load
    ethtx_ce_1       |   File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
    ethtx_ce_1       |   File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
    ethtx_ce_1       |   File "<frozen importlib._bootstrap_external>", line 843, in exec_module
    ethtx_ce_1       |   File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
    ethtx_ce_1       |   File "/app/wsgi.py", line 23, in <module>
    ethtx_ce_1       |     ethtx_config = EthTxConfig(
    ethtx_ce_1       | TypeError: __init__() got an unexpected keyword argument 'mongo_database'
    ethtx_ce_1       | [2021-10-15 13:09:59 +0000] [16] [INFO] Worker exiting (pid: 16)
    ethtx_ce_1       | [2021-10-15 13:09:59 +0000] [17] [ERROR] Exception in worker process
    ethtx_ce_1       | Traceback (most recent call last):
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/arbiter.py", line 589, in spawn_worker
    ethtx_ce_1       |     worker.init_process()
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/workers/base.py", line 134, in init_process
    ethtx_ce_1       |     self.load_wsgi()
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/workers/base.py", line 146, in load_wsgi
    ethtx_ce_1       |     self.wsgi = self.app.wsgi()
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/app/base.py", line 67, in wsgi
    ethtx_ce_1       |     self.callable = self.load()
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/app/wsgiapp.py", line 58, in load
    ethtx_ce_1       |     return self.load_wsgiapp()
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/app/wsgiapp.py", line 48, in load_wsgiapp
    ethtx_ce_1       |     return util.import_app(self.app_uri)
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/util.py", line 359, in import_app
    ethtx_ce_1       |     mod = importlib.import_module(module)
    ethtx_ce_1       |   File "/usr/local/lib/python3.8/importlib/__init__.py", line 127, in import_module
    ethtx_ce_1       |     return _bootstrap._gcd_import(name[level:], package, level)
    ethtx_ce_1       |   File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
    ethtx_ce_1       |   File "<frozen importlib._bootstrap>", line 991, in _find_and_load
    ethtx_ce_1       |   File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
    ethtx_ce_1       |   File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
    ethtx_ce_1       |   File "<frozen importlib._bootstrap_external>", line 843, in exec_module
    ethtx_ce_1       |   File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
    ethtx_ce_1       |   File "/app/wsgi.py", line 23, in <module>
    ethtx_ce_1       |     ethtx_config = EthTxConfig(
    ethtx_ce_1       | TypeError: __init__() got an unexpected keyword argument 'mongo_database'
    ethtx_ce_1       | [2021-10-15 13:09:59 +0000] [17] [INFO] Worker exiting (pid: 17)
    ethtx_ce_1       | Traceback (most recent call last):
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/arbiter.py", line 209, in run
    ethtx_ce_1       |     self.sleep()
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/arbiter.py", line 357, in sleep
    ethtx_ce_1       |     ready = select.select([self.PIPE[0]], [], [], 1.0)
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/arbiter.py", line 242, in handle_chld
    ethtx_ce_1       |     self.reap_workers()
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/arbiter.py", line 525, in reap_workers
    ethtx_ce_1       |     raise HaltServer(reason, self.WORKER_BOOT_ERROR)
    ethtx_ce_1       | gunicorn.errors.HaltServer: <HaltServer 'Worker failed to boot.' 3>
    ethtx_ce_1       | 
    ethtx_ce_1       | During handling of the above exception, another exception occurred:
    ethtx_ce_1       | 
    ethtx_ce_1       | Traceback (most recent call last):
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/bin/gunicorn", line 8, in <module>
    ethtx_ce_1       |     sys.exit(run())
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/app/wsgiapp.py", line 67, in run
    ethtx_ce_1       |     WSGIApplication("%(prog)s [OPTIONS] [APP_MODULE]").run()
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/app/base.py", line 231, in run
    ethtx_ce_1       |     super().run()
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/app/base.py", line 72, in run
    ethtx_ce_1       |     Arbiter(self).run()
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/arbiter.py", line 229, in run
    ethtx_ce_1       |     self.halt(reason=inst.reason, exit_status=inst.exit_status)
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/arbiter.py", line 342, in halt
    ethtx_ce_1       |     self.stop()
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/arbiter.py", line 393, in stop
    ethtx_ce_1       |     time.sleep(0.1)
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/arbiter.py", line 242, in handle_chld
    ethtx_ce_1       |     self.reap_workers()
    ethtx_ce_1       |   File "/root/.local/share/virtualenvs/app-4PlAip0Q/lib/python3.8/site-packages/gunicorn/arbiter.py", line 525, in reap_workers
    ethtx_ce_1       |     raise HaltServer(reason, self.WORKER_BOOT_ERROR)
    ethtx_ce_1       | gunicorn.errors.HaltServer: <HaltServer 'Worker failed to boot.' 3>
    ethtx_ce_ethtx_ce_1 exited with code 1
    
    opened by z3roTo0ne 3
  • Fix loss of precision decimal numbers

    Fix loss of precision decimal numbers

    Fixed the issue of loss of precision in the decimal representation of large floats. Converted float to Decimals and changed the precision of the context to 256 i.e. getcontext().prec = 256. Eventually returns the string representation of the Decimal object.

    This fixes the issue of scientific notation representation of floats both in Argument value field and also other fields in models from decoded_model.py

    opened by dudzicz 2
  • ENS lookup bug

    ENS lookup bug

    I was comparing ethtx output to other similar tools and found a case where ethtx resolves an incorrect ENS address.

    In ethtx.info, the offerer value is babywhale.eth. Clicking on babywhale.eth in ethtx uses the address 0x8af6e15ed513b5b73573f58158b1b0bbd5085ec7. But babywhale.eth on etherscan resolves to 0x9bf2eb61a3beb7afb1213029f3f1ae3e08ede755 https://ethtx.info/mainnet/0x665c4db0b7dcf44eb2ead3d455b12bfb244de9a2d3239d756ca3fbdbf21817bb/

    Meanwhile, two other transaction explorers (which don't support ENS resolution) show the value 0x8af6e15ed513b5b73573f58158b1b0bbd5085ec7 for the offerer https://phalcon.blocksec.com/tx/eth/0x665c4db0b7dcf44eb2ead3d455b12bfb244de9a2d3239d756ca3fbdbf21817bb https://tx.eth.samczsun.com/ethereum/0x665c4db0b7dcf44eb2ead3d455b12bfb244de9a2d3239d756ca3fbdbf21817bb

    0x8af6e15ed513b5b73573f58158b1b0bbd5085ec7 does hold two ENS addresses, but babywhale.eth is not one of them, so the wrong ENS address is getting displayed.

    bug 
    opened by engn33r 1
  • More flexible dependencies, no cursor timeout, cache 4bytes

    More flexible dependencies, no cursor timeout, cache 4bytes

    • Make more flexible deps - ethtx is easier to install in other apps
    • No timeout for mongo cursor - some collections may sometimes require more time to search
    • Cache 4bytes resposne, if some transactions have a lot of guessed functions/events, it definitely speeds up ethtx!
    • Fix README mongo string
    opened by kchojn 1
  • Port and standardization models with `pydantic`

    Port and standardization models with `pydantic`

    • all models now use pydantic
    • fix types in models
    • removed jsonpickle
    • extend function end event models
    • changing the order of methods in DecoderService
    • update requirements
    • add tests
    • fix bug with empty args from 4byte
    • update Readme
    • strip node URL from env
    opened by kchojn 1
  • Bug in tx data decoding (token transfers & account balances sections)

    Bug in tx data decoding (token transfers & account balances sections)

    Referring to this tx on etherscan, address 0x8c3FA50473065f1D90f186cA8ba1Aa76Aee409Bb is receiving 0.01 eth but as per the tx on ethtx.info the address is sending out the same amount.

    The emitted events show it as a donation sent event which would indicate the aforementioned address should be the recipient of the amount rather than the one sending it, and hence, I'm inclined to believe that the decoding on etherscan is correct and ethtx's isn't.

    I tried to make some more sense of the data and these points might help with debugging the issue: 0x8c3f.. is a gnosis safe multisig. Ethtx shows 0x8c3f.. is sending the eth to 0x34cf.., this recipient is actually the gnosis safe mastercopy contract. I think this is where the problem lies. this mastercopy be receiving the funds from the multisig doesn't seem right to me

    bug 
    opened by shreyjain711 2
  • Account balances broken for specific transaction

    Account balances broken for specific transaction

    opened by franz101 0
  • feat: erc1155 support

    feat: erc1155 support

    Tested with tx: 0x9848cc10366cf7dde89861a6ae5e1166e7d1edb6cd245c2592679848959f168c Decoded tx (removed block and tx metadata):

    events=[DecodedEvent(chain_id='mainnet', tx_hash='0x9848cc10366cf7dde89861a6ae5e1166e7d1edb6cd245c2592679848959f168c', timestamp=datetime.datetime(2021, 12, 13, 12, 16, 50), contract=AddressInfo(address='0x348fc118bcc65a92dc033a951af153d14d945312', name='Mintvial', badge='receiver'), index=261, call_id=None, event_signature='0xc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62', event_name='TransferSingle', parameters=[Argument(name='operator', type='address', value=AddressInfo(address='0x9e7c078f8da492d80d567705d0dd12dbfffd65ea', name='0x9e7c078f8da492d80d567705d0dd12dbfffd65ea', badge='sender')), Argument(name='from', type='address', value=AddressInfo(address='0x9e7c078f8da492d80d567705d0dd12dbfffd65ea', name='0x9e7c078f8da492d80d567705d0dd12dbfffd65ea', badge='sender')), Argument(name='to', type='address', value=AddressInfo(address='0x0000000000000000000000000000000000000000', name='0x0000000000000000000000000000000000000000', badge=None)), Argument(name='id', type='uint256', value=913), Argument(name='value', type='uint256', value=1)], event_guessed=False), DecodedEvent(chain_id='mainnet', tx_hash='0x9848cc10366cf7dde89861a6ae5e1166e7d1edb6cd245c2592679848959f168c', timestamp=datetime.datetime(2021, 12, 13, 12, 16, 50), contract=AddressInfo(address='0x49cf6f5d44e70224e2e23fdcdd2c053f30ada28b', name='CloneX', badge=None), index=262, call_id=None, event_signature='0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', event_name='Transfer', parameters=[Argument(name='from', type='address', value=AddressInfo(address='0x0000000000000000000000000000000000000000', name='0x0000000000000000000000000000000000000000', badge=None)), Argument(name='to', type='address', value=AddressInfo(address='0x9e7c078f8da492d80d567705d0dd12dbfffd65ea', name='0x9e7c078f8da492d80d567705d0dd12dbfffd65ea', badge='sender')), Argument(name='tokenId', type='nft', value={'address': '0x49cf6f5d44e70224e2e23fdcdd2c053f30ada28b?a=14609#inventory', 'name': 'NFT 14609'})], event_guessed=False), DecodedEvent(chain_id='mainnet', tx_hash='0x9848cc10366cf7dde89861a6ae5e1166e7d1edb6cd245c2592679848959f168c', timestamp=datetime.datetime(2021, 12, 13, 12, 16, 50), contract=AddressInfo(address='0x49cf6f5d44e70224e2e23fdcdd2c053f30ada28b', name='CloneX', badge=None), index=263, call_id=None, event_signature='0x2ce54db2c0bc64dc675f5fae90636ec2f0c88dbd8e7c6a19c9caca9193741b15', event_name='CloneXRevealed', parameters=[Argument(name='tokenId', type='uint256', value=14609), Argument(name='fileId', type='string', value='13192')], event_guessed=False)] calls=DecodedCall(chain_id='mainnet', timestamp=datetime.datetime(2021, 12, 13, 12, 16, 50), tx_hash='0x9848cc10366cf7dde89861a6ae5e1166e7d1edb6cd245c2592679848959f168c', call_id='', call_type='call', from_address=AddressInfo(address='0x9e7c078f8da492d80d567705d0dd12dbfffd65ea', name='0x9e7c078f8da492d80d567705d0dd12dbfffd65ea', badge='sender'), to_address=AddressInfo(address='0x348fc118bcc65a92dc033a951af153d14d945312', name='Mintvial', badge='receiver'), value=0.0, function_signature='0x5f6be614', function_name='migrateToken', arguments=[Argument(name='id', type='uint256', value=913)], outputs=[Argument(name='', type='uint256', value=14609)], gas_used=164970, error=None, status=True, indent=0, subcalls=[DecodedCall(chain_id='mainnet', timestamp=datetime.datetime(2021, 12, 13, 12, 16, 50), tx_hash='0x9848cc10366cf7dde89861a6ae5e1166e7d1edb6cd245c2592679848959f168c', call_id='0', call_type='call', from_address=AddressInfo(address='0x348fc118bcc65a92dc033a951af153d14d945312', name='Mintvial', badge='receiver'), to_address=AddressInfo(address='0x49cf6f5d44e70224e2e23fdcdd2c053f30ada28b', name='CloneX', badge=None), value=0.0, function_signature='0x937f2608', function_name='mintTransfer', arguments=[Argument(name='to', type='address', value=AddressInfo(address='0x9e7c078f8da492d80d567705d0dd12dbfffd65ea', name='0x9e7c078f8da492d80d567705d0dd12dbfffd65ea', badge='sender'))], outputs=[Argument(name='', type='uint256', value=14609)], gas_used=148545, error=None, status=True, indent=1, subcalls=[DecodedCall(chain_id='mainnet', timestamp=datetime.datetime(2021, 12, 13, 12, 16, 50), tx_hash='0x9848cc10366cf7dde89861a6ae5e1166e7d1edb6cd245c2592679848959f168c', call_id='0_0000', call_type='staticcall', from_address=AddressInfo(address='0x49cf6f5d44e70224e2e23fdcdd2c053f30ada28b', name='CloneX', badge=None), to_address=AddressInfo(address='0xffc4dbeace02c578cc189004c0ad25eeb8d8ba3f', name='CloneXRandomizer', badge=None), value=0.0, function_signature='0x14ff5ea3', function_name='getTokenId', arguments=[Argument(name='tokenId', type='uint256', value=14609)], outputs=[Argument(name='', type='string', value='13192')], gas_used=8473, error=None, status=True, indent=2, subcalls=[], function_guessed=False)], function_guessed=False)], function_guessed=False) transfers=[DecodedTransfer(from_address=AddressInfo(address='0x9e7c078f8da492d80d567705d0dd12dbfffd65ea', name='0x9e7c078f8da492d80d567705d0dd12dbfffd65ea', badge='sender'), to_address=AddressInfo(address='0x0000000000000000000000000000000000000000', name='0x0000000000000000000000000000000000000000', badge=None), token_address='0x348fc118bcc65a92dc033a951af153d14d945312?a=913#inventory', token_symbol='NFT 913', token_standard='ERC1155', value='1.0000'), DecodedTransfer(from_address=AddressInfo(address='0x0000000000000000000000000000000000000000', name='0x0000000000000000000000000000000000000000', badge=None), to_address=AddressInfo(address='0x9e7c078f8da492d80d567705d0dd12dbfffd65ea', name='0x9e7c078f8da492d80d567705d0dd12dbfffd65ea', badge='sender'), token_address='0x49cf6f5d44e70224e2e23fdcdd2c053f30ada28b?a=14609#inventory', token_symbol='NFT 14609', token_standard='ERC721', value='1.0000')] balances=[DecodedBalance(holder=AddressInfo(address='0x9e7c078f8da492d80d567705d0dd12dbfffd65ea', name='0x9e7c078f8da492d80d567705d0dd12dbfffd65ea', badge='sender'), tokens=[{'token_address': '0x348fc118bcc65a92dc033a951af153d14d945312?a=913#inventory', 'token_symbol': 'NFT 913', 'token_standard': 'ERC1155', 'balance': '-1.0000'}, {'token_address': '0x49cf6f5d44e70224e2e23fdcdd2c053f30ada28b?a=14609#inventory', 'token_symbol': 'NFT 14609', 'token_standard': 'ERC721', 'balance': '1.0000'}])] status=True
    

    Fixes #125

    feature 
    opened by 0xbhoori 0
Releases(0.3.21)
Spacegit is a .git exposed finder

Spacegit Spacegit is a basic .git exposed finder Usage: You need python3 installed to run spacegit use: python3 spacegit.py (url) Disclaimer: **This i

2 Nov 30, 2021
Casefy (/keɪsfaɪ/) is a lightweight Python package to convert the casing of strings

Casefy (/keɪsfaɪ/) is a lightweight Python package to convert the casing of strings. It has no third-party dependencies and supports Unicode.

Diego Miguel Lozano 12 Jan 08, 2023
UUID version 7, which are time-sortable (following the Peabody RFC4122 draft)

uuid7 - time-sortable UUIDs This module implements the version 7 UUIDs, proposed by Peabody and Davis in https://www.ietf.org/id/draft-peabody-dispatc

Steve Simmons 22 Dec 20, 2022
✨ Voici un code en Python par moi, et en français qui permet de générer du texte Lorem.

Lorem Gen ❗ Voici un code en Python par moi, et en français qui permet de générer du texte Lorem. Dépendences : pip install lorem_text 💖 Enjoy 🎫 Mon

MrGabin 3 Jun 07, 2021
A repo for working with and building daos

DAO Mix DAO Mix About How to DAO No Code Tools Getting Started Prerequisites Installation Usage On-Chain Governance Example Off-Chain governance Examp

Brownie Mixes 86 Dec 19, 2022
A Python script that parses and checks public proxies. Multithreading is supported.

A Python script that parses and checks public proxies. Multithreading is supported.

LevPrav 7 Nov 25, 2022
Attempts to crack the compression puzzle.

The Compression Puzzle One lovely Friday we were faced with this nice yet intriguing programming puzzle. One shall write a program that compresses str

Oto Brglez 14 Dec 29, 2022
A thing to simplify listening for PG notifications with asyncpg

A thing to simplify listening for PG notifications with asyncpg

ANNA 18 Dec 23, 2022
A simple package for handling variables in string.

A simple package for handling string variables. Welcome! This is a simple package for handling variables in string, You can add or remove variables wi

1 Dec 31, 2021
Multipurpose Growtopia Server tools, can be used for newbie to learn things.

Information Multipurpose Growtopia Server tools, can be used for newbie to learn things. Requirements - Python 3.x - Operating System (Recommended : W

Morphias 2 Oct 29, 2021
A Python script that transcript Arcaea chart file (.aff file) into AutoJS touchscreen script which automatically plays the Arcaea chart

ArcaeaAutoplay (AutoJS Version) A Python script that transcript Arcaea chart file (.aff file) into AutoJS touchscreen script which automatically plays

7 Dec 03, 2021
Simplex using Jordan exchanges taught in 236A

Simplex for 236A Python script to solve LP using simplex by Jordan exchanges taught in 236A. You will need python installed along with the 'numpy' and

Kunal Kishore 1 Nov 30, 2021
Definitely legit social credit generator with python

definitely-legit-social-credit-generator I made this simple GUI program for a meme, no cap. Video: https://youtu.be/RmjxKtoli04 How to run: Clone this

Joshua Malabanan 8 Nov 01, 2021
Python script to get some stats on nodes in a Blender material nodetree

Python script to get some stats on nodes in a Blender material nodetree. It counts the nodes, the node types and the max deep level for group nodes.

Alek Mugnozzo 2 Sep 03, 2022
Just some scripts to export vector tiles to geojson.

Vector tiles to GeoJSON Nowadays modern web maps are usually based on vector tiles. The great thing about vector tiles is, that they are not just imag

Lilith Wittmann 77 Jul 26, 2022
Automatically Generate Rulesets for IIS for Intelligent HTTP/S C2 Redirection

Automatically Generate Rulesets for IIS for Intelligent HTTP/S C2 Redirection This project converts a Cobalt Strike profile to a functional web.config

Jesse 99 Dec 13, 2022
Small project to interact with python, C, HTML, JavaScript, PHP.

Micro Hidroponic Small project to interact with python, C, HTML, JavaScript, PHP. Table of Contents General Info Technologies Used Screenshots Usage P

Filipe Martins 1 Nov 10, 2021
Color getter (including method to get random color or complementary color) made out of Python

python-color-getter Color getter (including method to get random color or complementary color) made out of Python Setup pip3 install git+https://githu

Jung Gyu Yoon 2 Sep 17, 2022
Helpful functions for use alongside the rich Python library.

🔧 Rich Tools A python package with helpful functions for use alongside with the rich python library. 󠀠󠀠 The current features are: Convert a Pandas

Avi Perl 14 Oct 14, 2022
Numbers-parser - Python module for parsing Apple Numbers .numbers files

numbers-parser numbers-parser is a Python module for parsing Apple Numbers .numbers files. It supports Numbers files generated by Numbers version 10.3

Jon Connell 154 Jan 05, 2023