Beispiel #1
0
def test_refund_transaction_of_custodial_to_custodial_under_threshold():
    client = testnet.create_client()
    faucet = testnet.Faucet(client)

    sender_custodial = CustodialApp.create(faucet.gen_account(), client)
    receiver_custodial = CustodialApp.create(faucet.gen_account(), client)

    # create a payment transaction
    intent_id = receiver_custodial.payment(user_id=0, amount=1_000_000)
    intent = identifier.decode_intent(intent_id, identifier.TDM)

    receiver_address = utils.account_address(intent.account_address)
    script = stdlib.encode_peer_to_peer_with_metadata_script(
        currency=utils.currency_code(intent.currency_code),
        payee=receiver_address,
        amount=intent.amount,
        metadata=txnmetadata.general_metadata(
            sender_custodial.find_user_sub_address_by_id(0),
            intent.sub_address),
        metadata_signature=b"",  # only travel rule metadata requires signature
    )

    sender = sender_custodial.available_child_vasp()
    txn = sender_custodial.create_transaction(sender, script,
                                              intent.currency_code)

    signed_txn = sender.sign(txn)
    client.submit(signed_txn)
    executed_txn = client.wait_for_transaction(signed_txn)

    # start to refund the transaction

    # find the event for the receiver, a p2p transaction may contains multiple receivers
    # in the future.
    event = txnmetadata.find_refund_reference_event(executed_txn,
                                                    receiver_address)
    assert event is not None
    amount = event.data.amount.amount
    currency_code = event.data.amount.currency
    refund_receiver_address = utils.account_address(event.data.sender)

    metadata = txnmetadata.refund_metadata_from_event(event)
    refund_txn_script = stdlib.encode_peer_to_peer_with_metadata_script(
        currency=utils.currency_code(currency_code),
        payee=refund_receiver_address,
        amount=amount,
        metadata=metadata,
        metadata_signature=b"",  # only travel rule metadata requires signature
    )

    # receiver is sender of refund txn
    sender = receiver_custodial.available_child_vasp()
    txn = receiver_custodial.create_transaction(sender, refund_txn_script,
                                                currency_code)
    refund_executed_txn = receiver_custodial.submit_and_wait(sender.sign(txn))
    assert refund_executed_txn is not None
def test_custodial_to_non_custodial():
    client = testnet.create_client()
    faucet = testnet.Faucet(client)

    sender_custodial = CustodialApp.create(faucet.gen_account())
    receiver = faucet.gen_account()

    amount = 1_000_000
    currency_code = testnet.TEST_CURRENCY_CODE

    script = stdlib.encode_peer_to_peer_with_metadata_script(
        currency=utils.currency_code(currency_code),
        payee=utils.account_address(receiver.account_address),
        amount=amount,
        metadata=txnmetadata.general_metadata(
            sender_custodial.find_user_sub_address_by_id(0), None),
        metadata_signature=b"",  # only travel rule metadata requires signature
    )

    sender = sender_custodial.available_child_vasp()
    seq_num = client.get_account_sequence(sender.account_address)
    txn = create_transaction(sender, seq_num, script, currency_code)

    signed_txn = sender.sign(txn)
    client.submit(signed_txn)
    executed_txn = client.wait_for_transaction(signed_txn)
    assert executed_txn is not None
def test_custodial_to_custodial_under_threshold():
    client = testnet.create_client()
    faucet = testnet.Faucet(client)

    sender_custodial = CustodialApp.create(faucet.gen_account())
    receiver_custodial = CustodialApp.create(faucet.gen_account())

    intent_id = receiver_custodial.payment(user_id=0, amount=1_000_000)

    intent = identifier.decode_intent(intent_id, identifier.TDM)

    script = stdlib.encode_peer_to_peer_with_metadata_script(
        currency=utils.currency_code(intent.currency_code),
        payee=utils.account_address(intent.account_address),
        amount=intent.amount,
        metadata=txnmetadata.general_metadata(
            sender_custodial.find_user_sub_address_by_id(0),
            intent.sub_address),
        metadata_signature=b"",  # only travel rule metadata requires signature
    )

    sender = sender_custodial.available_child_vasp()
    seq_num = client.get_account_sequence(sender.account_address)
    txn = create_transaction(sender, seq_num, script, intent.currency_code)

    signed_txn = sender.sign(txn)
    client.submit(signed_txn)
    executed_txn = client.wait_for_transaction(signed_txn)
    assert executed_txn is not None
Beispiel #4
0
def test_travel_rule_metadata():
    address = utils.account_address("f72589b71ff4f8d139674a3f7369c69b")
    metadata, sig_msg = txnmetadata.travel_rule("off chain reference id", address, 1000)

    assert metadata.hex() == "020001166f666620636861696e207265666572656e6365206964"
    assert (
        sig_msg.hex()
        == "020001166f666620636861696e207265666572656e6365206964f72589b71ff4f8d139674a3f7369c69be803000000000000404024244449454d5f41545445535424244040"
    )
def test_account_address():
    with pytest.raises(InvalidAccountAddressError):
        utils.account_address(bytes.fromhex("aaaa"))

    with pytest.raises(InvalidAccountAddressError):
        utils.account_address("aaaa")

    with pytest.raises(InvalidAccountAddressError):
        utils.account_address("0000000000000000000000000a550c1x")

    valid_address = "0000000000000000000000000a550c18"
    address = utils.account_address(valid_address)
    assert address
    assert utils.account_address(address) == address
    assert utils.account_address(bytes.fromhex(valid_address)) == address
Beispiel #6
0
    def _p2p_transfer(self, currency, amount, receiver_vasp_address, metadata,
                      signature) -> jsonrpc.Transaction:
        script = stdlib.encode_peer_to_peer_with_metadata_script(
            currency=utils.currency_code(currency),
            payee=utils.account_address(receiver_vasp_address),
            amount=diem_types.st.uint64(amount),
            metadata=metadata,
            metadata_signature=signature,
        )

        txn = self.create_transaction(script)
        return self._submit_and_wait(txn)
Beispiel #7
0
    def send_transaction_travel_rule(
        self,
        currency: DiemCurrency,
        amount: int,
        source_sub_address: str,
        dest_vasp_address: str,
        dest_sub_address: str,
        off_chain_reference_id: str,
        metadata_signature: bytes,
    ) -> Tuple[int, int]:
        account_info = self.fetch_account_info()
        if not account_info:
            raise RuntimeError(f"Could not find account {self.address_str}")

        sender = utils.account_address(self.address_str)
        metadata, metadata_sig = txnmetadata.travel_rule(
            off_chain_reference_id, sender, amount
        )

        # sender constructs transaction after off chain communication
        script = stdlib.encode_peer_to_peer_with_metadata_script(
            currency=utils.currency_code(currency.value),
            payee=utils.account_address(dest_vasp_address),
            amount=amount,
            metadata=metadata,
            metadata_signature=metadata_signature,
        )

        tx = self._custody.create_transaction(
            self._custody_account_name,
            account_info.sequence_number,
            script,
            currency.value,
        )
        self._diem_client.submit(tx)

        onchain_tx = self._diem_client.wait_for_transaction(tx, 30)
        return onchain_tx.version, account_info.sequence_number
def test_intent_identifier(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, "XUS", 123)
    assert intent_id == "diem://%s?c=%s&am=%d" % (enocded_addr_with_none_subaddr, "XUS", 123)

    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 == "XUS"
    assert intent.amount == 123

    assert account_id == intent.account_id
Beispiel #9
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
Beispiel #10
0
def test_intent_identifier():
    account_id = identifier.encode_account(test_onchain_address, None, "lbr")
    intent_id = identifier.encode_intent(account_id, "Coin1", 123)
    assert intent_id == "diem://%s?c=%s&am=%d" % (
        enocded_addr_with_none_subaddr, "Coin1", 123)

    intent = identifier.decode_intent(intent_id, "lbr")
    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 == "Coin1"
    assert intent.amount == 123

    assert account_id == intent.account_id
Beispiel #11
0
 def get_vasp_domain_map(self,
                         batch_size: int = 100) -> typing.Dict[str, str]:
     domain_map = {}
     event_index = 0
     tc_account = self.must_get_account(
         utils.account_address(TREASURY_ADDRESS))
     event_stream_key = tc_account.role.vasp_domain_events_key
     while True:
         events = self.get_events(event_stream_key, event_index, batch_size)
         for event in events:
             if event.data.removed:
                 del domain_map[event.data.domain]
             else:
                 domain_map[event.data.domain] = event.data.address
         if len(events) < batch_size:
             break
         event_index += batch_size
     return domain_map
Beispiel #12
0
def test_find_refund_reference_event():
    # None for no transaction given
    assert txnmetadata.find_refund_reference_event(None, None) is None

    receiver = utils.account_address("f72589b71ff4f8d139674a3f7369c69b")
    txn = jsonrpc.Transaction()
    txn.events.add(data=jsonrpc.EventData(type="unknown", receiver="f72589b71ff4f8d139674a3f7369c69b"))
    txn.events.add(data=jsonrpc.EventData(type="receivedpayment", receiver="unknown"))

    # None for not found
    event = txnmetadata.find_refund_reference_event(txn, receiver)
    assert event is None

    txn.events.add(data=jsonrpc.EventData(type="receivedpayment", receiver="f72589b71ff4f8d139674a3f7369c69b"))
    event = txnmetadata.find_refund_reference_event(txn, receiver)
    assert event is not None
    assert event.data.type == "receivedpayment"
    assert event.data.receiver == "f72589b71ff4f8d139674a3f7369c69b"
Beispiel #13
0
def test_process_incoming_travel_rule_txn() -> None:
    account = create_account("fake_account")
    sender_addr = "46db232847705e05525db0336fd9f337"
    receiver_addr = "lrw_vasp"
    sender_subaddr = generate_new_subaddress(account.id)
    amount = 1000 * 1_000_000
    sender = account_address(sender_addr)
    sequence = 1
    currency = DiemCurrency.XUS
    blockchain_version = 1

    off_chain_reference_id = "off_chain_reference_id"
    metadata, _ = travel_rule(off_chain_reference_id, sender, amount)

    storage.add_transaction(
        amount=amount,
        currency=currency,
        payment_type=TransactionType.OFFCHAIN,
        status=TransactionStatus.OFF_CHAIN_READY,
        source_id=account.id,
        source_address=sender_addr,
        source_subaddress=sender_subaddr,
        destination_address=receiver_addr,
        reference_id=off_chain_reference_id,
    )

    process_incoming_transaction(
        sender_address=sender_addr,
        receiver_address=receiver_addr,
        sequence=sequence,
        amount=amount,
        currency=currency,
        metadata=diem_types.Metadata__TravelRuleMetadata.bcs_deserialize(
            metadata),
        blockchain_version=blockchain_version,
    )

    # successfully parse meta and sequence
    tx = storage.get_transaction_by_details(source_address=sender_addr,
                                            source_subaddress=sender_subaddr,
                                            sequence=sequence)
    assert tx is not None
    assert tx.sequence == sequence
    assert tx.blockchain_version == blockchain_version
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
Beispiel #15
0
    def send_transaction(
        self,
        currency: DiemCurrency,
        amount: int,
        dest_vasp_address: str,
        dest_sub_address: str,
        source_sub_address: str = None,
    ) -> Tuple[int, int]:
        account_info = self.fetch_account_info()
        if not account_info:
            raise RuntimeError(f"Could not find account {self.address_str}")

        if source_sub_address is None:
            source_sub_address = secrets.token_hex(
                identifier.DIEM_SUBADDRESS_SIZE)

        meta = txnmetadata.general_metadata(
            from_subaddress=bytes.fromhex(source_sub_address),
            to_subaddress=bytes.fromhex(dest_sub_address),
        )

        script = stdlib.encode_peer_to_peer_with_metadata_script(
            currency=utils.currency_code(currency.value),
            payee=utils.account_address(dest_vasp_address),
            amount=amount,
            metadata=meta,
            metadata_signature=b"",
        )

        tx = self._custody.create_transaction(
            self._custody_account_name,
            account_info.sequence_number,
            script,
            currency.value,
        )
        self._diem_client.submit(tx)

        onchain_tx = self._diem_client.wait_for_transaction(tx, 30)
        return onchain_tx.version, account_info.sequence_number
def test_custodial_to_custodial_above_threshold():
    client = testnet.create_client()
    faucet = testnet.Faucet(client)

    sender_custodial = CustodialApp.create(faucet.gen_account())
    receiver_custodial = CustodialApp.create(faucet.gen_account())
    receiver_custodial.init_compliance_keys()

    intent_id = receiver_custodial.payment(user_id=0, amount=2_000_000_000)

    intent = identifier.decode_intent(intent_id, identifier.TDM)

    sender = sender_custodial.available_child_vasp()
    # sender & receiver communicate by off chain APIs
    off_chain_reference_id = "32323abc"
    metadata, metadata_signing_msg = txnmetadata.travel_rule(
        off_chain_reference_id, sender.account_address, intent.amount)
    metadata_signature = receiver_custodial.compliance_key.sign(
        metadata_signing_msg)

    # sender constructs transaction after off chain communication
    script = stdlib.encode_peer_to_peer_with_metadata_script(
        currency=utils.currency_code(intent.currency_code),
        payee=utils.account_address(intent.account_address),
        amount=intent.amount,
        metadata=metadata,
        metadata_signature=metadata_signature,
    )

    seq_num = client.get_account_sequence(sender.account_address)
    txn = create_transaction(sender, seq_num, script, intent.currency_code)

    signed_txn = sender.sign(txn)
    client.submit(signed_txn)
    executed_txn = client.wait_for_transaction(signed_txn)
    assert executed_txn is not None
Beispiel #17
0
 def vasp_account_address(self) -> diem_types.AccountAddress:
     return utils.account_address(self.vasp_address)