sof_solana_compat/
submit_ext.rs1use async_trait::async_trait;
2use bincode::serialize;
3use solana_signer::signers::Signers;
4use solana_transaction::versioned::VersionedTransaction;
5use thiserror::Error;
6
7use crate::{BuilderError, TxBuilder};
8
9#[derive(Debug, Error)]
11pub enum SolanaCompatSubmitError {
12 #[error("failed to build/sign transaction: {source}")]
14 Build {
15 source: BuilderError,
17 },
18 #[error(transparent)]
20 Submit {
21 source: sof_tx::SubmitError,
23 },
24 #[error("failed to encode signed transaction bytes: {message}")]
26 Encode {
27 message: String,
29 },
30}
31
32#[async_trait]
34pub trait TxSubmitClientSolanaExt {
35 async fn submit_unsigned<T>(
37 &mut self,
38 builder: TxBuilder,
39 signers: &T,
40 mode: sof_tx::SubmitMode,
41 ) -> Result<sof_tx::SubmitResult, SolanaCompatSubmitError>
42 where
43 T: Signers + Sync + ?Sized;
44
45 async fn submit_unsigned_with_context<T>(
47 &mut self,
48 builder: TxBuilder,
49 signers: &T,
50 mode: sof_tx::SubmitMode,
51 context: sof_tx::TxSubmitContext,
52 ) -> Result<sof_tx::SubmitResult, SolanaCompatSubmitError>
53 where
54 T: Signers + Sync + ?Sized;
55
56 async fn submit_transaction(
58 &mut self,
59 tx: VersionedTransaction,
60 mode: sof_tx::SubmitMode,
61 ) -> Result<sof_tx::SubmitResult, SolanaCompatSubmitError>;
62
63 async fn submit_transaction_with_context(
65 &mut self,
66 tx: VersionedTransaction,
67 mode: sof_tx::SubmitMode,
68 context: sof_tx::TxSubmitContext,
69 ) -> Result<sof_tx::SubmitResult, SolanaCompatSubmitError>;
70}
71
72#[async_trait]
73impl TxSubmitClientSolanaExt for sof_tx::TxSubmitClient {
74 async fn submit_unsigned<T>(
75 &mut self,
76 builder: TxBuilder,
77 signers: &T,
78 mode: sof_tx::SubmitMode,
79 ) -> Result<sof_tx::SubmitResult, SolanaCompatSubmitError>
80 where
81 T: Signers + Sync + ?Sized,
82 {
83 self.submit_unsigned_with_context(
84 builder,
85 signers,
86 mode,
87 sof_tx::TxSubmitContext::default(),
88 )
89 .await
90 }
91
92 async fn submit_unsigned_with_context<T>(
93 &mut self,
94 builder: TxBuilder,
95 signers: &T,
96 mode: sof_tx::SubmitMode,
97 context: sof_tx::TxSubmitContext,
98 ) -> Result<sof_tx::SubmitResult, SolanaCompatSubmitError>
99 where
100 T: Signers + Sync + ?Sized,
101 {
102 let blockhash = self
103 .refresh_latest_blockhash_bytes()
104 .await
105 .map_err(|source| SolanaCompatSubmitError::Submit {
106 source: sof_tx::SubmitError::Rpc { source },
107 })?
108 .ok_or(SolanaCompatSubmitError::Submit {
109 source: sof_tx::SubmitError::MissingRecentBlockhash,
110 })?;
111 let tx = builder
112 .build_and_sign(blockhash, signers)
113 .map_err(|source| SolanaCompatSubmitError::Build { source })?;
114 self.submit_transaction_with_context(tx, mode, context)
115 .await
116 }
117
118 async fn submit_transaction(
119 &mut self,
120 tx: VersionedTransaction,
121 mode: sof_tx::SubmitMode,
122 ) -> Result<sof_tx::SubmitResult, SolanaCompatSubmitError> {
123 self.submit_transaction_with_context(tx, mode, sof_tx::TxSubmitContext::default())
124 .await
125 }
126
127 async fn submit_transaction_with_context(
128 &mut self,
129 tx: VersionedTransaction,
130 mode: sof_tx::SubmitMode,
131 context: sof_tx::TxSubmitContext,
132 ) -> Result<sof_tx::SubmitResult, SolanaCompatSubmitError> {
133 let tx_bytes = serialize(&tx).map_err(|error| SolanaCompatSubmitError::Encode {
134 message: error.to_string(),
135 })?;
136 self.submit_signed_with_context(
137 sof_tx::SignedTx::VersionedTransactionBytes(tx_bytes),
138 mode,
139 context,
140 )
141 .await
142 .map_err(|source| SolanaCompatSubmitError::Submit { source })
143 }
144}