示例#1
0
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)
示例#2
0
 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
示例#3
0
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
示例#4
0
 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)
示例#5
0
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)
    )
示例#6
0
 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")
示例#7
0
 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)
示例#8
0
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,
    )
示例#9
0
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"}
示例#10
0
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()
示例#11
0
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'"
示例#12
0
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,
    )
示例#13
0
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
示例#14
0
 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
示例#15
0
 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
示例#17
0
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"
        },
    }
示例#18
0
 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)
示例#21
0
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)
示例#23
0
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)
示例#24
0
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()
示例#25
0
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)
示例#26
0
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
示例#28
0
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
示例#29
0
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"
示例#30
0
def main():

    kp = Keypair.random()
    print("Secret: {}".format(kp.secret))
    print("Public Key: {}".format(kp.public_key))
    print("")

    pass