Exemple #1
0
    def fund_trustline(self, address: str, asset: str) -> dict:

        wallet = self._get_wallet()
        if asset not in SUPPORTED_ASSETS[str(wallet.network.value)]:
            raise j.exceptions.NotFound("Unsupported asset")

        asset_code, asset_issuer = asset.split(":")

        server = wallet._get_horizon_server()

        source_account = wallet.load_account()

        base_fee = server.fetch_base_fee()
        transaction = (stellar_sdk.TransactionBuilder(
            source_account=source_account,
            network_passphrase=self._get_network_passphrase(
                wallet.network.value),
            base_fee=base_fee,
        ).append_begin_sponsoring_future_reserves_op(
            address).append_change_trust_op(
                asset_code=asset_code,
                asset_issuer=asset_issuer,
                source=address).append_end_sponsoring_future_reserves_op(
                    address).set_timeout(60).build())
        source_keypair = stellar_sdk.Keypair.from_secret(wallet.secret)
        transaction.sign(source_keypair)
        return {"addtrustline_transaction": transaction.to_xdr()}
Exemple #2
0
    def _create_recovery_transaction(
            self, vesting_address: str) -> stellar_sdk.TransactionEnvelope:
        activation_account_id = get_wallet().address
        horizon_server = self._get_horizon_server()
        source_account = horizon_server.load_account(vesting_address)
        source_account.sequence += 1
        tx = stellar_sdk.TransactionBuilder(
            source_account, network_passphrase=self._get_network_passphrase())
        tx.append_change_trust_op(asset_code="TFT",
                                  asset_issuer=self._get_tft_issuer(),
                                  limit="0")
        tx.append_manage_data_op(DATA_ENTRY_KEY, None)
        tx.append_account_merge_op(activation_account_id)
        txe = tx.build()

        # save the preauth transaction in our unlock service
        unlock_hash_signer = stellar_sdk.strkey.StrKey.encode_pre_auth_tx(
            txe.hash())
        data = {
            "unlockhash": unlock_hash_signer,
            "transaction_xdr": txe.to_xdr()
        }
        url = f"https://{'testnet.threefold.io' if self._get_network()=='TEST' else'tokenservices.threefold.io'}/threefoldfoundation/unlock_service/create_unlockhash_transaction"
        resp = j.tools.http.post(url, json={"args": data})
        resp.raise_for_status()
        return txe
Exemple #3
0
    def set_data_entry(self, name: str, value: str, address: str = None):
        """Sets, modifies or deletes a data entry (name/value pair) for an account

        To delete a data entry, set the value to an empty string.

        """

        address = address or self.address
        signing_key = stellar_sdk.Keypair.from_secret(self.secret)
        horizon_server = self._get_horizon_server()
        if address == self.address:
            account = self.load_account()
        else:
            account = horizon_server.load_account(address)
        base_fee = horizon_server.fetch_base_fee()
        transaction = (
            stellar_sdk.TransactionBuilder(
                source_account=account, network_passphrase=_NETWORK_PASSPHRASES[self.network.value], base_fee=base_fee,
            )
            .append_manage_data_op(name, value)
            .set_timeout(30)
            .build()
        )

        transaction.sign(signing_key)

        try:
            response = horizon_server.submit_transaction(transaction)
            j.logger.info("Transaction hash: {}".format(response["hash"]))
        except stellar_sdk.exceptions.BadRequestError as e:
            j.logger.debug(e)
            raise e
Exemple #4
0
    def _merge_account(self, address):
        server = self._get_horizon_server()
        account = server.load_account(address)
        # Increment the sequence number in case the unlock transaction was not processed before the load_account call
        # account.increment_sequence_number()
        balances = self._get_free_balances(address)
        base_fee = server.fetch_base_fee()
        transaction_builder = stellar_sdk.TransactionBuilder(
            source_account=account, network_passphrase=_NETWORK_PASSPHRASES[self.network.value], base_fee=base_fee
        )
        for balance in balances.balances:
            if balance.is_native():
                continue
            # Step 1: Transfer custom assets
            transaction_builder.append_payment_op(
                destination=self.address,
                amount=balance.balance,
                asset_code=balance.asset_code,
                asset_issuer=balance.asset_issuer,
            )
            # Step 2: Delete trustlines
            transaction_builder.append_change_trust_op(
                asset_issuer=balance.asset_issuer, asset_code=balance.asset_code, limit="0"
            )
        # Step 3: Merge account
        transaction_builder.append_account_merge_op(self.address)

        transaction_builder.set_timeout(30)
        transaction = transaction_builder.build()
        signer_kp = stellar_sdk.Keypair.from_secret(self.secret)
        transaction.sign(signer_kp)
        server.submit_transaction(transaction)
Exemple #5
0
    def activate_account(self, destination_address, starting_balance="12.50"):
        """Activates another account

        Args:
            destination_address (str): address of the destination
            starting_balance (str, optional): the balance that the destination address will start with. Must be a positive integer expressed as a string. Defaults to "12.50".
        """
        server = self._get_horizon_server()
        source_keypair = stellar_sdk.Keypair.from_secret(self.secret)

        source_account = self.load_account()

        base_fee = server.fetch_base_fee()
        transaction = (
            stellar_sdk.TransactionBuilder(
                source_account=source_account,
                network_passphrase=_NETWORK_PASSPHRASES[self.network.value],
                base_fee=base_fee,
            )
            .append_create_account_op(destination=destination_address, starting_balance=starting_balance)
            .build()
        )
        transaction.sign(source_keypair)
        try:
            response = server.submit_transaction(transaction)
            j.logger.info("Transaction hash: {}".format(response["hash"]))
        except stellar_sdk.exceptions.BadRequestError as e:
            j.logger.debug(e)
def create_buy_order(buying_account_secret, amount, network):
    buying_asset_code = "TFT"
    buying_asset_issuer = ASSET_ISSUERS[network][buying_asset_code]
    selling_asset_code = "BTC"
    selling_asset_issuer = ASSET_ISSUERS[network][selling_asset_code]
    price = "0.0000019"

    buying_kp = Keypair.from_secret(buying_account_secret)

    horizon_server = stellar_sdk.Server(_HORIZON_NETWORKS[network])
    source_account = horizon_server.load_account(buying_kp.public_key)
    transaction = (
        stellar_sdk.TransactionBuilder(
            source_account=source_account,
            network_passphrase=stellar_sdk.Network.TESTNET_NETWORK_PASSPHRASE
            if network == "test"
            else stellar_sdk.Network.PUBLIC_NETWORK_PASSPHRASE,
            base_fee=0,
        )
        .append_manage_buy_offer_op(
            selling_code=selling_asset_code,
            selling_issuer=selling_asset_issuer,
            buying_code=buying_asset_code,
            buying_issuer=buying_asset_issuer,
            amount=amount,
            price=price,
        )
        .set_timeout(60)
        .build()
    )
    transaction.sign(buying_kp)
    return transaction
def activate_account(source_keypair, new_account_kp, fullassetcode):
    split_asset = fullassetcode.split(":", 1)
    asset_code = split_asset[0]
    asset_issuer = split_asset[1]
    new_account_address = new_account_kp.public_key

    horizon_server = stellar_sdk.Server()

    source_account = horizon_server.load_account(source_keypair.public_key)

    base_fee = horizon_server.fetch_base_fee()
    transaction = (stellar_sdk.TransactionBuilder(
        source_account=source_account,
        network_passphrase=stellar_sdk.Network.TESTNET_NETWORK_PASSPHRASE,
        base_fee=base_fee,
    ).append_begin_sponsoring_future_reserves_op(
        new_account_address).append_create_account_op(
            destination=new_account_address,
            starting_balance="0").append_change_trust_op(
                asset_issuer=asset_issuer,
                asset_code=asset_code,
                source=new_account_address).
                   append_end_sponsoring_future_reserves_op(
                       new_account_address).set_timeout(60).build())
    transaction.sign(source_keypair)
    transaction.sign(new_account_kp)
    horizon_server.submit_transaction(transaction)
Exemple #8
0
def createpayment_transaction(accountsecret, destination, feedestination, fee,
                              asset, amount, network):

    network_passphrase = (stellar_sdk.Network.TESTNET_NETWORK_PASSPHRASE
                          if network == "test" else
                          stellar_sdk.Network.PUBLIC_NETWORK_PASSPHRASE)
    horizon_server = stellar_sdk.Server(
        "https://horizon-testnet.stellar.org" if network ==
        "test" else "https://horizon.stellar.org")

    keypair = Keypair.from_secret(accountsecret)
    from_address = keypair.public_key

    split_asset = asset.split(":", 1)
    asset_code = split_asset[0]
    asset_issuer = split_asset[1]

    source_account = horizon_server.load_account(from_address)
    txe = (stellar_sdk.TransactionBuilder(
        source_account=source_account,
        network_passphrase=network_passphrase,
        base_fee=0).append_payment_op(
            destination,
            amount,
            asset_code=asset_code,
            asset_issuer=asset_issuer).append_payment_op(
                feedestination,
                fee,
                asset_code=asset_code,
                asset_issuer=asset_issuer).set_timeout(60 * 3).build())

    txe.sign(keypair)
    print(txe.to_xdr())
Exemple #9
0
 def _create_unlock_transaction(self, escrow_kp, unlock_time):
     server = self._get_horizon_server()
     escrow_account = server.load_account(escrow_kp.public_key)
     escrow_account.increment_sequence_number()
     tx = (
         stellar_sdk.TransactionBuilder(escrow_account)
         .append_set_options_op(master_weight=0, low_threshold=1, med_threshold=1, high_threshold=1)
         .add_time_bounds(unlock_time, 0)
         .build()
     )
     tx.sign(escrow_kp)
     return tx
Exemple #10
0
    def modify_signing_requirements(self,
                                    public_keys_signers,
                                    signature_count,
                                    low_treshold=0,
                                    high_treshold=2,
                                    master_weight=2):
        """modify_signing_requirements sets to amount of signatures required for the creation of multisig account. It also adds
           the public keys of the signer to this account

        Args:
            public_keys_signers (list): list of public keys of signers
            signature_count (int): amount of signatures requires to transfer funds
            low_treshold (int, optional): amount of signatures required for low security operations (transaction processing, allow trust, bump sequence). Defaults to 1.
            high_treshold (int, optional): amount of signatures required for high security operations (set options, account merge). Defaults to 2.
            master_weight (int, optional): A number from 0-255 (inclusive) representing the weight of the master key. If the weight of the master key is updated to 0, it is effectively disabled. Defaults to 2.
        """
        server = self._get_horizon_server()
        account = self.load_account()
        source_keypair = stellar_sdk.Keypair.from_secret(self.secret)

        transaction_builder = stellar_sdk.TransactionBuilder(account)
        # set the signing options
        transaction_builder.append_set_options_op(
            low_threshold=low_treshold,
            med_threshold=signature_count,
            high_threshold=high_treshold,
            master_weight=master_weight,
        )

        # For every public key given, add it as a signer to this account
        for public_key_signer in public_keys_signers:
            transaction_builder.append_ed25519_public_key_signer(
                public_key_signer, 1)

        transaction_builder.set_timeout(30)
        tx = transaction_builder.build()
        tx.sign(source_keypair)

        try:
            response = server.submit_transaction(tx)
            j.logger.info(response)
            j.logger.info(
                f"Set the signers of {self.address} to require {signature_count} signers"
            )
        except stellar_sdk.exceptions.BadRequestError:
            j.logger.info(
                "Transaction need additional signatures in order to send")
            return tx.to_xdr()
Exemple #11
0
def end_sponsorship(activatorsecret, sponsoredaccount):
    activator_kp = Keypair.from_secret(activatorsecret)

    horizon_server = stellar_sdk.Server()

    source_account = horizon_server.load_account(activator_kp.public_key)

    base_fee = horizon_server.fetch_base_fee()
    transaction = (stellar_sdk.TransactionBuilder(
        source_account=source_account,
        network_passphrase=stellar_sdk.Network.TESTNET_NETWORK_PASSPHRASE,
        base_fee=base_fee,
    ).append_revoke_account_sponsorship_op(sponsoredaccount).build())
    transaction.sign(activator_kp)
    horizon_server.submit_transaction(transaction)
    print(f"Stopped sponsoring account {sponsoredaccount }")
Exemple #12
0
    def merge_into_account(self, destination_address: str):
        """Merges XLMs into destination address

        Args:
            destination_address (str): address to send XLMs to
        """
        server = self._get_horizon_server()
        source_keypair = stellar_sdk.Keypair.from_secret(self.secret)

        source_account = self.load_account()

        base_fee = server.fetch_base_fee()

        transaction_builder = stellar_sdk.TransactionBuilder(
            source_account=source_account,
            network_passphrase=_NETWORK_PASSPHRASES[self.network.value],
            base_fee=base_fee,
        )

        balances = self.get_balance()
        for balance in balances.balances:
            if balance.is_native():
                continue
            # Step 1: Transfer custom assets
            if decimal.Decimal(balance.balance) > decimal.Decimal(0):
                transaction_builder.append_payment_op(
                    destination=destination_address,
                    amount=balance.balance,
                    asset_code=balance.asset_code,
                    asset_issuer=balance.asset_issuer,
                )
            # Step 2: Delete trustlines
            transaction_builder.append_change_trust_op(
                asset_issuer=balance.asset_issuer,
                asset_code=balance.asset_code,
                limit="0")

        transaction_builder.append_account_merge_op(
            destination=destination_address)
        transaction = transaction_builder.build()

        transaction.sign(source_keypair)
        try:
            response = server.submit_transaction(transaction)
            j.logger.info("Transaction hash: {}".format(response["hash"]))
        except stellar_sdk.exceptions.BadRequestError as e:
            j.logger.debug(e)
Exemple #13
0
    def _set_account_signers(self, address, public_key_signer, preauth_tx_hash, signer_kp):
        server = self._get_horizon_server()
        if address == self.address:
            account = self.load_account()
        else:
            account = server.load_account(address)
        tx = (
            stellar_sdk.TransactionBuilder(account)
            .append_pre_auth_tx_signer(preauth_tx_hash, 1)
            .append_ed25519_public_key_signer(public_key_signer, 1)
            .append_set_options_op(master_weight=1, low_threshold=2, med_threshold=2, high_threshold=2)
            .build()
        )

        tx.sign(signer_kp)
        response = server.submit_transaction(tx)
        j.logger.info(response)
        j.logger.info(f"Set the signers of {address} to {public_key_signer} and {preauth_tx_hash}")
Exemple #14
0
    def remove_signer(self, public_key_signer):
        """remove_signer removes a public key as a signer from the source account

        Args:
            public_key_signer (str): public key of an account
        """
        server = self._get_horizon_server()
        account = self.load_account()
        tx = stellar_sdk.TransactionBuilder(account).append_ed25519_public_key_signer(public_key_signer, 0).build()

        source_keypair = stellar_sdk.Keypair.from_secret(self.secret)

        tx.sign(source_keypair)
        try:
            response = server.submit_transaction(tx)
            j.logger.info(response)
            j.logger.info("Multisig tx signed and sent")
        except stellar_sdk.exceptions.BadRequestError:
            j.logger.info("Transaction need additional signatures in order to send")
            return tx.to_xdr()
Exemple #15
0
    def _change_trustline(self, asset_code, issuer, limit=None, secret=None):
        """Create a trustline between you and the issuer of an asset

        Args:
            asset_code (str): code which form the asset. For example: 'BTC', 'TFT', ...
            issuer (str): address of the asset issuer
            limit ([type], optional): The limit for the asset, defaults to max int64(922337203685.4775807). If the limit is set to “0” it deletes the trustline. Defaults to None.
            secret (str, optional): Secret to use will use instance property if empty. Defaults to None.
        """
        # if no secret is provided we assume we change trustlines for this account
        secret = secret or self.secret

        server = self._get_horizon_server()
        source_keypair = stellar_sdk.Keypair.from_secret(secret)
        source_public_key = source_keypair.public_key
        source_account = server.load_account(source_public_key)

        base_fee = server.fetch_base_fee()

        transaction = (
            stellar_sdk.TransactionBuilder(
                source_account=source_account,
                network_passphrase=_NETWORK_PASSPHRASES[self.network.value],
                base_fee=base_fee,
            )
            .append_change_trust_op(asset_issuer=issuer, asset_code=asset_code, limit=limit)
            .set_timeout(30)
            .build()
        )

        transaction.sign(source_keypair)

        try:
            server.submit_transaction(transaction)
            if limit is None:
                j.logger.info(f"Added trustline {asset_code}:{issuer} to account {self.address}")
        except stellar_sdk.exceptions.BadRequestError as e:
            j.logger.debug(e)
            raise e
Exemple #16
0
    def merge_into_account(self, destination_address: str):
        """Merges XLMs into destination address

        Args:
            destination_address (str): address to send XLMs to
        """
        server = self._get_horizon_server()
        source_keypair = stellar_sdk.Keypair.from_secret(self.secret)

        source_account = self.load_account()

        base_fee = server.fetch_base_fee()
        transaction = (stellar_sdk.TransactionBuilder(
            source_account=source_account,
            network_passphrase=self.network["network_passphrase"],
            base_fee=base_fee,
        ).append_account_merge_op(destination=destination_address).build())
        transaction.sign(source_keypair)
        try:
            response = server.submit_transaction(transaction)
            print("Transaction hash: {}".format(response["hash"]))
        except stellar_sdk.exceptions.BadRequestError as e:
            print(e)
Exemple #17
0
    def _activate_account(self, address):
        wallet = self._get_wallet()
        tftasset = wallet._get_asset()
        server = wallet._get_horizon_server()

        source_account = wallet.load_account()

        base_fee = server.fetch_base_fee()
        transaction = (stellar_sdk.TransactionBuilder(
            source_account=source_account,
            network_passphrase=self._get_network_passphrase(
                wallet.network.value),
            base_fee=base_fee,
        ).append_begin_sponsoring_future_reserves_op(
            address).append_create_account_op(
                destination=address,
                starting_balance="0").append_change_trust_op(
                    asset_issuer=tftasset.issuer,
                    asset_code=tftasset.code,
                    source=address).append_end_sponsoring_future_reserves_op(
                        address).set_timeout(60).build())
        source_keypair = stellar_sdk.Keypair.from_secret(wallet.secret)
        transaction.sign(source_keypair)
        return transaction.to_xdr()
Exemple #18
0
    def transfer(
        self,
        destination_address,
        amount,
        asset="XLM",
        locked_until=None,
        memo_text=None,
        memo_hash=None,
        fund_transaction=True,
        from_address=None,
        timeout=30,
        sequence_number: int = None,
        sign: bool = True,
    ):
        """Transfer assets to another address

        Args:
            destination_address (str): address of the destination
            amount (str): can be a floating point number with 7 numbers after the decimal point expressed as a string
            asset (str, optional): asset to transfer. Defaults to "XLM". if you wish to specify an asset it should be in format 'assetcode:issuer'. Where issuer is the address of the
            issuer of the asset.
            locked_until (float, optional): epoch timestamp indicating until when the tokens  should be locked. Defaults to None.
            memo_text (Union[str, bytes], optional): memo text to add to the transaction, a string encoded using either ASCII or UTF-8, up to 28-bytes long. Defaults to None.
            memo_hash (Union[str, bytes], optional): memo hash to add to the transaction, A 32 byte hash. Defaults to None.
            fund_transaction (bool, optional): use the threefoldfoundation transaction funding service. Defautls to True.
            from_address (str, optional): Use a different address to send the tokens from, useful in multisig use cases. Defaults to None.
            timeout (int,optional: Seconds from now on until when the transaction to be submitted to the stellar network
            sequence_number (int,optional): specify a specific sequence number ( will still be increased by one) instead of loading it from the account
            sign (bool,optional) : Do not sign and submit the transaction

        Raises:
            Exception: If asset not in correct format
            stellar_sdk.exceptions.BadRequestError: not enough funds for opertaion
            stellar_sdk.exceptions.BadRequestError: bad transfer authentication

        Returns:
            [type]: [description]
        """
        issuer = None
        j.logger.info(f"Sending {amount} {asset} to {destination_address}")
        if asset != "XLM":
            assetStr = asset.split(":")
            if len(assetStr) != 2:
                raise Exception("Wrong asset format should be in format 'assetcode:issuer'")
            asset = assetStr[0]
            issuer = assetStr[1]

        if locked_until is not None:
            return self._transfer_locked_tokens(
                destination_address,
                amount,
                asset,
                issuer,
                locked_until,
                memo_text=memo_text,
                memo_hash=memo_hash,
                fund_transaction=fund_transaction,
                from_address=from_address,
            )

        horizon_server = self._get_horizon_server()

        base_fee = horizon_server.fetch_base_fee()
        if from_address:
            source_account = horizon_server.load_account(from_address)
        else:
            source_account = self.load_account()

        if sequence_number:
            source_account.sequence = sequence_number

        transaction_builder = stellar_sdk.TransactionBuilder(
            source_account=source_account,
            network_passphrase=_NETWORK_PASSPHRASES[self.network.value],
            base_fee=base_fee,
        )
        transaction_builder.append_payment_op(
            destination=destination_address,
            amount=str(amount),
            asset_code=asset,
            asset_issuer=issuer,
            source=source_account.account_id,
        )
        transaction_builder.set_timeout(timeout)
        if memo_text is not None:
            transaction_builder.add_text_memo(memo_text)
        if memo_hash is not None:
            transaction_builder.add_hash_memo(memo_hash)

        transaction = transaction_builder.build()
        transaction = transaction.to_xdr()

        if asset == "TFT" or asset == "FreeTFT":
            if fund_transaction:
                transaction = self._fund_transaction(transaction=transaction)
                transaction = transaction["transaction_xdr"]

        if not sign:
            return transaction

        transaction = stellar_sdk.TransactionEnvelope.from_xdr(transaction, _NETWORK_PASSPHRASES[self.network.value])

        my_keypair = stellar_sdk.Keypair.from_secret(self.secret)
        transaction.sign(my_keypair)
        response = horizon_server.submit_transaction(transaction)
        tx_hash = response["hash"]
        j.logger.info(f"Transaction hash: {tx_hash}")
        return tx_hash
Exemple #19
0
    def _create_vesting_account(self, owner_address) -> str:

        if self._is_multisig_account(owner_address):
            raise j.exceptions.Value("Multisig accounts are not supported")

        existing_escrow_address = self._check_has_vesting_account(
            owner_address)
        if existing_escrow_address:
            return existing_escrow_address

        escrow_kp = stellar_sdk.Keypair.random()
        escrow_address = escrow_kp.public_key

        horizon_server = self._get_horizon_server()

        base_fee = horizon_server.fetch_base_fee()
        # TODO: serialize with a gevent pool

        wallet = get_wallet()
        if not wallet:
            raise j.exceptions.Value("Service unavailable")

        activation_account = wallet.load_account()

        tftasset = wallet._get_asset()

        txb = (stellar_sdk.TransactionBuilder(
            activation_account,
            network_passphrase=self._get_network_passphrase(
            )).append_create_account_op(
                escrow_address, starting_balance="7.6").append_change_trust_op(
                    "TFT", self._get_tft_issuer(), source=escrow_address))
        activation_kp = stellar_sdk.Keypair.from_secret(wallet.secret)

        tx = txb.build()
        tx.sign(activation_kp)
        tx.sign(escrow_kp)
        horizon_server.submit_transaction(tx)
        # TODO: try except and clean up the unfinished vesting account
        vesting_account = horizon_server.load_account(escrow_address)
        txb = stellar_sdk.TransactionBuilder(
            vesting_account, network_passphrase=self._get_network_passphrase(
            )).append_ed25519_public_key_signer(owner_address,
                                                weight=5,
                                                source=escrow_address)
        recovery_transaction = self._create_recovery_transaction(
            escrow_address)

        txb.append_pre_auth_tx_signer(recovery_transaction.hash(),
                                      weight=10,
                                      source=escrow_address)
        for cosigner in self._get_cosigners():
            txb.append_ed25519_public_key_signer(cosigner,
                                                 weight=1,
                                                 source=escrow_address)
        txb.append_manage_data_op(DATA_ENTRY_KEY,
                                  VESTING_SCHEME,
                                  source=escrow_address)
        txb.append_set_options_op(master_weight=0,
                                  low_threshold=10,
                                  med_threshold=10,
                                  high_threshold=10,
                                  source=escrow_address)

        tx = txb.build()
        tx.sign(escrow_kp)
        horizon_server.submit_transaction(tx)
        return escrow_address