def test_buy_crowdfund_not_enough_gas(dbsession: Session, eth_network_id: UUID, web3: Web3, eth_service: EthereumService, token, toycrowd, withdraw_address): """Perform a crowdfundn buy operation without giving enough gas for the transaction.""" with transaction.manager: # Create withdraw operation caccount = dbsession.query(CryptoAddressAccount).one() # Use 4 as the heurestics for block account that doesn't happen right away, but still sensible to wait for it soonish asset = toycrowd() caccount.withdraw(Decimal(0.005), asset.external_id, "Buying Toycrowd", required_confirmation_count=1) print("Withdrawing") success_op_count, failed_op_count = eth_service.run_waiting_operations() assert success_op_count == 1 assert failed_op_count == 0 with transaction.manager: ops = list(dbsession.query(CryptoOperation).all()) assert len(ops) == 3 # Create + deposit + withdraw op = ops[-1] txid = bin_to_txid(op.txid) # This should make the tx to included in a block confirm_transaction(web3, txid) # This should trigger incoming notification eth_service.run_listener_operations() # Now we should get block number for the withdraw updates, failures = eth_service.run_confirmation_updates() assert failures == 1 with transaction.manager: op = dbsession.query(CryptoOperation).all()[-1] assert op.is_failed() assert "gas" in op.get_failure_reason()
def test_deposit_token(dbsession, eth_network_id, web3: Web3, eth_service: EthereumService, coinbase: str, deposit_address: str, token: Token): """"See that we can deposit tokens to accounts.""" # Import a contract where coinbase has all balance with transaction.manager: network = dbsession.query(AssetNetwork).get(eth_network_id) import_token(network, eth_address_to_bin(token.address)) # Run import token operation success_count, failure_count = eth_service.run_waiting_operations() assert success_count == 1 assert failure_count == 0 # Coinbase transfers token balance to deposit address txid = token.transfer(deposit_address, Decimal(4000)) confirm_transaction(web3, txid) # We should pick up incoming deposit success_count, failure_count = eth_service.run_listener_operations() assert success_count == 1 assert failure_count == 0 # Check that data is setup correctly on incoming transaction with transaction.manager: op = dbsession.query(CryptoOperation).all()[-1] opid = op.id assert not op.completed_at address = dbsession.query(CryptoAddress).filter_by(address=eth_address_to_bin(deposit_address)).one() asset = op.holding_account.asset assert op.holding_account.get_balance() == 4000 assert op.completed_at is None assert address.get_account(asset).account.get_balance() == 0 # Not credited until confirmations reached assert address.crypto_address_accounts.count() == 1 # Wait the token transaction to get enough confirmations wait_for_op_confirmations(eth_service, opid) # Check that the transaction is not final with transaction.manager: op = dbsession.query(CryptoOperation).get(opid) assert op.completed_at assert op.completed_at address = dbsession.query(CryptoAddress).filter_by(address=eth_address_to_bin(deposit_address)).one() asset = op.holding_account.asset assert op.holding_account.get_balance() == 0 assert address.get_account(asset).account.get_balance() == 4000 assert op.state == CryptoOperationState.success
def withdraw_address(web3: Web3, dbsession, eth_service: EthereumService, coinbase, deposit_address) -> str: """Create a managed hosted wallet that has withdraw balance for testing.""" txid = send_balance_to_address(web3, deposit_address, TEST_VALUE) confirm_transaction(web3, txid) assert web3.eth.getBalance(deposit_address) > 0 success_op_count, failed_op_count = eth_service.run_listener_operations() assert success_op_count == 1 assert failed_op_count == 0 with transaction.manager: # We bypass normal transction confirmation count mechanism to credit the account right away to speed up the test deposit = dbsession.query(CryptoAddressDeposit).one() deposit.resolve() return deposit_address
def withdraw_address(web3: Web3, dbsession, eth_service: EthereumService, coinbase, deposit_address) -> str: """Create a managed hosted wallet that has withdraw balance for testing.""" # Do a transaction over ETH network txid = send_balance_to_address(web3, deposit_address, TEST_VALUE) confirm_transaction(web3, txid) assert web3.eth.getBalance(deposit_address) > 0 success_op_count, failed_op_count = eth_service.run_listener_operations() assert success_op_count == 1 assert failed_op_count == 0 with transaction.manager: # We bypass normal transction confirmation count mechanism to credit the account right away to speed up the test deposit = dbsession.query(CryptoAddressDeposit).one() deposit.resolve() return deposit_address
def test_buy_crowdfund_with_gas(dbsession: Session, eth_network_id: UUID, web3: Web3, eth_service: EthereumService, token, toycrowd, rich_withdraw_address): """Perform a crowdfunnd buy operation without giving enough gas for the transaction.""" with transaction.manager: # Create withdraw operation caccount = dbsession.query(CryptoAddressAccount).one() # Use 4 as the heurestics for block account that doesn't happen right away, but still sensible to wait for it soonish asset = toycrowd() op = caccount.withdraw(Decimal(3), asset.external_id, "Buying Toycrowd", required_confirmation_count=1) op.other_data["gas"] = 2500333 # Limit should be ~100k success_op_count, failed_op_count = eth_service.run_waiting_operations() assert failed_op_count == 0 assert success_op_count == 1 with transaction.manager: ops = list(dbsession.query(CryptoOperation).all()) assert len(ops) == 3 # Create + deposit + withdraw op = ops[-1] txid = bin_to_txid(op.txid) # This should make the tx to included in a block confirm_transaction(web3, txid) # Set op.block eth_service.run_confirmation_updates() # Grab block number where out tx is with transaction.manager: ops = list(dbsession.query(CryptoOperation).all()) op = ops[-1] block_num = op.block wallet = get_wallet(web3, rich_withdraw_address) token_events = token.get_all_events() wallet_events = wallet.get_all_events() # Confirm we got it all right receipt = web3.eth.getTransactionReceipt(txid) logs = receipt["logs"] assert logs[0]["topics"][0] == token_events["Buy"] assert logs[1]["topics"][0] == token_events["Transfer"] assert logs[2]["topics"][0] == wallet_events["Withdraw"] data = get_crowdsale_data(token) assert data["wei_raised"] == to_wei("3", "ether") # Give tx time to confirm, so all confirmations will be there for db update run required_conf = 3 wait_for_block_number(web3, block_num + required_conf + 1, timeout=60) # This should trigger incoming notification eth_service.run_listener_operations() updates, failures = eth_service.run_confirmation_updates() assert failures == 0 assert updates == 2 # 1 eth withdraw, 1 token deposit # Check our db is updated with transaction.manager: # There is now new operation to deposit tokens ops = list(dbsession.query(CryptoOperation).all()) assert len(ops) == 4 op = ops[-1] # type: CryptoOperation assert op.operation_type == CryptoOperationType.deposit assert op.state == CryptoOperationState.success assert op.amount == 6 asset = toycrowd() crypto_address = dbsession.query(CryptoAddress).one() # type: CryptoAddress caccount = crypto_address.get_account(asset) assert caccount.account.get_balance() == 6