Beispiel #1
0
    def finalize_transfer_unlock(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 a transfer of assets from a sidechain by unlocking then
        after the burn is final and a new anchor was made.
        NOTE anybody can unlock so sender is not necessary.
        The amount to unlock is the difference between total burn and
        already unlocked amount.
        Bridge tempo is taken from config_data
        """
        logger.info(from_chain + ' -> ' + to_chain)
        aergo_from = self._connect_aergo(from_chain)
        aergo_to = self.get_aergo(to_chain, privkey_name, privkey_pwd)
        tx_sender = str(aergo_to.account.address)
        if receiver is None:
            receiver = tx_sender
        bridge_to = self.config_data('networks', to_chain, 'bridges',
                                     from_chain, 'addr')
        bridge_from = self.config_data('networks', from_chain, 'bridges',
                                       to_chain, 'addr')
        asset_address = self.config_data('networks', to_chain, 'tokens',
                                         asset_name, 'addr')

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

        balance = get_balance(receiver, asset_address, aergo_to)
        logger.info("\U0001f4b0 %s balance on destination before transfer: %s",
                    asset_name, balance / 10**18)

        gas_limit = 300000
        aer_balance = get_balance(tx_sender, 'aergo', aergo_to)
        if aer_balance < gas_limit * self.gas_price:
            err = "not enough aer balance to pay tx fee"
            raise InsufficientBalanceError(err)

        tx_hash = unlock(aergo_to, receiver, burn_proof, asset_address,
                         bridge_to, gas_limit, self.gas_price)
        logger.info('\U0001f513 Unlock success: %s', tx_hash)

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

        aergo_to.disconnect()
        aergo_from.disconnect()
        return tx_hash
Beispiel #2
0
    def unfreeze(
        self,
        from_chain: str,
        to_chain: str,
        receiver: str = None,
        lock_height: int = 0,
        privkey_name: str = 'default',
        privkey_pwd: str = None,
    ) -> str:
        """ Finalize ERC20Aergo transfer to Aergo Mainnet by unfreezing
            (aers are already minted and freezed in the bridge contract)
        """
        logger.info(from_chain + ' -> ' + to_chain)
        asset_name = 'aergo_erc20'
        w3 = self.get_web3(from_chain)
        aergo_to = self.get_aergo(to_chain, privkey_name, privkey_pwd)
        tx_sender = str(aergo_to.account.address)
        bridge_to = self.get_bridge_contract_address(to_chain, from_chain)
        bridge_from = self.get_bridge_contract_address(from_chain, to_chain)
        asset_address = self.get_asset_address(asset_name, from_chain)
        if receiver is None:
            receiver = tx_sender
        if not is_aergo_address(receiver):
            raise InvalidArgumentsError(
                "Receiver {} must be an Aergo address".format(receiver))

        balance = aergo_u.get_balance(receiver, 'aergo', aergo_to)
        logger.info("\U0001f4b0 %s balance on destination before transfer: %s",
                    asset_name, balance / 10**18)

        gas_limit = 300000
        if receiver != tx_sender:
            aer_balance = aergo_u.get_balance(tx_sender, 'aergo', aergo_to)
            if aer_balance < gas_limit * self.aergo_gas_price:
                err = "not enough aer balance to pay tx fee"
                raise InsufficientBalanceError(err)

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

        tx_hash, _ = eth_to_aergo.unfreeze(aergo_to, receiver, lock_proof,
                                           bridge_to, gas_limit,
                                           self.aergo_gas_price)
        logger.info('\U0001f4a7 Unfreeze success: %s', tx_hash)
        # new balance on destination
        balance = aergo_u.get_balance(receiver, 'aergo', aergo_to)
        logger.info("\U0001f4b0 %s balance on destination after transfer: %s",
                    asset_name, balance / 10**18)
        aergo_to.disconnect()

        # record mint address in file
        return tx_hash
Beispiel #3
0
    def burn_to_eth(
        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 token transfer back to ethereum origin"""
        logger.info(from_chain + ' -> ' + to_chain)
        if not is_ethereum_address(receiver):
            raise InvalidArgumentsError(
                "receiver {} must be an Ethereum address".format(receiver))
        aergo_from = self.get_aergo(from_chain, privkey_name, privkey_pwd)
        sender = str(aergo_from.account.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)

        gas_limit = 300000
        balance = aergo_u.get_balance(sender, token_pegged, aergo_from)
        if balance < amount:
            raise InsufficientBalanceError("not enough token balance")
        logger.info("\U0001f4b0 %s balance on origin before transfer: %s",
                    asset_name, balance / 10**18)

        aer_balance = aergo_u.get_balance(sender, 'aergo', aergo_from)
        if aer_balance < gas_limit * self.aergo_gas_price:
            err = "not enough aer balance to pay tx fee"
            raise InsufficientBalanceError(err)

        burn_height, tx_hash, _ = aergo_to_eth.burn(aergo_from, bridge_from,
                                                    receiver, amount,
                                                    token_pegged, gas_limit,
                                                    self.aergo_gas_price)
        logger.info('\U0001f525 Burn success: %s', tx_hash)

        # remaining balance on origin : aer or asset
        balance = aergo_u.get_balance(sender, token_pegged, aergo_from)
        logger.info(
            "\U0001f4b0 remaining %s balance on origin after transfer: %s",
            asset_name, balance / 10**18)

        aergo_from.disconnect()
        return burn_height, tx_hash
Beispiel #4
0
    def unlock_to_aergo(
        self,
        from_chain: str,
        to_chain: str,
        asset_name: str,
        receiver: str,
        burn_height: int = 0,
        privkey_name: str = 'default',
        privkey_pwd: str = None,
    ) -> str:
        """ Finalize Aergo 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))
        w3 = self.get_web3(from_chain)
        aergo_to = self.get_aergo(to_chain, privkey_name, privkey_pwd)
        tx_sender = str(aergo_to.account.address)
        bridge_to = self.get_bridge_contract_address(to_chain, from_chain)
        bridge_from = self.get_bridge_contract_address(from_chain, to_chain)
        asset_address = self.get_asset_address(asset_name, to_chain)

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

        balance = aergo_u.get_balance(receiver, asset_address, aergo_to)
        logger.info("\U0001f4b0 %s balance on destination before transfer: %s",
                    asset_name, balance / 10**18)

        gas_limit = 300000
        aer_balance = aergo_u.get_balance(tx_sender, 'aergo', aergo_to)
        if aer_balance < gas_limit * self.aergo_gas_price:
            err = "not enough aer balance to pay tx fee"
            raise InsufficientBalanceError(err)

        tx_hash, _ = eth_to_aergo.unlock(aergo_to, receiver, burn_proof,
                                         asset_address, bridge_to, gas_limit,
                                         self.aergo_gas_price)
        logger.info('\U0001f513 Unlock success: %s', tx_hash)

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

        return tx_hash
Beispiel #5
0
    def lock_to_eth(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 Aergo Standard Token transfer to Ethereum sidechain"""
        logger.info(from_chain + ' -> ' + to_chain)
        if not is_ethereum_address(receiver):
            raise InvalidArgumentsError(
                "receiver {} must be an Ethereum address".format(receiver))
        if asset_name == 'aergo':
            raise InvalidArgumentsError(
                'aer cannot be locked on Aergo, must be frozen')
        aergo_from = self.get_aergo(from_chain, privkey_name, privkey_pwd)
        sender = str(aergo_from.account.address)
        bridge_from = self.get_bridge_contract_address(from_chain, to_chain)
        asset_address = self.get_asset_address(asset_name, from_chain)

        gas_limit = 300000
        balance = aergo_u.get_balance(sender, asset_address, aergo_from)
        if balance < amount:
            raise InsufficientBalanceError("not enough token balance")
        logger.info("\U0001f4b0 %s balance on origin before transfer: %s",
                    asset_name, balance / 10**18)

        aer_balance = aergo_u.get_balance(sender, 'aergo', aergo_from)
        if aer_balance < gas_limit * self.aergo_gas_price:
            err = "not enough aer balance to pay tx fee"
            raise InsufficientBalanceError(err)

        lock_height, tx_hash, _ = aergo_to_eth.lock(aergo_from, bridge_from,
                                                    receiver, amount,
                                                    asset_address, gas_limit,
                                                    self.aergo_gas_price)
        logger.info('\U0001f512 Lock success: %s', tx_hash)

        # remaining balance on origin : aer or asset
        balance = aergo_u.get_balance(sender, asset_address, aergo_from)
        logger.info(
            "\U0001f4b0 remaining %s balance on origin after transfer: %s",
            asset_name, balance / 10**18)

        aergo_from.disconnect()
        return lock_height, tx_hash
Beispiel #6
0
    def initiate_transfer_burn(
        self,
        from_chain: str,
        to_chain: str,
        asset_name: str,
        amount: int,
        receiver: str = None,
        privkey_name: str = 'default',
        privkey_pwd: str = None,
    ) -> Tuple[int, str]:
        """ Initiate a transfer from a sidechain by burning the assets.
        """
        logger.info(from_chain + ' -> ' + to_chain)
        aergo_from = self.get_aergo(from_chain, privkey_name, privkey_pwd)
        sender = str(aergo_from.account.address)
        if receiver is None:
            receiver = sender
        bridge_from = self.config_data('networks', from_chain, 'bridges',
                                       to_chain, 'addr')
        token_pegged = self.config_data('networks', to_chain, 'tokens',
                                        asset_name, 'pegs', from_chain)
        balance = get_balance(sender, token_pegged, aergo_from)
        logger.info("\U0001f4b0 %s balance on sidechain before transfer: %s",
                    asset_name, balance / 10**18)
        if balance < amount:
            raise InsufficientBalanceError("not enough balance")

        gas_limit = 300000
        aer_balance = get_balance(sender, 'aergo', aergo_from)
        if aer_balance < gas_limit * self.gas_price:
            err = "not enough aer balance to pay tx fee"
            raise InsufficientBalanceError(err)

        burn_height, tx_hash = burn(aergo_from, bridge_from, receiver, amount,
                                    token_pegged, gas_limit, self.gas_price)
        logger.info('\U0001f525 Burn success: %s', tx_hash)

        # remaining balance on sidechain
        balance = get_balance(sender, token_pegged, aergo_from)
        logger.info(
            "\U0001f4b0 remaining %s balance on sidechain after transfer: %s",
            asset_name, balance / 10**18)

        aergo_from.disconnect()

        return burn_height, tx_hash
Beispiel #7
0
    def freeze(
        self,
        from_chain: str,
        to_chain: str,
        amount: int,
        receiver: str,
        privkey_name: str = 'default',
        privkey_pwd: str = None,
    ) -> Tuple[int, str]:
        """ Initiate Aer transfer back to Ethereum AergoERC20 sidechain"""
        logger.info(from_chain + ' -> ' + to_chain)
        if not is_ethereum_address(receiver):
            raise InvalidArgumentsError(
                "receiver {} must be an Ethereum address".format(receiver))
        asset_name = 'aergo_erc20'
        aergo_from = self.get_aergo(from_chain, privkey_name, privkey_pwd)
        sender = str(aergo_from.account.address)
        bridge_from = self.get_bridge_contract_address(from_chain, to_chain)

        gas_limit = 300000
        balance = aergo_u.get_balance(sender, 'aergo', aergo_from)
        if balance < amount + gas_limit * self.aergo_gas_price:
            raise InsufficientBalanceError("not enough token balance")
        logger.info("\U0001f4b0 %s balance on origin before transfer: %s",
                    asset_name, balance / 10**18)

        freeze_height, tx_hash, _ = aergo_to_eth.freeze(
            aergo_from, bridge_from, receiver, amount, gas_limit,
            self.aergo_gas_price)
        logger.info('\u2744 Freeze success: %s', tx_hash)

        # remaining balance on origin : aer or asset
        balance = aergo_u.get_balance(sender, 'aergo', aergo_from)
        logger.info(
            "\U0001f4b0 remaining %s balance on origin after transfer: %s",
            asset_name, balance / 10**18)

        aergo_from.disconnect()
        return freeze_height, tx_hash
Beispiel #8
0
 def get_balance(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_wallet_address(account_name)
     aergo = self._connect_aergo(network_name)
     if asset_name == 'aergo':
         asset_addr = 'aergo'
     else:
         asset_addr = self.get_asset_address(asset_name, network_name,
                                             asset_origin_chain)
     balance = get_balance(account_addr, asset_addr, aergo)
     aergo.disconnect()
     return balance, asset_addr
Beispiel #9
0
 def get_balance_aergo(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.config_data('wallet', account_name, 'addr')
     if not is_aergo_address(account_addr):
         raise InvalidArgumentsError(
             "Account {} must be an Aergo address".format(account_addr))
     aergo = self.connect_aergo(network_name)
     asset_addr = self.get_asset_address(asset_name, network_name,
                                         asset_origin_chain)
     balance = aergo_u.get_balance(account_addr, asset_addr, aergo)
     aergo.disconnect()
     return balance, asset_addr
Beispiel #10
0
    def finalize_transfer_mint(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 a transfer of assets to a sidechain by minting then
        after the lock is final and a new anchor was made.
        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)
        aergo_from = self._connect_aergo(from_chain)
        aergo_to = self.get_aergo(to_chain, privkey_name, privkey_pwd)
        tx_sender = str(aergo_to.account.address)
        if receiver is None:
            receiver = tx_sender
        bridge_from = self.config_data('networks', from_chain, 'bridges',
                                       to_chain, 'addr')
        bridge_to = self.config_data('networks', to_chain, 'bridges',
                                     from_chain, 'addr')
        asset_address = self.config_data('networks', from_chain, 'tokens',
                                         asset_name, 'addr')
        save_pegged_token_address = False
        try:
            token_pegged = self.config_data('networks', from_chain, 'tokens',
                                            asset_name, 'pegs', to_chain)
            balance = get_balance(receiver, token_pegged, aergo_to)
            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 = 300000
        aer_balance = get_balance(tx_sender, 'aergo', aergo_to)
        if aer_balance < gas_limit * self.gas_price:
            err = "not enough aer balance to pay tx fee"
            raise InsufficientBalanceError(err)

        lock_proof = build_lock_proof(aergo_from, aergo_to, receiver,
                                      bridge_from, bridge_to, lock_height,
                                      asset_address)
        logger.info("\u2699 Built lock proof")
        token_pegged, tx_hash = mint(aergo_to, receiver, lock_proof,
                                     asset_address, bridge_to, gas_limit,
                                     self.gas_price)
        logger.info('\u26cf Mint success: %s', tx_hash)

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

        aergo_from.disconnect()
        aergo_to.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
Beispiel #11
0
    def mint_to_aergo(
        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,
    ) -> str:
        """ Finalize ERC20 token or Ether transfer to Aergo sidechain """
        logger.info(from_chain + ' -> ' + to_chain)
        w3 = self.get_web3(from_chain)
        aergo_to = self.get_aergo(to_chain, privkey_name, privkey_pwd)
        tx_sender = str(aergo_to.account.address)
        bridge_to = self.get_bridge_contract_address(to_chain, from_chain)
        bridge_from = self.get_bridge_contract_address(from_chain, to_chain)
        asset_address = self.get_asset_address(asset_name, from_chain)
        if receiver is None:
            receiver = tx_sender
        if not is_aergo_address(receiver):
            raise InvalidArgumentsError(
                "Receiver {} must be an Aergo address".format(receiver))

        save_pegged_token_address = False
        try:
            token_pegged = self.get_asset_address(
                asset_name, to_chain, asset_origin_chain=from_chain)
            balance = aergo_u.get_balance(receiver, token_pegged, aergo_to)
            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 = 300000
        aer_balance = aergo_u.get_balance(tx_sender, 'aergo', aergo_to)
        if aer_balance < gas_limit * self.aergo_gas_price:
            err = "not enough aer balance to pay tx fee"
            raise InsufficientBalanceError(err)

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

        token_pegged, tx_hash, _ = eth_to_aergo.mint(aergo_to, receiver,
                                                     lock_proof, asset_address,
                                                     bridge_to, gas_limit,
                                                     self.aergo_gas_price)
        logger.info('\u26cf Mint success: %s', tx_hash)
        # new balance on destination
        balance = aergo_u.get_balance(receiver, token_pegged, aergo_to)
        logger.info("\U0001f4b0 %s balance on destination after transfer: %s",
                    asset_name, balance / 10**18)
        aergo_to.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 tx_hash