Ejemplo n.º 1
0
def generate_payment_options_with_qr(payment):
    payment_options_with_qr = []

    vasp_addr = OnchainWallet().address_str
    logger.debug(f"Current vasp address: {vasp_addr}")
    full_payment_addr = identifier.encode_account(vasp_addr,
                                                  payment.subaddress,
                                                  CHAIN_HRP)
    logger.debug(f"Rendering full payment link: {full_payment_addr}")

    bech32addr = identifier.encode_account(vasp_addr, payment.subaddress,
                                           CHAIN_HRP)

    for payment_option in payment.payment_options:
        payment_link = f"diem://{bech32addr}?c={payment_option.currency}&am={payment_option.amount}"
        payment_option_attributes = dict(
            address=bech32addr,
            currency=payment_option.currency,
            amount=payment_option.amount,
            payment_link=payment_link,
        )
        qr = pyqrcode.create(payment_link)
        payment_option_attributes["qr_b64"] = qr.png_as_base64_str(scale=10)

        payment_options_with_qr.append(payment_option_attributes)

    return payment_options_with_qr
Ejemplo n.º 2
0
def test_account_identifier():
    account = LocalAccount()
    assert account.account_identifier() == identifier.encode_account(
        account.account_address, None, account.hrp)
    subaddress = identifier.gen_subaddress()
    assert account.account_identifier(subaddress) == identifier.encode_account(
        account.account_address, subaddress, account.hrp)
Ejemplo n.º 3
0
    def new_payment_object(self,
                           sender=LocalAccount.generate(),
                           receiver=LocalAccount.generate()):
        amount = 1_000_000_000_000
        currency = testnet.TEST_CURRENCY_CODE
        sender_account_id = identifier.encode_account(
            sender.account_address, identifier.gen_subaddress(), self.hrp())
        sender_kyc_data = offchain.individual_kyc_data(
            given_name="Jack",
            surname="G",
            address=offchain.AddressObject(city="San Francisco"),
        )

        receiver_account_id = identifier.encode_account(
            receiver.account_address,
            identifier.gen_subaddress(),
            self.hrp(),
        )

        return offchain.new_payment_object(
            sender_account_id,
            sender_kyc_data,
            receiver_account_id,
            amount,
            currency,
        )
Ejemplo n.º 4
0
def save_outbound_transaction(
    sender_id: int,
    destination_address: str,
    destination_subaddress: str,
    amount: int,
    currency: DiemCurrency,
) -> Transaction:
    sender_onchain_address = context.get().config.vasp_address
    sender_subaddress = account.generate_new_subaddress(account_id=sender_id)
    return commit_transaction(
        _new_payment_command_transaction(
            offchain.PaymentCommand.init(
                identifier.encode_account(
                    sender_onchain_address, sender_subaddress, _hrp()
                ),
                _user_kyc_data(sender_id),
                identifier.encode_account(
                    destination_address, destination_subaddress, _hrp()
                ),
                amount,
                currency.value,
            ),
            TransactionStatus.OFF_CHAIN_OUTBOUND,
        )
    )
Ejemplo n.º 5
0
def test_encode_addr_fail(hrp_addresses):
    hrp = hrp_addresses[0]
    # wrong subadress (length should be 8 bytes)
    with pytest.raises(InvalidSubAddressError):
        identifier.encode_account(test_onchain_address, test_sub_address[:-2], hrp)

    # wrong address (length should be 16 bytes)
    with pytest.raises(InvalidAccountAddressError):
        identifier.encode_account(test_onchain_address + "ff", test_sub_address[:-2], hrp)
Ejemplo n.º 6
0
    def get_transaction_response_object(
            cls, account_id: int, transaction: Transaction) -> Dict[str, str]:
        direction = get_transaction_direction(account_id=account_id,
                                              transaction=transaction)

        blockchain_tx = None

        if transaction.type == TransactionType.EXTERNAL:
            blockchain_tx = {
                "amount": transaction.amount,
                "source": transaction.source_address,
                "destination": transaction.destination_address,
                "expirationTime": "",
                "sequenceNumber": transaction.sequence,
                "status": transaction.status,
                "version": transaction.blockchain_version,
            }

        return {
            "id": transaction.id,
            "amount": transaction.amount,
            "currency": transaction.currency,
            "direction": direction.value.lower(),
            "status": transaction.status,
            "timestamp": transaction.created_timestamp.isoformat(),
            "source": {
                "vasp_name":
                transaction.source_address,
                "user_id":
                transaction.source_subaddress,
                "full_addr":
                identifier.encode_account(
                    transaction.source_address,
                    transaction.source_subaddress,
                    context.get().config.diem_address_hrp(),
                ),
            },
            "destination": {
                "vasp_name":
                transaction.destination_address,
                "user_id":
                transaction.destination_subaddress,
                "full_addr":
                identifier.encode_account(
                    transaction.destination_address,
                    transaction.destination_subaddress,
                    context.get().config.diem_address_hrp(),
                ),
            },
            "is_internal": transaction.type == TransactionType.INTERNAL,
            "blockchain_tx": blockchain_tx,
        }
Ejemplo n.º 7
0
def test_process_inbound_command(monkeypatch):
    hrp = context.get().config.diem_address_hrp()
    user = OneUser.run(db_session,
                       account_amount=100_000_000_000,
                       account_currency=currency)
    amount = 10_000_000_000
    sender = LocalAccount.generate()
    sender_subaddress = identifier.gen_subaddress()
    receiver_subaddress = generate_new_subaddress(user.account_id)
    cmd = offchain.PaymentCommand.init(
        identifier.encode_account(sender.account_address, sender_subaddress,
                                  hrp),
        _user_kyc_data(user.account_id),
        identifier.encode_account(context.get().config.vasp_address,
                                  receiver_subaddress, hrp),
        amount,
        currency.value,
    )

    with monkeypatch.context() as m:
        client = context.get().offchain_client
        m.setattr(
            client,
            "process_inbound_request",
            lambda _, cmd: client.create_inbound_payment_command(
                cmd.cid, cmd.payment),
        )
        code, resp = process_inbound_command(cmd.payment.sender.address, cmd)
        assert code == 200
        assert resp

    txn = get_transaction_by_reference_id(cmd.reference_id())
    assert txn
    assert txn.status == TransactionStatus.OFF_CHAIN_INBOUND

    cmd = _txn_payment_command(txn)
    assert cmd.is_inbound(), str(cmd)

    with monkeypatch.context() as m:
        m.setattr(
            context.get().offchain_client,
            "send_command",
            lambda cmd, _: offchain.reply_request(cmd.cid),
        )
        process_offchain_tasks()

        db_session.refresh(txn)
        assert txn.status == TransactionStatus.OFF_CHAIN_OUTBOUND
def test_send_payment_with_invalid_account_identifier_onchain_account_address_as_payee(
        stub_client: RestClient, target_client: RestClient, currency: str,
        hrp: str) -> None:
    """
    Test Plan:

    1. Generate valid receive payment account identifier.
    2. Extract account onchain address and subaddress from receiving payment account identifier.
    3. Use an invalid onchain account address and extracted subaddress to create a new account identifier.
    4. Call send payment `POST /accounts/{account_id}/payments` with created account identifier.
    5. Expect server response 400 client error, and sender account balance is not changed.
    """

    amount = 1_000_000
    sender_account = target_client.create_account(balances={currency: amount})
    receiver_account = stub_client.create_account()
    try:
        receiver_account_identifier = receiver_account.generate_account_identifier(
        )
        _, subaddress = identifier.decode_account(receiver_account_identifier,
                                                  hrp)
        invalid_account_address = LocalAccount().account_address
        invalid_account_identifier = identifier.encode_account(
            invalid_account_address, subaddress, hrp)
        with pytest.raises(requests.HTTPError, match="400 Client Error"):
            sender_account.send_payment(currency=currency,
                                        amount=amount,
                                        payee=invalid_account_identifier)
        assert sender_account.balance(currency) == amount
    finally:
        receiver_account.log_events()
        sender_account.log_events()
def test_send_payment_with_invalid_account_identifier_hrp_as_payee(
        sender_account: AccountResource, receiver_account: AccountResource,
        currency: str, hrp: str) -> None:
    """
    Test Plan:

    1. Generate valid receive payment account identifier.
    2. Extract account onchain address and subaddress from receiving payment account identifier.
    3. Use a different hrp and extracted account address and subaddress to create a new account identifier.
    4. Call send payment `POST /accounts/{account_id}/payments` with created account identifier.
    5. Expect server response 400 client error, and sender account balance is not changed.
    """

    initial_amount = sender_account.balance(currency)
    receiver_account_identifier = receiver_account.generate_account_identifier(
    )
    account_address, subaddress = identifier.decode_account(
        receiver_account_identifier, hrp)
    new_hrp = identifier.TDM if hrp != identifier.TDM else identifier.PDM
    new_account_identifier = identifier.encode_account(account_address,
                                                       subaddress, new_hrp)
    with pytest.raises(requests.HTTPError, match="400 Client Error"):
        sender_account.send_payment(currency=currency,
                                    amount=amount,
                                    payee=new_account_identifier)
    assert sender_account.balance(currency) == initial_amount
Ejemplo n.º 10
0
async def test_send_payment_with_invalid_account_identifier_hrp_as_payee(
        stub_client: RestClient, target_client: RestClient, currency: str,
        hrp: str) -> None:
    """
    Test Plan:

    1. Generate valid receive payment account identifier.
    2. Extract account onchain address and subaddress from receiving payment account identifier.
    3. Use a different hrp and extracted account address and subaddress to create a new account identifier.
    4. Call send payment `POST /accounts/{account_id}/payments` with created account identifier.
    5. Expect server response 400 client error, and sender account balance is not changed.
    """

    amount = 1_000_000
    sender_account = await target_client.create_account(
        balances={currency: amount})
    receiver_account = await stub_client.create_account()
    try:
        receiver_account_identifier = await receiver_account.generate_account_identifier(
        )
        account_address, subaddress = identifier.decode_account(
            receiver_account_identifier, hrp)
        new_hrp = identifier.TDM if hrp != identifier.TDM else identifier.PDM
        new_account_identifier = identifier.encode_account(
            account_address, subaddress, new_hrp)
        with pytest.raises(aiohttp.ClientResponseError, match="400"):
            await sender_account.send_payment(currency=currency,
                                              amount=amount,
                                              payee=new_account_identifier)
        assert await sender_account.balance(currency) == amount
    finally:
        await receiver_account.log_events()
        await sender_account.log_events()
def test_could_not_find_compliance_key_of_x_request_sender_address(sender_app, receiver_app):
    account = testnet.gen_account(testnet.create_client())
    account_id = identifier.encode_account(account.account_address, None, sender_app.hrp)
    request = minimum_required_fields_request_sample(sender_app, receiver_app)
    request["command"]["payment"]["sender"]["address"] = account_id
    resp = send_request(request, sender_app, receiver_app, "failure", sender_address=account_id)
    assert_response_protocol_error(resp, "invalid_http_header")
def test_could_not_find_onchain_account_by_x_request_sender_address(sender_app, receiver_app):
    account = LocalAccount.generate()
    account_id = identifier.encode_account(account.account_address, None, sender_app.hrp)
    request = minimum_required_fields_request_sample(sender_app, receiver_app)
    request["command"]["payment"]["sender"]["address"] = account_id
    resp = send_request(request, sender_app, receiver_app, "failure", sender_address=account_id)
    assert_response_protocol_error(resp, "invalid_http_header")
Ejemplo n.º 13
0
 def payment(self, user_id: int, amount: int) -> str:
     account_id = identifier.encode_account(
         self._children[0].account_address,
         self._users[user_id],
         identifier.TLB  # testnet HRP
     )
     return identifier.encode_intent(account_id, testnet.TEST_CURRENCY_CODE,
                                     amount)
Ejemplo n.º 14
0
def process_incoming_transaction(
    version,
    sender_address,
    sender_sub_address,
    receiver_address,
    receiver_sub_address,
    amount,
    currency,
) -> None:
    """This function receives incoming payment events from the chain"""
    # Check if the payment is intended for us - this address is configured via environment variable, see config.py
    if receiver_address != OnchainWallet().address_str:
        logging.debug("Received payment to unknown base address.")
        raise WrongReceiverAddressException("wrongaddr")

    # Locate payment id and payment options related to the given subaddress
    payment = Payment.find_by_subaddress(receiver_sub_address)
    if payment is None:
        logging.debug(
            f"Could not find the qualifying payment {receiver_sub_address}, ignoring."
        )
        # TODO - Process for errant payments?
        raise PaymentForSubaddrNotFoundException("wrongsubaddr")

    if payment.status != PaymentStatus.created:
        logging.debug(f"Payment status is invalid: {payment.status}")
        raise PaymentStatusException("invalidpaymentstatus")

    if payment.is_expired():
        logging.debug(f"Payment expired: {payment.expiry_date}. Rejecting.")
        payment.set_status(PaymentStatus.rejected)
        db_session.commit()
        # TODO - Do we need a reaper process to simply mark expired payments as such?
        raise PaymentExpiredException("paymentexpired")

    # verify payment matches any of the payment options for this payment id
    if not payment.is_payment_option_valid(amount, currency):
        logging.debug(
            "Payment does not match any of the relevant payment options, ignoring."
        )
        # TODO - Set status to rejected here or ignore?
        raise PaymentOptionNotFoundException("paymentoptionnotfound")

    # We're good - mark as cleared
    logging.debug(f"Clearing payment id {payment.id}")
    payment.set_status(PaymentStatus.cleared)
    # version is tx_id

    payment.add_chain_transaction(
        identifier.encode_account(sender_address, sender_sub_address,
                                  CHAIN_HRP),
        amount,
        currency,
        version,
    )
    db_session.commit()
Ejemplo n.º 15
0
def get_deposit_address(account_id: Optional[int] = None,
                        account_name: Optional[str] = None):
    account = get_account(account_id=account_id, account_name=account_name)
    subaddress = generate_new_subaddress(account.id)

    return identifier.encode_account(
        context.get().config.vasp_account_address(),
        subaddress,
        context.get().config.diem_address_hrp(),
    )
Ejemplo n.º 16
0
def test_intent_identifier_with_sub_address(hrp_addresses):
    hrp, enocded_addr_with_none_subaddr, enocded_addr_with_subaddr = hrp_addresses
    account_id = identifier.encode_account(test_onchain_address, test_sub_address, hrp)
    intent_id = identifier.encode_intent(account_id, "XUS", 123)
    assert intent_id == "diem://%s?c=%s&am=%d" % (enocded_addr_with_subaddr, "XUS", 123)

    intent = identifier.decode_intent(intent_id, hrp)
    assert intent.account_address_bytes.hex() == test_onchain_address
    assert intent.sub_address == bytes.fromhex(test_sub_address)
    assert intent.currency_code == "XUS"
    assert intent.amount == 123
Ejemplo n.º 17
0
def test_encode_addr_success(hrp_addresses):
    hrp, enocded_addr_with_none_subaddr, enocded_addr_with_subaddr = hrp_addresses

    # test with none sub_address
    enocded_addr = identifier.encode_account(test_onchain_address, None, hrp)
    assert enocded_addr == enocded_addr_with_none_subaddr

    # even with zero sub_address, expected should not change from above
    enocded_addr = identifier.encode_account(test_onchain_address, zero_sub_address, hrp)
    assert enocded_addr == enocded_addr_with_none_subaddr

    # test with some subaddress
    enocded_addr = identifier.encode_account(test_onchain_address, test_sub_address, hrp)
    assert enocded_addr == enocded_addr_with_subaddr

    # accept AccountAddress and bytes sub-address as params too
    enocded_addr = identifier.encode_account(
        utils.account_address(test_onchain_address), utils.sub_address(test_sub_address), hrp
    )
    assert enocded_addr == enocded_addr_with_subaddr
Ejemplo n.º 18
0
def test_intent_identifier_with_sub_address():
    account_id = identifier.encode_account(test_onchain_address,
                                           test_sub_address, "lbr")
    intent_id = identifier.encode_intent(account_id, "Coin1", 123)
    assert intent_id == "diem://%s?c=%s&am=%d" % (enocded_addr_with_subaddr,
                                                  "Coin1", 123)

    intent = identifier.decode_intent(intent_id, "lbr")
    assert intent.account_address_bytes.hex() == test_onchain_address
    assert intent.sub_address == bytes.fromhex(test_sub_address)
    assert intent.currency_code == "Coin1"
    assert intent.amount == 123
Ejemplo n.º 19
0
def test_intent_identifier():
    child_vasp_address = "d738a0b9851305dfe1d17707f0841dbc"
    user_sub_address = "9072d012034a880f"
    currency_code = "XUS"
    amount = 10_000_000

    account_id = identifier.encode_account(
        child_vasp_address,
        utils.sub_address(user_sub_address),
        identifier.TDM  # testnet HRP
    )
    intent_id = identifier.encode_intent(account_id, currency_code, amount)

    assert intent_id == "diem://tdm1p6uu2pwv9zvzalcw3wurlppqahjg895qjqd9gsrcr9dqh8?c=XUS&am=10000000"
Ejemplo n.º 20
0
def test_intent_identifier_without_params(hrp_addresses):
    hrp, enocded_addr_with_none_subaddr, enocded_addr_with_subaddr = hrp_addresses
    account_id = identifier.encode_account(test_onchain_address, None, hrp)
    intent_id = identifier.encode_intent(account_id)
    assert intent_id == "diem://%s" % enocded_addr_with_none_subaddr

    intent = identifier.decode_intent(intent_id, hrp)
    assert intent.account_address == utils.account_address(test_onchain_address)
    assert intent.account_address_bytes.hex() == test_onchain_address
    assert intent.sub_address is None
    assert intent.currency_code is None
    assert intent.amount is None

    assert account_id == intent.account_id
Ejemplo n.º 21
0
 async def _refund(self, reason: RefundReason, event: jsonrpc.Event) -> None:
     self._create_txn(PENDING_INBOUND_ACCOUNT_ID, event)
     payee = identifier.encode_account(event.data.sender, None, self.hrp)
     self.store.create(
         Transaction,
         account_id=PENDING_INBOUND_ACCOUNT_ID,
         status=Transaction.Status.pending,
         type=Transaction.Type.sent_payment,
         currency=event.data.amount.currency,
         amount=event.data.amount.amount,
         payee=payee,
         payee_account_identifier=payee,
         refund_diem_txn_version=event.transaction_version,
         refund_reason=reason,
     )
def send_request_json(
    request_json, sender_app, receiver_app, expected_resp_status, sender_address=None
) -> CommandResponseObject:
    if sender_address is None:
        subaddresses = sender_app.users["foo"].subaddresses
        subaddress = subaddresses[len(subaddresses) - 1] if len(subaddresses) > 0 else None
        account_address = sender_app._available_child_vasp().account_address
        sender_address = identifier.encode_account(account_address, subaddress, sender_app.hrp)
    return send_request_json_with_headers(
        request_json,
        sender_app,
        receiver_app,
        expected_resp_status,
        {
            http_header.X_REQUEST_ID: str(uuid.uuid4()),
            http_header.X_REQUEST_SENDER_ADDRESS: sender_address,
        },
    )
def refund_transfer(user1: UserClient, user2: UserClient, transfer_amount: int,
                    currency: str):
    user1_balance_before_transfer = user1.get_balance(currency)
    user2_balance_before_transfer = user2.get_balance(currency)

    # addr2 = user2.get_recv_addr()
    subaddress = secrets.token_hex(identifier.DIEM_SUBADDRESS_SIZE)
    deposit_address_with_wrong_subaddress = identifier.encode_account(
        os.getenv("VASP_ADDR_2"),
        subaddress,
        "tdm",
    )

    # user1 sends money to wrong address
    user1.transfer(deposit_address_with_wrong_subaddress, transfer_amount,
                   currency)

    # check funds have left user 1 account
    user1.wait_for_balance(currency,
                           user1_balance_before_transfer - transfer_amount, 20)
    sent_txns = [
        txn for txn in user1.get_transactions()
        if txn.get("direction") == "sent"
    ]

    assert len(sent_txns) == 1
    assert sent_txns[0].get("amount") == transfer_amount

    # user2 never receives the transfer due to wrong subaddress
    assert user2.get_balance(currency) == user2_balance_before_transfer
    txns2 = user2.get_transactions()
    assert len(txns2) == 0

    # user1 gets refund back
    user1.wait_for_balance(currency, user1_balance_before_transfer, 20)
    txns1 = user1.get_transactions()
    assert txns1[0].get("amount") == transfer_amount
    assert txns1[0].get("status") == "completed"
Ejemplo n.º 24
0
def main():
    # generate private key
    private_key = Ed25519PrivateKey.generate()
    # generate auth key
    auth_key = AuthKey.from_public_key(private_key.public_key())

    # create intent identifier
    account_identifier = identifier.encode_account(
        utils.account_address_hex(auth_key.account_address()), None,
        identifier.TDM)
    encoded_intent_identifier = identifier.encode_intent(
        account_identifier, "XUS", 10000000)
    print(f"Encoded IntentIdentifier: {encoded_intent_identifier}")

    # deserialize IntentIdentifier
    intent_identifier = identifier.decode_intent(encoded_intent_identifier,
                                                 identifier.TDM)

    print(
        f"Account (HEX) from intent: {utils.account_address_hex(intent_identifier.account_address)}"
    )
    print(f"Amount from intent: {intent_identifier.amount}")
    print(f"Currency from intent: {intent_identifier.currency_code}")
Ejemplo n.º 25
0
async def test_payment_command_sender_address_can_only_be_written_once(
    currency: str,
    travel_rule_threshold: int,
    stub_wallet_app: App,
    hrp: str,
    stub_client: RestClient,
    target_client: RestClient,
) -> None:
    """
    Test Plan:

    1. Generate a valid account identifier from receiver account as payee.
    2. Disable stub wallet application background tasks.
    3. Send a payment that requires off-chain PaymentCommand to the receiver account identifier.
    4. Send initial payment command to receiver wallet offchain API endpoint.
    5. Wait for receiver's wallet application to send payment command back with receiver ready for settlement.
    6. Update payment command sender address.
    7. Send the updated payment command to receiver with sender ready for settlement.
    8. Expect http response status code is 400
    9. Expect response `CommandResponseObject` with failure status, `command_error` error type,
       and `invalid_overwrite` error code.
    """

    target_kyc = await target_client.get_kyc_sample()
    stub_kyc = await stub_client.get_kyc_sample()
    sender_account = await stub_client.create_account(
        balances={currency: travel_rule_threshold},
        kyc_data=target_kyc.minimum,
        disable_background_tasks=True,
    )
    receiver_account = await target_client.create_account(kyc_data=stub_kyc.minimum)
    try:
        payee = await receiver_account.generate_account_identifier()

        payment = await sender_account.send_payment(currency=currency, amount=travel_rule_threshold, payee=payee)
        txn = stub_wallet_app.store.find(Transaction, id=payment.id)
        # send initial payment command
        initial_cmd = await OffChainAPIv2(stub_wallet_app).send_initial_payment_command(txn)

        # wait for receiver to update payment command
        await wait_for_event(sender_account, "updated_payment_command")
        # find updated payment command
        updated_cmd = stub_wallet_app.store.find(PaymentCommand, reference_id=initial_cmd.reference_id())
        offchain_cmd = updated_cmd.to_offchain_command()

        # update sender address
        sender_account_address = offchain_cmd.sender_account_address(hrp)
        new_subaddress = stub_wallet_app._gen_subaddress(sender_account.id)
        new_sender_address = identifier.encode_account(sender_account_address, new_subaddress, hrp)
        new_sender = replace(offchain_cmd.payment.sender, address=new_sender_address)
        new_payment = replace(offchain_cmd.payment, sender=new_sender)
        new_offchain_cmd = replace(offchain_cmd, payment=new_payment, my_actor_address=new_sender_address)

        new_cmd = new_offchain_cmd.new_command(status=offchain.Status.ready_for_settlement)

        with pytest.raises(offchain.CommandResponseError) as err:
            await OffChainAPIv2(stub_wallet_app).send_offchain_command_without_retries(new_cmd)

        assert_response_error(err.value.resp, "invalid_overwrite", "command_error", field="payment.sender.address")
    finally:
        await receiver_account.log_events()
        await sender_account.log_events()
Ejemplo n.º 26
0
def db():
    clear_db()
    # Add Merchant and Payment for testing
    merchant = Merchant(
        api_key=TOKEN_1,
        settlement_information=MERCHANT_MOCK_ADDR,
        settlement_currency=MERCHAND_CURRENCY,
    )
    db_session.add(merchant)
    db_session.commit()

    payment = Payment(
        id=PAYMENT_ID,
        merchant_id=merchant.id,
        merchant_reference_id=CREATED_ORDER_ID,
        requested_amount=1,
        requested_currency="USD",
        subaddress=PAYMENT_SUBADDR,
        expiry_date=datetime.utcnow() + timedelta(minutes=10),
    )
    payment.payment_options.extend([
        PaymentOption(
            payment_id=payment.id,
            amount=PAYMENT_AMOUNT,
            currency=PAYMENT_CURRENCY,
        ),
        PaymentOption(
            payment_id=payment.id,
            amount=PAYMENT_AMOUNT_2,
            currency=PAYMENT_CURRENCY,
        ),
    ])

    cleared_payment = Payment(
        id=CLEARED_PAYMENT_ID,
        merchant_reference_id=CLEARED_ORDER_ID,
        merchant_id=merchant.id,
        requested_amount=10,
        requested_currency="USD",
        status=PaymentStatus.cleared,
        subaddress="f3704755d1100cd2",
        expiry_date=datetime.utcnow() - timedelta(minutes=10),
    )
    cleared_payment.payment_options.append(
        PaymentOption(
            payment_id=cleared_payment.id,
            amount=cleared_payment.requested_amount,
            currency=cleared_payment.requested_currency,
        ))
    cleared_payment.add_chain_transaction(
        sender_address=identifier.encode_account(SENDER_MOCK_ADDR,
                                                 SENDER_MOCK_SUBADDR,
                                                 CHAIN_HRP),
        amount=10,
        currency=DEFAULT_DIEM_CURRENCY,
        tx_id=CLEARED_TX_ID,
    )

    rejected_payment = Payment(
        id=REJECTED_PAYMENT_ID,
        merchant_id=merchant.id,
        merchant_reference_id=REJECTED_ORDER_ID,
        status=PaymentStatus.rejected,
        requested_amount=100,
        requested_currency="USD",
        expiry_date=datetime.utcnow(),
        subaddress=REJECTED_PAYMENT_SUBADDR,
    )

    expired_payment = Payment(
        id=EXPIRED_PAYMENT_ID,
        merchant_id=merchant.id,
        merchant_reference_id=EXPIRED_ORDER_ID,
        requested_amount=100,
        requested_currency="USD",
        subaddress=EXPIRED_PAYMENT_SUBADDR,
        expiry_date=datetime.utcnow() - timedelta(seconds=1),
    )

    db_session.add(rejected_payment)
    db_session.add(cleared_payment)
    db_session.add(expired_payment)
    db_session.add(payment)

    db_session.commit()

    yield db_session
def get_merchant_full_addr(payment):
    return identifier.encode_account(OnchainWallet().address_str,
                                     payment.subaddress, CHAIN_HRP)
Ejemplo n.º 28
0
def test_encode_decode_with_random_hrp():
    # test with none sub_address
    id = identifier.encode_account(test_onchain_address, None, "abc")
    addr, sub = identifier.decode_account(id, "abc")
    assert addr.to_hex() == test_onchain_address
    assert sub is None
Ejemplo n.º 29
0
def main():
    print("#1 connect to testnet")
    client = testnet.create_client()

    print("#2 Generate Keys")
    # generate private key for sender account
    sender_private_key = Ed25519PrivateKey.generate()
    # generate auth key for sender account
    sender_auth_key = AuthKey.from_public_key(sender_private_key.public_key())
    print(
        f"Generated sender address: {utils.account_address_hex(sender_auth_key.account_address())}"
    )

    print("#3 Create account")
    faucet = testnet.Faucet(client)
    testnet.Faucet.mint(faucet, sender_auth_key.hex(), 100000000, CURRENCY)

    print("#4 Get account information")
    sender_account = client.get_account(sender_auth_key.account_address())

    events_key = sender_account.received_events_key
    print("#5 Start event listener")
    get_events_example.subscribe(client, events_key)

    print("#6 Add money to account")
    faucet = testnet.Faucet(client)
    testnet.Faucet.mint(faucet, sender_auth_key.hex(), 10000000, CURRENCY)

    print("#7 Generate Keys")
    # generate private key for receiver account
    receiver_private_key = Ed25519PrivateKey.generate()
    # generate auth key for receiver account
    receiver_auth_key = AuthKey.from_public_key(
        receiver_private_key.public_key())
    print(
        f"Generated receiver address: {utils.account_address_hex(receiver_auth_key.account_address())}"
    )

    print("#8 Create second account")
    faucet = testnet.Faucet(client)
    testnet.Faucet.mint(faucet, receiver_auth_key.hex(), 1000000, CURRENCY)

    print("#9 Generate IntentIdentifier")
    account_identifier = identifier.encode_account(
        utils.account_address_hex(receiver_auth_key.account_address()), None,
        identifier.TDM)
    encoded_intent_identifier = identifier.encode_intent(
        account_identifier, CURRENCY, 10000000)
    print(f"Encoded IntentIdentifier: {encoded_intent_identifier}")

    print("#10 Deserialize IntentIdentifier")
    intent_identifier = identifier.decode_intent(encoded_intent_identifier,
                                                 identifier.TDM)
    print(
        f"Account (HEX) from intent: {utils.account_address_hex(intent_identifier.account_address)}"
    )
    print(f"Amount from intent: {intent_identifier.amount}")
    print(f"Currency from intent: {intent_identifier.currency_code}")

    print("#11 Peer 2 peer transaction")
    # create script
    script = stdlib.encode_peer_to_peer_with_metadata_script(
        currency=utils.currency_code(intent_identifier.currency_code),
        payee=intent_identifier.account_address,
        amount=intent_identifier.amount,
        metadata=b'',  # no requirement for metadata and metadata signature
        metadata_signature=b'',
    )
    # create transaction
    raw_transaction = diem_types.RawTransaction(
        sender=sender_auth_key.account_address(),
        sequence_number=sender_account.sequence_number,
        payload=diem_types.TransactionPayload__Script(script),
        max_gas_amount=1_000_000,
        gas_unit_price=0,
        gas_currency_code=CURRENCY,
        expiration_timestamp_secs=int(time.time()) + 30,
        chain_id=testnet.CHAIN_ID,
    )
    # sign transaction
    signature = sender_private_key.sign(
        utils.raw_transaction_signing_msg(raw_transaction))
    public_key_bytes = utils.public_key_bytes(sender_private_key.public_key())

    signed_txn = utils.create_signed_transaction(raw_transaction,
                                                 public_key_bytes, signature)
    # submit transaction
    client.submit(signed_txn)
    # wait for transaction
    client.wait_for_transaction(signed_txn)
Ejemplo n.º 30
0
 def gen_user_account_id(self, user_name: str) -> str:
     subaddress = identifier.gen_subaddress()
     self.users[user_name].subaddresses.append(subaddress)
     return identifier.encode_account(self._available_child_vasp().account_address, subaddress, self.hrp)