mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 12:19:24 +00:00
Restore publish_transaction RPC to Serai
This commit is contained in:
@@ -14,18 +14,16 @@ use borsh::BorshDeserialize;
|
|||||||
pub use serai_abi as abi;
|
pub use serai_abi as abi;
|
||||||
use abi::{
|
use abi::{
|
||||||
primitives::{BlockHash, network_id::ExternalNetworkId},
|
primitives::{BlockHash, network_id::ExternalNetworkId},
|
||||||
Block, Event,
|
Transaction, Block, Event,
|
||||||
};
|
};
|
||||||
|
|
||||||
use async_lock::RwLock;
|
use async_lock::RwLock;
|
||||||
|
|
||||||
/// RPC client functionality for the coins module.
|
mod coins;
|
||||||
pub mod coins;
|
pub use coins::Coins;
|
||||||
use coins::*;
|
|
||||||
|
|
||||||
/// RPC client functionality for the validator sets module.
|
mod validator_sets;
|
||||||
pub mod validator_sets;
|
pub use validator_sets::ValidatorSets;
|
||||||
use validator_sets::*;
|
|
||||||
|
|
||||||
/// An error from the RPC.
|
/// An error from the RPC.
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
@@ -164,6 +162,16 @@ impl Serai {
|
|||||||
Self::block_internal(self.call("blockchain/block", &format!(r#"{{ "block": {block} }}"#))).await
|
Self::block_internal(self.call("blockchain/block", &format!(r#"{{ "block": {block} }}"#))).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Publish a transaction onto the Serai blockchain.
|
||||||
|
pub async fn publish_transaction(&self, transaction: &Transaction) -> Result<(), RpcError> {
|
||||||
|
self
|
||||||
|
.call(
|
||||||
|
"blockchain/publish_transaction",
|
||||||
|
&format!(r#"{{ "transaction": {} }}"#, hex::encode(borsh::to_vec(transaction).unwrap())),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
/// Scope this RPC client to the state as of a specific block.
|
/// Scope this RPC client to the state as of a specific block.
|
||||||
///
|
///
|
||||||
/// This will yield an error if the block chosen isn't finalized. This ensures, given an honest
|
/// This will yield an error if the block chosen isn't finalized. This ensures, given an honest
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use std::{sync::Arc, ops::Deref, collections::HashSet};
|
use core::{ops::Deref, future::Future};
|
||||||
|
use std::{sync::Arc, collections::HashSet};
|
||||||
|
|
||||||
use rand_core::{RngCore, OsRng};
|
use rand_core::{RngCore, OsRng};
|
||||||
|
|
||||||
@@ -8,8 +9,9 @@ use sp_consensus::BlockStatus;
|
|||||||
use sp_block_builder::BlockBuilder;
|
use sp_block_builder::BlockBuilder;
|
||||||
use sp_api::ProvideRuntimeApi;
|
use sp_api::ProvideRuntimeApi;
|
||||||
use sc_client_api::BlockBackend;
|
use sc_client_api::BlockBackend;
|
||||||
|
use sc_transaction_pool_api::TransactionPool;
|
||||||
|
|
||||||
use serai_abi::{primitives::prelude::*, SubstrateBlock as Block};
|
use serai_abi::{primitives::prelude::*, Transaction, SubstrateBlock as Block};
|
||||||
|
|
||||||
use serai_runtime::SeraiApi;
|
use serai_runtime::SeraiApi;
|
||||||
|
|
||||||
@@ -27,6 +29,7 @@ pub(crate) fn module<
|
|||||||
+ ProvideRuntimeApi<Block, Api: SeraiApi<Block>>,
|
+ ProvideRuntimeApi<Block, Api: SeraiApi<Block>>,
|
||||||
>(
|
>(
|
||||||
client: Arc<C>,
|
client: Arc<C>,
|
||||||
|
pool: Arc<impl 'static + TransactionPool<Block = Block>>,
|
||||||
) -> Result<RpcModule<impl 'static + Send + Sync>, Box<dyn std::error::Error + Send + Sync>> {
|
) -> Result<RpcModule<impl 'static + Send + Sync>, Box<dyn std::error::Error + Send + Sync>> {
|
||||||
let mut module = RpcModule::new(client);
|
let mut module = RpcModule::new(client);
|
||||||
|
|
||||||
@@ -80,5 +83,36 @@ pub(crate) fn module<
|
|||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
module.register_async_method("blockchain/publish_transaction", move |params, client, _ext| {
|
||||||
|
let pool = pool.clone();
|
||||||
|
async move {
|
||||||
|
#[derive(sp_core::serde::Deserialize)]
|
||||||
|
#[serde(crate = "sp_core::serde")]
|
||||||
|
struct TransactionRequest {
|
||||||
|
transaction: String,
|
||||||
|
};
|
||||||
|
let Ok(transaction) = params.parse::<TransactionRequest>() else {
|
||||||
|
return Err(Error::InvalidRequest(r#"missing `string` "transaction" field"#));
|
||||||
|
};
|
||||||
|
let Ok(transaction) = hex::decode(transaction.transaction) else {
|
||||||
|
Err(Error::InvalidRequest(r#"transaction was not hex-encoded"#))?
|
||||||
|
};
|
||||||
|
let Ok(transaction) =
|
||||||
|
<Transaction as borsh::BorshDeserialize>::deserialize_reader(&mut transaction.as_slice())
|
||||||
|
else {
|
||||||
|
Err(Error::InvalidRequest(r#"transaction could not be deserialized"#))?
|
||||||
|
};
|
||||||
|
pool
|
||||||
|
.submit_one(
|
||||||
|
client.info().best_hash,
|
||||||
|
sc_transaction_pool_api::TransactionSource::External,
|
||||||
|
transaction,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(|e| Error::InvalidTransaction(format!("{e}")))?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
|
||||||
Ok(module)
|
Ok(module)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,14 +36,14 @@ pub fn create_full<
|
|||||||
+ HeaderBackend<Block>
|
+ HeaderBackend<Block>
|
||||||
+ HeaderMetadata<Block, Error = BlockchainError>
|
+ HeaderMetadata<Block, Error = BlockchainError>
|
||||||
+ BlockBackend<Block>,
|
+ BlockBackend<Block>,
|
||||||
P: 'static + TransactionPool,
|
P: 'static + TransactionPool<Block = Block>,
|
||||||
>(
|
>(
|
||||||
deps: FullDeps<C, P>,
|
deps: FullDeps<C, P>,
|
||||||
) -> Result<RpcModule<()>, Box<dyn std::error::Error + Send + Sync>> {
|
) -> Result<RpcModule<()>, Box<dyn std::error::Error + Send + Sync>> {
|
||||||
let FullDeps { id, client, pool, authority_discovery } = deps;
|
let FullDeps { id, client, pool, authority_discovery } = deps;
|
||||||
|
|
||||||
let mut root = RpcModule::new(());
|
let mut root = RpcModule::new(());
|
||||||
root.merge(blockchain::module(client.clone())?)?;
|
root.merge(blockchain::module(client.clone(), pool)?)?;
|
||||||
root.merge(validator_sets::module(client.clone()))?;
|
root.merge(validator_sets::module(client.clone()))?;
|
||||||
if let Some(authority_discovery) = authority_discovery {
|
if let Some(authority_discovery) = authority_discovery {
|
||||||
root.merge(p2p_validators::module(id, client, authority_discovery)?)?;
|
root.merge(p2p_validators::module(id, client, authority_discovery)?)?;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ pub(super) enum Error {
|
|||||||
Internal(&'static str),
|
Internal(&'static str),
|
||||||
InvalidRequest(&'static str),
|
InvalidRequest(&'static str),
|
||||||
InvalidStateReference,
|
InvalidStateReference,
|
||||||
|
InvalidTransaction(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Error> for jsonrpsee::types::error::ErrorObjectOwned {
|
impl From<Error> for jsonrpsee::types::error::ErrorObjectOwned {
|
||||||
@@ -19,10 +20,15 @@ impl From<Error> for jsonrpsee::types::error::ErrorObjectOwned {
|
|||||||
jsonrpsee::types::error::ErrorObjectOwned::owned(-2, str, Option::<()>::None)
|
jsonrpsee::types::error::ErrorObjectOwned::owned(-2, str, Option::<()>::None)
|
||||||
}
|
}
|
||||||
Error::InvalidStateReference => jsonrpsee::types::error::ErrorObjectOwned::owned(
|
Error::InvalidStateReference => jsonrpsee::types::error::ErrorObjectOwned::owned(
|
||||||
-4,
|
-3,
|
||||||
"the block used as the reference was not locally held",
|
"the block used as the reference was not locally held",
|
||||||
Option::<()>::None,
|
Option::<()>::None,
|
||||||
),
|
),
|
||||||
|
Error::InvalidTransaction(str) => jsonrpsee::types::error::ErrorObjectOwned::owned(
|
||||||
|
-4,
|
||||||
|
format!("transaction was not accepted to the mempool: {str}"),
|
||||||
|
Option::<()>::None,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user