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" } }""" )
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))
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))
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
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
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)
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))
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_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
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))