示例#1
0
def token_asset(dbsession, eth_network_id, deposit_address,
                eth_service: EthereumService) -> UUID:
    """Database asset referring to the token contract.

    deposit_address will hold 10000 tokens

    :return: Asset id
    """

    with transaction.manager:
        network = dbsession.query(AssetNetwork).get(eth_network_id)
        asset = network.create_asset(name="MyToken",
                                     symbol="MY",
                                     supply=Decimal(10000),
                                     asset_class=AssetClass.token)
        address = CryptoAddress.get_network_address(
            network, eth_address_to_bin(deposit_address))
        op = address.create_token(asset)
        opid = op.id
        aid = asset.id

    # This gives op a txid
    success, fails = eth_service.run_waiting_operations()
    assert success == 1

    wait_for_op_confirmations(eth_service, opid)

    with transaction.manager:
        network = dbsession.query(AssetNetwork).get(eth_network_id)
        asset = dbsession.query(Asset).get(aid)
        address = CryptoAddress.get_network_address(
            network, eth_address_to_bin(deposit_address))
        account = address.get_account(asset)
        assert account.account.get_balance() > 0
        return aid
示例#2
0
def token_asset(dbsession, eth_network_id, deposit_address, eth_service: EthereumService) -> UUID:
    """Database asset referring to the token contract.

    deposit_address will hold 10000 tokens

    :return: Asset id
    """

    with transaction.manager:
        network = dbsession.query(AssetNetwork).get(eth_network_id)
        asset = network.create_asset(name="MyToken", symbol="MY", supply=Decimal(10000), asset_class=AssetClass.token)
        address = CryptoAddress.get_network_address(network, eth_address_to_bin(deposit_address))
        op = address.create_token(asset)
        opid = op.id
        aid = asset.id

    # This gives op a txid
    success, fails = eth_service.run_waiting_operations()
    assert success == 1

    wait_for_op_confirmations(eth_service, opid)

    with transaction.manager:
        network = dbsession.query(AssetNetwork).get(eth_network_id)
        asset = dbsession.query(Asset).get(aid)
        address = CryptoAddress.get_network_address(network, eth_address_to_bin(deposit_address))
        account = address.get_account(asset)
        assert account.account.get_balance() > 0
        return aid
def test_starter_token(dbsession, registry, eth_network_id, web3: Web3, eth_service: EthereumService, house_address, toybox):
    """See that a fresh user account is supplied with some play assets."""

    with transaction.manager:
        user = create_user(dbsession, registry)
        setup_user_account(user)

    # Let all the events completed
    success, fail = eth_service.run_event_cycle()
    assert success == 1
    assert fail == 0

    # We need another event cycle to process the initial asset transfers
    with transaction.manager:
        user = dbsession.query(User).first()
        opid = user.user_data["starter_asset_txs"][0]["toybox"]
        assert opid

    wait_for_op_confirmations(eth_service, opid)

    # Let the transfer come through
    eth_service.run_event_cycle()

    # Make sure we confirm the deposit
    with transaction.manager:
        user = dbsession.query(User).first()
        user_depo = user.owned_crypto_operations.join(CryptoOperation).filter_by(operation_type=CryptoOperationType.deposit).first()
        opid = user_depo.crypto_operation.id

    wait_for_op_confirmations(eth_service, opid)

    with transaction.manager:

        # Sanity check our token contract posts us logs
        user = dbsession.query(User).first()
        client = get_rpc_client(web3)
        asset = dbsession.query(Asset).get(toybox)
        address = bin_to_eth_address(asset.external_id)
        network = dbsession.query(AssetNetwork).get(eth_network_id)
        user_address = UserCryptoAddress.get_default(user, network).address
        house_address = dbsession.query(CryptoAddress).get(house_address)
        house = bin_to_eth_address(house_address.address)
        token = Token.get(web3, address)

        # Check we correctly resolved low level logs
        token_logs = client.get_logs(from_block=0, address=[address])
        wallet_logs = client.get_logs(from_block=0, address=[house])
        assert len(token_logs) > 0
        assert len(wallet_logs) > 0

        # Check contract state matches
        assert token.contract.call().balanceOf(house) == 9990
        assert token.contract.call().balanceOf(bin_to_eth_address(user_address.address)) == 10

        # Check our internal book keeping matches
        assert house_address.get_account(asset).account.get_balance() == 9990
        assert user_address.get_account(asset).account.get_balance() == 10
def test_deposit_eth(dbsession, eth_network_id, web3, eth_service, coinbase, deposit_address):
    """Accept incoming deposit."""

    # Do a transaction over ETH network

    txid = send_balance_to_address(web3, deposit_address, TEST_VALUE)
    confirm_transaction(web3, txid)

    success_op_count, failed_op_count = eth_service.run_listener_operations()
    assert success_op_count == 1
    assert failed_op_count == 0

    # We get a operation, which is not resolved yet due to block confirmation numbers
    with transaction.manager:

        # Account not yet updated
        address = dbsession.query(CryptoAddress).filter_by(address=eth_address_to_bin(deposit_address)).one()
        eth_asset = get_ether_asset(dbsession)
        assert address.get_account(eth_asset).account.get_balance() == 0

        # We have one ETH account on this address
        assert address.crypto_address_accounts.count() == 1

        # We have one pending operation
        ops = list(dbsession.query(CryptoOperation).all())
        assert len(ops) == 2  # Create + deposit
        op = ops[-1]
        assert isinstance(op, CryptoAddressDeposit)
        assert op.holding_account.get_balance() == TEST_VALUE
        assert op.completed_at is None
        opid = op.id

    # Wait that we reach critical confirmation count
    wait_for_op_confirmations(eth_service, opid)

    # Now account shoult have been settled
    with transaction.manager:

        # We have one complete operation
        ops = list(dbsession.query(CryptoOperation).all())
        assert len(ops) == 2  # Create + deposit
        op = ops[-1]
        assert isinstance(op, CryptoAddressDeposit)
        assert op.holding_account.get_balance() == 0
        assert op.completed_at is not None

        address = dbsession.query(CryptoAddress).filter_by(address=eth_address_to_bin(deposit_address)).one()

        # We have one ETH account on this address
        assert address.crypto_address_accounts.count() == 1

        # We have one credited account
        eth_asset = get_ether_asset(dbsession)
        caccount = address.get_account(eth_asset)
        assert caccount.account.get_balance() == TEST_VALUE
        assert op.state == CryptoOperationState.success
def test_deposit_eth(dbsession, eth_network_id, web3, eth_service, coinbase, deposit_address):
    """Accept incoming deposit."""

    # Do a transaction over ETH network

    txid = send_balance_to_address(web3, deposit_address, TEST_VALUE)
    confirm_transaction(web3, txid)

    success_op_count, failed_op_count = eth_service.run_listener_operations()
    assert success_op_count == 1
    assert failed_op_count == 0

    # We get a operation, which is not resolved yet due to block confirmation numbers
    with transaction.manager:

        # Account not yet updated
        address = dbsession.query(CryptoAddress).filter_by(address=eth_address_to_bin(deposit_address)).one()
        eth_asset = get_ether_asset(dbsession)
        assert address.get_account(eth_asset).account.get_balance() == 0

        # We have one ETH account on this address
        assert address.crypto_address_accounts.count() == 1

        # We have one pending operation
        ops = list(dbsession.query(CryptoOperation).all())
        assert len(ops) == 2  # Create + deposit
        op = ops[-1]
        assert isinstance(op, CryptoAddressDeposit)
        assert op.holding_account.get_balance() == TEST_VALUE
        assert op.completed_at is None
        opid = op.id

    # Wait that we reach critical confirmation count
    wait_for_op_confirmations(eth_service, opid)

    # Now account shoult have been settled
    with transaction.manager:

        # We have one complete operation
        ops = list(dbsession.query(CryptoOperation).all())
        assert len(ops) == 2  # Create + deposit
        op = ops[-1]
        assert isinstance(op, CryptoAddressDeposit)
        assert op.holding_account.get_balance() == 0
        assert op.completed_at is not None

        address = dbsession.query(CryptoAddress).filter_by(address=eth_address_to_bin(deposit_address)).one()

        # We have one ETH account on this address
        assert address.crypto_address_accounts.count() == 1

        # We have one credited account
        eth_asset = get_ether_asset(dbsession)
        caccount = address.get_account(eth_asset)
        assert caccount.account.get_balance() == TEST_VALUE
        assert op.state == CryptoOperationState.success
def test_create_token(dbsession, eth_network_id, eth_service, coinbase, deposit_address):
    """Test user initiated token creation."""

    # Initiate token creation operation
    with transaction.manager:
        network = dbsession.query(AssetNetwork).get(eth_network_id)
        asset = network.create_asset(name="MyToken", symbol="MY", supply=Decimal(10000), asset_class=AssetClass.token)
        address = CryptoAddress.get_network_address(network, eth_address_to_bin(deposit_address))
        op = address.create_token(asset)
        opid = op.id
        aid = asset.id
        assert op.completed_at is None

        # Check asset is intact
        assert asset.symbol == "MY"
        assert asset.supply == 10000
        assert asset.name == "MyToken"

    # This gives op a txid when smart contract creation tx is posted to geth
    success_count, failure_count = eth_service.run_waiting_operations()
    assert success_count == 1
    assert failure_count == 0

    # Check that initial asset data is in place
    with transaction.manager:
        op = dbsession.query(CryptoOperation).get(opid)
        network = dbsession.query(AssetNetwork).get(eth_network_id)
        address = CryptoAddress.get_network_address(network, eth_address_to_bin(deposit_address))
        asset = network.get_asset(aid)

        assert op.txid
        assert not op.block
        assert op.broadcasted_at is not None
        assert op.completed_at is None

        # Initial balance doesn't hit us until tx has been confirmed
        assert address.get_account(asset).account.get_balance() == 0

        # Asset has received its smart contract address
        assert asset.external_id

    # Wait that the smart contract creation is confirmed
    wait_for_op_confirmations(eth_service, opid)

    # Initial balance doesn't hit us until op has enough confirmations
    with transaction.manager:
        op = dbsession.query(CryptoOperation).get(opid)
        network = dbsession.query(AssetNetwork).get(eth_network_id)
        address = CryptoAddress.get_network_address(network, eth_address_to_bin(deposit_address))
        asset = network.get_asset(aid)

        assert op.broadcasted_at is not None
        assert op.completed_at is not None
        assert address.get_account(asset).account.get_balance() == 10000
def test_create_token(dbsession, eth_network_id, eth_service, coinbase, deposit_address):
    """Test user initiated token creation."""

    # Initiate token creation operation
    with transaction.manager:
        network = dbsession.query(AssetNetwork).get(eth_network_id)
        asset = network.create_asset(name="MyToken", symbol="MY", supply=Decimal(10000), asset_class=AssetClass.token)
        address = CryptoAddress.get_network_address(network, eth_address_to_bin(deposit_address))
        op = address.create_token(asset)
        opid = op.id
        aid = asset.id
        assert op.completed_at is None

        # Check asset is intact
        assert asset.symbol == "MY"
        assert asset.supply == 10000
        assert asset.name == "MyToken"

    # This gives op a txid when smart contract creation tx is posted to geth
    success_count, failure_count = eth_service.run_waiting_operations()
    assert success_count == 1
    assert failure_count == 0

    # Check that initial asset data is in place
    with transaction.manager:
        op = dbsession.query(CryptoOperation).get(opid)
        network = dbsession.query(AssetNetwork).get(eth_network_id)
        address = CryptoAddress.get_network_address(network, eth_address_to_bin(deposit_address))
        asset = network.get_asset(aid)

        assert op.txid
        assert not op.block
        assert op.broadcasted_at is not None
        assert op.completed_at is None

        # Initial balance doesn't hit us until tx has been confirmed
        assert address.get_account(asset).account.get_balance() == 0

        # Asset has received its smart contract address
        assert asset.external_id

    # Wait that the smart contract creation is confirmed
    wait_for_op_confirmations(eth_service, opid)

    # Initial balance doesn't hit us until op has enough confirmations
    with transaction.manager:
        op = dbsession.query(CryptoOperation).get(opid)
        network = dbsession.query(AssetNetwork).get(eth_network_id)
        address = CryptoAddress.get_network_address(network, eth_address_to_bin(deposit_address))
        asset = network.get_asset(aid)

        assert op.broadcasted_at is not None
        assert op.completed_at is not None
        assert address.get_account(asset).account.get_balance() == 10000
示例#8
0
def test_starter_eth(dbsession, registry, eth_network_id, web3: Web3,
                     eth_service: EthereumService, house_address, starter_eth):
    """Test the user gets some starter ETH when signing up."""

    with transaction.manager:
        user = create_user(dbsession, registry)
        setup_user_account(user, do_mainnet=True)

    # Let all the events completed
    success, fail = eth_service.run_event_cycle()
    assert success >= 1
    assert fail == 0

    # When op is confirmed, the user account is correctly credited
    with transaction.manager:
        user = dbsession.query(User).first()
        txid = user.user_data["starter_asset_txs"][0]["eth"]

    confirm_transaction(web3, txid)

    # Let the transfer come through
    eth_service.run_event_cycle()

    with transaction.manager:
        user = dbsession.query(User).first()
        client = get_rpc_client(web3)
        asset = get_ether_asset(dbsession)
        ua = user.owned_crypto_addresses.first()
        address = bin_to_eth_address(ua.address.address)

        # Sanity check we get events from starter deposit
        logs = client.get_logs(from_block=0, address=[address])

        ops = list(user.owned_crypto_operations)

        # The event was processed on log level
        assert len(logs) == 1

        # The last user operation is deposit
        depo = ops[-1]
        assert isinstance(depo.crypto_operation, CryptoAddressDeposit)
        opid = depo.crypto_operation.id

    # Wait deposit to confirm
    wait_for_op_confirmations(eth_service, opid)

    with transaction.manager:
        # User ETH balance is expected
        asset = get_ether_asset(dbsession)
        user = dbsession.query(User).first()
        ua = user.owned_crypto_addresses.first()
        caccout = ua.address.get_account(asset)
        assert caccout.account.get_balance() == Decimal("0.1")
def test_starter_eth(dbsession, registry, eth_network_id, web3: Web3, eth_service: EthereumService, house_address, starter_eth):
    """Test the user gets some starter ETH when signing up."""

    with transaction.manager:
        user = create_user(dbsession, registry)
        setup_user_account(user)

    # Let all the events completed
    success, fail = eth_service.run_event_cycle()
    assert success >= 1
    assert fail == 0

    # When op is confirmed, the user account is correctly credited
    with transaction.manager:
        user = dbsession.query(User).first()
        txid = user.user_data["starter_asset_txs"][0]["eth"]

    confirm_transaction(web3, txid)

    # Let the transfer come through
    eth_service.run_event_cycle()

    with transaction.manager:
        user = dbsession.query(User).first()
        client = get_rpc_client(web3)
        asset = get_ether_asset(dbsession)
        ua = user.owned_crypto_addresses.first()
        address = bin_to_eth_address(ua.address.address)

        # Sanity check we get events from starter deposit
        logs = client.get_logs(from_block=0, address=[address])

        ops = list(user.owned_crypto_operations)

        # The event was processed on log level
        assert len(logs) == 1

        # The last user operation is deposit
        depo = ops[-1]
        assert isinstance(depo.crypto_operation, CryptoAddressDeposit)
        opid = depo.crypto_operation.id

    # Wait deposit to confirm
    wait_for_op_confirmations(eth_service, opid)

    with transaction.manager:
        # User ETH balance is expected
        asset = get_ether_asset(dbsession)
        user = dbsession.query(User).first()
        ua = user.owned_crypto_addresses.first()
        caccout = ua.address.get_account(asset)
        assert caccout.account.get_balance() == Decimal("0.1")
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
def test_withdraw_token(dbsession, eth_network_id, web3: Web3, eth_service: EthereumService, deposit_address: str, token_asset: str, target_account: str):
    """"See that we can withdraw token outside to an account."""

    with transaction.manager:
        address = dbsession.query(CryptoAddress).filter_by(address=eth_address_to_bin(deposit_address)).one()
        asset = dbsession.query(Asset).get(token_asset)
        caccount = address.get_account(asset)

        op = caccount.withdraw(Decimal(2000), eth_address_to_bin(target_account), "Sending to friend")
        opid = op.id

        assert caccount.account.get_balance() == 8000

    # Run import token operation
    success_count, failure_count = eth_service.run_waiting_operations()
    assert success_count == 1
    assert failure_count == 0

    # TX was broadcasted, marked as complete
    with transaction.manager:
        op = dbsession.query(CryptoOperation).get(opid)
        assert isinstance(op, CryptoAddressWithdraw)
        asset = dbsession.query(Asset).get(token_asset)
        assert op.broadcasted_at
        assert not op.completed_at

    wait_for_op_confirmations(eth_service, opid)

    # After tx has been mined the new balances should match
    with transaction.manager:
        op = dbsession.query(CryptoOperation).get(opid)
        assert op.broadcasted_at
        assert op.completed_at
        asset = dbsession.query(Asset).get(token_asset)

        # Tokens have been removed on from account
        token = Token.get(web3, bin_to_eth_address(asset.external_id))
        assert token.contract.call().balanceOf(deposit_address) == 8000

        # Tokens have been credited on to account
        token = Token.get(web3, bin_to_eth_address(asset.external_id))
        assert token.contract.call().balanceOf(target_account) == 2000
def test_withdraw_token(dbsession, eth_network_id, web3: Web3, eth_service: EthereumService, deposit_address: str, token_asset: str, target_account: str):
    """"See that we can withdraw token outside to an account."""

    with transaction.manager:
        address = dbsession.query(CryptoAddress).filter_by(address=eth_address_to_bin(deposit_address)).one()
        asset = dbsession.query(Asset).get(token_asset)
        caccount = address.get_account(asset)

        op = caccount.withdraw(Decimal(2000), eth_address_to_bin(target_account), "Sending to friend")
        opid = op.id

        assert caccount.account.get_balance() == 8000

    # Run import token operation
    success_count, failure_count = eth_service.run_waiting_operations()
    assert success_count == 1
    assert failure_count == 0

    # TX was broadcasted, marked as complete
    with transaction.manager:
        op = dbsession.query(CryptoOperation).get(opid)
        assert isinstance(op, CryptoAddressWithdraw)
        asset = dbsession.query(Asset).get(token_asset)
        assert op.broadcasted_at
        assert not op.completed_at

    wait_for_op_confirmations(eth_service, opid)

    with transaction.manager:
        op = dbsession.query(CryptoOperation).get(opid)
        assert op.broadcasted_at
        assert op.completed_at
        asset = dbsession.query(Asset).get(token_asset)

        # Tokens have been removed on from account
        token = Token.get(web3, bin_to_eth_address(asset.external_id))
        assert token.contract.call().balanceOf(deposit_address) == 8000

        # Tokens have been credited on to account
        token = Token.get(web3, bin_to_eth_address(asset.external_id))
        assert token.contract.call().balanceOf(target_account) == 2000
def test_transfer_tokens_between_accounts(dbsession, eth_network_id, web3: Web3, eth_service: EthereumService, deposit_address: str, token_asset: str, coinbase: str):
    """Transfer tokens between two internal accounts.

    Do transfers in two batches to make sure subsequent events top up correctly.
    """

    # Initiate a target address creatin
    with transaction.manager:
        network = dbsession.query(AssetNetwork).get(eth_network_id)
        opid = CryptoAddress.create_address(network).id

    # Run address creation
    success_count, failure_count = eth_service.run_waiting_operations()
    assert success_count == 1
    assert failure_count == 0

    # We resolved address creation operation.
    # Get the fresh address for the future withdraw targets.
    with transaction.manager:
        op = dbsession.query(CryptoAddressCreation).get(opid)
        addr = op.address.address
        assert addr

    # Move tokens between accounts
    with transaction.manager:
        address = dbsession.query(CryptoAddress).filter_by(address=eth_address_to_bin(deposit_address)).one()
        asset = dbsession.query(Asset).get(token_asset)
        caccount = address.get_account(asset)

        op = caccount.withdraw(Decimal(2000), addr, "Sending to friend")
        opid = op.id

    # Resolve the 1st transaction
    eth_service.run_event_cycle()
    wait_for_op_confirmations(eth_service, opid)

    # See that our internal balances match
    with transaction.manager:

        # Withdraw operation is complete
        op = dbsession.query(CryptoOperation).get(opid)
        assert op.completed_at
        assert op.completed_at, "Op not confirmed {}".format(op)

        # We should have received a Transfer operation targetting target account
        op = dbsession.query(CryptoOperation).join(CryptoAddressAccount).join(CryptoAddress).filter_by(address=addr).one()
        opid = op.id

    # Confirm incoming Transfer
    wait_for_op_confirmations(eth_service, opid, timeout=180)

    # Check Transfer looks valid
    with transaction.manager:
        op = dbsession.query(CryptoOperation).get(opid)
        assert op.completed_at
        assert op.completed_at, "Op not confirmed {}".format(op)

        asset = dbsession.query(Asset).get(token_asset)
        source = dbsession.query(CryptoAddress).filter_by(address=eth_address_to_bin(deposit_address)).one()
        target = dbsession.query(CryptoAddress).filter_by(address=addr).one()

        assert source.get_account(asset).account.get_balance() == 8000
        assert target.get_account(asset).account.get_balance() == 2000

    # Add some ETH on deposit_address
    txid = send_balance_to_address(web3, deposit_address, TEST_VALUE)
    confirm_transaction(web3, txid)
    eth_service.run_event_cycle()

    # Wait for confirmations to have ETH deposit credired
    with transaction.manager:
        op = dbsession.query(CryptoOperation).filter_by(txid=txid_to_bin(txid)).one()
        opid = op.id
        confirmed = op.completed_at
    if not confirmed:
        wait_for_op_confirmations(eth_service, opid)

    # Send some more tokens + ether, so we see account can't get mixed up
    with transaction.manager:
        address = dbsession.query(CryptoAddress).filter_by(address=eth_address_to_bin(deposit_address)).one()
        asset = dbsession.query(Asset).get(token_asset)
        caccount = address.get_account(asset)

        op = caccount.withdraw(Decimal(4000), addr, "Sending tokens to friend äää")

        eth_asset = get_ether_asset(dbsession)
        caccount = address.get_account(eth_asset)
        op = caccount.withdraw(TEST_VALUE, addr, "Sending ETH to friend äää")
        opid = op.id

    # Resolve second transaction
    eth_service.run_event_cycle()
    wait_for_op_confirmations(eth_service, opid)

    # See that our internal balances match
    with transaction.manager:
        op = dbsession.query(CryptoOperation).get(opid)
        assert op.completed_at
        assert op.completed_at
        asset = dbsession.query(Asset).get(token_asset)
        source = dbsession.query(CryptoAddress).filter_by(address=eth_address_to_bin(deposit_address)).one()
        target = dbsession.query(CryptoAddress).filter_by(address=addr).one()
        eth_asset = get_ether_asset(dbsession)

        assert source.get_account(asset).account.get_balance() == 4000
        assert target.get_account(asset).account.get_balance() == 6000
        assert target.get_account(eth_asset).account.get_balance() == TEST_VALUE

    # Transfer 3:
    # Send everything back plus some ether
    with transaction.manager:
        address = dbsession.query(CryptoAddress).filter_by(address=addr).one()
        asset = dbsession.query(Asset).get(token_asset)
        caccount = address.get_account(asset)

        op = caccount.withdraw(Decimal(6000), eth_address_to_bin(deposit_address), "Sending everything back to friend äää")
        opid = op.id

    # Resolve third transaction
    wait_for_op_confirmations(eth_service, opid)
    eth_service.run_event_cycle()

    # See that our internal balances match
    with transaction.manager:
        op = dbsession.query(CryptoOperation).get(opid)
        assert op.completed_at
        assert op.completed_at
        asset = dbsession.query(Asset).get(token_asset)
        source = dbsession.query(CryptoAddress).filter_by(address=eth_address_to_bin(deposit_address)).one()
        target = dbsession.query(CryptoAddress).filter_by(address=addr).one()

        assert source.get_account(asset).account.get_balance() == 10000
        assert target.get_account(asset).account.get_balance() == 0

        eth_asset = get_ether_asset(dbsession)
        assert source.get_account(eth_asset).account.get_balance() == 0
        assert target.get_account(eth_asset).account.get_balance() == TEST_VALUE
def test_transfer_tokens_between_accounts(dbsession, eth_network_id, web3: Web3, eth_service: EthereumService, deposit_address: str, token_asset: str, coinbase: str):
    """Transfer tokens between two internal accounts.

    Do transfers in two batches to make sure subsequent events top up correctly.
    """

    # Initiate a target address creatin
    with transaction.manager:
        network = dbsession.query(AssetNetwork).get(eth_network_id)
        opid = CryptoAddress.create_address(network).id

    # Run address creation
    success_count, failure_count = eth_service.run_waiting_operations()
    assert success_count == 1
    assert failure_count == 0

    # We resolved address creation operation.
    # Get the fresh address for the future withdraw targets.
    with transaction.manager:
        op = dbsession.query(CryptoAddressCreation).get(opid)
        addr = op.address.address
        assert addr

    # Move tokens between accounts
    with transaction.manager:
        address = dbsession.query(CryptoAddress).filter_by(address=eth_address_to_bin(deposit_address)).one()
        asset = dbsession.query(Asset).get(token_asset)
        caccount = address.get_account(asset)

        op = caccount.withdraw(Decimal(2000), addr, "Sending to friend")
        opid = op.id

    # Resolve the 1st transaction
    eth_service.run_event_cycle()
    wait_for_op_confirmations(eth_service, opid)

    # See that our internal balances match
    with transaction.manager:

        # Withdraw operation is complete
        op = dbsession.query(CryptoOperation).get(opid)
        assert op.completed_at
        assert op.completed_at, "Op not confirmed {}".format(op)

        # We should have received a Transfer operation targetting target account
        op = dbsession.query(CryptoOperation).join(CryptoAddressAccount).join(CryptoAddress).filter_by(address=addr).one()
        opid = op.id

    # Confirm incoming Transfer
    wait_for_op_confirmations(eth_service, opid, timeout=180)

    # Check Transfer looks valid
    with transaction.manager:
        op = dbsession.query(CryptoOperation).get(opid)
        assert op.completed_at
        assert op.completed_at, "Op not confirmed {}".format(op)

        asset = dbsession.query(Asset).get(token_asset)
        source = dbsession.query(CryptoAddress).filter_by(address=eth_address_to_bin(deposit_address)).one()
        target = dbsession.query(CryptoAddress).filter_by(address=addr).one()

        assert source.get_account(asset).account.get_balance() == 8000
        assert target.get_account(asset).account.get_balance() == 2000

    # Add some ETH on deposit_address
    txid = send_balance_to_address(web3, deposit_address, TEST_VALUE)
    confirm_transaction(web3, txid)
    eth_service.run_event_cycle()

    # Wait for confirmations to have ETH deposit credired
    with transaction.manager:
        op = dbsession.query(CryptoOperation).filter_by(txid=txid_to_bin(txid)).one()
        opid = op.id
        confirmed = op.completed_at
    if not confirmed:
        wait_for_op_confirmations(eth_service, opid)

    # Send some more tokens + ether, so we see account can't get mixed up
    with transaction.manager:
        address = dbsession.query(CryptoAddress).filter_by(address=eth_address_to_bin(deposit_address)).one()
        asset = dbsession.query(Asset).get(token_asset)
        caccount = address.get_account(asset)

        op = caccount.withdraw(Decimal(4000), addr, "Sending tokens to friend äää")

        eth_asset = get_ether_asset(dbsession)
        caccount = address.get_account(eth_asset)
        op = caccount.withdraw(TEST_VALUE, addr, "Sending ETH to friend äää")
        opid = op.id

    # Resolve second transaction
    eth_service.run_event_cycle()
    wait_for_op_confirmations(eth_service, opid)

    # See that our internal balances match
    with transaction.manager:
        op = dbsession.query(CryptoOperation).get(opid)
        assert op.completed_at
        assert op.completed_at
        asset = dbsession.query(Asset).get(token_asset)
        source = dbsession.query(CryptoAddress).filter_by(address=eth_address_to_bin(deposit_address)).one()
        target = dbsession.query(CryptoAddress).filter_by(address=addr).one()
        eth_asset = get_ether_asset(dbsession)

        assert source.get_account(asset).account.get_balance() == 4000
        assert target.get_account(asset).account.get_balance() == 6000
        assert target.get_account(eth_asset).account.get_balance() == TEST_VALUE

    # Transfer 3:
    # Send everything back plus some ether
    with transaction.manager:
        address = dbsession.query(CryptoAddress).filter_by(address=addr).one()
        asset = dbsession.query(Asset).get(token_asset)
        caccount = address.get_account(asset)

        op = caccount.withdraw(Decimal(6000), eth_address_to_bin(deposit_address), "Sending everything back to friend äää")
        opid = op.id

    # Resolve third transaction
    wait_for_op_confirmations(eth_service, opid)
    eth_service.run_event_cycle()

    # See that our internal balances match
    with transaction.manager:
        op = dbsession.query(CryptoOperation).get(opid)
        assert op.completed_at
        assert op.completed_at
        asset = dbsession.query(Asset).get(token_asset)
        source = dbsession.query(CryptoAddress).filter_by(address=eth_address_to_bin(deposit_address)).one()
        target = dbsession.query(CryptoAddress).filter_by(address=addr).one()

        assert source.get_account(asset).account.get_balance() == 10000
        assert target.get_account(asset).account.get_balance() == 0

        eth_asset = get_ether_asset(dbsession)
        assert source.get_account(eth_asset).account.get_balance() == 0
        assert target.get_account(eth_asset).account.get_balance() == TEST_VALUE
示例#16
0
def test_starter_token(dbsession, registry, eth_network_id, web3: Web3,
                       eth_service: EthereumService, house_address, toybox):
    """See that a fresh user account is supplied with some play assets."""

    with transaction.manager:
        user = create_user(dbsession, registry)
        setup_user_account(user, do_mainnet=True)

    # Let all the events completed
    success, fail = eth_service.run_event_cycle()
    assert success == 1
    assert fail == 0

    # We need another event cycle to process the initial asset transfers
    with transaction.manager:
        user = dbsession.query(User).first()
        opid = user.user_data["starter_asset_txs"][0]["toybox"]
        assert opid

    wait_for_op_confirmations(eth_service, opid)

    # Let the transfer come through
    eth_service.run_event_cycle()

    # Make sure we confirm the deposit
    with transaction.manager:
        user = dbsession.query(User).first()
        user_depo = user.owned_crypto_operations.join(
            CryptoOperation).filter_by(
                operation_type=CryptoOperationType.deposit).first()
        opid = user_depo.crypto_operation.id

    wait_for_op_confirmations(eth_service, opid)

    with transaction.manager:

        # Sanity check our token contract posts us logs
        user = dbsession.query(User).first()
        client = get_rpc_client(web3)
        asset = dbsession.query(Asset).get(toybox)
        address = bin_to_eth_address(asset.external_id)
        network = dbsession.query(AssetNetwork).get(eth_network_id)
        user_address = UserCryptoAddress.get_default(user, network).address
        house_address = dbsession.query(CryptoAddress).get(house_address)
        house = bin_to_eth_address(house_address.address)
        token = Token.get(web3, address)

        # Check we correctly resolved low level logs
        token_logs = client.get_logs(from_block=0, address=[address])
        wallet_logs = client.get_logs(from_block=0, address=[house])
        assert len(token_logs) > 0
        assert len(wallet_logs) > 0

        # Check contract state matches
        assert token.contract.call().balanceOf(house) == 9990
        assert token.contract.call().balanceOf(
            bin_to_eth_address(user_address.address)) == 10

        # Check our internal book keeping matches
        assert house_address.get_account(asset).account.get_balance() == 9990
        assert user_address.get_account(asset).account.get_balance() == 10