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
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
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]
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, )
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
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) )
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
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, )
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)
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)
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
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
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)
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
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()
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 = "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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
""" 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...")
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}")
def getPublicKeyFromSecret(secretKey): public = Keypair.from_secret(secretKey) return public.public_key
def generarPar(self): keypair = Keypair.random() return [keypair.public_key, keypair.secret]
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)
""" 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,
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)
""" 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)
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