def create_assets_for_distributing(amount): # Keys for accounts to issue and receive the new asset issuing_keypair = Keypair.from_secret(os.getenv("ISSUING_PRIVATE")) issuing_public = issuing_keypair.public_key issuing_account = server.load_account(issuing_public) distributor_keypair = Keypair.from_secret(os.getenv("DISTRIBUTOR_INRX_PRIVATE_KEY")) distributor_public = distributor_keypair.public_key distributor_account = server.load_account(distributor_public) inr_asset = Asset("INRx", issuing_public) payment_transaction = ( TransactionBuilder( source_account=issuing_account, network_passphrase=Network.TESTNET_NETWORK_PASSPHRASE, base_fee=server.fetch_base_fee(), ) .append_change_trust_op(inr_asset.code, inr_asset.issuer, None, distributor_public) .append_payment_op( destination=distributor_public, amount=amount, asset_code=inr_asset.code, asset_issuer=inr_asset.issuer, ) .build() ) payment_transaction.sign(issuing_keypair) payment_transaction.sign(distributor_keypair) resp = server.submit_transaction(payment_transaction) pprint(resp) account_details = server.accounts().account_id(distributor_public).call() print("\n\ndistributor new balance: ", account_details["balances"][0]["balance"], inr_asset.code)
def test_can_sign(self): can_sign_kp = Keypair.from_secret( "SD7X7LEHBNMUIKQGKPARG5TDJNBHKC346OUARHGZL5ITC6IJPXHILY36") can_not_sign_kp = Keypair.from_public_key( "GAXDYNIBA5E4DXR5TJN522RRYESFQ5UNUXHIPTFGVLLD5O5K552DF5ZH") assert can_sign_kp.can_sign() is True assert can_not_sign_kp.can_sign() is False
def test_interactive_withdraw_bad_post_data(client): usd = Asset.objects.create( code="USD", issuer=Keypair.random().public_key, sep24_enabled=True, withdrawal_enabled=True, distribution_seed=Keypair.random().secret, withdrawal_max_amount=10000, ) withdraw = Transaction.objects.create( asset=usd, kind=Transaction.KIND.withdrawal, protocol=Transaction.PROTOCOL.sep24, ) payload = interactive_jwt_payload(withdraw, "withdraw") token = jwt.encode(payload, settings.SERVER_JWT_KEY, algorithm="HS256").decode("ascii") response = client.get(f"{WEBAPP_PATH}" f"?token={token}" f"&transaction_id={withdraw.id}" f"&asset_code={withdraw.asset.code}") assert response.status_code == 200 assert client.session["authenticated"] is True response = client.post( f"{WEBAPP_PATH}/submit" f"?transaction_id={withdraw.id}" f"&asset_code={withdraw.asset.code}", {"amount": 20000}, ) assert response.status_code == 400
def test_create_from_invalid_public_key_raise(self, invalid_public_key): with pytest.raises( Ed25519PublicKeyInvalidError, match="Invalid Ed25519 Public Key: {}".format( invalid_public_key), ): Keypair.from_public_key(invalid_public_key)
def test_interactive_withdraw_get_no_content_tx_complete( mock_content_for_transaction, mock_form_for_transaction, client ): usd = Asset.objects.create( code="USD", issuer=Keypair.random().public_key, sep24_enabled=True, withdrawal_enabled=True, distribution_seed=Keypair.random().secret, ) withdraw = Transaction.objects.create( asset=usd, kind=Transaction.KIND.withdrawal, status=Transaction.STATUS.completed ) mock_form_for_transaction.return_value = None mock_content_for_transaction.return_value = None payload = interactive_jwt_payload(withdraw, "withdraw") token = jwt.encode(payload, settings.SERVER_JWT_KEY, algorithm="HS256").decode( "ascii" ) response = client.get( f"{WEBAPP_PATH}" f"?token={token}" f"&transaction_id={withdraw.id}" f"&asset_code={withdraw.asset.code}" ) assert response.status_code == 422 assert client.session["authenticated"] is True assert ( "The anchor did not provide content, is the interactive flow already complete?" in str(response.content) )
def to_xlm(self) -> str: if isinstance(self.key, (ED25519Priv, ED25519Pub)): if self.version == Version.PRIVATE: return Keypair.from_raw_ed25519_seed(self.key.get_private_bytes()).secret else: return Keypair.from_raw_ed25519_public_key(self.key.get_public_bytes()).public_key else: raise ValueError("Can only derive XLM from ED25519")
def test_generate_mnemonic_phrase_strength_raise(self): strength = 1024 with pytest.raises( ValueError, match= "Strength should be one of the following \(128, 160, 192, 224, 256\), but it is not \(%d\)." % strength, ): Keypair.generate_mnemonic_phrase(strength=strength)
def deposit(account: str, request: Request) -> Response: """ POST /transactions/deposit/interactive Creates an `incomplete` deposit Transaction object in the database and returns the URL entry-point for the interactive flow. """ asset_code = request.POST.get("asset_code") stellar_account = request.POST.get("account") lang = request.POST.get("lang") if lang: err_resp = validate_language(lang) if err_resp: return err_resp activate_lang_for_request(lang) # Verify that the request is valid. if not all([asset_code, stellar_account]): return render_error_response( _("`asset_code` and `account` are required parameters") ) # Verify that the asset code exists in our database, with deposit enabled. asset = Asset.objects.filter(code=asset_code).first() if not asset: return render_error_response(_("unknown asset: %s") % asset_code) elif not asset.deposit_enabled: return render_error_response(_("invalid operation for asset %s") % asset_code) try: Keypair.from_public_key(stellar_account) except Ed25519PublicKeyInvalidError: return render_error_response(_("invalid 'account'")) # Construct interactive deposit pop-up URL. transaction_id = create_transaction_id() Transaction.objects.create( id=transaction_id, stellar_account=account, asset=asset, kind=Transaction.KIND.deposit, status=Transaction.STATUS.incomplete, to_address=account, ) logger.info(f"Created deposit transaction {transaction_id}") url = interactive_url( request, str(transaction_id), stellar_account, asset_code, settings.OPERATION_DEPOSIT, ) return Response( {"type": "interactive_customer_info_needed", "url": url, "id": transaction_id}, status=status.HTTP_200_OK, )
def test_withdraw_invalid_operation(client): """`GET /withdraw` fails with an invalid asset argument.""" eth = Asset.objects.create( code="ETH", issuer=Keypair.random().public_key, sep24_enabled=True, withdrawal_enabled=False, distribution_seed=Keypair.random().secret, ) response = client.post(WITHDRAW_PATH, {"asset_code": eth.code}, follow=True) content = response.json() assert response.status_code == 400 assert content == {"error": "invalid operation for asset ETH"}
def test_withdraw_interactive_no_asset(client): """ `GET /transactions/withdraw/webapp` fails with no asset_code. """ Asset.objects.create( code="USD", issuer=Keypair.random().public_key, sep24_enabled=True, withdrawal_enabled=True, distribution_seed=Keypair.random().secret, ) response = client.get(f"{WEBAPP_PATH}?transaction_id=2", follow=True) assert response.status_code == 400 assert "asset_code" in response.content.decode()
def test_withdraw_invalid_amount(client): usd = Asset.objects.create( code="USD", issuer=Keypair.random().public_key, sep24_enabled=True, withdrawal_enabled=True, distribution_seed=Keypair.random().secret, withdrawal_max_amount=1000, ) response = client.post( WITHDRAW_PATH, {"asset_code": usd.code, "amount": 10000}, follow=True ) assert response.status_code == 400 assert response.json()["error"] == "invalid 'amount'"
def deposit(account: str, request: Request) -> Response: """ `POST /transactions/deposit/interactive` initiates the deposit and returns an interactive deposit form to the user. """ asset_code = request.POST.get("asset_code") stellar_account = request.POST.get("account") # Verify that the request is valid. if not all([asset_code, stellar_account]): return render_error_response( "`asset_code` and `account` are required parameters") # Verify that the asset code exists in our database, with deposit enabled. asset = Asset.objects.filter(code=asset_code).first() if not asset or not asset.deposit_enabled: return render_error_response( f"invalid operation for asset {asset_code}") try: Keypair.from_public_key(stellar_account) except Ed25519PublicKeyInvalidError: return render_error_response("invalid 'account'") # Verify the optional request arguments. verify_optional_args = _verify_optional_args(request) if verify_optional_args: return verify_optional_args # Construct interactive deposit pop-up URL. transaction_id = create_transaction_id() Transaction.objects.create( id=transaction_id, stellar_account=account, asset=asset, kind=Transaction.KIND.deposit, status=Transaction.STATUS.incomplete, to_address=account, ) url = rdi.interactive_url(request, str(transaction_id), stellar_account, asset_code) return Response( { "type": "interactive_customer_info_needed", "url": url, "id": transaction_id }, status=status.HTTP_200_OK, )
def test_interactive_withdraw_pending_anchor(mock_after_form_validation, client): usd = Asset.objects.create( code="USD", issuer=Keypair.random().public_key, sep24_enabled=True, withdrawal_enabled=True, distribution_seed=Keypair.random().secret, ) withdraw = Transaction.objects.create(asset=usd, kind=Transaction.KIND.withdrawal, protocol=Transaction.PROTOCOL.sep24) payload = interactive_jwt_payload(withdraw, "withdraw") token = jwt.encode(payload, settings.SERVER_JWT_KEY, algorithm="HS256").decode("ascii") response = client.get(f"{WEBAPP_PATH}" f"?token={token}" f"&transaction_id={withdraw.id}" f"&asset_code={withdraw.asset.code}") assert response.status_code == 200 assert client.session["authenticated"] is True response = client.get(f"{WEBAPP_PATH}" f"?token={token}" f"&transaction_id={withdraw.id}" f"&asset_code={withdraw.asset.code}") assert response.status_code == 403 assert "Unexpected one-time auth token" in str(response.content) def mark_as_pending_anchor(_, transaction): transaction.status = Transaction.STATUS.pending_anchor transaction.save() mock_after_form_validation.side_effect = mark_as_pending_anchor response = client.post( f"{WEBAPP_PATH}/submit" f"?transaction_id={withdraw.id}" f"&asset_code={withdraw.asset.code}", {"amount": 200.0}, ) assert response.status_code == 302 assert client.session["authenticated"] is False withdraw.refresh_from_db() assert withdraw.status == Transaction.STATUS.pending_anchor
def distribution_account(self): """ The Stellar public key derived from `Asset.distribution_seed` """ if not self.distribution_seed: return None return Keypair.from_secret(str(self.distribution_seed)).public_key
def test_create_from_secret(self): secret = "SD7X7LEHBNMUIKQGKPARG5TDJNBHKC346OUARHGZL5ITC6IJPXHILY36" kp = Keypair.from_secret(secret) assert isinstance(kp, Keypair) assert (kp.public_key == "GDFQVQCYYB7GKCGSCUSIQYXTPLV5YJ3XWDMWGQMDNM4EAXAL7LITIBQ7") assert kp.secret == secret
def test_to_xdr(self): # GDF5O4OWEMVBY5FLDHWA5RZTYSV2U276XGKZZ6VSHDDR3THSQ6OQS7UM source = Keypair.from_secret( "SCCS5ZBI7WVIJ4SW36WGOQQIWJYCL3VOAULSXX3FB57USIO25EDOYQHH") destination = "GDJJRRMBK4IWLEPJGIE6SXD2LP7REGZODU7WDC3I2D6MR37F4XSHBKX2" amount = "1000.0" sequence = 1 memo = IdMemo(100) fee = 200 asset = Asset.native() time_bounds = TimeBounds(12345, 56789) ops = [ Payment(destination, asset, amount), ManageData("hello", "world") ] tx = Transaction(source, sequence, fee, ops, memo, time_bounds) network = Network.public_network() te = TransactionEnvelope(tx, network) assert binascii.hexlify(te.hash()).decode() == te.hash_hex() te.sign(source) hashx = bytes.fromhex( "94e8223a518ac16a8cb110ab1952ef14da2c10b264645c38c8b3d82bd2b20000") te.sign_hashx(hashx) te_xdr = "AAAAAMvXcdYjKhx0qxnsDsczxKuqa/65lZz6sjjHHczyh50JAAAAyAAAAAAAAAABAAAAAQAAAAAAADA5AAAAAAAA3dUAAAACAAAAAAAAAGQAAAACAAAAAAAAAAEAAAAA0pjFgVcRZZHpMgnpXHpb/xIbLh0/YYto0PzI7+Xl5HAAAAAAAAAAAlQL5AAAAAAAAAAACgAAAAVoZWxsbwAAAAAAAAEAAAAFd29ybGQAAAAAAAAAAAAAAvKHnQkAAABAM4dg0J1LEFBmbDESJ5d+60WCuZC8lnA80g45qyEgz2oRBSNw1mOfZETnL/BgrebkG/K03oI2Wqcs9lvDKrDGDE0sOBsAAAAglOgiOlGKwWqMsRCrGVLvFNosELJkZFw4yLPYK9KyAAA=" assert te.to_xdr() == te_xdr restore_te = TransactionEnvelope.from_xdr(te_xdr, network) assert restore_te.to_xdr() == te_xdr
def test_good_withdrawal_integration(client, acc1_usd_withdrawal_transaction_factory): withdraw = acc1_usd_withdrawal_transaction_factory( protocol=Transaction.PROTOCOL.sep6) response = client.get( WITHDRAW_PATH, { "asset_code": withdraw.asset.code, "type": "bank_account", "dest": "test bank account number", }, ) content = json.loads(response.content) assert response.status_code == 200 assert content.pop("memo") assert content.pop("memo_type") == Transaction.MEMO_TYPES.hash assert content == { "account_id": Keypair.from_secret(USD_DISTRIBUTION_SEED).public_key, "min_amount": round(withdraw.asset.withdrawal_min_amount, withdraw.asset.significant_decimals), "max_amount": round(withdraw.asset.withdrawal_max_amount, withdraw.asset.significant_decimals), "fee_fixed": round(withdraw.asset.withdrawal_fee_fixed, withdraw.asset.significant_decimals), "fee_percent": withdraw.asset.withdrawal_fee_percent, "extra_info": { "test": "test" }, }
def create_channel_account(self, transaction: Transaction): kp = Keypair.random() settings.HORIZON_SERVER._client.get( f"https://friendbot.stellar.org/?addr={kp.public_key}" ) transaction.channel_seed = kp.secret transaction.save()
def test_process_response_strict_send_success(client): """ Tests successful processing of the SUCCESS_PAYMENT_TRANSACTION_JSON """ asset = Asset.objects.create( code="TEST", issuer=TEST_ASSET_ISSUER_PUBLIC_KEY, distribution_seed=TEST_ASSET_DISTRIBUTION_SEED, ) transaction = Transaction.objects.create( asset=asset, stellar_account=Keypair.random().public_key, amount_in=1001, kind=Transaction.KIND.send, status=Transaction.STATUS.pending_sender, memo=SUCCESS_STRICT_SEND_PAYMENT["memo"], protocol=Transaction.PROTOCOL.sep31, receiving_anchor_account=TEST_ASSET_DISTRIBUTION_PUBLIC_KEY, ) json = deepcopy(SUCCESS_STRICT_SEND_PAYMENT) Command.process_response(json, TEST_ASSET_DISTRIBUTION_PUBLIC_KEY) transaction.refresh_from_db() assert transaction.from_address assert transaction.stellar_transaction_id assert transaction.paging_token assert transaction.status == Transaction.STATUS.pending_receiver assert transaction.amount_in == 1001
def test_auth_get_account(client): """`GET <auth>` succeeds with a valid TransactionEnvelope XDR.""" response = client.get(f"/auth?account={STELLAR_ACCOUNT_1}", follow=True) content = json.loads(response.content) assert content["network_passphrase"] == "Test SDF Network ; September 2015" assert content["transaction"] envelope_xdr = content["transaction"] envelope_object = TransactionEnvelope.from_xdr( envelope_xdr, network_passphrase=settings.STELLAR_NETWORK_PASSPHRASE) transaction_object = envelope_object.transaction assert transaction_object.sequence == 0 assert len(transaction_object.operations) == 1 manage_data_op = transaction_object.operations[0] assert manage_data_op.type_code() == Xdr.const.MANAGE_DATA assert manage_data_op.data_name == "SEP 24 Reference auth" assert len(manage_data_op.data_value) == 64 signatures = envelope_object.signatures assert len(signatures) == 1 server_signature = signatures[0] tx_hash = envelope_object.hash() server_public_key = Keypair.from_public_key( settings.STELLAR_DISTRIBUTION_ACCOUNT_ADDRESS) server_public_key.verify(tx_hash, server_signature.signature)
def test_interactive_withdraw_bad_issuer(client): usd = Asset.objects.create( code="USD", issuer=Keypair.random().public_key, sep24_enabled=True, withdrawal_enabled=True, distribution_seed=Keypair.random().secret, ) withdraw = Transaction.objects.create(asset=usd) payload = interactive_jwt_payload(withdraw, "withdraw") payload["iss"] = "bad iss" token = jwt.encode(payload, settings.SERVER_JWT_KEY, algorithm="HS256").decode() response = client.get(f"{WEBAPP_PATH}?token={token}") assert "Invalid token issuer" in str(response.content) assert response.status_code == 403
def test_already_signed_raise(self): # GDF5O4OWEMVBY5FLDHWA5RZTYSV2U276XGKZZ6VSHDDR3THSQ6OQS7UM source = Keypair.from_secret( "SCCS5ZBI7WVIJ4SW36WGOQQIWJYCL3VOAULSXX3FB57USIO25EDOYQHH") destination = "GDJJRRMBK4IWLEPJGIE6SXD2LP7REGZODU7WDC3I2D6MR37F4XSHBKX2" amount = "1000.0" sequence = 1 memo = IdMemo(100) fee = 200 asset = Asset.native() time_bounds = TimeBounds(12345, 56789) ops = [ Payment(destination, asset, amount), ManageData("hello", "world") ] tx = Transaction(source, sequence, fee, ops, memo, time_bounds) network = Network.public_network() te = TransactionEnvelope(tx, network) assert binascii.hexlify(te.hash()).decode() == te.hash_hex() # te.sign(source) te.sign("SCCS5ZBI7WVIJ4SW36WGOQQIWJYCL3VOAULSXX3FB57USIO25EDOYQHH") hashx = bytes.fromhex( "94e8223a518ac16a8cb110ab1952ef14da2c10b264645c38c8b3d82bd2b20000") te.sign_hashx(hashx) with pytest.raises(SignatureExistError, match="The keypair has already signed."): te.sign(source) with pytest.raises(SignatureExistError, match="The preimage has already signed."): te.sign_hashx(hashx)
def test_auth_get_account(client): """`GET <auth>` succeeds with a valid TransactionEnvelope XDR.""" response = client.get(f"{endpoint}?account={STELLAR_ACCOUNT_1}", follow=True) content = json.loads(response.content) assert content["network_passphrase"] == "Test SDF Network ; September 2015" assert content["transaction"] envelope_xdr = content["transaction"] envelope_object = TransactionEnvelope.from_xdr( envelope_xdr, network_passphrase=settings.STELLAR_NETWORK_PASSPHRASE) transaction_object = envelope_object.transaction assert transaction_object.sequence == 0 assert len(transaction_object.operations) == 1 manage_data_op = transaction_object.operations[0] assert manage_data_op.type_code() == Xdr.const.MANAGE_DATA assert manage_data_op.data_name == f"{urlparse(settings.HOST_URL).netloc} auth" assert len(manage_data_op.data_value) <= 64 assert len(base64.b64decode(manage_data_op.data_value)) == 48 signatures = envelope_object.signatures assert len(signatures) == 1 server_signature = signatures[0] tx_hash = envelope_object.hash() server_public_key = Keypair.from_public_key(settings.SIGNING_KEY) server_public_key.verify(tx_hash, server_signature.signature)
def sign_challenge(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) return envelope_object.to_xdr()
def test_auth_get_success(client): """`GET <auth>` succeeds with a valid TransactionEnvelope XDR.""" response = client.get(f"{endpoint}?account={STELLAR_ACCOUNT_1}", follow=True) content = json.loads(response.content) assert content["network_passphrase"] == "Test SDF Network ; September 2015" assert content["transaction"] envelope_xdr = content["transaction"] envelope_object = TransactionEnvelope.from_xdr( envelope_xdr, network_passphrase=settings.STELLAR_NETWORK_PASSPHRASE) transaction_object = envelope_object.transaction assert transaction_object.sequence == 0 assert len(transaction_object.operations) == 2 home_domain_op = transaction_object.operations[0] assert isinstance(home_domain_op, ManageData) assert home_domain_op.data_name == f"{urlparse(settings.HOST_URL).netloc} auth" assert len(home_domain_op.data_value) <= 64 assert len(base64.b64decode(home_domain_op.data_value)) == 48 web_auth_domain_op = transaction_object.operations[1] assert isinstance(web_auth_domain_op, ManageData) assert web_auth_domain_op.data_name == "web_auth_domain" assert (web_auth_domain_op.data_value == f"{urlparse(settings.HOST_URL).netloc}".encode()) signatures = envelope_object.signatures assert len(signatures) == 1 tx_hash = envelope_object.hash() server_public_key = Keypair.from_public_key(settings.SIGNING_KEY) server_public_key.verify(tx_hash, signatures[0].signature)
def test_withdraw_authenticated_success( client, acc1_usd_withdrawal_transaction_factory): """`GET /withdraw` succeeds with the SEP 10 authentication flow.""" client_address = "GDKFNRUATPH4BSZGVFDRBIGZ5QAFILVFRIRYNSQ4UO7V2ZQAPRNL73RI" client_seed = "SDKWSBERDHP3SXW5A3LXSI7FWMMO5H7HG33KNYBKWH2HYOXJG2DXQHQY" acc1_usd_withdrawal_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.post(WITHDRAW_PATH, {"asset_code": "USD"}, follow=True, **header) content = json.loads(response.content) assert content["type"] == "interactive_customer_info_needed"
def test_withdrawal_transaction_created( client, acc1_usd_withdrawal_transaction_factory ): withdraw = acc1_usd_withdrawal_transaction_factory( protocol=Transaction.PROTOCOL.sep6 ) distribution_address = Keypair.from_secret(USD_DISTRIBUTION_SEED).public_key response = client.get( WITHDRAW_PATH, {"asset_code": withdraw.asset.code, "type": "good type", "dest": "test",}, ) assert response.status_code == 200 t = ( Transaction.objects.filter(kind=Transaction.KIND.withdrawal) .order_by("-started_at") .first() ) assert t assert t.memo_type == Transaction.MEMO_TYPES.hash assert t.receiving_anchor_account == distribution_address assert t.stellar_account == "test source address" assert not t.amount_in assert t.asset == withdraw.asset assert t.kind == Transaction.KIND.withdrawal assert t.status == Transaction.STATUS.pending_user_transfer_start assert t.protocol == Transaction.PROTOCOL.sep6
def create_stellar_deposit(transaction: Transaction) -> bool: """ Performs final status and signature checks before calling submit_stellar_deposit(). Returns true on successful submission, false otherwise. `transaction` will be placed in the error status if submission fails or if it is a multisig transaction and is not signed by the channel account. """ if transaction.status not in [ Transaction.STATUS.pending_anchor, Transaction.STATUS.pending_trust, ]: raise ValueError( f"unexpected transaction status {transaction.status} for " "create_stellar_deposit", ) elif transaction.amount_in is None or transaction.amount_fee is None: transaction.status = Transaction.STATUS.error transaction.status_message = ( "`amount_in` and `amount_fee` must be populated, skipping transaction" ) transaction.save() raise ValueError(transaction.status_message) # if the distribution account's master signer's weight is great or equal to the its # medium threshold, verify the transaction is signed by it's channel account 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 not master_signer or master_signer["weight"] < thresholds[ "med_threshold"]: envelope = TransactionEnvelope.from_xdr( transaction.envelope_xdr, settings.STELLAR_NETWORK_PASSPHRASE) try: _verify_te_signed_by_account_id(envelope, transaction.channel_account) except InvalidSep10ChallengeError: transaction.status = Transaction.STATUS.error transaction.status_message = gettext( "Multisig transaction's envelope was not signed by channel account" ) transaction.save() return False # otherwise, create the envelope and sign it with the distribution account's secret else: distribution_acc, _ = get_account_obj( Keypair.from_public_key(transaction.asset.distribution_account)) envelope = create_transaction_envelope(transaction, distribution_acc) envelope.sign(transaction.asset.distribution_seed) try: submit_stellar_deposit(transaction, envelope) except (RuntimeError, BaseHorizonError) as e: transaction.status_message = f"{e.__class__.__name__}: {e.message}" transaction.status = Transaction.STATUS.error transaction.save() logger.error(transaction.status_message) return False else: return True
def test_withdraw_client_domain_saved(client): kp = Keypair.random() usd = Asset.objects.create( code="USD", issuer=Keypair.random().public_key, sep24_enabled=True, withdrawal_enabled=True, distribution_seed=Keypair.random().secret, ) response = client.post( WITHDRAW_PATH, {"asset_code": usd.code, "account": kp.public_key}, ) content = response.json() assert response.status_code == 200, json.dumps(content, indent=2) assert Transaction.objects.count() == 1 transaction = Transaction.objects.first() assert transaction.client_domain == "test.com"
def main(): kp = Keypair.random() print("Secret: {}".format(kp.secret)) print("Public Key: {}".format(kp.public_key)) print("") pass