Beispiel #1
0
def create_address(web3: Web3, dbsession: Session, opid: UUID):
    """User requests new hosted address.

    We create a hosted wallet contract. The contract id is associated with the user in the database. We hold the the only owner address of the wallet.

    The wallet code is based on https://github.com/ethereum/meteor-dapp-wallet/blob/master/Wallet.sol
    """

    assert isinstance(opid, UUID)

    @retryable(tm=dbsession.transaction_manager)
    def finish_op():
        op = dbsession.query(CryptoOperation).get(opid)
        txid = wallet.initial_txid
        receipt = web3.eth.getTransactionReceipt(txid)

        op.txid = txid_to_bin(txid)
        op.block = receipt["blockNumber"]
        op.address.address = eth_address_to_bin(wallet.address)
        op.external_address = op.address.address

        # There is no broadcast wait, so we can close this right away
        op.mark_performed()
        op.mark_broadcasted()
        op.mark_complete()

    logger.info("Starting wallet creation for %s", opid)
    wallet = HostedWallet.create(web3)
    logger.info("Updating db for wallet creation for %s", opid)
    finish_op()
Beispiel #2
0
def create_address(web3: Web3, dbsession: Session, opid: UUID):
    """User requests new hosted address.

    We create a hosted wallet contract. The contract id is associated with the user in the database. We hold the the only owner address of the wallet.

    The wallet code is based on https://github.com/ethereum/meteor-dapp-wallet/blob/master/Wallet.sol
    """

    assert isinstance(opid, UUID)

    @retryable(tm=dbsession.transaction_manager)
    def finish_op():
        op = dbsession.query(CryptoOperation).get(opid)
        txid = wallet.initial_txid
        receipt = web3.eth.getTransactionReceipt(txid)

        op.txid = txid_to_bin(txid)
        op.block = receipt["blockNumber"]
        op.address.address = eth_address_to_bin(wallet.address)
        op.external_address = op.address.address

        # There is no broadcast wait, so we can close this right away
        op.mark_performed()
        op.mark_broadcasted()
        op.mark_complete()

    logger.info("Starting wallet creation for %s", opid)
    wallet = HostedWallet.create(web3)
    logger.info("Updating db for wallet creation for %s", opid)
    finish_op()
Beispiel #3
0
 def setup_listeners(self):
     """Setup subsystems that scan for incoming events from geth."""
     wallet_contract = HostedWallet.contract_class(self.web3)
     token_contract = Token.contract_class(self.web3)
     self.eth_wallet_listener = EthWalletListener(self.web3, wallet_contract, self.dbsession, self.asset_network_id, registry=self.registry)
     self.eth_token_listener = EthTokenListener(self.web3, token_contract, self.dbsession, self.asset_network_id, registry=self.registry)
     self.confirmation_updater = DatabaseConfirmationUpdater(self.web3, self.dbsession, self.asset_network_id, self.registry)
     self.op_queue_manager = OperationQueueManager(self.web3, self.dbsession, self.asset_network_id, self.registry)
Beispiel #4
0
    def setup_listeners(self):
        """Setup subsystems that scan for incoming events from geth."""
        wallet_contract = HostedWallet.contract_class(self.web3)
        token_contract = Token.contract_class(self.web3)

        self.eth_wallet_listener = EthWalletListener(self.web3, wallet_contract, self.dbsession, self.asset_network_id, registry=self.registry)

        self.eth_token_listener = EthTokenListener(self.web3, token_contract, self.dbsession, self.asset_network_id, registry=self.registry)

        self.confirmation_updater = DatabaseConfirmationUpdater(self.web3, self.dbsession, self.asset_network_id, self.registry)
        self.op_queue_manager = OperationQueueManager(self.web3, self.dbsession, self.asset_network_id, self.registry)
Beispiel #5
0
def hosted_wallet(web3: Web3, coinbase: str) -> HostedWallet:
    """Deploy a smart contract to local private blockchain so test functions can stress it out.

    :param client: py.test fixture to create RPC client to call geth node

    :param geth_node: py.test fixture to spin up geth node with test network parameters

    :param coinbase: Ethereum account number for coinbase account where our mined ETHs appear

    :return: 0x prefixed hexadecimal address of the deployed contract
    """

    return HostedWallet.create(web3)
Beispiel #6
0
def hosted_wallet(web3: Web3, coinbase: str) -> HostedWallet:
    """Deploy a smart contract to local private blockchain so test functions can stress it out.

    :param client: py.test fixture to create RPC client to call geth node

    :param geth_node: py.test fixture to spin up geth node with test network parameters

    :param coinbase: Ethereum account number for coinbase account where our mined ETHs appear

    :return: 0x prefixed hexadecimal address of the deployed contract
    """

    return HostedWallet.create(web3, contract_name="Wallet2")
Beispiel #7
0
def withdraw_token(web3: Web3, dbsession: Session, opid: UUID):
    """Perform token withdraw operation from the wallet."""

    @retryable(tm=dbsession.transaction_manager)
    def prepare_withdraw():
        # Check everyting looks sane
        op = dbsession.query(CryptoOperation).get(opid)
        assert op.crypto_account.id
        assert op.crypto_account.account.id
        assert op.holding_account.id
        assert op.holding_account.get_balance() > 0
        assert op.external_address
        assert op.required_confirmation_count  # Should be set by the creator
        asset = op.holding_account.asset
        assert asset.asset_class == AssetClass.token

        from_address = bin_to_eth_address(op.crypto_account.address.address)
        to_address = bin_to_eth_address(op.external_address)
        asset_address = bin_to_eth_address(asset.external_id)

        # How much we are withdrawing
        amount = op.holding_account.transactions.one().amount
        op.mark_performed()  # Don't try to pick this op automatically again
        return from_address, to_address, asset_address, amount

    @retryable(tm=dbsession.transaction_manager)
    def close_withdraw():
        # Fill in details.
        # Block number will be filled in later, when confirmation updater picks a transaction receipt for this operation.
        op = dbsession.query(CryptoOperation).get(opid)
        op.txid = txid_to_bin(txid)
        op.block = None
        op.mark_broadcasted()

    from_address, to_address, asset_address, amount = prepare_withdraw()
    wallet = HostedWallet.get(web3, from_address)
    token = Token.get(web3, asset_address)
    amount = token.validate_transfer_amount(amount)
    # Perform actual transfer outside retryable transaction
    # boundaries to avoid double withdrwa
    txid = wallet.execute(token.contract, "transfer", [to_address, amount])
    close_withdraw()
Beispiel #8
0
def withdraw_eth(web3: Web3, dbsession: Session, opid: UUID):
    """Perform ETH withdraw operation from the wallet."""
    @retryable(tm=dbsession.transaction_manager)
    def prepare_withdraw():
        # Check everyting looks sane
        op = dbsession.query(CryptoOperation).get(opid)
        assert op.crypto_account.id
        assert op.crypto_account.account.id
        assert op.holding_account.id
        assert op.holding_account.get_balance() > 0
        assert op.external_address
        assert op.required_confirmation_count  # Should be set by the creator

        address = bin_to_eth_address(op.crypto_account.address.address)

        # How much we are withdrawing
        amount = op.holding_account.transactions.one().amount
        op.mark_performed()  # Don't pick this to action list anymore

        gas = op.other_data.get("gas")
        data = op.other_data.get("data")

        return address, amount, op.external_address, gas, data

    @retryable(tm=dbsession.transaction_manager)
    def close_withdraw():
        # Fill in details.
        # Block number will be filled in later, when confirmation updater picks a transaction receipt for this operation.
        op = dbsession.query(CryptoOperation).get(opid)
        op.txid = txid_to_bin(txid)
        op.block = None
        op.mark_broadcasted()

    address, amount, external_address, gas, data = prepare_withdraw()
    # Do actual network communications outside the transaction,
    # so we avoid double withdraws in the case transaction is retried
    wallet = HostedWallet.get(web3, address)
    txid = wallet.withdraw(bin_to_eth_address(external_address),
                           amount,
                           max_gas=gas,
                           data=data)
    close_withdraw()
Beispiel #9
0
def withdraw_token(web3: Web3, dbsession: Session, opid: UUID):
    """Perform token withdraw operation from the wallet."""
    @retryable(tm=dbsession.transaction_manager)
    def prepare_withdraw():
        # Check everyting looks sane
        op = dbsession.query(CryptoOperation).get(opid)
        assert op.crypto_account.id
        assert op.crypto_account.account.id
        assert op.holding_account.id
        assert op.holding_account.get_balance() > 0
        assert op.external_address
        assert op.required_confirmation_count  # Should be set by the creator
        asset = op.holding_account.asset
        assert asset.asset_class == AssetClass.token

        from_address = bin_to_eth_address(op.crypto_account.address.address)
        to_address = bin_to_eth_address(op.external_address)
        asset_address = bin_to_eth_address(asset.external_id)

        # How much we are withdrawing
        amount = op.holding_account.transactions.one().amount
        op.mark_performed()  # Don't try to pick this op automatically again
        return from_address, to_address, asset_address, amount

    @retryable(tm=dbsession.transaction_manager)
    def close_withdraw():
        # Fill in details.
        # Block number will be filled in later, when confirmation updater picks a transaction receipt for this operation.
        op = dbsession.query(CryptoOperation).get(opid)
        op.txid = txid_to_bin(txid)
        op.block = None
        op.mark_broadcasted()

    from_address, to_address, asset_address, amount = prepare_withdraw()
    wallet = HostedWallet.get(web3, from_address)
    token = Token.get(web3, asset_address)
    amount = token.validate_transfer_amount(amount)
    # Perform actual transfer outside retryable transaction
    # boundaries to avoid double withdrwa
    txid = wallet.execute(token.contract, "transfer", [to_address, amount])
    close_withdraw()
Beispiel #10
0
def withdraw_eth(web3: Web3, dbsession: Session, opid: UUID):
    """Perform ETH withdraw operation from the wallet."""

    @retryable(tm=dbsession.transaction_manager)
    def prepare_withdraw():
        # Check everyting looks sane
        op = dbsession.query(CryptoOperation).get(opid)
        assert op.crypto_account.id
        assert op.crypto_account.account.id
        assert op.holding_account.id
        assert op.holding_account.get_balance() > 0
        assert op.external_address
        assert op.required_confirmation_count  # Should be set by the creator

        address = bin_to_eth_address(op.crypto_account.address.address)

        # How much we are withdrawing
        amount = op.holding_account.transactions.one().amount
        op.mark_performed()  # Don't pick this to action list anymore

        return address, amount, op.external_address

    @retryable(tm=dbsession.transaction_manager)
    def close_withdraw():
        # Fill in details.
        # Block number will be filled in later, when confirmation updater picks a transaction receipt for this operation.
        op = dbsession.query(CryptoOperation).get(opid)
        op.txid = txid_to_bin(txid)
        op.block = None
        op.mark_broadcasted()

    address, amount, external_address = prepare_withdraw()
    # Do actual network communications outside the transaction,
    # so we avoid double withdraws in the case transaction is retried
    wallet = HostedWallet.get(web3, address)
    txid = wallet.withdraw(bin_to_eth_address(external_address), amount)
    close_withdraw()
Beispiel #11
0
def get_wallet(web3, address):
    return HostedWallet.get(web3, address)