예제 #1
0
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 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
예제 #4
0
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
예제 #5
0
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
예제 #6
0
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