def distribute_tokens(logger: Logger, dbsession: Session, network: str, ethereum_node_url: Union[str, Web3], ethereum_abi_file: Optional[str], ethereum_private_key: Optional[str], ethereum_gas_limit: Optional[int], ethereum_gas_price: Optional[int], token_address: str, dists: List[DistributionEntry]) -> Tuple[int, int]: """Sends tokens to their first owners in primary markets.""" check_good_private_key(ethereum_private_key) abi = get_abi(ethereum_abi_file) web3 = create_web3(ethereum_node_url) service = EthereumStoredTXService(network, dbsession, web3, ethereum_private_key, ethereum_gas_price, ethereum_gas_limit, BroadcastAccount, PreparedTransaction) logger.info( "Starting creating distribution transactions for %s token from nonce %s", token_address, service.get_next_nonce()) total = sum([dist.amount * 10**18 for dist in dists]) available = service.get_raw_token_balance(token_address, abi) if total > available: raise NotEnoughTokens( "Not enough tokens for distribution. Account {} has {} raw token balance, needed {}" .format(service.get_or_create_broadcast_account().address, available, total)) new_distributes = old_distributes = 0 for d in tqdm(dists): if not service.is_distributed(d.external_id, token_address): # Going to tx queue raw_amount = int(d.amount * 10**18) note = "Distributing tokens, raw amount: {}".format(raw_amount) service.distribute_tokens(d.external_id, d.address, raw_amount, token_address, abi, note) new_distributes += 1 else: # CSV reimports old_distributes += 1 logger.info("Prepared transactions for broadcasting for network %s", network) return new_distributes, old_distributes
def distribute_single(logger: Logger, dbsession: Session, network: str, ethereum_node_url: Union[str, Web3], ethereum_abi_file: Optional[str], ethereum_private_key: Optional[str], ethereum_gas_limit: Optional[int], ethereum_gas_price: Optional[int], token_address: str, ext_id: str, email: str, name: str, to_address: str, amount: Decimal) -> bool: """Send out a single transfer. :return: True if a new tx for broadcasting was created """ d = DistributionEntry(ext_id, email, name, to_address, amount) check_good_private_key(ethereum_private_key) abi = get_abi(ethereum_abi_file) web3 = create_web3(ethereum_node_url) service = EthereumStoredTXService(network, dbsession, web3, ethereum_private_key, ethereum_gas_price, ethereum_gas_limit, BroadcastAccount, PreparedTransaction) logger.info( "Starting creating distribution transactions for %s token from nonce %s", token_address, service.get_next_nonce()) total = d.amount * 10**18 available = service.get_raw_token_balance(token_address, abi) if total > available: raise NotEnoughTokens( "Not enough tokens for distribution. Account {} has {} raw token balance, needed {}" .format(service.get_or_create_broadcast_account().address, available, total)) if not service.is_distributed(d.external_id, token_address): # Going to tx queue raw_amount = int(d.amount * 10**18) note = "Distributing tokens, raw amount: {}".format(raw_amount) service.distribute_tokens(d.external_id, d.address, raw_amount, token_address, abi, note) logger.info("New broadcast has been created") return True else: logger.error("Already distributed") return False
def deploy_token_contracts( logger: Logger, dbsession: Session, network: str, ethereum_node_url: Union[str, Web3], ethereum_abi_file: Optional[str], ethereum_private_key: Optional[str], ethereum_gas_limit: Optional[int], ethereum_gas_price: Optional[int], name: str, symbol: str, amount: int, transfer_restriction: str): """Issue out a new Ethereum token.""" assert type(amount) == int decimals = 18 # Everything else is bad idea check_good_private_key(ethereum_private_key) abi = get_abi(ethereum_abi_file) web3 = create_web3(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) logger.info("Starting creating transactions from nonce %s", service.get_next_nonce()) # Deploy security token note = "Deploying 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 = "Deploying unrestricted transfer policy for {}".format(name) deploy_tx2 = service.deploy_contract("UnrestrictedTransferAgent", abi, note) # Set transfer agent note = "Whitelisting deployment account for {} issuer control".format(name) contract_address = deploy_tx1.contract_address update_tx1 = service.interact_with_contract( "SecurityToken", abi, contract_address, note, "addAddressToWhitelist", {"addr": deploy_tx1.get_from()}) # Set transfer agent note = "Making transfer restriction policy for {} effective".format(name) contract_address = deploy_tx1.contract_address update_tx2 = service.interact_with_contract( "SecurityToken", abi, contract_address, note, "setTransactionVerifier", {"newVerifier": deploy_tx2.contract_address}) # Issue out initial shares note = "Creating {} initial shares for {}".format(amount, name) contract_address = deploy_tx1.contract_address amount_18 = int(amount * 10**decimals) update_tx3 = service.interact_with_contract("SecurityToken", abi, contract_address, note, "issueTokens", {"value": amount_18}) logger.info("Prepared transactions for broadcasting for network %s", network) logger.info("STO token contract address is %s%s%s", colorama.Fore.LIGHTGREEN_EX, deploy_tx1.contract_address, colorama.Fore.RESET) return [deploy_tx1, deploy_tx2, update_tx1, update_tx2, update_tx3]