Пример #1
0
    def get_balance_eth(
        self,
        asset_name: str,
        network_name: str,
        asset_origin_chain: str = None,
        account_name: str = 'default',
        account_addr: str = None,
    ) -> Tuple[int, str]:
        """ Get account name balance of asset_name on network_name,
        and specify asset_origin_chain for a pegged asset query,
        """
        if account_addr is None:
            account_addr = self.get_eth_wallet_address(account_name)
        if not is_ethereum_address(account_addr):
            raise InvalidArgumentsError(
                "Account {} must be an Ethereum address".format(account_addr))
        w3 = self.get_web3(network_name)
        asset_addr = self.get_asset_address(asset_name, network_name,
                                            asset_origin_chain)
        if asset_origin_chain is None:
            if asset_addr == 'ether':
                balance = eth_u.get_balance(account_addr, asset_addr, w3)
                return balance, asset_addr
            abi = self.load_erc20_abi(network_name, asset_name)
        else:
            abi = self.load_minted_erc20_abi(network_name, asset_origin_chain)

        balance = eth_u.get_balance(account_addr, asset_addr, w3, abi)
        return balance, asset_addr
Пример #2
0
    def unlock_to_eth(
        self,
        from_chain: str,
        to_chain: str,
        asset_name: str,
        receiver: str = None,
        burn_height: int = 0,
        privkey_name: str = 'default',
        privkey_pwd: str = None,
    ) -> str:
        """ Finalize ERC20 or Eth transfer back to Ethereum origin """
        logger.info(from_chain + ' -> ' + to_chain)
        bridge_to_abi = self.load_bridge_abi(to_chain, from_chain)
        erc20_abi = self.load_erc20_abi(to_chain, asset_name)
        aergo_from = self.connect_aergo(from_chain)
        # get ethereum tx signer
        w3 = self.get_web3(to_chain)
        signer_acct = self.get_signer(w3, privkey_name, privkey_pwd)
        tx_sender = signer_acct.address

        if receiver is None:
            receiver = tx_sender
        if not is_ethereum_address(receiver):
            raise InvalidArgumentsError(
                "receiver {} must be an Ethereum address".format(receiver))

        bridge_from = self.get_bridge_contract_address(from_chain, to_chain)
        bridge_to = self.get_bridge_contract_address(to_chain, from_chain)
        asset_address = self.get_asset_address(asset_name, to_chain)
        balance = eth_u.get_balance(receiver, asset_address, w3, erc20_abi)
        logger.info(
            "\U0001f4b0 %s balance on destination before transfer : %s",
            asset_name, balance / 10**18)

        gas_limit = 200000
        eth_balance = eth_u.get_balance(tx_sender, 'ether', w3)
        if eth_balance * 10**9 < gas_limit * self.eth_gas_price:
            err = "not enough aer balance to pay tx fee"
            raise InsufficientBalanceError(err)

        burn_proof = aergo_to_eth.build_burn_proof(aergo_from, w3, receiver,
                                                   bridge_from, bridge_to,
                                                   bridge_to_abi, burn_height,
                                                   asset_address)
        logger.info("\u2699 Built burn proof")

        tx_hash, _ = aergo_to_eth.unlock(w3, signer_acct, receiver, burn_proof,
                                         asset_address, bridge_to,
                                         bridge_to_abi, gas_limit,
                                         self.eth_gas_price)
        logger.info('\U0001f513 Unlock success: %s', tx_hash)

        # new balance on origin
        balance = eth_u.get_balance(receiver, asset_address, w3, erc20_abi)
        logger.info("\U0001f4b0 %s balance on destination after transfer : %s",
                    asset_name, balance / 10**18)

        aergo_from.disconnect()
        return tx_hash
Пример #3
0
    def lock_to_aergo(
        self,
        from_chain: str,
        to_chain: str,
        asset_name: str,
        amount: int,
        receiver: str,
        privkey_name: str = 'default',
        privkey_pwd: str = None,
    ) -> Tuple[int, str]:
        """ Initiate ERC20 token or Ether transfer to Aergo sidechain """
        logger.info(from_chain + ' -> ' + to_chain)
        if not is_aergo_address(receiver):
            raise InvalidArgumentsError(
                "Receiver {} must be an Aergo address".format(receiver))
        bridge_from_abi = self.load_bridge_abi(from_chain, to_chain)
        erc20_abi = self.load_erc20_abi(from_chain, asset_name)
        w3 = self.get_web3(from_chain)
        signer_acct = self.get_signer(w3, privkey_name, privkey_pwd)
        token_owner = signer_acct.address
        bridge_from = self.get_bridge_contract_address(from_chain, to_chain)
        erc20_address = self.get_asset_address(asset_name, from_chain)

        balance = eth_u.get_balance(token_owner, erc20_address, w3, erc20_abi)
        logger.info("\U0001f4b0 %s balance on origin before transfer : %s",
                    asset_name, balance / 10**18)
        if balance < amount:
            raise InsufficientBalanceError("not enough token balance")

        gas_limit = 500000  # estimation
        eth_balance = eth_u.get_balance(token_owner, 'ether', w3)
        if eth_balance * 10**9 < gas_limit * self.eth_gas_price:
            err = "not enough eth balance to pay tx fee"
            raise InsufficientBalanceError(err)

        next_nonce, tx_hash = eth_u.increase_approval(bridge_from,
                                                      erc20_address, amount,
                                                      w3, erc20_abi,
                                                      signer_acct, gas_limit,
                                                      self.eth_gas_price)
        logger.info("\u2b06 Increase approval success: %s", tx_hash)

        lock_height, tx_hash, _ = eth_to_aergo.lock(
            w3, signer_acct, receiver, amount, bridge_from, bridge_from_abi,
            erc20_address, gas_limit, self.eth_gas_price, next_nonce)
        logger.info('\U0001f512 Lock success: %s', tx_hash)

        balance = eth_u.get_balance(token_owner, erc20_address, w3, erc20_abi)
        logger.info(
            "\U0001f4b0 remaining %s balance on origin after transfer: %s",
            asset_name, balance / 10**18)
        return lock_height, tx_hash
Пример #4
0
    def burn_to_aergo(
        self,
        from_chain: str,
        to_chain: str,
        asset_name: str,
        amount: int,
        receiver: str,
        privkey_name: str = 'default',
        privkey_pwd: str = None,
    ) -> Tuple[int, str]:
        """ Initiate minted Standard token transfer back to aergo origin"""
        logger.info(from_chain + ' -> ' + to_chain)
        if not is_aergo_address(receiver):
            raise InvalidArgumentsError(
                "Receiver {} must be an Aergo address".format(receiver))
        bridge_from_abi = self.load_bridge_abi(from_chain, to_chain)
        minted_erc20_abi = self.load_minted_erc20_abi(from_chain, to_chain)
        w3 = self.get_web3(from_chain)
        signer_acct = self.get_signer(w3, privkey_name, privkey_pwd)
        token_owner = signer_acct.address
        bridge_from = self.get_bridge_contract_address(from_chain, to_chain)
        token_pegged = self.get_asset_address(asset_name,
                                              from_chain,
                                              asset_origin_chain=to_chain)

        balance = eth_u.get_balance(token_owner, token_pegged, w3,
                                    minted_erc20_abi)
        logger.info("\U0001f4b0 %s balance on origin before transfer : %s",
                    asset_name, balance / 10**18)
        if balance < amount:
            raise InsufficientBalanceError("not enough token balance")

        gas_limit = 200000
        eth_balance = eth_u.get_balance(token_owner, 'ether', w3)
        if eth_balance * 10**9 < gas_limit * self.eth_gas_price:
            err = "not enough aer balance to pay tx fee"
            raise InsufficientBalanceError(err)

        burn_height, tx_hash, _ = eth_to_aergo.burn(w3, signer_acct, receiver,
                                                    amount, bridge_from,
                                                    bridge_from_abi,
                                                    token_pegged, gas_limit,
                                                    self.eth_gas_price)
        logger.info('\U0001f525 Burn success: %s', tx_hash)

        balance = eth_u.get_balance(token_owner, token_pegged, w3,
                                    minted_erc20_abi)
        logger.info(
            "\U0001f4b0 remaining %s balance on origin after transfer: %s",
            asset_name, balance / 10**18)
        return burn_height, tx_hash
Пример #5
0
    def mint_to_eth(
        self,
        from_chain: str,
        to_chain: str,
        asset_name: str,
        receiver: str = None,
        lock_height: int = 0,
        privkey_name: str = 'default',
        privkey_pwd: str = None,
    ) -> Tuple[str, str]:
        """ Finalize Aergo Standard Token transfer to Ethereum sidechain
        NOTE anybody can mint so sender is not necessary.
        The amount to mint is the difference between total deposit and
        already minted amount.
        Bridge tempo is taken from config_data
        """
        logger.info(from_chain + ' -> ' + to_chain)
        bridge_to_abi = self.load_bridge_abi(to_chain, from_chain)
        minted_erc20_abi = self.load_minted_erc20_abi(to_chain, from_chain)
        aergo_from = self.connect_aergo(from_chain)
        w3 = self.get_web3(to_chain)
        signer_acct = self.get_signer(w3, privkey_name, privkey_pwd)
        tx_sender = signer_acct.address
        if receiver is None:
            receiver = tx_sender
        if not is_ethereum_address(receiver):
            raise InvalidArgumentsError(
                "receiver {} must be an Ethereum address".format(receiver))
        bridge_from = self.get_bridge_contract_address(from_chain, to_chain)
        bridge_to = self.get_bridge_contract_address(to_chain, from_chain)
        asset_address = self.get_asset_address(asset_name, from_chain)

        save_pegged_token_address = False
        try:
            token_pegged = self.get_asset_address(
                asset_name, to_chain, asset_origin_chain=from_chain)
            balance = eth_u.get_balance(receiver, token_pegged, w3,
                                        minted_erc20_abi)
            logger.info(
                "\U0001f4b0 %s balance on destination before transfer : %s",
                asset_name, balance / 10**18)
        except KeyError:
            logger.info("Pegged token unknow by wallet")
            save_pegged_token_address = True

        gas_limit = 2000000
        eth_balance = eth_u.get_balance(tx_sender, 'ether', w3)
        if eth_balance * 10**9 < gas_limit * self.eth_gas_price:
            err = "not enough aer balance to pay tx fee"
            raise InsufficientBalanceError(err)

        lock_proof = aergo_to_eth.build_lock_proof(aergo_from, w3, receiver,
                                                   bridge_from, bridge_to,
                                                   bridge_to_abi, lock_height,
                                                   asset_address)
        logger.info("\u2699 Built lock proof")

        token_pegged, tx_hash, _ = aergo_to_eth.mint(w3, signer_acct, receiver,
                                                     lock_proof, asset_address,
                                                     bridge_to, bridge_to_abi,
                                                     gas_limit,
                                                     self.eth_gas_price)
        logger.info('\u26cf Mint success: %s', tx_hash)

        # new balance on sidechain
        balance = eth_u.get_balance(receiver, token_pegged, w3,
                                    minted_erc20_abi)
        logger.info("\U0001f4b0 %s balance on destination after transfer : %s",
                    asset_name, balance / 10**18)

        aergo_from.disconnect()

        # record mint address in file
        if save_pegged_token_address:
            logger.info("------ Store mint address in config.json -----------")
            self.config_data('networks',
                             from_chain,
                             'tokens',
                             asset_name,
                             'pegs',
                             to_chain,
                             value=token_pegged)
            self.save_config()
        return token_pegged, tx_hash