Beispiel #1
0
def _command_transaction_status(
        command: offchain.PaymentCommand,
        default: TransactionStatus) -> TransactionStatus:
    if command.is_both_ready():
        return TransactionStatus.OFF_CHAIN_READY
    elif command.is_abort():
        return TransactionStatus.CANCELED
    return default
Beispiel #2
0
def _send_kyc_data_and_receipient_signature(
    command: offchain.PaymentCommand, ) -> offchain.PaymentCommand:
    sig_msg = command.travel_rule_metadata_signature_message(_hrp())
    user_id = get_account_id_from_subaddr(
        command.receiver_subaddress(_hrp()).hex())

    return command.new_command(
        recipient_signature=_compliance_private_key().sign(sig_msg).hex(),
        kyc_data=_user_kyc_data(user_id),
        status=offchain.Status.ready_for_settlement,
    )
Beispiel #3
0
 def _kyc_data_result(
     self, action: str, ret: ActionResultType, command: offchain.PaymentCommand
 ) -> offchain.Command:
     if ret == ActionResult.PASS:
         if command.is_receiver():
             return self._send_kyc_data_and_receipient_signature(command)
         return command.new_command(status=offchain.Status.ready_for_settlement)
     return command.new_command(
         status=offchain.Status.abort,
         abort_code=offchain.AbortCode.reject_kyc_data,
         abort_message=f"{action}: {ret}",
     )
Beispiel #4
0
    def _send_kyc_data_and_receipient_signature(
        self,
        command: offchain.PaymentCommand,
    ) -> offchain.PaymentCommand:
        sig_msg = command.travel_rule_metadata_signature_message(self.hrp)
        subaddress = command.receiver_subaddress(self.hrp)
        user = self._find_user_by_subaddress(subaddress)

        return command.new_command(
            recipient_signature=self.compliance_key.sign(sig_msg).hex(),
            kyc_data=user.kyc_data(),
            status=offchain.Status.ready_for_settlement,
        )
 def _create_payment_command(self,
                             account_id: str,
                             cmd: offchain.PaymentCommand,
                             validate: bool = False) -> None:
     self.app.store.create(
         PaymentCommand,
         before_create=lambda _: cmd.validate(None) if validate else None,
         account_id=account_id,
         is_sender=cmd.is_sender(),
         reference_id=cmd.reference_id(),
         is_inbound=cmd.is_inbound(),
         cid=cmd.id(),
         payment_object=asdict(cmd.payment),
     )
    def _ready_for_settlement(
            self, account_id: str,
            cmd: offchain.PaymentCommand) -> offchain.Command:
        if cmd.is_sender():
            return cmd.new_command(status=Status.ready_for_settlement)

        sig_msg = cmd.travel_rule_metadata_signature_message(
            self.app.diem_account.hrp)
        sig = self.app.diem_account.sign_by_compliance_key(sig_msg).hex()
        kyc_data = self.app.store.find(Account,
                                       id=account_id).kyc_data_object()
        return cmd.new_command(recipient_signature=sig,
                               kyc_data=kyc_data,
                               status=Status.ready_for_settlement)
 def _offchain_action_evaluate_kyc_data(
         self, account_id: str,
         cmd: offchain.PaymentCommand) -> offchain.Command:
     op_kyc_data = cmd.counterparty_actor_obj().kyc_data
     if op_kyc_data is None or self.app.kyc_sample.match_kyc_data(
             "reject", op_kyc_data):
         return self._new_reject_kyc_data(cmd, "KYC data is rejected")
     elif self.app.kyc_sample.match_any_kyc_data(
         ["soft_match", "soft_reject"], op_kyc_data):
         return cmd.new_command(status=Status.soft_match)
     elif self.app.kyc_sample.match_kyc_data("minimum", op_kyc_data):
         return self._ready_for_settlement(account_id, cmd)
     else:
         return self._new_reject_kyc_data(cmd,
                                          "KYC data is not from samples")
 def _update_payment_command(self,
                             cmd: PaymentCommand,
                             offchain_cmd: offchain.PaymentCommand,
                             validate: bool = False) -> None:
     prior = cmd.to_offchain_command()
     self.app.store.update(
         cmd,
         before_update=lambda _: offchain_cmd.validate(prior)
         if validate else None,
         cid=offchain_cmd.id(),
         is_inbound=offchain_cmd.is_inbound(),
         is_abort=offchain_cmd.is_abort(),
         is_ready=offchain_cmd.is_both_ready(),
         payment_object=asdict(offchain_cmd.payment),
     )
Beispiel #9
0
def _new_payment_command_transaction(command: offchain.PaymentCommand,
                                     status: TransactionStatus) -> Transaction:
    payment = command.payment
    sender_address, source_subaddress = _account_address_and_subaddress(
        payment.sender.address)
    destination_address, destination_subaddress = _account_address_and_subaddress(
        payment.receiver.address)
    source_id = get_account_id_from_subaddr(source_subaddress)
    destination_id = get_account_id_from_subaddr(destination_subaddress)

    return Transaction(
        type=TransactionType.OFFCHAIN,
        status=status,
        amount=payment.action.amount,
        currency=payment.action.currency,
        created_timestamp=datetime.utcnow(),
        source_id=source_id,
        source_address=sender_address,
        source_subaddress=source_subaddress,
        destination_id=destination_id,
        destination_address=destination_address,
        destination_subaddress=destination_subaddress,
        reference_id=command.reference_id(),
        command_json=offchain.to_json(command),
    )
 def _offchain_action_review_kyc_data(
         self, account_id: str,
         cmd: offchain.PaymentCommand) -> offchain.Command:
     op_kyc_data = cmd.counterparty_actor_obj().kyc_data
     if op_kyc_data is None or self.app.kyc_sample.match_kyc_data(
             "soft_reject", op_kyc_data):
         return self._new_reject_kyc_data(
             cmd, "KYC data review result is reject")
     return self._ready_for_settlement(account_id, cmd)
 def _offchain_action_clear_soft_match(
         self, account_id: str,
         cmd: offchain.PaymentCommand) -> offchain.Command:
     account = self.app.store.find(Account, id=account_id)
     if account.reject_additional_kyc_data_request:
         return self._new_reject_kyc_data(cmd,
                                          "no need additional KYC data")
     return cmd.new_command(additional_kyc_data="{%r: %r}" %
                            ("account_id", account_id))
Beispiel #12
0
def _lock_and_save_inbound_command(
        command: offchain.PaymentCommand) -> Transaction:
    def validate_and_save(txn: Optional[Transaction]) -> Transaction:
        if txn:
            prior = _txn_payment_command(txn)
            if command == prior:
                return
            command.validate(prior)
            txn.command_json = offchain.to_json(command)
            txn.status = _command_transaction_status(
                command, TransactionStatus.OFF_CHAIN_INBOUND)
        else:
            txn = _new_payment_command_transaction(
                command, TransactionStatus.OFF_CHAIN_INBOUND)
        return txn

    return lock_for_update(command.reference_id(), validate_and_save)
Beispiel #13
0
 def travel_metadata(self,
                     cmd: offchain.PaymentCommand) -> Tuple[bytes, bytes]:
     metadata = cmd.travel_rule_metadata(self.hrp)
     return (metadata, bytes.fromhex(str(cmd.payment.recipient_signature)))
Beispiel #14
0
 def _enqueue_follow_up_action(self,
                               command: offchain.PaymentCommand) -> None:
     if command.follow_up_action():
         self.task_queue.append(lambda app: app._offchain_business_action(
             command.reference_id()))
 def _new_reject_kyc_data(self, cmd: offchain.PaymentCommand,
                          msg: str) -> offchain.Command:
     return cmd.new_command(status=Status.abort,
                            abort_code=AbortCode.reject_kyc_data,
                            abort_message=msg)