Skip to content

Commit f26226f

Browse files
committed
Add pre commit
1 parent 53af4ae commit f26226f

File tree

8 files changed

+252
-109
lines changed

8 files changed

+252
-109
lines changed

.pre-commit-config.yaml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
repos:
2+
- repo: local
3+
hooks:
4+
# Hooks for workspace
5+
- id: cargo-fmt-workspace
6+
name: Cargo format for workspace
7+
language: "rust"
8+
entry: cargo +nightly-2024-12-03 fmt --manifest-path ./Cargo.toml --all -- --config-path rustfmt.toml
9+
pass_filenames: false
10+
types_or: ["rust", "cargo", "cargo-lock"]
11+
files: .
12+
- id: cargo-clippy-workspace
13+
name: Cargo clippy for workspace
14+
language: "rust"
15+
entry: cargo +1.87.0 clippy --manifest-path ./Cargo.toml --tests -- -D warnings
16+
pass_filenames: false
17+
types_or: ["rust", "cargo", "cargo-lock"]
18+
files: .
19+
- id: cargo-test-workspace
20+
name: Cargo test for workspace
21+
language: "rust"
22+
entry: cargo +1.87.0 test --manifest-path ./Cargo.toml
23+
pass_filenames: false
24+
types_or: ["rust", "cargo", "cargo-lock"]
25+
files: .

rustfmt.toml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
edition = "2021"
2+
3+
# Merge all imports into a clean vertical list of module imports.
4+
imports_granularity = "One"
5+
group_imports = "One"
6+
imports_layout = "Vertical"
7+
8+
# Better grep-ability.
9+
empty_item_single_line = false
10+
11+
# Consistent pipe layout.
12+
match_arm_leading_pipes = "Preserve"
13+
14+
# Align Fields
15+
enum_discrim_align_threshold = 80
16+
struct_field_align_threshold = 80
17+
18+
# Allow up to two blank lines for visual grouping.
19+
blank_lines_upper_bound = 2
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: Pre-commit checks
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches: [main]
7+
8+
jobs:
9+
pre-commit:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v3
13+
with:
14+
# Need to grab the history of the PR
15+
fetch-depth: 0
16+
- uses: actions/setup-node@v4
17+
with:
18+
node-version-file: "package.json"
19+
registry-url: "https://registry.npmjs.org"
20+
- uses: ./.github/actions/python-poetry
21+
- uses: actions-rs/toolchain@v1
22+
with:
23+
profile: minimal
24+
toolchain: 1.85.1
25+
components: clippy
26+
- uses: actions-rs/toolchain@v1
27+
with:
28+
profile: minimal
29+
toolchain: nightly-2024-12-03
30+
components: rustfmt
31+
- name: Install Protoc
32+
uses: arduino/setup-protoc@v3
33+
with:
34+
version: "28.x"
35+
- uses: pnpm/action-setup@v4
36+
name: Install pnpm
37+
with:
38+
run_install: true
39+
- name: Install Anchor CLI
40+
run: |
41+
cargo install --git https://github.com/coral-xyz/anchor avm
42+
avm install 0.31.0
43+
avm use 0.31.0
44+
- uses: pre-commit/[email protected]
45+
if: ${{ github.event_name == 'pull_request' }}
46+
with:
47+
# Run only on files changed in the PR
48+
extra_args: --from-ref ${{ github.event.pull_request.base.sha }} --to-ref ${{ github.event.pull_request.head.sha }}
49+
- uses: pre-commit/[email protected]
50+
if: ${{ github.event_name != 'pull_request' }}

src/config.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,25 @@
1-
use std::path::PathBuf;
2-
31
use clap::Parser;
42

5-
63
#[derive(Parser, Clone, Debug)]
74
pub struct RunOptions {
85
/// The API key to use for auction server authentication.
96
#[arg(long = "pythnet-url", env = "PYTHNET_URL")]
10-
pub pythnet_url: String,
7+
pub pythnet_url: String,
118
/// Path to the file containing the secret key.
129
#[arg(long = "secret-key", env = "SECRET_KEY")]
13-
pub secret_key_path: String,
10+
pub secret_key_path: String,
1411
/// The Wormhole program ID.
15-
#[arg(long = "wormhole-pid", env = "WORMHOLE_PID", default_value = "H3fxXJ86ADW2PNuDDmZJg6mzTtPxkYCpNuQUTgmJ7AjU")]
16-
pub wormhole_pid: String,
12+
#[arg(
13+
long = "wormhole-pid",
14+
env = "WORMHOLE_PID",
15+
default_value = "H3fxXJ86ADW2PNuDDmZJg6mzTtPxkYCpNuQUTgmJ7AjU"
16+
)]
17+
pub wormhole_pid: String,
1718
/// The address of the accumulator contract.
18-
#[arg(long = "accumulator-address", env = "ACCUMULATOR_ADDRESS", default_value = "G9LV2mp9ua1znRAfYwZz5cPiJMAbo1T6mbjdQsDZuMJg")]
19+
#[arg(
20+
long = "accumulator-address",
21+
env = "ACCUMULATOR_ADDRESS",
22+
default_value = "G9LV2mp9ua1znRAfYwZz5cPiJMAbo1T6mbjdQsDZuMJg"
23+
)]
1924
pub accumulator_address: String,
2025
}

src/main.rs

Lines changed: 87 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,88 @@
1-
use borsh::BorshDeserialize;
2-
use observation::{Body, SignedBody};
3-
use posted_message::PostedMessageUnreliableData;
4-
use secp256k1::SecretKey;
5-
use solana_account_decoder::UiAccountEncoding;
6-
use solana_client::{
7-
nonblocking::pubsub_client::PubsubClient, pubsub_client::PubsubClientError, rpc_config::{RpcAccountInfoConfig, RpcProgramAccountsConfig}
1+
use {
2+
borsh::BorshDeserialize,
3+
clap::Parser,
4+
core::panic,
5+
observation::{
6+
Body,
7+
SignedBody,
8+
},
9+
posted_message::PostedMessageUnreliableData,
10+
secp256k1::SecretKey,
11+
solana_account_decoder::UiAccountEncoding,
12+
solana_client::{
13+
nonblocking::pubsub_client::PubsubClient,
14+
pubsub_client::PubsubClientError,
15+
rpc_config::{
16+
RpcAccountInfoConfig,
17+
RpcProgramAccountsConfig,
18+
},
19+
},
20+
solana_sdk::pubkey::Pubkey,
21+
std::{
22+
fs,
23+
str::FromStr,
24+
time::Duration,
25+
},
26+
tokio::time::sleep,
27+
tokio_stream::StreamExt,
828
};
9-
use solana_sdk::pubkey::Pubkey;
10-
use tokio::time::sleep;
11-
use core::panic;
12-
use std::{fs, path::PathBuf, str::FromStr, time::Duration};
13-
use tokio_stream::StreamExt;
14-
use clap::Parser;
1529

16-
mod posted_message;
30+
mod config;
1731
mod observation;
32+
mod posted_message;
1833
mod serde_array;
19-
mod config;
2034

2135
const PYTHNET_CHAIN_ID: u16 = 26;
2236

2337
struct ListenerConfig {
24-
ws_url: String,
25-
secret_key: SecretKey,
26-
wormhole_pid: Pubkey,
38+
ws_url: String,
39+
secret_key: SecretKey,
40+
wormhole_pid: Pubkey,
2741
accumulator_address: Pubkey,
2842
}
2943

30-
fn find_message_pda(
31-
wormhole_pid: &Pubkey,
32-
ring_index: u32,
33-
) -> Pubkey {
44+
fn find_message_pda(wormhole_pid: &Pubkey, ring_index: u32) -> Pubkey {
3445
Pubkey::find_program_address(
3546
&[b"AccumulatorMessage", &ring_index.to_be_bytes()],
3647
wormhole_pid,
37-
).0
48+
)
49+
.0
3850
}
3951

4052
async fn run_listener(config: ListenerConfig) -> Result<(), PubsubClientError> {
4153
let client = PubsubClient::new(config.ws_url.as_str()).await?;
42-
let (mut stream, unsubscribe) = client.program_subscribe(
43-
&config.wormhole_pid,
44-
Some(RpcProgramAccountsConfig {
45-
filters: None,
46-
account_config: RpcAccountInfoConfig {
47-
encoding: Some(UiAccountEncoding::Base64),
48-
data_slice: None,
49-
commitment: Some(solana_sdk::commitment_config::CommitmentConfig::confirmed()),
50-
min_context_slot: None,
51-
},
52-
with_context: None,
53-
sort_results: None
54-
}),
55-
)
56-
.await?;
54+
let (mut stream, unsubscribe) = client
55+
.program_subscribe(
56+
&config.wormhole_pid,
57+
Some(RpcProgramAccountsConfig {
58+
filters: None,
59+
account_config: RpcAccountInfoConfig {
60+
encoding: Some(UiAccountEncoding::Base64),
61+
data_slice: None,
62+
commitment: Some(
63+
solana_sdk::commitment_config::CommitmentConfig::confirmed(),
64+
),
65+
min_context_slot: None,
66+
},
67+
with_context: None,
68+
sort_results: None,
69+
}),
70+
)
71+
.await?;
5772

5873
while let Some(update) = stream.next().await {
59-
let message_pda = find_message_pda(
60-
&config.wormhole_pid,
61-
(update.context.slot % 10_000) as u32
62-
);
74+
let message_pda =
75+
find_message_pda(&config.wormhole_pid, (update.context.slot % 10_000) as u32);
6376
if message_pda.to_string() != update.value.pubkey {
6477
continue; // Skip updates that are not for the expected PDA
6578
}
6679

67-
let unreliable_data: Option<PostedMessageUnreliableData> = update.value.account.data.decode().map(|data| {
68-
BorshDeserialize::deserialize(&mut data.as_slice()).ok()
69-
}).flatten();
80+
let unreliable_data: Option<PostedMessageUnreliableData> = update
81+
.value
82+
.account
83+
.data
84+
.decode()
85+
.and_then(|data| BorshDeserialize::deserialize(&mut data.as_slice()).ok());
7086

7187
if let Some(unreliable_data) = unreliable_data {
7288
if PYTHNET_CHAIN_ID != unreliable_data.emitter_chain {
@@ -77,13 +93,13 @@ async fn run_listener(config: ListenerConfig) -> Result<(), PubsubClientError> {
7793
}
7894

7995
let body = Body {
80-
timestamp: unreliable_data.submission_time,
81-
nonce: unreliable_data.nonce,
82-
emitter_chain: unreliable_data.emitter_chain,
83-
emitter_address: unreliable_data.emitter_address,
84-
sequence: unreliable_data.sequence,
96+
timestamp: unreliable_data.submission_time,
97+
nonce: unreliable_data.nonce,
98+
emitter_chain: unreliable_data.emitter_chain,
99+
emitter_address: unreliable_data.emitter_address,
100+
sequence: unreliable_data.sequence,
85101
consistency_level: unreliable_data.consistency_level,
86-
payload: unreliable_data.payload.clone(),
102+
payload: unreliable_data.payload.clone(),
87103
};
88104

89105
match body.sign(config.secret_key.secret_bytes()) {
@@ -105,7 +121,9 @@ async fn run_listener(config: ListenerConfig) -> Result<(), PubsubClientError> {
105121
unsubscribe().await
106122
});
107123

108-
Err(PubsubClientError::ConnectionClosed("Stream ended".to_string()))
124+
Err(PubsubClientError::ConnectionClosed(
125+
"Stream ended".to_string(),
126+
))
109127
}
110128

111129
fn load_secret_key(path: String) -> SecretKey {
@@ -115,7 +133,10 @@ fn load_secret_key(path: String) -> SecretKey {
115133
return SecretKey::from_byte_array(byte_array).expect("Invalid secret key length");
116134
}
117135

118-
let content = fs::read_to_string(path).expect("Invalid secret key file").trim().to_string();
136+
let content = fs::read_to_string(path)
137+
.expect("Invalid secret key file")
138+
.trim()
139+
.to_string();
119140
if let Ok(secret_key) = SecretKey::from_str(&content) {
120141
return secret_key;
121142
}
@@ -127,18 +148,24 @@ fn load_secret_key(path: String) -> SecretKey {
127148
async fn main() {
128149
let run_options = config::RunOptions::parse();
129150
let secret_key = load_secret_key(run_options.secret_key_path);
130-
let client = PubsubClient::new(&run_options.pythnet_url).await.expect("Invalid WebSocket URL");
151+
let client = PubsubClient::new(&run_options.pythnet_url)
152+
.await
153+
.expect("Invalid WebSocket URL");
131154
drop(client); // Drop the client to avoid holding the connection open
132-
let accumulator_address = Pubkey::from_str(&run_options.accumulator_address).expect("Invalid accumulator address");
133-
let wormhole_pid = Pubkey::from_str(&run_options.wormhole_pid).expect("Invalid Wormhole program ID");
155+
let accumulator_address =
156+
Pubkey::from_str(&run_options.accumulator_address).expect("Invalid accumulator address");
157+
let wormhole_pid =
158+
Pubkey::from_str(&run_options.wormhole_pid).expect("Invalid Wormhole program ID");
134159

135160
loop {
136-
if let Err(e) = run_listener(ListenerConfig {
161+
if let Err(e) = run_listener(ListenerConfig {
137162
ws_url: run_options.pythnet_url.clone(),
138-
secret_key,
139-
wormhole_pid,
163+
secret_key,
164+
wormhole_pid,
140165
accumulator_address,
141-
}).await {
166+
})
167+
.await
168+
{
142169
tracing::error!(error = ?e, "Error listening to messages");
143170
sleep(Duration::from_millis(200)).await; // Wait before retrying
144171
}

0 commit comments

Comments
 (0)