def test_check_memo_required_with_path_payment_strict_send_raise_sync(
         self, httpserver):
     self.__inject_mock_server(httpserver)
     horizon_url = httpserver.url_for("/")
     server = Server(horizon_url)
     keypair = Keypair.from_secret(
         "SDQXFKA32UVQHUTLYJ42N56ZUEM5PNVVI4XE7EA5QFMLA2DHDCQX3GPY")
     account = Account(keypair.public_key, 1)
     transaction = (TransactionBuilder(account).append_payment_op(
         self.DESTINATION_ACCOUNT_NO_MEMO_REQUIRED, "10",
         "XLM").append_path_payment_strict_receive_op(
             self.DESTINATION_ACCOUNT_NO_MEMO_REQUIRED,
             "XLM",
             None,
             "10",
             "BTC",
             "GA7GYB3QGLTZNHNGXN3BMANS6TC7KJT3TCGTR763J4JOU4QHKL37RVV2",
             "1",
             [],
         ).append_path_payment_strict_send_op(
             self.DESTINATION_ACCOUNT_MEMO_REQUIRED_C,
             "XLM",
             None,
             "10",
             "BTC",
             "GA7GYB3QGLTZNHNGXN3BMANS6TC7KJT3TCGTR763J4JOU4QHKL37RVV2",
             "1",
             [],
         ).append_account_merge_op(
             self.DESTINATION_ACCOUNT_MEMO_REQUIRED_D).build())
     transaction.sign(keypair)
     with pytest.raises(
             AccountRequiresMemoError,
             match="Destination account requires a memo in the transaction.",
     ) as err:
         server.submit_transaction(transaction)
     assert err.value.account_id == self.DESTINATION_ACCOUNT_MEMO_REQUIRED_C
     assert err.value.operation_index == 2
Ejemplo n.º 2
0
    def _change_trustline(self, asset_code, issuer, limit=None, secret=None):
        """Create a trustline between you and the issuer of an asset.
        :param asset_code: code which form the asset. For example: 'BTC', 'TFT', ...
        :type asset_code: str
        :param issuer: address of the asset issuer.
        :type issuer: str
        :param limit: The limit for the asset, defaults to max int64(922337203685.4775807). If the limit is set to “0” it deletes the trustline
        """
        # if no secret is provided we assume we change trustlines for this account
        if secret is None:
            secret = self.secret

        server = self._get_horizon_server()
        source_keypair = 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 = (
            TransactionBuilder(
                source_account=source_account,
                network_passphrase=_NETWORK_PASSPHRASES[str(self.network)],
                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:
            response = server.submit_transaction(transaction)
            self._log_info("Transaction hash: {}".format(response["hash"]))
        except BadRequestError as e:
            self._log_debug(e)
            raise e
Ejemplo n.º 3
0
 def pagoAssets(self, Destino, monto, codigo, asset_usuario):
     server = Server(horizon_url=self.Horizon_url)
     root_keypair = Keypair.from_secret(self.sLlave)
     root_account = server.load_account(account_id=root_keypair.public_key)
     base_fee = server.fetch_base_fee()
     transaction = TransactionBuilder(
         source_account=root_account,
         network_passphrase=self.networkTrabajar,
         base_fee=base_fee) \
         .append_payment_op(  # add a payment operation to the transaction
         destination=Destino,
         asset_code=str(codigo),
         amount=str(monto),
         asset_issuer=asset_usuario) \
         .set_timeout(30) \
         .build()  # mark this transaction as valid only for the next 30 seconds
     transaction.sign(root_keypair)
     try:
         response = server.submit_transaction(transaction)
         return [True, response]
     except exceptions.BadRequestError as d:
         # print(d)
         return [False, d]
Ejemplo n.º 4
0
    def test_verify_challenge_transaction_signers_raise_no_client_signer_found(self):
        server_kp = Keypair.random()
        client_kp_a = Keypair.random()
        client_kp_b = Keypair.random()
        client_kp_c = Keypair.random()
        timeout = 600
        network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
        domain_name = "example.com"

        challenge = build_challenge_transaction(
            server_secret=server_kp.secret,
            client_account_id=client_kp_a.public_key,
            domain_name=domain_name,
            network_passphrase=network_passphrase,
            timeout=timeout,
        )

        transaction = TransactionEnvelope.from_xdr(challenge, network_passphrase)
        transaction.sign(client_kp_a)
        transaction.sign(client_kp_b)
        transaction.sign(client_kp_c)

        challenge_tx = transaction.to_xdr()
        signers = [
            Ed25519PublicKeySigner(Keypair.random().public_key, 1),
            Ed25519PublicKeySigner(Keypair.random().public_key, 2),
            Ed25519PublicKeySigner(Keypair.random().public_key, 4),
        ]

        with pytest.raises(
            InvalidSep10ChallengeError,
            match="Transaction not signed by any client signer.",
        ):
            verify_challenge_transaction_signers(
                challenge_tx,
                server_kp.public_key,
                domain_name,
                network_passphrase,
                signers,
            )
Ejemplo n.º 5
0
    def test_to_xdr_v0(self):
        source = Keypair.from_public_key(
            "GC3GJU6L7V7ZLPLKG3NTMC6GYYKBMNNKCPP36FG3LWEVPOHUPY6QJIGL")
        destination = "GDJJRRMBK4IWLEPJGIE6SXD2LP7REGZODU7WDC3I2D6MR37F4XSHBKX2"
        amount = "1000.0"
        sequence = 2
        memo = NoneMemo()
        fee = 200
        asset = Asset.native()
        time_bounds = TimeBounds(12345, 56789)
        ops = [Payment(destination, asset, amount)]

        tx_object = Transaction(source, sequence, fee, ops, memo, time_bounds,
                                False).to_xdr_object()

        restore_transaction = Transaction.from_xdr_object(tx_object, False)
        assert isinstance(restore_transaction, Transaction)
        assert restore_transaction.source == MuxedAccount.from_account(
            source.public_key)
        assert restore_transaction.fee == fee
        assert restore_transaction.memo == memo
        assert restore_transaction.time_bounds == time_bounds
        assert restore_transaction.sequence == sequence
Ejemplo n.º 6
0
def test_interactive_deposit_post_no_content_tx_complete(
    mock_content_for_template, mock_form_for_transaction, client
):
    usd = Asset.objects.create(
        code="USD",
        issuer=Keypair.random().public_key,
        sep24_enabled=True,
        deposit_enabled=True,
    )
    deposit = Transaction.objects.create(
        asset=usd, kind=Transaction.KIND.deposit, status=Transaction.STATUS.completed
    )
    mock_form_for_transaction.return_value = None
    mock_content_for_template.return_value = {"test": "value"}
    payload = interactive_jwt_payload(deposit, "deposit")
    token = jwt.encode(payload, settings.SERVER_JWT_KEY, algorithm="HS256").decode(
        "ascii"
    )
    response = client.get(
        f"{WEBAPP_PATH}"
        f"?token={token}"
        f"&transaction_id={deposit.id}"
        f"&asset_code={usd.code}"
    )
    assert response.status_code == 200
    assert client.session["authenticated"] is True

    response = client.post(
        f"{WEBAPP_PATH}/submit"
        f"?transaction_id={deposit.id}"
        f"&asset_code={deposit.asset.code}"
    )
    assert response.status_code == 422
    assert (
        "The anchor did not provide content, is the interactive flow already complete?"
        in str(response.content)
    )
Ejemplo n.º 7
0
def test_deposit_interactive_complete(mock_interactive_url, client):
    usd = Asset.objects.create(
        code="USD",
        issuer=Keypair.random().public_key,
        sep24_enabled=True,
        deposit_enabled=True,
    )
    deposit = Transaction.objects.create(
        asset=usd, status=Transaction.STATUS.incomplete
    )
    payload = interactive_jwt_payload(deposit, "deposit")
    token = jwt.encode(payload, settings.SERVER_JWT_KEY, algorithm="HS256").decode(
        "ascii"
    )
    mock_interactive_url.return_value = "https://test.com/customFlow"

    response = client.get(
        f"{WEBAPP_PATH}"
        f"?token={token}"
        f"&transaction_id={deposit.id}"
        f"&asset_code={deposit.asset.code}"
    )
    assert response.status_code == 302
    mock_interactive_url.assert_called_once()
    assert client.session["authenticated"] is True

    response = client.get(
        DEPOSIT_PATH + "/complete",
        {"transaction_id": deposit.id, "callback": "test.com/callback"},
    )
    assert response.status_code == 302
    redirect_to_url = response.get("Location")
    assert "more_info" in redirect_to_url
    assert "callback=test.com%2Fcallback" in redirect_to_url

    deposit.refresh_from_db()
    assert deposit.status == Transaction.STATUS.pending_user_transfer_start
Ejemplo n.º 8
0
def test_deposit_authenticated_success(client, acc1_usd_deposit_transaction_factory):
    """`GET /deposit` succeeds with the SEP 10 authentication flow."""
    from polaris.tests.auth_test import endpoint

    deposit = acc1_usd_deposit_transaction_factory()

    # SEP 10.
    response = client.get(f"{endpoint}?account={client_address}", follow=True)
    content = json.loads(response.content)

    envelope_xdr = content["transaction"]
    envelope_object = TransactionEnvelope.from_xdr(
        envelope_xdr, network_passphrase=settings.STELLAR_NETWORK_PASSPHRASE
    )
    client_signing_key = Keypair.from_secret(client_seed)
    envelope_object.sign(client_signing_key)
    client_signed_envelope_xdr = envelope_object.to_xdr()

    response = client.post(
        endpoint,
        data={"transaction": client_signed_envelope_xdr},
        content_type="application/json",
    )
    content = json.loads(response.content)
    encoded_jwt = content["token"]
    assert encoded_jwt

    header = {"HTTP_AUTHORIZATION": f"Bearer {encoded_jwt}"}
    response = client.post(
        DEPOSIT_PATH,
        {"asset_code": "USD", "account": deposit.stellar_account},
        follow=True,
        **header,
    )
    content = json.loads(response.content)
    assert response.status_code == 200
    assert content["type"] == "interactive_customer_info_needed"
    def test_read_challenge_transaction_mux_server_id_raise(self):
        server_kp = Keypair.random()
        client_account_id = "GBDIT5GUJ7R5BXO3GJHFXJ6AZ5UQK6MNOIDMPQUSMXLIHTUNR2Q5CFNF"
        timeout = 600
        network_passphrase = Network.TESTNET_NETWORK_PASSPHRASE
        anchor_name = "SDF"

        challenge = build_challenge_transaction(
            server_secret=server_kp.secret,
            client_account_id=client_account_id,
            anchor_name=anchor_name,
            network_passphrase=network_passphrase,
            timeout=timeout,
        )
        with pytest.raises(
                ValueError,
                match=
                "Invalid server_account_id, multiplexed account are not supported.",
        ):
            read_challenge_transaction(
                challenge,
                "MAAAAAAAAAAAJURAAB2X52XFQP6FBXLGT6LWOOWMEXWHEWBDVRZ7V5WH34Y22MPFBHUHY",
                network_passphrase,
            )
Ejemplo n.º 10
0
def test_deposit_authenticated_success(client,
                                       acc1_usd_deposit_transaction_factory):
    """`GET /deposit` succeeds with the SEP 10 authentication flow."""
    client_address = "GDKFNRUATPH4BSZGVFDRBIGZ5QAFILVFRIRYNSQ4UO7V2ZQAPRNL73RI"
    client_seed = "SDKWSBERDHP3SXW5A3LXSI7FWMMO5H7HG33KNYBKWH2HYOXJG2DXQHQY"
    deposit = acc1_usd_deposit_transaction_factory()

    # SEP 10.
    response = client.get(f"/auth?account={client_address}", follow=True)
    content = json.loads(response.content)

    envelope_xdr = content["transaction"]
    envelope_object = TransactionEnvelope.from_xdr(
        envelope_xdr, network_passphrase=settings.STELLAR_NETWORK_PASSPHRASE)
    client_signing_key = Keypair.from_secret(client_seed)
    envelope_object.sign(client_signing_key)
    client_signed_envelope_xdr = envelope_object.to_xdr()

    response = client.post(
        "/auth",
        data={"transaction": client_signed_envelope_xdr},
        content_type="application/json",
    )
    content = json.loads(response.content)
    encoded_jwt = content["token"]
    assert encoded_jwt

    header = {"HTTP_AUTHORIZATION": f"Bearer {encoded_jwt}"}
    response = client.get(
        f"/deposit?asset_code=USD&account={deposit.stellar_account}",
        follow=True,
        **header,
    )
    content = json.loads(response.content)
    assert response.status_code == 403
    assert content["type"] == "interactive_customer_info_needed"
    def test_verify_challenge_transaction_signers_raise_unrecognized_signatures(
            self):
        server_kp = Keypair.random()
        client_kp_a = Keypair.random()
        client_kp_b = Keypair.random()
        client_kp_c = Keypair.random()
        client_kp_unrecognized = Keypair.random()

        timeout = 600
        network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
        home_domain = "example.com"

        challenge = build_challenge_transaction(
            server_secret=server_kp.secret,
            client_account_id=client_kp_a.public_key,
            home_domain=home_domain,
            network_passphrase=network_passphrase,
            timeout=timeout,
        )

        transaction = TransactionEnvelope.from_xdr(challenge,
                                                   network_passphrase)
        transaction.sign(client_kp_a)
        transaction.sign(client_kp_b)
        transaction.sign(client_kp_c)
        transaction.sign(client_kp_unrecognized)

        challenge_tx = transaction.to_xdr()
        signers = [
            Ed25519PublicKeySigner(client_kp_a.public_key, 1),
            Ed25519PublicKeySigner(client_kp_b.public_key, 2),
            Ed25519PublicKeySigner(client_kp_c.public_key, 4),
            Ed25519PublicKeySigner(Keypair.random().public_key, 255),
        ]
        with pytest.raises(InvalidSep10ChallengeError,
                           match="Transaction has unrecognized signatures."):
            verify_challenge_transaction_signers(
                challenge_tx,
                server_kp.public_key,
                home_domain,
                network_passphrase,
                signers,
            )
class TestPayStellarUri:
    @pytest.mark.parametrize(
        "destination, amount, asset, memo, callback, message, network_passphrase, origin_domain, signature, signer, uri",
        [
            (
                "GCALNQQBXAPZ2WIRSDDBMSTAKCUH5SG6U76YBFLQLIXJTF7FE5AX7AOO",
                "120.1234567",
                None,
                TextMemo("skdjfasf"),
                None,
                "pay me with lumens",
                None,
                "someDomain.com",
                None,
                "SBPOVRVKTTV7W3IOX2FJPSMPCJ5L2WU2YKTP3HCLYPXNI5MDIGREVNYC",
                "web+stellar:pay?destination=GCALNQQBXAPZ2WIRSDDBMSTAKCUH5SG6U76YBFLQLIXJTF7FE5AX7AOO&amount=120.1234567&memo=skdjfasf&memo_type=MEMO_TEXT&msg=pay%20me%20with%20lumens&origin_domain=someDomain.com&signature=tbsLtlK%2FfouvRWk2UWFP47yHYeI1g1NEC%2FfEQvuXG6V8P%2BbeLxplYbOVtTk1g94Wp97cHZ3pVJy%2FtZNYobl3Cw%3D%3D",
            ),
            (
                "GCALNQQBXAPZ2WIRSDDBMSTAKCUH5SG6U76YBFLQLIXJTF7FE5AX7AOO",
                "120.1234567",
                None,
                TextMemo("skdjfasf"),
                None,
                "pay me with lumens",
                None,
                "someDomain.com",
                "testSignature",
                "SBPOVRVKTTV7W3IOX2FJPSMPCJ5L2WU2YKTP3HCLYPXNI5MDIGREVNYC",
                "web+stellar:pay?destination=GCALNQQBXAPZ2WIRSDDBMSTAKCUH5SG6U76YBFLQLIXJTF7FE5AX7AOO&amount=120.1234567&memo=skdjfasf&memo_type=MEMO_TEXT&msg=pay%20me%20with%20lumens&origin_domain=someDomain.com&signature=tbsLtlK%2FfouvRWk2UWFP47yHYeI1g1NEC%2FfEQvuXG6V8P%2BbeLxplYbOVtTk1g94Wp97cHZ3pVJy%2FtZNYobl3Cw%3D%3D",
            ),
            (
                "GCALNQQBXAPZ2WIRSDDBMSTAKCUH5SG6U76YBFLQLIXJTF7FE5AX7AOO",
                "120.1234567",
                None,
                TextMemo("skdjfasf"),
                None,
                "pay me with lumens",
                None,
                "someDomain.com",
                None,
                None,
                "web+stellar:pay?destination=GCALNQQBXAPZ2WIRSDDBMSTAKCUH5SG6U76YBFLQLIXJTF7FE5AX7AOO&amount=120.1234567&memo=skdjfasf&memo_type=MEMO_TEXT&msg=pay%20me%20with%20lumens&origin_domain=someDomain.com",
            ),
            (
                "GCALNQQBXAPZ2WIRSDDBMSTAKCUH5SG6U76YBFLQLIXJTF7FE5AX7AOO",
                "120.1234567",
                None,
                TextMemo("skdjfasf"),
                None,
                "pay me with lumens",
                None,
                "someDomain.com",
                "testSignature",
                None,
                "web+stellar:pay?destination=GCALNQQBXAPZ2WIRSDDBMSTAKCUH5SG6U76YBFLQLIXJTF7FE5AX7AOO&amount=120.1234567&memo=skdjfasf&memo_type=MEMO_TEXT&msg=pay%20me%20with%20lumens&origin_domain=someDomain.com&signature=testSignature",
            ),
            (
                "GCALNQQBXAPZ2WIRSDDBMSTAKCUH5SG6U76YBFLQLIXJTF7FE5AX7AOO",
                "120.1234567",
                None,
                TextMemo("skdjfasf"),
                None,
                "_" * 300,
                None,
                "someDomain.com",
                None,
                "SBPOVRVKTTV7W3IOX2FJPSMPCJ5L2WU2YKTP3HCLYPXNI5MDIGREVNYC",
                "web+stellar:pay?destination=GCALNQQBXAPZ2WIRSDDBMSTAKCUH5SG6U76YBFLQLIXJTF7FE5AX7AOO&amount=120.1234567&memo=skdjfasf&memo_type=MEMO_TEXT&msg=____________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________&origin_domain=someDomain.com&signature=d94yTtEX0PMUDwwYfzLuVx6luuEiVlxyVQrkR%2FM4NIundX2VqXLVE%2F6FX8G5x4MZ1qc0u661t4Rfu5SKyTIjCg%3D%3D",
            ),
            (
                "GCALNQQBXAPZ2WIRSDDBMSTAKCUH5SG6U76YBFLQLIXJTF7FE5AX7AOO",
                "120.1234567",
                None,
                NoneMemo(),
                None,
                "pay me with lumens",
                None,
                "someDomain.com",
                None,
                Keypair.from_secret(
                    "SBPOVRVKTTV7W3IOX2FJPSMPCJ5L2WU2YKTP3HCLYPXNI5MDIGREVNYC"
                ),
                "web+stellar:pay?destination=GCALNQQBXAPZ2WIRSDDBMSTAKCUH5SG6U76YBFLQLIXJTF7FE5AX7AOO&amount=120.1234567&msg=pay%20me%20with%20lumens&origin_domain=someDomain.com&signature=t9glBiurQ1MUyk3T5BIqxgJwbrNT1ZDIzQ6aKDJmPgM8heN1NEk%2FusfMq6lSaqtxUuysfZisgPM8TiSY0ckyCw%3D%3D",
            ),
            (
                "GCALNQQBXAPZ2WIRSDDBMSTAKCUH5SG6U76YBFLQLIXJTF7FE5AX7AOO",
                "120.1234567",
                None,
                TextMemo("skdjfasf"),
                None,
                "pay me with lumens",
                None,
                "someDomain.com",
                None,
                Keypair.from_secret(
                    "SBPOVRVKTTV7W3IOX2FJPSMPCJ5L2WU2YKTP3HCLYPXNI5MDIGREVNYC"
                ),
                "web+stellar:pay?destination=GCALNQQBXAPZ2WIRSDDBMSTAKCUH5SG6U76YBFLQLIXJTF7FE5AX7AOO&amount=120.1234567&memo=skdjfasf&memo_type=MEMO_TEXT&msg=pay%20me%20with%20lumens&origin_domain=someDomain.com&signature=tbsLtlK%2FfouvRWk2UWFP47yHYeI1g1NEC%2FfEQvuXG6V8P%2BbeLxplYbOVtTk1g94Wp97cHZ3pVJy%2FtZNYobl3Cw%3D%3D",
            ),
            (
                "GCALNQQBXAPZ2WIRSDDBMSTAKCUH5SG6U76YBFLQLIXJTF7FE5AX7AOO",
                "120.1234567",
                Asset.native(),
                TextMemo("skdjfasf"),
                None,
                "pay me with lumens",
                None,
                "someDomain.com",
                None,
                Keypair.from_secret(
                    "SBPOVRVKTTV7W3IOX2FJPSMPCJ5L2WU2YKTP3HCLYPXNI5MDIGREVNYC"
                ),
                "web+stellar:pay?destination=GCALNQQBXAPZ2WIRSDDBMSTAKCUH5SG6U76YBFLQLIXJTF7FE5AX7AOO&amount=120.1234567&memo=skdjfasf&memo_type=MEMO_TEXT&msg=pay%20me%20with%20lumens&origin_domain=someDomain.com&signature=tbsLtlK%2FfouvRWk2UWFP47yHYeI1g1NEC%2FfEQvuXG6V8P%2BbeLxplYbOVtTk1g94Wp97cHZ3pVJy%2FtZNYobl3Cw%3D%3D",
            ),
            (
                "GCALNQQBXAPZ2WIRSDDBMSTAKCUH5SG6U76YBFLQLIXJTF7FE5AX7AOO",
                "120.1234567",
                Asset.native(),
                IdMemo(10086),
                None,
                "pay me with lumens",
                None,
                "someDomain.com",
                None,
                Keypair.from_secret(
                    "SBPOVRVKTTV7W3IOX2FJPSMPCJ5L2WU2YKTP3HCLYPXNI5MDIGREVNYC"
                ),
                "web+stellar:pay?destination=GCALNQQBXAPZ2WIRSDDBMSTAKCUH5SG6U76YBFLQLIXJTF7FE5AX7AOO&amount=120.1234567&memo=10086&memo_type=MEMO_ID&msg=pay%20me%20with%20lumens&origin_domain=someDomain.com&signature=cTyphv1qE6YqnwKu1O4psEzA8O6vNYu%2FDbvGb0Nu53V%2FL8U7LoGknX1JOGLsgGjOXdfAmJbG8rxF8I9DD%2BvjCA%3D%3D",
            ),
            (
                "GCALNQQBXAPZ2WIRSDDBMSTAKCUH5SG6U76YBFLQLIXJTF7FE5AX7AOO",
                "120.1234567",
                Asset.native(),
                HashMemo(
                    "218a3ef357324c496d07f7d7b31be5c2a11a1ac44af9b81938a6c5b9c0684af4"
                ),
                None,
                "pay me with lumens",
                None,
                "someDomain.com",
                None,
                Keypair.from_secret(
                    "SBPOVRVKTTV7W3IOX2FJPSMPCJ5L2WU2YKTP3HCLYPXNI5MDIGREVNYC"
                ),
                "web+stellar:pay?destination=GCALNQQBXAPZ2WIRSDDBMSTAKCUH5SG6U76YBFLQLIXJTF7FE5AX7AOO&amount=120.1234567&memo=IYo%2B81cyTEltB%2FfXsxvlwqEaGsRK%2BbgZOKbFucBoSvQ%3D&memo_type=MEMO_HASH&msg=pay%20me%20with%20lumens&origin_domain=someDomain.com&signature=CzqyewhypDQGCBlvxSj%2BazIm5iS2GDqcOlBeXT%2FB7s8ogEXC8hNa6HjOArdbTkvNCUvTl6lgyKOj%2FeeNE%2BA5DQ%3D%3D",
            ),
            (
                "GCALNQQBXAPZ2WIRSDDBMSTAKCUH5SG6U76YBFLQLIXJTF7FE5AX7AOO",
                "120.1234567",
                Asset.native(),
                ReturnHashMemo(
                    "218a3ef357324c496d07f7d7b31be5c2a11a1ac44af9b81938a6c5b9c0684af4"
                ),
                None,
                "pay me with lumens",
                None,
                "someDomain.com",
                None,
                Keypair.from_secret(
                    "SBPOVRVKTTV7W3IOX2FJPSMPCJ5L2WU2YKTP3HCLYPXNI5MDIGREVNYC"
                ),
                "web+stellar:pay?destination=GCALNQQBXAPZ2WIRSDDBMSTAKCUH5SG6U76YBFLQLIXJTF7FE5AX7AOO&amount=120.1234567&memo=IYo%2B81cyTEltB%2FfXsxvlwqEaGsRK%2BbgZOKbFucBoSvQ%3D&memo_type=MEMO_RETURN&msg=pay%20me%20with%20lumens&origin_domain=someDomain.com&signature=4OJcgA0qxjUhqJL79MeK%2BkHgNjdKXiGhufvw2yjcXud7Ce%2BG53N0qSUpgXDT8OBDQRrI7Pe%2FUPu0%2FCM7DJkXAQ%3D%3D",
            ),
            (
                "GCALNQQBXAPZ2WIRSDDBMSTAKCUH5SG6U76YBFLQLIXJTF7FE5AX7AOO",
                "120.1234567",
                Asset(
                    "Hello",
                    "GBDIT5GUJ7R5BXO3GJHFXJ6AZ5UQK6MNOIDMPQUSMXLIHTUNR2Q5CFNF"
                ),
                TextMemo("Hello World"),
                "https://example.com/callback",
                "pay me with lumens",
                Network.TESTNET_NETWORK_PASSPHRASE,
                "someDomain.com",
                "testSignature",
                Keypair.from_secret(
                    "SBPOVRVKTTV7W3IOX2FJPSMPCJ5L2WU2YKTP3HCLYPXNI5MDIGREVNYC"
                ),
                "web+stellar:pay?destination=GCALNQQBXAPZ2WIRSDDBMSTAKCUH5SG6U76YBFLQLIXJTF7FE5AX7AOO&amount=120.1234567&asset_code=Hello&asset_issuer=GBDIT5GUJ7R5BXO3GJHFXJ6AZ5UQK6MNOIDMPQUSMXLIHTUNR2Q5CFNF&memo=Hello%20World&memo_type=MEMO_TEXT&callback=url%3Ahttps%3A%2F%2Fexample.com%2Fcallback&msg=pay%20me%20with%20lumens&network_passphrase=Test%20SDF%20Network%20%3B%20September%202015&origin_domain=someDomain.com&signature=k5cDMVTD2W2lKeEGqakjOTf3aPuPumlr8ObBOvauaa2QiXqa7%2Bw9WRgtmo6NaPXdOoFG5ScUIp9k7PdeuPieCw%3D%3D",
            ),
        ],
    )
    def test_to_uri(
        self,
        destination,
        amount,
        asset,
        memo,
        callback,
        message,
        network_passphrase,
        origin_domain,
        signature,
        signer,
        uri,
    ):
        uri_builder = PayStellarUri(
            destination=destination,
            amount=amount,
            asset=asset,
            memo=memo,
            callback=callback,
            message=message,
            network_passphrase=network_passphrase,
            origin_domain=origin_domain,
            signature=signature,
        )
        if signer:
            uri_builder.sign(signer)
        assert uri_builder.to_uri() == uri

    def test_message_too_long_raise(self):
        message = "_" * 301
        with pytest.raises(ValueError,
                           match="Message must not exceed 300 characters."):
            PayStellarUri(
                "GCALNQQBXAPZ2WIRSDDBMSTAKCUH5SG6U76YBFLQLIXJTF7FE5AX7AOO",
                message=message,
            )

    def test_invalid_memo_raise(self):
        memo = "invalid memo"
        with pytest.raises(ValueError, match="Invalid memo."):
            PayStellarUri(
                "GCALNQQBXAPZ2WIRSDDBMSTAKCUH5SG6U76YBFLQLIXJTF7FE5AX7AOO",
                memo=memo)

    def test_equal(self):
        assert PayStellarUri(
            "GCALNQQBXAPZ2WIRSDDBMSTAKCUH5SG6U76YBFLQLIXJTF7FE5AX7AOO"
        ) == PayStellarUri(
            "GCALNQQBXAPZ2WIRSDDBMSTAKCUH5SG6U76YBFLQLIXJTF7FE5AX7AOO")
class TestStellarTransactionStellarUri:
    xdr = "AAAAAP+yw+ZEuNg533pUmwlYxfrq6/BoMJqiJ8vuQhf6rHWmAAAAZAB8NHAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAYAAAABSFVHAAAAAABAH0wIyY3BJBS2qHdRPAV80M8hF7NBpxRjXyjuT9kEbH//////////AAAAAAAAAAA="
    tx = TransactionEnvelope.from_xdr(xdr, Network.TESTNET_NETWORK_PASSPHRASE)

    @pytest.mark.parametrize(
        "tx, replace, callback, pubkey, message, network_passphrase, origin_domain, signature, signer, uri",
        [
            (
                tx,
                [
                    Replacement("sourceAccount", "X",
                                "account on which to create the trustline")
                ],
                None,
                None,
                None,
                None,
                None,
                None,
                None,
                "web+stellar:tx?xdr=AAAAAP%2Byw%2BZEuNg533pUmwlYxfrq6%2FBoMJqiJ8vuQhf6rHWmAAAAZAB8NHAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAYAAAABSFVHAAAAAABAH0wIyY3BJBS2qHdRPAV80M8hF7NBpxRjXyjuT9kEbH%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FAAAAAAAAAAA%3D&replace=sourceAccount%3AX%3BX%3Aaccount%20on%20which%20to%20create%20the%20trustline",
            ),
            (
                tx,
                None,
                None,
                None,
                None,
                None,
                None,
                None,
                None,
                "web+stellar:tx?xdr=AAAAAP%2Byw%2BZEuNg533pUmwlYxfrq6%2FBoMJqiJ8vuQhf6rHWmAAAAZAB8NHAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAYAAAABSFVHAAAAAABAH0wIyY3BJBS2qHdRPAV80M8hF7NBpxRjXyjuT9kEbH%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FAAAAAAAAAAA%3D",
            ),
            (
                tx,
                [
                    Replacement("sourceAccount", "X",
                                "account on which to create the trustline"),
                    Replacement("seqNum", "Y", "sequence for sourceAccount"),
                ],
                None,
                None,
                None,
                None,
                None,
                None,
                None,
                "web+stellar:tx?xdr=AAAAAP%2Byw%2BZEuNg533pUmwlYxfrq6%2FBoMJqiJ8vuQhf6rHWmAAAAZAB8NHAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAYAAAABSFVHAAAAAABAH0wIyY3BJBS2qHdRPAV80M8hF7NBpxRjXyjuT9kEbH%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FAAAAAAAAAAA%3D&replace=sourceAccount%3AX%2CseqNum%3AY%3BX%3Aaccount%20on%20which%20to%20create%20the%20trustline%2CY%3Asequence%20for%20sourceAccount",
            ),
            (
                tx,
                [
                    Replacement("sourceAccount", "X",
                                "account on which to create the trustline")
                ],
                None,
                None,
                None,
                None,
                None,
                None,
                "SBPOVRVKTTV7W3IOX2FJPSMPCJ5L2WU2YKTP3HCLYPXNI5MDIGREVNYC",
                "web+stellar:tx?xdr=AAAAAP%2Byw%2BZEuNg533pUmwlYxfrq6%2FBoMJqiJ8vuQhf6rHWmAAAAZAB8NHAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAYAAAABSFVHAAAAAABAH0wIyY3BJBS2qHdRPAV80M8hF7NBpxRjXyjuT9kEbH%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FAAAAAAAAAAA%3D&replace=sourceAccount%3AX%3BX%3Aaccount%20on%20which%20to%20create%20the%20trustline&signature=VES7qVW1mbxV7PFDi8DvyrxP2EUhYqqGnw%2B%2BQEeIZeYIlrdvc9qqQo0dqtOR4qb2npoml1rlp%2F30WPikSaE6Bg%3D%3D",
            ),
            (
                tx,
                [
                    Replacement("sourceAccount", "X",
                                "account on which to create the trustline")
                ],
                None,
                None,
                None,
                None,
                None,
                "testSignature",
                "SBPOVRVKTTV7W3IOX2FJPSMPCJ5L2WU2YKTP3HCLYPXNI5MDIGREVNYC",
                "web+stellar:tx?xdr=AAAAAP%2Byw%2BZEuNg533pUmwlYxfrq6%2FBoMJqiJ8vuQhf6rHWmAAAAZAB8NHAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAYAAAABSFVHAAAAAABAH0wIyY3BJBS2qHdRPAV80M8hF7NBpxRjXyjuT9kEbH%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FAAAAAAAAAAA%3D&replace=sourceAccount%3AX%3BX%3Aaccount%20on%20which%20to%20create%20the%20trustline&signature=VES7qVW1mbxV7PFDi8DvyrxP2EUhYqqGnw%2B%2BQEeIZeYIlrdvc9qqQo0dqtOR4qb2npoml1rlp%2F30WPikSaE6Bg%3D%3D",
            ),
            (
                tx,
                [
                    Replacement("sourceAccount", "X",
                                "account on which to create the trustline")
                ],
                None,
                None,
                None,
                None,
                None,
                "testSignature",
                None,
                "web+stellar:tx?xdr=AAAAAP%2Byw%2BZEuNg533pUmwlYxfrq6%2FBoMJqiJ8vuQhf6rHWmAAAAZAB8NHAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAYAAAABSFVHAAAAAABAH0wIyY3BJBS2qHdRPAV80M8hF7NBpxRjXyjuT9kEbH%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FAAAAAAAAAAA%3D&replace=sourceAccount%3AX%3BX%3Aaccount%20on%20which%20to%20create%20the%20trustline&signature=testSignature",
            ),
            (
                tx,
                [
                    Replacement("sourceAccount", "X",
                                "account on which to create the trustline")
                ],
                None,
                None,
                None,
                None,
                None,
                None,
                Keypair.from_secret(
                    "SBPOVRVKTTV7W3IOX2FJPSMPCJ5L2WU2YKTP3HCLYPXNI5MDIGREVNYC"
                ),
                "web+stellar:tx?xdr=AAAAAP%2Byw%2BZEuNg533pUmwlYxfrq6%2FBoMJqiJ8vuQhf6rHWmAAAAZAB8NHAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAYAAAABSFVHAAAAAABAH0wIyY3BJBS2qHdRPAV80M8hF7NBpxRjXyjuT9kEbH%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FAAAAAAAAAAA%3D&replace=sourceAccount%3AX%3BX%3Aaccount%20on%20which%20to%20create%20the%20trustline&signature=VES7qVW1mbxV7PFDi8DvyrxP2EUhYqqGnw%2B%2BQEeIZeYIlrdvc9qqQo0dqtOR4qb2npoml1rlp%2F30WPikSaE6Bg%3D%3D",
            ),
            (
                tx,
                [
                    Replacement("sourceAccount", "X",
                                "account on which to create the trustline")
                ],
                "https://someSigningService.com",
                "GAU2ZSYYEYO5S5ZQSMMUENJ2TANY4FPXYGGIMU6GMGKTNVDG5QYFW6JS",
                "a" * 300,
                Network.TESTNET_NETWORK_PASSPHRASE,
                "someDomain.com",
                "testSignature",
                "SBPOVRVKTTV7W3IOX2FJPSMPCJ5L2WU2YKTP3HCLYPXNI5MDIGREVNYC",
                "web+stellar:tx?xdr=AAAAAP%2Byw%2BZEuNg533pUmwlYxfrq6%2FBoMJqiJ8vuQhf6rHWmAAAAZAB8NHAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAYAAAABSFVHAAAAAABAH0wIyY3BJBS2qHdRPAV80M8hF7NBpxRjXyjuT9kEbH%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FAAAAAAAAAAA%3D&callback=url%3Ahttps%3A%2F%2FsomeSigningService.com&replace=sourceAccount%3AX%3BX%3Aaccount%20on%20which%20to%20create%20the%20trustline&pubkey=GAU2ZSYYEYO5S5ZQSMMUENJ2TANY4FPXYGGIMU6GMGKTNVDG5QYFW6JS&msg=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&network_passphrase=Test%20SDF%20Network%20%3B%20September%202015&origin_domain=someDomain.com&signature=8uiZ2r7KT3gRsO%2BrzmofGHyl%2FLFMfOgNtx5oOddK2rAy8M%2BOgBYOSQpASNbIm%2BIvZVojxv8tKTYuzOkbyhPODA%3D%3D",
            ),
        ],
    )
    def test_to_uri(
        self,
        tx,
        replace,
        callback,
        pubkey,
        message,
        network_passphrase,
        origin_domain,
        signature,
        signer,
        uri,
    ):
        uri_builder = TransactionStellarUri(
            transaction_envelope=tx,
            replace=replace,
            callback=callback,
            pubkey=pubkey,
            message=message,
            network_passphrase=network_passphrase,
            origin_domain=origin_domain,
            signature=signature,
        )
        if signer:
            uri_builder.sign(signer)
        assert uri_builder.to_uri() == uri

    def test_message_too_long_raise(self):
        message = "_" * 301
        with pytest.raises(ValueError,
                           match="Message must not exceed 300 characters."):
            TransactionStellarUri(
                transaction_envelope=self.tx,
                message=message,
            )

    def test_equal(self):
        assert TransactionStellarUri(
            transaction_envelope=self.tx) == TransactionStellarUri(
                transaction_envelope=self.tx)
Ejemplo n.º 14
0
from stellar_sdk.sep.txrep import from_txrep, to_txrep
from stellar_sdk import Keypair, TransactionBuilder, Network, Account

source_secret_key = "SBFZCHU5645DOKRWYBXVOXY2ELGJKFRX6VGGPRYUWHQ7PMXXJNDZFMKD"

source_keypair = Keypair.from_secret(source_secret_key)
source_public_key = source_keypair.public_key

receiver_public_key = "GA7YNBW5CBTJZ3ZZOWX3ZNBKD6OE7A7IHUQVWMY62W2ZBG2SGZVOOPVH"
source_account = Account(source_public_key, 12345)


transaction = (
    TransactionBuilder(
        source_account=source_account,
        network_passphrase=Network.TESTNET_NETWORK_PASSPHRASE,
        base_fee=100,
    )
    .add_text_memo("Hello, Stellar!")
    .append_payment_op(receiver_public_key, "350.1234567", "XLM")
    .set_timeout(30)
    .build()
)

transaction.sign(source_keypair)

# convert transaction to txrep
txrep = to_txrep(transaction)
print(f"txrep: \n{txrep}")
# convert txrep to transaction
tx = from_txrep(txrep, Network.TESTNET_NETWORK_PASSPHRASE)
Ejemplo n.º 15
0
    def test_to_xdr_v0(self):
        sequence = 1
        source = Account(
            "GDF5O4OWEMVBY5FLDHWA5RZTYSV2U276XGKZZ6VSHDDR3THSQ6OQS7UM",
            sequence)
        builder = TransactionBuilder(source,
                                     Network.TESTNET_NETWORK_PASSPHRASE,
                                     base_fee=150,
                                     v1=False)
        builder.add_text_memo("Stellar Python SDK")
        builder.add_time_bounds(1565590000, 1565600000)
        te = (builder.append_create_account_op(
            "GDNSSYSCSSJ76FER5WEEXME5G4MTCUBKDRQSKOYP36KUKVDB2VCMERS6",
            "5.5",
            "GDF5O4OWEMVBY5FLDHWA5RZTYSV2U276XGKZZ6VSHDDR3THSQ6OQS7UM",
        ).append_change_trust_op(
            "XCN",
            "GDF5O4OWEMVBY5FLDHWA5RZTYSV2U276XGKZZ6VSHDDR3THSQ6OQS7UM",
            "100000",
        ).append_payment_op(
            "GAXN7HZQTHIPW7N2HGPAXMR42LPJ5VLYXMCCOX4D3JC4CQZGID3UYUPF",
            "12.25",
            "XLM",
        ).append_path_payment_strict_receive_op(
            "GAXN7HZQTHIPW7N2HGPAXMR42LPJ5VLYXMCCOX4D3JC4CQZGID3UYUPF",
            "XLM",
            None,
            "100",
            "XCN",
            "GDF5O4OWEMVBY5FLDHWA5RZTYSV2U276XGKZZ6VSHDDR3THSQ6OQS7UM",
            "1000.5",
            [
                Asset(
                    "USD",
                    "GDNSSYSCSSJ76FER5WEEXME5G4MTCUBKDRQSKOYP36KUKVDB2VCMERS6",
                ),
                Asset(
                    "BTC",
                    "GDNSSYSCSSJ76FER5WEEXME5G4MTCUBKDRQSKOYP36KUKVDB2VCMERS6",
                ),
            ],
        ).append_path_payment_strict_send_op(
            "GAXN7HZQTHIPW7N2HGPAXMR42LPJ5VLYXMCCOX4D3JC4CQZGID3UYUPF",
            "XLM",
            None,
            "100",
            "XCN",
            "GDF5O4OWEMVBY5FLDHWA5RZTYSV2U276XGKZZ6VSHDDR3THSQ6OQS7UM",
            "1000.5",
            [
                Asset(
                    "USD",
                    "GDNSSYSCSSJ76FER5WEEXME5G4MTCUBKDRQSKOYP36KUKVDB2VCMERS6",
                ),
                Asset(
                    "BTC",
                    "GDNSSYSCSSJ76FER5WEEXME5G4MTCUBKDRQSKOYP36KUKVDB2VCMERS6",
                ),
            ],
        ).append_allow_trust_op(
            "GDNSSYSCSSJ76FER5WEEXME5G4MTCUBKDRQSKOYP36KUKVDB2VCMERS6", "XCN",
            True
        ).append_set_options_op(
            "GAXN7HZQTHIPW7N2HGPAXMR42LPJ5VLYXMCCOX4D3JC4CQZGID3UYUPF",
            1,
            6,
            20,
            20,
            20,
            20,
            "stellarcn.org",
            Signer.ed25519_public_key(
                "GAXN7HZQTHIPW7N2HGPAXMR42LPJ5VLYXMCCOX4D3JC4CQZGID3UYUPF",
                10),
            "GDF5O4OWEMVBY5FLDHWA5RZTYSV2U276XGKZZ6VSHDDR3THSQ6OQS7UM",
        ).append_ed25519_public_key_signer(
            "GCN4HBZGFPOAI5DF4YQIS6OBC6KJKDC7CJSS5B4FWEXMJSWOPEYABLSD", 5
        ).append_hashx_signer(
            bytes.fromhex(
                "3389e9f0f1a65f19736cacf544c2e825313e8447f569233bb8db39aa607c8000"
            ),
            10,
        ).append_pre_auth_tx_signer(
            bytes.fromhex(
                "2db4b22ca018119c5027a80578813ffcf582cda4aa9e31cd92b43cfa4fc5a000"
            ),
            10,
        ).append_inflation_op().append_manage_data_op(
            "hello", "overcat"
        ).append_bump_sequence_op(10).append_manage_buy_offer_op(
            "XCN",
            "GCN4HBZGFPOAI5DF4YQIS6OBC6KJKDC7CJSS5B4FWEXMJSWOPEYABLSD",
            "XLM",
            None,
            "10.5",
            "11.25",
        ).append_manage_sell_offer_op(
            "XLM",
            None,
            "XCN",
            "GCN4HBZGFPOAI5DF4YQIS6OBC6KJKDC7CJSS5B4FWEXMJSWOPEYABLSD",
            "10.5",
            Price(8, 9),
            10086,
        ).append_create_passive_sell_offer_op(
            "XCN",
            "GCN4HBZGFPOAI5DF4YQIS6OBC6KJKDC7CJSS5B4FWEXMJSWOPEYABLSD",
            "XLM",
            None,
            "10.5",
            "11.25",
        ).append_account_merge_op(
            "GAXN7HZQTHIPW7N2HGPAXMR42LPJ5VLYXMCCOX4D3JC4CQZGID3UYUPF"
        ).append_claim_claimable_balance_op(
            "00000000da0d57da7d4850e7fc10d2a9d0ebc731f7afb40574c03395b17d49149b91f5be"
        ).append_create_claimable_balance_op(
            Asset.native(),
            "100",
            [
                Claimant(
                    destination=
                    "GCXGGIREYPENNT3LYFRD5I2SDALFWM3NKKLIQD3DMJ63ML5N3FG4OQQG")
            ],
        ).build())
        xdr = "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"
        assert te.to_xdr() == xdr

        xdr_signed = "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"
        signer = Keypair.from_secret(
            "SCCS5ZBI7WVIJ4SW36WGOQQIWJYCL3VOAULSXX3FB57USIO25EDOYQHH")
        te.sign(signer)
        assert te.to_xdr() == xdr_signed

        restore_te = TransactionBuilder.from_xdr(
            xdr_signed, Network.TESTNET_NETWORK_PASSPHRASE).build()
        assert restore_te.to_xdr() == xdr
        assert source.sequence == sequence + 1
        restore_builder = TransactionBuilder.from_xdr(
            xdr_signed, Network.TESTNET_NETWORK_PASSPHRASE)
        assert restore_builder.v1 is False
        assert restore_builder.build().to_xdr() == xdr
Ejemplo n.º 16
0
    def test_to_xdr_v1(self):
        sequence = 1
        source = Account(
            "GDF5O4OWEMVBY5FLDHWA5RZTYSV2U276XGKZZ6VSHDDR3THSQ6OQS7UM",
            sequence)
        builder = TransactionBuilder(source,
                                     Network.TESTNET_NETWORK_PASSPHRASE,
                                     base_fee=150,
                                     v1=True)
        builder.add_text_memo("Stellar Python SDK")
        builder.add_time_bounds(1565590000, 1565600000)
        te = (builder.append_create_account_op(
            "GDNSSYSCSSJ76FER5WEEXME5G4MTCUBKDRQSKOYP36KUKVDB2VCMERS6",
            "5.5",
            "GDF5O4OWEMVBY5FLDHWA5RZTYSV2U276XGKZZ6VSHDDR3THSQ6OQS7UM",
        ).append_change_trust_op(
            "XCN",
            "GDF5O4OWEMVBY5FLDHWA5RZTYSV2U276XGKZZ6VSHDDR3THSQ6OQS7UM",
            "100000",
        ).append_payment_op(
            "GAXN7HZQTHIPW7N2HGPAXMR42LPJ5VLYXMCCOX4D3JC4CQZGID3UYUPF",
            "12.25",
            "XLM",
        ).append_path_payment_strict_receive_op(
            "GAXN7HZQTHIPW7N2HGPAXMR42LPJ5VLYXMCCOX4D3JC4CQZGID3UYUPF",
            "XLM",
            None,
            "100",
            "XCN",
            "GDF5O4OWEMVBY5FLDHWA5RZTYSV2U276XGKZZ6VSHDDR3THSQ6OQS7UM",
            "1000.5",
            [
                Asset(
                    "USD",
                    "GDNSSYSCSSJ76FER5WEEXME5G4MTCUBKDRQSKOYP36KUKVDB2VCMERS6",
                ),
                Asset(
                    "BTC",
                    "GDNSSYSCSSJ76FER5WEEXME5G4MTCUBKDRQSKOYP36KUKVDB2VCMERS6",
                ),
            ],
        ).append_path_payment_strict_send_op(
            "GAXN7HZQTHIPW7N2HGPAXMR42LPJ5VLYXMCCOX4D3JC4CQZGID3UYUPF",
            "XLM",
            None,
            "100",
            "XCN",
            "GDF5O4OWEMVBY5FLDHWA5RZTYSV2U276XGKZZ6VSHDDR3THSQ6OQS7UM",
            "1000.5",
            [
                Asset(
                    "USD",
                    "GDNSSYSCSSJ76FER5WEEXME5G4MTCUBKDRQSKOYP36KUKVDB2VCMERS6",
                ),
                Asset(
                    "BTC",
                    "GDNSSYSCSSJ76FER5WEEXME5G4MTCUBKDRQSKOYP36KUKVDB2VCMERS6",
                ),
            ],
        ).append_allow_trust_op(
            "GDNSSYSCSSJ76FER5WEEXME5G4MTCUBKDRQSKOYP36KUKVDB2VCMERS6", "XCN",
            True
        ).append_set_options_op(
            "GAXN7HZQTHIPW7N2HGPAXMR42LPJ5VLYXMCCOX4D3JC4CQZGID3UYUPF",
            1,
            6,
            20,
            20,
            20,
            20,
            "stellarcn.org",
            Signer.ed25519_public_key(
                "GAXN7HZQTHIPW7N2HGPAXMR42LPJ5VLYXMCCOX4D3JC4CQZGID3UYUPF",
                10),
            "GDF5O4OWEMVBY5FLDHWA5RZTYSV2U276XGKZZ6VSHDDR3THSQ6OQS7UM",
        ).append_ed25519_public_key_signer(
            "GCN4HBZGFPOAI5DF4YQIS6OBC6KJKDC7CJSS5B4FWEXMJSWOPEYABLSD", 5
        ).append_hashx_signer(
            bytes.fromhex(
                "3389e9f0f1a65f19736cacf544c2e825313e8447f569233bb8db39aa607c8000"
            ),
            10,
        ).append_pre_auth_tx_signer(
            bytes.fromhex(
                "2db4b22ca018119c5027a80578813ffcf582cda4aa9e31cd92b43cfa4fc5a000"
            ),
            10,
        ).append_inflation_op().append_manage_data_op(
            "hello", "overcat"
        ).append_bump_sequence_op(10).append_manage_buy_offer_op(
            "XCN",
            "GCN4HBZGFPOAI5DF4YQIS6OBC6KJKDC7CJSS5B4FWEXMJSWOPEYABLSD",
            "XLM",
            None,
            "10.5",
            "11.25",
        ).append_manage_sell_offer_op(
            "XLM",
            None,
            "XCN",
            "GCN4HBZGFPOAI5DF4YQIS6OBC6KJKDC7CJSS5B4FWEXMJSWOPEYABLSD",
            "10.5",
            Price(8, 9),
            10086,
        ).append_create_passive_sell_offer_op(
            "XCN",
            "GCN4HBZGFPOAI5DF4YQIS6OBC6KJKDC7CJSS5B4FWEXMJSWOPEYABLSD",
            "XLM",
            None,
            "10.5",
            "11.25",
        ).append_account_merge_op(
            "GAXN7HZQTHIPW7N2HGPAXMR42LPJ5VLYXMCCOX4D3JC4CQZGID3UYUPF"
        ).append_claim_claimable_balance_op(
            "00000000da0d57da7d4850e7fc10d2a9d0ebc731f7afb40574c03395b17d49149b91f5be"
        ).append_create_claimable_balance_op(
            Asset.native(),
            "100",
            [
                Claimant(
                    destination=
                    "GCXGGIREYPENNT3LYFRD5I2SDALFWM3NKKLIQD3DMJ63ML5N3FG4OQQG")
            ],
        ).build())

        xdr_unsigned = te.to_xdr()

        signer = Keypair.from_secret(
            "SCCS5ZBI7WVIJ4SW36WGOQQIWJYCL3VOAULSXX3FB57USIO25EDOYQHH")
        te.sign(signer)
        restore_builder = TransactionBuilder.from_xdr(
            te.to_xdr(), Network.TESTNET_NETWORK_PASSPHRASE)
        assert restore_builder.v1 is True
        assert restore_builder.build().to_xdr() == xdr_unsigned
Ejemplo n.º 17
0
import requests
from stellar_sdk import Server, Keypair, TransactionBuilder, Network

horizon = Server("https://horizon-testnet.stellar.org")

# create keys
sender_keypair = Keypair.random()
receiver_keypair = Keypair.random()

# create accounts
url = 'https://friendbot.stellar.org'
sender_create_response = requests.get(
    url, params={'addr': sender_keypair.public_key})
print("create sender account", sender_create_response)
receiver_create_response = requests.get(
    url, params={'addr': receiver_keypair.public_key})
print("create receiver account", receiver_create_response)

# load sender account
sender_account = horizon.load_account(sender_keypair.public_key)
print("get sender account", sender_account)

# make payment
base_fee = horizon.fetch_base_fee()
transaction = (TransactionBuilder(
    source_account=sender_account,
    network_passphrase=Network.TESTNET_NETWORK_PASSPHRASE,
    base_fee=base_fee,
).append_payment_op(receiver_keypair.public_key, "5.0", "XLM").build())
transaction.sign(sender_keypair)
paymnet_response = horizon.submit_transaction(transaction)
Ejemplo n.º 18
0
from stellar_sdk import Server, TransactionBuilder, Keypair, Network

sponsor_secret = "SAOJHTVFCYVKUMPNQI7RUSI566GKWXP7RXOHP4SV6JAVUQKSIWGPZFPJ"
new_account_secret = "SCN5D72JHQAHUHGIA23SLS3LBYCPHJWD7HLYNJRBBZIG4PD74UCGQBYM"

sponsor_keypair = Keypair.from_secret(sponsor_secret)
newly_created_keypair = Keypair.from_secret(new_account_secret)

server = Server("https://horizon-testnet.stellar.org")
network_passphrase = Network.TESTNET_NETWORK_PASSPHRASE

# Sponsoring Account Creation
# https://github.com/stellar/stellar-protocol/blob/master/core/cap-0033.md#example-sponsoring-account-creation
sponsor_account = server.load_account(sponsor_keypair.public_key)
sponsoring_account_creation_te = TransactionBuilder(
    source_account=sponsor_account, network_passphrase=network_passphrase
).append_begin_sponsoring_future_reserves_op(
    sponsored_id=newly_created_keypair.public_key,
    source=sponsor_keypair.public_key).append_create_account_op(
        destination=newly_created_keypair.public_key,
        starting_balance="10",
        source=sponsor_keypair.public_key
    ).append_end_sponsoring_future_reserves_op(
        source=newly_created_keypair.public_key).build()
sponsoring_account_creation_te.sign(sponsor_keypair)
sponsoring_account_creation_te.sign(new_account_secret)
sponsoring_account_creation_resp = server.submit_transaction(
    sponsoring_account_creation_te)
print(sponsoring_account_creation_resp)

# Revoke Account Sponsorship
Ejemplo n.º 19
0
    def _transfer_locked_tokens(self,
                                destination_address,
                                amount,
                                asset_code,
                                asset_issuer,
                                unlock_time,
                                memo_text=None,
                                memo_hash=None,
                                fund_transaction=True,
                                from_address=None):
        """Transfer locked assets to another address
        :param destination_address: address of the destination.
        :type destination_address: str
        :param amount: amount, can be a floating point number with 7 numbers after the decimal point expressed as a Decimal or a string.
        :type amount: Union[str, Decimal]
        :param asset_code: asset to transfer
        :type asset_code: str
        :param asset_issuer: if the asset_code is different from 'XlM', the issuer address
        :type asset_issuer: str
        :param unlock_time: an epoch timestamp indicating when the funds should be unlocked.
        :type unlock_time: float
        :param text_memo: optional memo text to add to the transaction, a string encoded using either ASCII or UTF-8, up to 28-bytes long
        :type: Union[str, bytes]
        :param memo_hash: optional memo hash to add to the transaction, A 32 byte hash
        :type: Union[str, bytes]
        :param fund_transaction: use the threefoldfoundation transaction funding service
        :type: fund_transaction: bool
        :param from_address: Use a different address to send the tokens from, useful in multisig use cases.
        :type from_address: str
        """
        unlock_time = math.ceil(unlock_time)

        self._log_info("Creating escrow account")
        escrow_kp = Keypair.random()

        # minimum account balance as described at https://www.stellar.org/developers/guides/concepts/fees.html#minimum-account-balance
        horizon_server = self._get_horizon_server()
        base_fee = horizon_server.fetch_base_fee()
        base_reserve = 0.5
        minimum_account_balance = (
            2 + 1 + 3) * base_reserve  # 1 trustline and 3 signers
        required_XLM = minimum_account_balance + base_fee * 0.0000001 * 3

        self._log_info("Activating escrow account")
        self.activate_account(escrow_kp.public_key,
                              str(math.ceil(required_XLM)))

        if asset_code != "XLM":
            self._log_info("Adding trustline to escrow account")
            self.add_trustline(asset_code, asset_issuer, escrow_kp.secret)

        preauth_tx = self._create_unlock_transaction(escrow_kp, unlock_time)
        preauth_tx_hash = preauth_tx.hash()

        # save the preauth transaction in our unlock service
        unlock_hash = strkey.StrKey.encode_pre_auth_tx(preauth_tx_hash)
        self._create_unlockhash_transaction(
            unlock_hash=unlock_hash, transaction_xdr=preauth_tx.to_xdr())

        self._set_escrow_account_signers(escrow_kp.public_key,
                                         destination_address, preauth_tx_hash,
                                         escrow_kp)
        self._log_info("Unlock Transaction:")
        self._log_info(preauth_tx.to_xdr())

        self.transfer(escrow_kp.public_key,
                      amount,
                      asset_code + ":" + asset_issuer,
                      memo_text=memo_text,
                      memo_hash=memo_hash,
                      fund_transaction=fund_transaction,
                      from_address=from_address)
        return preauth_tx.to_xdr()
Ejemplo n.º 20
0
    def test_to_xdr(self):
        sequence = 1
        source = Account(
            "GDF5O4OWEMVBY5FLDHWA5RZTYSV2U276XGKZZ6VSHDDR3THSQ6OQS7UM",
            sequence)
        builder = TransactionBuilder(source,
                                     Network.TESTNET_NETWORK_PASSPHRASE,
                                     base_fee=150)
        builder.add_text_memo("Stellar Python SDK")
        builder.add_time_bounds(1565590000, 1565600000)
        te = (builder.append_create_account_op(
            "GDNSSYSCSSJ76FER5WEEXME5G4MTCUBKDRQSKOYP36KUKVDB2VCMERS6",
            "5.5",
            "GDF5O4OWEMVBY5FLDHWA5RZTYSV2U276XGKZZ6VSHDDR3THSQ6OQS7UM",
        ).append_change_trust_op(
            "XCN",
            "GDF5O4OWEMVBY5FLDHWA5RZTYSV2U276XGKZZ6VSHDDR3THSQ6OQS7UM",
            "100000",
        ).append_payment_op(
            "GAXN7HZQTHIPW7N2HGPAXMR42LPJ5VLYXMCCOX4D3JC4CQZGID3UYUPF",
            "12.25",
            "XLM",
        ).append_path_payment_op(
            "GAXN7HZQTHIPW7N2HGPAXMR42LPJ5VLYXMCCOX4D3JC4CQZGID3UYUPF",
            "XLM",
            None,
            "100",
            "XCN",
            "GDF5O4OWEMVBY5FLDHWA5RZTYSV2U276XGKZZ6VSHDDR3THSQ6OQS7UM",
            "1000.5",
            [
                Asset(
                    "USD",
                    "GDNSSYSCSSJ76FER5WEEXME5G4MTCUBKDRQSKOYP36KUKVDB2VCMERS6",
                ),
                Asset(
                    "BTC",
                    "GDNSSYSCSSJ76FER5WEEXME5G4MTCUBKDRQSKOYP36KUKVDB2VCMERS6",
                ),
            ],
        ).append_path_payment_strict_receive_op(
            "GAXN7HZQTHIPW7N2HGPAXMR42LPJ5VLYXMCCOX4D3JC4CQZGID3UYUPF",
            "XLM",
            None,
            "100",
            "XCN",
            "GDF5O4OWEMVBY5FLDHWA5RZTYSV2U276XGKZZ6VSHDDR3THSQ6OQS7UM",
            "1000.5",
            [
                Asset(
                    "USD",
                    "GDNSSYSCSSJ76FER5WEEXME5G4MTCUBKDRQSKOYP36KUKVDB2VCMERS6",
                ),
                Asset(
                    "BTC",
                    "GDNSSYSCSSJ76FER5WEEXME5G4MTCUBKDRQSKOYP36KUKVDB2VCMERS6",
                ),
            ],
        ).append_path_payment_strict_send_op(
            "GAXN7HZQTHIPW7N2HGPAXMR42LPJ5VLYXMCCOX4D3JC4CQZGID3UYUPF",
            "XLM",
            None,
            "100",
            "XCN",
            "GDF5O4OWEMVBY5FLDHWA5RZTYSV2U276XGKZZ6VSHDDR3THSQ6OQS7UM",
            "1000.5",
            [
                Asset(
                    "USD",
                    "GDNSSYSCSSJ76FER5WEEXME5G4MTCUBKDRQSKOYP36KUKVDB2VCMERS6",
                ),
                Asset(
                    "BTC",
                    "GDNSSYSCSSJ76FER5WEEXME5G4MTCUBKDRQSKOYP36KUKVDB2VCMERS6",
                ),
            ],
        ).append_allow_trust_op(
            "GDNSSYSCSSJ76FER5WEEXME5G4MTCUBKDRQSKOYP36KUKVDB2VCMERS6", "XCN",
            True
        ).append_set_options_op(
            "GAXN7HZQTHIPW7N2HGPAXMR42LPJ5VLYXMCCOX4D3JC4CQZGID3UYUPF",
            1,
            6,
            20,
            20,
            20,
            20,
            "stellarcn.org",
            Signer.ed25519_public_key(
                "GAXN7HZQTHIPW7N2HGPAXMR42LPJ5VLYXMCCOX4D3JC4CQZGID3UYUPF",
                10),
            "GDF5O4OWEMVBY5FLDHWA5RZTYSV2U276XGKZZ6VSHDDR3THSQ6OQS7UM",
        ).append_ed25519_public_key_signer(
            "GCN4HBZGFPOAI5DF4YQIS6OBC6KJKDC7CJSS5B4FWEXMJSWOPEYABLSD", 5
        ).append_hashx_signer(
            bytes.fromhex(
                "3389e9f0f1a65f19736cacf544c2e825313e8447f569233bb8db39aa607c8000"
            ),
            10,
        ).append_pre_auth_tx_signer(
            bytes.fromhex(
                "2db4b22ca018119c5027a80578813ffcf582cda4aa9e31cd92b43cfa4fc5a000"
            ),
            10,
        ).append_inflation_op().append_manage_data_op(
            "hello",
            "overcat").append_bump_sequence_op(10).append_manage_buy_offer_op(
                "XCN",
                "GCN4HBZGFPOAI5DF4YQIS6OBC6KJKDC7CJSS5B4FWEXMJSWOPEYABLSD",
                "XLM",
                None,
                "10.5",
                "11.25",
            ).append_manage_sell_offer_op(
                "XLM",
                None,
                "XCN",
                "GCN4HBZGFPOAI5DF4YQIS6OBC6KJKDC7CJSS5B4FWEXMJSWOPEYABLSD",
                "10.5",
                Price(8, 9),
                10086,
            ).append_create_passive_sell_offer_op(
                "XCN",
                "GCN4HBZGFPOAI5DF4YQIS6OBC6KJKDC7CJSS5B4FWEXMJSWOPEYABLSD",
                "XLM",
                None,
                "10.5",
                "11.25",
            ).append_account_merge_op(
                "GAXN7HZQTHIPW7N2HGPAXMR42LPJ5VLYXMCCOX4D3JC4CQZGID3UYUPF").
              build())

        xdr = "AAAAAMvXcdYjKhx0qxnsDsczxKuqa/65lZz6sjjHHczyh50JAAAKjAAAAAAAAAACAAAAAQAAAABdUQHwAAAAAF1RKQAAAAABAAAAElN0ZWxsYXIgUHl0aG9uIFNESwAAAAAAEgAAAAEAAAAAy9dx1iMqHHSrGewOxzPEq6pr/rmVnPqyOMcdzPKHnQkAAAAAAAAAANspYkKUk/8Uke2IS7CdNxkxUCocYSU7D9+VRVRh1UTCAAAAAANHO8AAAAAAAAAABgAAAAFYQ04AAAAAAMvXcdYjKhx0qxnsDsczxKuqa/65lZz6sjjHHczyh50JAAAA6NSlEAAAAAAAAAAAAQAAAAAu358wmdD7fbo5nguyPNLentV4uwQnX4PaRcFDJkD3TAAAAAAAAAAAB00zoAAAAAAAAAACAAAAAAAAAAA7msoAAAAAAC7fnzCZ0Pt9ujmeC7I80t6e1Xi7BCdfg9pFwUMmQPdMAAAAAVhDTgAAAAAAy9dx1iMqHHSrGewOxzPEq6pr/rmVnPqyOMcdzPKHnQkAAAACVFgvQAAAAAIAAAABVVNEAAAAAADbKWJClJP/FJHtiEuwnTcZMVAqHGElOw/flUVUYdVEwgAAAAFCVEMAAAAAANspYkKUk/8Uke2IS7CdNxkxUCocYSU7D9+VRVRh1UTCAAAAAAAAAAIAAAAAAAAAADuaygAAAAAALt+fMJnQ+326OZ4LsjzS3p7VeLsEJ1+D2kXBQyZA90wAAAABWENOAAAAAADL13HWIyocdKsZ7A7HM8Srqmv+uZWc+rI4xx3M8oedCQAAAAJUWC9AAAAAAgAAAAFVU0QAAAAAANspYkKUk/8Uke2IS7CdNxkxUCocYSU7D9+VRVRh1UTCAAAAAUJUQwAAAAAA2yliQpST/xSR7YhLsJ03GTFQKhxhJTsP35VFVGHVRMIAAAAAAAAADQAAAAAAAAAAO5rKAAAAAAAu358wmdD7fbo5nguyPNLentV4uwQnX4PaRcFDJkD3TAAAAAFYQ04AAAAAAMvXcdYjKhx0qxnsDsczxKuqa/65lZz6sjjHHczyh50JAAAAAlRYL0AAAAACAAAAAVVTRAAAAAAA2yliQpST/xSR7YhLsJ03GTFQKhxhJTsP35VFVGHVRMIAAAABQlRDAAAAAADbKWJClJP/FJHtiEuwnTcZMVAqHGElOw/flUVUYdVEwgAAAAAAAAAHAAAAANspYkKUk/8Uke2IS7CdNxkxUCocYSU7D9+VRVRh1UTCAAAAAVhDTgAAAAABAAAAAQAAAADL13HWIyocdKsZ7A7HM8Srqmv+uZWc+rI4xx3M8oedCQAAAAUAAAABAAAAAC7fnzCZ0Pt9ujmeC7I80t6e1Xi7BCdfg9pFwUMmQPdMAAAAAQAAAAEAAAABAAAABgAAAAEAAAAUAAAAAQAAABQAAAABAAAAFAAAAAEAAAAUAAAAAQAAAA1zdGVsbGFyY24ub3JnAAAAAAAAAQAAAAAu358wmdD7fbo5nguyPNLentV4uwQnX4PaRcFDJkD3TAAAAAoAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAACbw4cmK9wEdGXmIIl5wReUlQxfEmUuh4WxLsTKznkwAAAAAAUAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAIzienw8aZfGXNsrPVEwuglMT6ER/VpIzu42zmqYHyAAAAAAAoAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEttLIsoBgRnFAnqAV4gT/89YLNpKqeMc2StDz6T8WgAAAAAAoAAAAAAAAACQAAAAAAAAAKAAAABWhlbGxvAAAAAAAAAQAAAAdvdmVyY2F0AAAAAAAAAAALAAAAAAAAAAoAAAAAAAAADAAAAAFYQ04AAAAAAJvDhyYr3AR0ZeYgiXnBF5SVDF8SZS6HhbEuxMrOeTAAAAAAAAAAAAAGQixAAAAALQAAAAQAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAFYQ04AAAAAAJvDhyYr3AR0ZeYgiXnBF5SVDF8SZS6HhbEuxMrOeTAAAAAAAAZCLEAAAAAIAAAACQAAAAAAACdmAAAAAAAAAAQAAAABWENOAAAAAACbw4cmK9wEdGXmIIl5wReUlQxfEmUuh4WxLsTKznkwAAAAAAAAAAAABkIsQAAAAC0AAAAEAAAAAAAAAAgAAAAALt+fMJnQ+326OZ4LsjzS3p7VeLsEJ1+D2kXBQyZA90wAAAAAAAAAAA=="
        assert te.to_xdr() == xdr

        xdr_signed = "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"
        signer = Keypair.from_secret(
            "SCCS5ZBI7WVIJ4SW36WGOQQIWJYCL3VOAULSXX3FB57USIO25EDOYQHH")
        te.sign(signer)
        assert te.to_xdr() == xdr_signed

        restore_te = TransactionBuilder.from_xdr(
            xdr_signed, Network.TESTNET_NETWORK_PASSPHRASE).build()
        assert restore_te.to_xdr() == xdr
        assert source.sequence == sequence + 1
Ejemplo n.º 21
0
"""
Challenge 8: Path Payments
"""
from stellar_sdk import Server, Keypair, TransactionBuilder, Network, Asset
import json

# 1. Load Keys
server = Server("https://horizon-testnet.stellar.org")
stellar_quest_keypair = Keypair.from_secret("Shhhhh")
quest_account_pub_key = stellar_quest_keypair.public_key
quest_account_priv_key = stellar_quest_keypair.secret

# 2. Create Asset Objects
asset_to_buy = Asset(
    "SRT", "GCDNJUBQSX7AJWLJACMJ7I4BC3Z47BQUTMHEICZLE6MU4KQBRYG5JY6B")
native_asset = Asset('XLM')

# 3. Get Path Payment

path_payments = Server.strict_receive_paths(server,
                                            source=[native_asset],
                                            destination_asset=asset_to_buy,
                                            destination_amount='100').call()
path = [
    Asset(asset['destination_asset_code'], asset['destination_asset_issuer'])
    for asset in path_payments['_embedded']['records']
]
print(path)

# 4. Use Stellar Quest account to send path payment
print("Building Transaction...")
Ejemplo n.º 22
0
from stellar_sdk import Server, TransactionBuilder, Keypair, Network
from stellar_sdk.exceptions import NotFoundError
from stellar_sdk.sep.exceptions import InvalidSep10ChallengeError
from stellar_sdk.sep.stellar_web_authentication import build_challenge_transaction, read_challenge_transaction, \
    verify_challenge_transaction_threshold, verify_challenge_transaction_signed_by_client_master_key

server_keypair = Keypair.from_secret(
    "SBGCNEOQGECW5R4A55C26ZFS736IONKCHY5PPPSFZVXSJSU63MWNM4K6")
client_master_keypair = Keypair.from_secret(
    "SDWZHXKWSHTQ2YGPT6YQQSOJWJX5JX2IEU7KOLGQ2XEJEECIQHUU3RMR")
client_signer_keypair1 = Keypair.from_secret(
    "SCKJFEF2H767XINUY5YFBORUO7AAWOAXSTQ2B2YHSI6N4UF23HFV42I7")
client_signer_keypair2 = Keypair.from_secret(
    "SCE2JBZ6FKPTQ5LM4X4NIZOOZPIC5DXVG6VP2TKSBZCQAGXABJV55IN5")

server = Server("https://horizon-testnet.stellar.org")
anchor_name = "hello"
network_passphrase = Network.TESTNET_NETWORK_PASSPHRASE


def setup_multisig():
    client_master_account = server.load_account(
        client_master_keypair.public_key)
    te = TransactionBuilder(client_master_account, network_passphrase) \
        .append_ed25519_public_key_signer(client_signer_keypair1.public_key, 40) \
        .append_ed25519_public_key_signer(client_signer_keypair2.public_key, 60) \
        .append_set_options_op(master_weight=0, low_threshold=1, med_threshold=10, high_threshold=100) \
        .build()
    te.sign(client_master_keypair)
    resp = server.submit_transaction(te)
    print(resp)
def get_or_create_transaction_destination_account(
    transaction: Transaction,
) -> Tuple[Optional[Account], bool, bool]:
    """
    Returns:
        Tuple[Optional[Account]: The account(s) found or created for the Transaction
        bool: boolean, True if created, False otherwise.
        bool: boolean, True if trustline doesn't exist, False otherwise.

    If the account doesn't exist, Polaris must create the account using an account provided by the
    anchor. Polaris can use the distribution account of the anchored asset or a channel account if
    the asset's distribution account requires non-master signatures.

    If the transacted asset's distribution account does not require non-master signatures, Polaris
    can create the destination account using the distribution account.

    If the transacted asset's distribution account does require non-master signatures, the anchor
    should save a keypair of a pre-existing Stellar account to use as the channel account via
    DepositIntegration.create_channel_account(). See the function docstring for more info.

    On failure to create the destination account, a RuntimeError exception is raised.
    """
    try:
        account, json_resp = get_account_obj(
            Keypair.from_public_key(transaction.stellar_account)
        )
        return account, False, is_pending_trust(transaction, json_resp)
    except RuntimeError:
        master_signer = None
        if transaction.asset.distribution_account_master_signer:
            master_signer = transaction.asset.distribution_account_master_signer
        thresholds = transaction.asset.distribution_account_thresholds
        if master_signer and master_signer["weight"] >= thresholds["med_threshold"]:
            source_account_kp = Keypair.from_secret(transaction.asset.distribution_seed)
            source_account, _ = get_account_obj(source_account_kp)
        else:
            from polaris.integrations import registered_deposit_integration as rdi

            rdi.create_channel_account(transaction)
            source_account_kp = Keypair.from_secret(transaction.channel_seed)
            source_account, _ = get_account_obj(source_account_kp)

        builder = TransactionBuilder(
            source_account=source_account,
            network_passphrase=settings.STELLAR_NETWORK_PASSPHRASE,
            # this transaction contains one operation so base_fee will be multiplied by 1
            base_fee=settings.MAX_TRANSACTION_FEE_STROOPS
            or settings.HORIZON_SERVER.fetch_base_fee(),
        )
        transaction_envelope = builder.append_create_account_op(
            destination=transaction.stellar_account,
            starting_balance=settings.ACCOUNT_STARTING_BALANCE,
        ).build()
        transaction_envelope.sign(source_account_kp)

        try:
            settings.HORIZON_SERVER.submit_transaction(transaction_envelope)
        except BaseHorizonError as submit_exc:  # pragma: no cover
            raise RuntimeError(
                "Horizon error when submitting create account to horizon: "
                f"{submit_exc.message}"
            )

        transaction.status = Transaction.STATUS.pending_trust
        transaction.save()
        logger.info(
            f"Transaction {transaction.id} is now pending_trust of destination account"
        )
        account, _ = get_account_obj(
            Keypair.from_public_key(transaction.stellar_account)
        )
        return account, True, True
    except BaseHorizonError as e:
        raise RuntimeError(f"Horizon error when loading stellar account: {e.message}")
Ejemplo n.º 24
0
def getPublicKeyFromSecret(secretKey): 
    public = Keypair.from_secret(secretKey)
    return public.public_key
Ejemplo n.º 25
0
 def generarPar(self):
     keypair = Keypair.random()
     return [keypair.public_key, keypair.secret]
Ejemplo n.º 26
0
import requests

from stellar_sdk import Keypair

keypair = Keypair.random()

print("Public Key: " + keypair.public_key)
print("Secret Seed: " + keypair.secret)

url = 'https://friendbot.stellar.org'
response = requests.get(url, params={'addr': keypair.public_key})
print(response)
Ejemplo n.º 27
0
"""
Challenge 6: Sponsoring Reserves
"""
from stellar_sdk import Server, Keypair, TransactionBuilder, Network, FeeBumpTransaction, ClaimPredicate, Claimant, Asset
import requests

# 1. Load Keys
server = Server("https://horizon-testnet.stellar.org")
stellar_quest_keypair = Keypair.from_secret("Shhhhh")
quest_account_pub_key = stellar_quest_keypair.public_key
quest_account_priv_key = stellar_quest_keypair.secret

other_account = Keypair.random()
other_account_pub_key = other_account.public_key
other_account_priv_key = other_account.secret

# 2. Create Transaction
print("Building Transaction...")

base_fee = server.fetch_base_fee()
account = server.load_account(quest_account_pub_key)

transaction = TransactionBuilder(
    source_account=account,
    network_passphrase=Network.TESTNET_NETWORK_PASSPHRASE,
    base_fee=base_fee,
).append_begin_sponsoring_future_reserves_op(
    sponsored_id=other_account_pub_key,
    source=quest_account_pub_key
).append_create_account_op(
    destination=other_account_pub_key,
Ejemplo n.º 28
0
from stellar_sdk import Keypair, Server, TransactionBuilder, Network, Asset

server = Server(horizon_url="https://horizon-testnet.stellar.org")
source_keypair = Keypair.from_secret(
    "SA6XHAH4GNLRWWWF6TEVEWNS44CBNFAJWHWOPZCVZOUXSQA7BOYN7XHC")

source_account = server.load_account(account_id=source_keypair.public_key)

path = [
    Asset("USD", "GBBM6BKZPEHWYO3E3YKREDPQXMS4VK35YLNU7NFBRI26RAN7GI5POFBB"),
    Asset("EUR", "GDTNXRLOJD2YEBPKK7KCMR7J33AAG5VZXHAJTHIG736D6LVEFLLLKPDL")
]
transaction = TransactionBuilder(
    source_account=source_account, network_passphrase=Network.TESTNET_NETWORK_PASSPHRASE, base_fee=100) \
    .append_path_payment_strict_receive_op(destination="GBBM6BKZPEHWYO3E3YKREDPQXMS4VK35YLNU7NFBRI26RAN7GI5POFBB",
                            send_code="XLM", send_issuer=None, send_max="1000", dest_code="GBP",
                            dest_issuer="GASOCNHNNLYFNMDJYQ3XFMI7BYHIOCFW3GJEOWRPEGK2TDPGTG2E5EDW",
                            dest_amount="5.50", path=path) \
    .set_timeout(30) \
    .build()
transaction.sign(source_keypair)
response = server.submit_transaction(transaction)
Ejemplo n.º 29
0
"""
Challenge 1: Create a Stellar Account
"""
from stellar_sdk import Server, Keypair, TransactionBuilder, Network
import requests

# 1. Load Keys
server = Server("https://horizon-testnet.stellar.org")
stellar_quest_keypair = Keypair.from_secret("Shhhhh")
quest_account_pub_key = stellar_quest_keypair.public_key
quest_account_priv_key = stellar_quest_keypair.secret

# 2. Create Another account
print("Loading Accounts...")

random_keypair = Keypair.random()
random_keypair_pub_key = random_keypair.public_key
random_keypair_priv_key = random_keypair.secret

# 3. Fund Another account using TestBot
print("Funding Random Account...")

url = 'https://friendbot.stellar.org'
response = requests.get(url, params={'addr': random_keypair.public_key})
print(f"Friendbot responded with {response}")

# 4. Use said account to fund my account
print("Building Transaction...")

base_fee = server.fetch_base_fee()
random_account = server.load_account(random_keypair_pub_key)
Ejemplo n.º 30
0
    def transfer(
        self,
        destination_address,
        amount,
        asset="XLM",
        locked_until=None,
        memo_text=None,
        memo_hash=None,
        fund_transaction=True,
        from_address=None,
    ):
        """Transfer assets to another address
        :param destination_address: address of the destination.
        :type destination_address: str
        :param amount: amount, can be a floating point number with 7 numbers after the decimal point expressed as a Decimal or a string.
        :type amount: Union[str, Decimal]
        :param asset: asset to transfer (if none is specified the default 'XLM' is used),
        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.
        :type asset: str
        :param locked_until: optional epoch timestamp indicating until when the tokens  should be locked.
        :type locked_until: float
        :param text_memo: optional memo text to add to the transaction, a string encoded using either ASCII or UTF-8, up to 28-bytes long
        :type: Union[str, bytes]
        :param memo_hash: optional memo hash to add to the transaction, A 32 byte hash
        :type: Union[str, bytes]
        :param fund_transaction: use the threefoldfoundation transaction funding service
        :type: fund_transaction: bool
        :param from_address: Use a different address to send the tokens from, useful in multisig use cases.
        :type from_address: str
        """
        issuer = None
        self._log_info(f"Sending {amount} {asset} to {destination_address}")
        if asset != "XLM":
            assetStr = asset.split(":")
            if len(assetStr) != 2:
                raise Exception("Wrong asset format")
            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()

        transaction_builder = TransactionBuilder(
            source_account=source_account,
            network_passphrase=_NETWORK_PASSPHRASES[str(self.network)],
            base_fee=base_fee)
        transaction_builder.append_payment_op(
            destination=destination_address,
            amount=amount,
            asset_code=asset,
            asset_issuer=issuer,
            source=source_account.account_id,
        )
        transaction_builder.set_timeout(30)
        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 in _NETWORK_KNOWN_TRUSTS[str(self.network)]:
            if fund_transaction:
                transaction = self._fund_transaction(transaction=transaction)
                transaction = transaction["transaction_xdr"]

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

        my_keypair = Keypair.from_secret(self.secret)
        transaction.sign(my_keypair)

        try:
            response = horizon_server.submit_transaction(transaction)
            tx_hash = response["hash"]
            self._log_info("Transaction hash: {}".format(tx_hash))
            return tx_hash
        except BadRequestError as e:
            result_codes = e.extras.get("result_codes")
            operations = result_codes.get("operations")
            if operations is not None:
                for op in operations:
                    if op == "op_underfunded":
                        raise e
                    # if op_bad_auth is returned then we assume the transaction needs more signatures
                    # so we return the transaction as xdr
                    elif op == "op_bad_auth":
                        self._log_info(
                            "Transaction might need additional signatures in order to send"
                        )
                        return transaction.to_xdr()
            raise e