tempo_programmatic_node/
main.rs1use tempo::{
4 InvalidPoolTransactionError, PoolTransaction, PoolTransactionError, TempoOverrides,
5 tempo_main_with,
6};
7
8#[global_allocator]
9static ALLOC: tempo::cli_util::allocator::Allocator = tempo::cli_util::allocator::new_allocator();
10
11fn main() -> Result<(), Box<dyn std::error::Error>> {
12 const MAX_EXTERNAL_TX_ENCODED_LEN: usize = 128 * 1024;
13
14 let overrides = TempoOverrides::new().map_tempo_node(|node| {
15 node.map_pool_builder(|pool| {
17 pool.with_additional_stateless_validation(|origin, tx| {
19 let size = tx.encoded_length();
20 if origin.is_external() && size > MAX_EXTERNAL_TX_ENCODED_LEN {
21 return Err(InvalidPoolTransactionError::OversizedData {
22 size,
23 limit: MAX_EXTERNAL_TX_ENCODED_LEN,
24 });
25 }
26
27 Ok(())
28 })
29 .with_additional_stateful_validation(|_origin, tx, state| {
31 let account = match state.basic_account(tx.sender_ref()) {
32 Ok(account) => account.unwrap_or_default(),
33 Err(_err) => {
34 return Err(InvalidPoolTransactionError::other(
35 ProgrammaticPoolError::SenderStateUnavailable,
36 ));
37 }
38 };
39
40 if account.balance.is_zero() {
41 return Err(InvalidPoolTransactionError::other(
42 ProgrammaticPoolError::ZeroBalanceSender,
43 ));
44 }
45
46 Ok(())
47 })
48 })
49 });
50
51 tempo_main_with(overrides)?;
52 Ok(())
53}
54
55#[derive(Debug)]
57enum ProgrammaticPoolError {
58 SenderStateUnavailable,
59 ZeroBalanceSender,
60}
61
62impl std::fmt::Display for ProgrammaticPoolError {
63 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64 match self {
65 Self::SenderStateUnavailable => f.write_str("failed to read sender account state"),
66 Self::ZeroBalanceSender => f.write_str("sender account has zero balance"),
67 }
68 }
69}
70
71impl std::error::Error for ProgrammaticPoolError {}
72
73impl PoolTransactionError for ProgrammaticPoolError {
74 fn is_bad_transaction(&self) -> bool {
75 false
77 }
78
79 fn as_any(&self) -> &dyn std::any::Any {
80 self
81 }
82}