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)
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)