def test_reply_request():
    resp = offchain.reply_request("cid")
    assert json.loads(offchain.to_json(resp)) == json.loads(
        """{
  "cid": "cid",
  "_ObjectType": "CommandResponseObject",
  "status": "success"
}"""
    )

    resp = offchain.reply_request(
        "cid",
        offchain.OffChainErrorObject(
            type=offchain.OffChainErrorType.command_error,
            field="kyc_data",
            code="code1",
            message="message",
        ),
    )
    assert json.loads(offchain.to_json(resp)) == json.loads(
        """{
  "cid": "cid",
  "_ObjectType": "CommandResponseObject",
  "status": "failure",
  "error": {
    "type": "command_error",
    "code": "code1",
    "field": "kyc_data",
    "message": "message"
  }
}"""
    )
Пример #2
0
    def process_inbound_request(
        self, x_request_id: str, request_sender_address: str, request_bytes: bytes
    ) -> typing.Tuple[int, bytes]:
        cid = None
        try:
            inbound_command = self.offchain_client.process_inbound_request(request_sender_address, request_bytes)
            cid = inbound_command.id()
            self.save_command(inbound_command)
            resp = offchain.reply_request(cid)
            code = 200
        except offchain.Error as e:
            logger.exception(e)
            resp = offchain.reply_request(cid if cid else None, e.obj)
            code = 400

        return (code, offchain.jws.serialize(resp, self.compliance_key.sign))
Пример #3
0
 def process_inbound_request(x_request_id: str, jws_key_address: str,
                             content: bytes):
     command = receiver_client.process_inbound_request(
         jws_key_address, content)
     resp = offchain.reply_request(command.cid)
     return (200, offchain.jws.serialize(resp,
                                         receiver.compliance_key.sign))
Пример #4
0
    async def process(self, request_id: str, sender_address: str,
                      request_bytes: bytes) -> CommandResponseObject:
        try:
            if not request_id:
                raise offchain.protocol_error(
                    offchain.ErrorCode.missing_http_header,
                    "missing %s" % offchain.X_REQUEST_ID)
            if not offchain.UUID_REGEX.match(request_id):
                raise offchain.protocol_error(
                    offchain.ErrorCode.invalid_http_header,
                    "invalid %s" % offchain.X_REQUEST_ID)
            request = await self.app.offchain.deserialize_inbound_request(
                sender_address, request_bytes)
        except offchain.Error as e:
            err_msg = "process offchain request id or bytes is invalid, request id: %s, bytes: %s"
            self.app.logger.exception(err_msg, request_id, request_bytes)
            return offchain.reply_request(cid=None, err=e.obj)

        cached = self.cache.get(request.cid)
        if cached:
            return cached
        response = await self._process_offchain_request(
            sender_address, request)
        self.cache[request.cid] = response
        return response
Пример #5
0
def test_submit_txn_when_both_ready(monkeypatch):
    user = OneUser.run(db_session,
                       account_amount=100_000_000_000,
                       account_currency=currency)
    amount = 10_000_000_000
    receiver = LocalAccount.generate()
    subaddress = identifier.gen_subaddress()
    txn = save_outbound_transaction(user.account_id, receiver.account_address,
                                    subaddress, amount, currency)
    cmd = _txn_payment_command(txn)
    receiver_cmd = dataclasses.replace(
        cmd, my_actor_address=cmd.payment.receiver.address)
    receiver_ready_cmd = receiver_cmd.new_command(
        recipient_signature=b"recipient_signature".hex(),
        status=offchain.Status.ready_for_settlement,
        kyc_data=_user_kyc_data(user.account_id),
    )

    with monkeypatch.context() as m:
        client = context.get().offchain_client
        m.setattr(
            client,
            "process_inbound_request",
            lambda _, c: client.create_inbound_payment_command(
                c.cid, c.payment),
        )
        code, resp = process_inbound_command(cmd.payment.receiver.address,
                                             receiver_ready_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)

    process_offchain_tasks()
    db_session.refresh(txn)
    assert txn.status == TransactionStatus.OFF_CHAIN_READY

    # sync command and submit
    with monkeypatch.context() as m:
        m.setattr(
            context.get().offchain_client,
            "send_command",
            lambda cmd, _: offchain.reply_request(cmd.cid),
        )
        m.setattr(
            context.get(),
            "p2p_by_travel_rule",
            jsonrpc_txn_sample,
        )
        process_offchain_tasks()

    db_session.refresh(txn)
    assert txn.status == TransactionStatus.COMPLETED
    assert txn.sequence == 5
    assert txn.blockchain_version == 3232
Пример #6
0
 async def _process_offchain_request(
         self, sender_address: str,
         request: CommandRequestObject) -> CommandResponseObject:
     try:
         handler = "_handle_offchain_%s" % utils.to_snake(
             request.command_type)
         if not hasattr(self, handler):
             raise offchain.protocol_error(
                 offchain.ErrorCode.unknown_command_type,
                 "unknown command_type: %s" % request.command_type,
                 field="command_type",
             )
         fn = getattr(self, handler)
         result = await fn(sender_address, request)
         return offchain.reply_request(cid=request.cid, result=result)
     except offchain.Error as e:
         err_msg = "process offchain request failed, sender_address: %s, request: %s"
         self.app.logger.exception(err_msg, sender_address, request)
         return offchain.reply_request(cid=request.cid, err=e.obj)
Пример #7
0
    def process_inbound_request(
            self, x_request_id: str, request_sender_address: str,
            request_bytes: bytes) -> typing.Tuple[int, bytes]:
        cid = None
        try:
            if not x_request_id:
                raise offchain.protocol_error(
                    offchain.ErrorCode.missing_http_header,
                    "missing %s" % offchain.X_REQUEST_ID)

            inbound_command = self.offchain_client.process_inbound_request(
                request_sender_address, request_bytes)
            cid = inbound_command.id()
            self.save_command(inbound_command)
            resp = offchain.reply_request(cid)
            code = 200
        except offchain.Error as e:
            logger.exception(e)
            resp = offchain.reply_request(cid if cid else None, e.obj)
            code = 400

        return (code, offchain.jws.serialize(resp, self.compliance_key.sign))
Пример #8
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
Пример #9
0
def test_save_outbound_transaction(monkeypatch):
    user = OneUser.run(db_session,
                       account_amount=100_000_000_000,
                       account_currency=currency)
    amount = 10_000_000_000
    receiver = LocalAccount.generate()
    subaddress = identifier.gen_subaddress()
    txn = save_outbound_transaction(user.account_id, receiver.account_address,
                                    subaddress, amount, currency)

    assert txn.id in get_account_transaction_ids(user.account_id)
    assert txn.reference_id is not None
    assert txn.command_json is not None

    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_WAIT
Пример #10
0
def _jws(cid: Optional[str],
         err: Optional[offchain.OffChainErrorObject] = None):
    code = 400 if err else 200
    resp = offchain.reply_request(cid)
    return (code, offchain.jws.serialize(resp, _compliance_private_key().sign))