示例#1
0
    def submit_solana_transaction(
            self,
            tx: solana.Transaction,
            invoice_list: Optional[InvoiceList] = None,
            commitment: Optional[Commitment] = Commitment.SINGLE,
            dedupe_id: Optional[bytes] = None) -> SubmitTransactionResult:
        """Submit a Solana transaction to Agora.

        :param tx: The Solana transaction.
        :param invoice_list: (optional) An :class:`InvoiceList <agora.model.invoice.InvoiceList>` to associate with the
            transaction
        :param commitment: The :class:`Commitment <agora.solana.commitment.Commitment>` to use.
        :param dedupe_id: The dedupe ID to use for the transaction submission
        :return: A :class:`SubmitTransactionResult <agora.client.internal.SubmitTransactionResult>` object.
        """

        attempt = 0
        tx_bytes = tx.marshal()

        def _submit_request():
            nonlocal attempt

            attempt += 1
            req = tx_pb.SubmitTransactionRequest(
                transaction=model_pb.Transaction(value=tx_bytes, ),
                invoice_list=invoice_list.to_proto() if invoice_list else None,
                commitment=commitment.to_proto(),
                dedupe_id=dedupe_id,
            )
            resp = self._transaction_stub_v4.SubmitTransaction(
                req, metadata=self._metadata, timeout=_GRPC_TIMEOUT_SECONDS)

            if resp.result == tx_pb.SubmitTransactionResponse.Result.REJECTED:
                raise TransactionRejectedError()
            if resp.result == tx_pb.SubmitTransactionResponse.Result.PAYER_REQUIRED:
                raise PayerRequiredError()

            result = SubmitTransactionResult(tx_id=resp.signature.value)
            if resp.result == tx_pb.SubmitTransactionResponse.Result.ALREADY_SUBMITTED:
                # If this occurs on the first attempt, it's likely due to the submission of two identical transactions
                # in quick succession and we should raise the error to the caller. Otherwise, it's likely that the
                # transaction completed successfully on a previous attempt that failed due to a transient error.
                if attempt == 1:
                    raise AlreadySubmittedError(tx_id=resp.signature.value)
            elif resp.result == tx_pb.SubmitTransactionResponse.Result.FAILED:
                result.errors = TransactionErrors.from_solana_tx(
                    tx, resp.transaction_error, resp.signature.value)
            elif resp.result == tx_pb.SubmitTransactionResponse.Result.INVOICE_ERROR:
                result.invoice_errors = resp.invoice_errors
            elif resp.result != tx_pb.SubmitTransactionResponse.Result.OK:
                raise TransactionError(
                    f'unexpected result from agora: {resp.result}',
                    tx_id=resp.signature.value)

            return result

        return retry(self._retry_strategies, _submit_request)
示例#2
0
    def sign_transaction(
            self,
            tx: solana.Transaction,
            invoice_list: Optional[InvoiceList] = None
    ) -> SignTransactionResult:
        """ Submits a transaction

        :param tx:
        :param invoice_list:
        :return: A :class:`SignTransactionResult <agora.client.internal.SignTransactionResult>` object.
        """
        tx_bytes = tx.marshal()

        result = SignTransactionResult()

        def _submit_request():
            req = tx_pb.SignTransactionRequest(
                transaction=model_pb.Transaction(value=tx_bytes, ),
                invoice_list=invoice_list.to_proto() if invoice_list else None,
            )
            resp = self._transaction_stub_v4.SignTransaction(
                req, metadata=self._metadata, timeout=_GRPC_TIMEOUT_SECONDS)

            if resp.signature and len(
                    resp.signature.value) == solana.SIGNATURE_LENGTH:
                result.tx_id = resp.signature.value

            if resp.result == tx_pb.SignTransactionResponse.Result.REJECTED:
                raise TransactionRejectedError()
            elif resp.result == tx_pb.SignTransactionResponse.Result.INVOICE_ERROR:
                result.invoice_errors = resp.invoice_errors
            elif resp.result != tx_pb.SignTransactionResponse.Result.OK:
                raise TransactionError(
                    f'unexpected result from agora: {resp.result}',
                    tx_id=resp.signature.value)

            return result

        return retry(self._retry_strategies, _submit_request)