Skip to content

Commit

Permalink
Adding database managed transaction broadcast
Browse files Browse the repository at this point in the history
  • Loading branch information
miohtama committed Nov 28, 2018
1 parent 2fe419d commit 1ad4ef8
Show file tree
Hide file tree
Showing 14 changed files with 667 additions and 58 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,5 @@ registrar.json

# Created by pytest
.pytest_cache

*.sqlite
50 changes: 45 additions & 5 deletions corporategovernance/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"""
import logging
import os
import sys

import configobj
Expand All @@ -11,6 +12,7 @@
import click
import click_config_file
import coloredlogs
from corporategovernance.db import setup_database


class UnknownConfiguredNetwork(Exception):
Expand Down Expand Up @@ -38,12 +40,14 @@ def create_command_line_logger(log_level):
# Config file docs: https://github.com/phha/click_config_file
@click.group()
@click.option('--config-file', required=False, default="ethereum")
@click.option('--database-file', required=False, default="transactions.sqlite")
@click.option('--network', required=False, default="ethereum")
@click.option('--ethereum-node-url', required=False, default="http://localhost:8545")
@click.option('--ethereum-contract-abi', required=False)
@click.option('--ethereum-abi-file', required=False)
@click.option('--ethereum-gas-price', required=False)
@click.option('--ethereum-gas-limit', required=False)
@click.option('--ethereum-private-key', required=False)
@click.option('--ethereum-contract-name', required=False, default="contracts/security-token/SecurityToken.sol")
@click.option('--log-level', default="INFO")
@click.pass_context
def cli(ctx, config_file, **kwargs):
Expand All @@ -54,6 +58,10 @@ def cli(ctx, config_file, **kwargs):

# Fill in arguments from the configuration file
if config_file:

if not os.path.exists(config_file):
sys.exit("Config file does not exist {}".format(config_file))

config = configobj.ConfigObj(config_file, raise_errors=True)

# TODO: Bug here - could not figure out how to pull out from click if an option is set on a command line or are we using default.
Expand All @@ -68,23 +76,55 @@ def cli(ctx, config_file, **kwargs):
kwargs[opt.name] = config_file_value # TODO: opt.process_value

log_level = kwargs["log_level"]

config = BoardCommmadConfiguration(**kwargs)
config.logger = create_command_line_logger(log_level.upper())
logger = config.logger = create_command_line_logger(log_level.upper())

# Mute SQLAlchemy logger who is quite a verbose friend otherwise
sa_logger = logging.getLogger("sqlalchemy")
sa_logger.setLevel(logging.WARN)

dbfile = os.path.abspath(config.database_file)
config.dbsession = setup_database(dbfile)
ctx.obj = config

version = pkg_resources.require("corporategovernance")[0].version
copyright = "Copyright TokenMarket Ltd. 2018"
config.logger.info("Corporate governance tool for security tokens, version %s - %s", version, copyright)
logger.info("Corporate governance tool for security tokens, version %s - %s", version, copyright)
logger.info("Using database %s", dbfile)



# click subcommand docs
@cli.command()
@click.option('--symbol', required=True)
@click.option('--name', required=True)
@click.option('--amount', required=True)
def issue(ctx, symbol, name, amount):
pass
@click.option('--transfer-restriction', required=False, default="unrestricted")
@click.pass_obj
def issue(config: BoardCommmadConfiguration, symbol, name, amount, transfer_restriction):
"""Issue out a new security token."""

logger = config.logger

assert config.network == "ethereum" # Nothing else implemented yet

from corporategovernance.ethereum.issuance import deploy_token_contracts

dbsession = config.dbsession

deploy_token_contracts(logger,
dbsession,
config.network,
ethereum_node_url=config.ethereum_node_url,
ethereum_abi_file=config.ethereum_abi_file,
ethereum_private_key=config.ethereum_private_key,
ethereum_gas_limit=config.ethereum_gas_limit,
ethereum_gas_price=config.ethereum_gas_price,
name=name,
symbol=symbol,
amount=amount,
transfer_restriction=transfer_restriction)

@cli.command()
@click.option('--address', required=True)
Expand Down
26 changes: 26 additions & 0 deletions corporategovernance/db.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import os

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

from .models.implementation import Base


def setup_database(db_filename):

# https://docs.sqlalchemy.org/en/latest/dialects/sqlite.html
url = "sqlite+pysqlite:///" + db_filename

engine = create_engine(url, echo=False)

if not os.path.exists(url):
init_db(engine)

Session = sessionmaker(bind=engine)
session = Session()
return session


def init_db(engine):
Base.metadata.create_all(engine)

4 changes: 0 additions & 4 deletions corporategovernance/ethereum/diagnostics.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@ class NeedMoney(Exception):
pass


class NeedPrivateKey(Exception):
pass


def diagnose(logger: Logger, node_url: str, private_key_hex: str) -> Optional[Exception]:
"""Run Ethereum connection and account diagnostics.
Expand Down
66 changes: 66 additions & 0 deletions corporategovernance/ethereum/issuance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"""Issuing out tokenised shares."""
from logging import Logger

from corporategovernance.ethereum.manifest import get_package
from corporategovernance.ethereum.txservice import EthereumStoredTXService
from corporategovernance.ethereum.utils import get_abi, check_good_private_key
from corporategovernance.models.implementation import BroadcastAccount, PreparedTransaction
from sqlalchemy.orm import Session
from web3 import Web3, HTTPProvider
from web3.contract import Contract


def deploy_token_contracts(logger: Logger,
dbsession: Session,
network: str,
ethereum_node_url: str,
ethereum_abi_file: str,
ethereum_private_key: str,
ethereum_gas_limit: str,
ethereum_gas_price: str,
name: str,
symbol: str,
amount: int,
transfer_restriction: str):
"""Issue out a new Ethereum token."""

check_good_private_key(ethereum_private_key)

abi = get_abi(ethereum_abi_file)

web3 = Web3(HTTPProvider(ethereum_node_url))

# We do not have anything else implemented yet
assert transfer_restriction == "unrestricted"

service = EthereumStoredTXService(network, dbsession, web3, ethereum_private_key, ethereum_gas_price, ethereum_gas_limit, BroadcastAccount, PreparedTransaction)

# Deploy security token
note = "Token contract for {}".format(name)
deploy_tx1 = service.deploy_contract("SecurityToken", abi, note, constructor_args={"_name": name, "_symbol": symbol}) # See SecurityToken.sol

# Deploy transfer agent
note = "Unrestricted transfer manager for {}".format(name)
deploy_tx1 = service.deploy_contract("UnrestrictedTransferAgent", abi, note)

# Set transfer agent
note = "Setting security token transfer manager for {}".format(name)
contract_address = deploy_tx1.contract_address
update_tx1 = service.interact_with_contract("SecurityToken", abi, contract_address, note, "setTransactionVerifier", {"newVerifier": deploy_tx1.contract_address})

# Issue out initial shares
note = "Creating {} initial shares for {}".format(amount, name)
contract_address = deploy_tx1.contract_address
amount_18 = amount * 10**18
update_tx2 = service.interact_with_contract("SecurityToken", abi, contract_address, note, "issueTokens", {"value": amount_18})

logger.info("Prepared transactions for broadcasting")









28 changes: 0 additions & 28 deletions corporategovernance/ethereum/issue.py

This file was deleted.

Loading

0 comments on commit 1ad4ef8

Please sign in to comment.