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
示例#2
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
示例#3
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
示例#4
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
示例#5
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
示例#6
0
def test_generate_account_payment_uri_with_currency_and_amount(
        account: AccountResource, currency: str, hrp: str) -> None:
    amount = 1123
    uri = account.generate_payment_uri(currency=currency, amount=amount)
    assert uri.id
    assert uri.account_id == account.id
    assert uri.currency == currency
    assert uri.amount == amount

    intent = identifier.decode_intent(uri.payment_uri, hrp)
    assert intent.account_address
    assert intent.subaddress
    assert intent.currency_code == currency
    assert intent.amount == amount
示例#7
0
def test_generate_account_payment_uri_without_currency_and_amount(
        account: AccountResource, hrp: str) -> None:
    uri = account.generate_payment_uri()
    assert uri.id
    assert uri.account_id == account.id
    assert uri.currency is None
    assert uri.amount is None
    assert uri.payment_uri

    intent = identifier.decode_intent(uri.payment_uri, hrp)
    assert intent.account_address
    assert intent.subaddress
    assert intent.currency_code is None
    assert intent.amount is None
示例#8
0
def test_intent_identifier_decode_errors(hrp_addresses):
    hrp, enocded_addr_with_none_subaddr, enocded_addr_with_subaddr = hrp_addresses
    # amount is not int
    with pytest.raises(identifier.InvalidIntentIdentifierError):
        identifier.decode_intent("diem://%s?c=XUS&am=str" % (enocded_addr_with_none_subaddr), hrp)

    # too many amount
    with pytest.raises(identifier.InvalidIntentIdentifierError):
        identifier.decode_intent("diem://%s?c=XUS&am=2&am=3" % (enocded_addr_with_none_subaddr), hrp)

    # scheme not match
    with pytest.raises(identifier.InvalidIntentIdentifierError):
        identifier.decode_intent("hello://%s?am=2&c=XUS" % (enocded_addr_with_none_subaddr), hrp)

    # hrp not match
    with pytest.raises(identifier.InvalidIntentIdentifierError):
        identifier.decode_intent("diem://%s?am=2&c=XUS" % (enocded_addr_with_none_subaddr), "xdm")
示例#9
0
    def pay(
        self,
        user_name: str,
        intent_id: str,
        desc: typing.Optional[str] = None,
        original_payment_reference_id: typing.Optional[str] = None,
    ) -> str:
        """make payment from given user account to intent_id"""

        intent = identifier.decode_intent(intent_id, self.hrp)
        command = offchain.PaymentCommand.init(
            self.gen_user_account_id(user_name),
            self.users[user_name].kyc_data(),
            intent.account_id,
            intent.amount,
            intent.currency_code,
            original_payment_reference_id=original_payment_reference_id,
            description=desc,
        )
        self.save_command(command)
        return command.reference_id()
示例#10
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}")
示例#11
0
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
示例#12
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)
示例#13
0
def test_intent_identifier_decode_errors():
    # amount is not int
    with pytest.raises(identifier.InvalidIntentIdentifierError):
        identifier.decode_intent(
            "diem://%s?c=Coin1&am=str" % (enocded_addr_with_none_subaddr),
            "lbr")

    # amount not exist
    with pytest.raises(identifier.InvalidIntentIdentifierError):
        identifier.decode_intent(
            "diem://%s?c=Coin1" % (enocded_addr_with_none_subaddr), "lbr")

    # too many amount
    with pytest.raises(identifier.InvalidIntentIdentifierError):
        identifier.decode_intent(
            "diem://%s?c=Coin1&am=2&am=3" % (enocded_addr_with_none_subaddr),
            "lbr")

    # amount is none
    with pytest.raises(identifier.InvalidIntentIdentifierError):
        identifier.decode_intent(
            "diem://%s?c=Coin1&am=" % (enocded_addr_with_none_subaddr), "lbr")

    # currency code not exist
    with pytest.raises(identifier.InvalidIntentIdentifierError):
        identifier.decode_intent(
            "diem://%s?am=2" % (enocded_addr_with_none_subaddr), "lbr")

    # scheme not match
    with pytest.raises(identifier.InvalidIntentIdentifierError):
        identifier.decode_intent(
            "hello://%s?am=2&c=Coin1" % (enocded_addr_with_none_subaddr),
            "lbr")

    # hrp not match
    with pytest.raises(identifier.InvalidIntentIdentifierError):
        identifier.decode_intent(
            "diem://%s?am=2&c=Coin1" % (enocded_addr_with_none_subaddr), "tlb")
示例#14
0
 def subaddress(uri: str) -> str:
     return utils.hex(identifier.decode_intent(uri, hrp).subaddress)