Skip to content

Commit 249a49c

Browse files
committed
pyth-lazer-agent readme and clippy config
1 parent 84c6a40 commit 249a49c

File tree

8 files changed

+108
-9
lines changed

8 files changed

+108
-9
lines changed

apps/pyth-lazer-agent/Cargo.lock

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apps/pyth-lazer-agent/Cargo.toml

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "pyth-lazer-agent"
3-
version = "0.1.2"
3+
version = "0.1.3"
44
edition = "2024"
55

66
[dependencies]
@@ -36,3 +36,43 @@ url = { version = "2.5.4", features = ["serde"] }
3636

3737
[dev-dependencies]
3838
tempfile = "3.20.0"
39+
40+
[lints.rust]
41+
unsafe_code = "deny"
42+
43+
[lints.clippy]
44+
wildcard_dependencies = "deny"
45+
46+
collapsible_if = "allow"
47+
collapsible_else_if = "allow"
48+
49+
allow_attributes_without_reason = "warn"
50+
51+
# Panics
52+
expect_used = "warn"
53+
fallible_impl_from = "warn"
54+
indexing_slicing = "warn"
55+
panic = "warn"
56+
panic_in_result_fn = "warn"
57+
string_slice = "warn"
58+
todo = "warn"
59+
unchecked_duration_subtraction = "warn"
60+
unreachable = "warn"
61+
unwrap_in_result = "warn"
62+
unwrap_used = "warn"
63+
64+
# Correctness
65+
cast_lossless = "warn"
66+
cast_possible_truncation = "warn"
67+
cast_possible_wrap = "warn"
68+
cast_sign_loss = "warn"
69+
collection_is_never_read = "warn"
70+
match_wild_err_arm = "warn"
71+
path_buf_push_overwrite = "warn"
72+
read_zero_byte_vec = "warn"
73+
same_name_method = "warn"
74+
suspicious_operation_groupings = "warn"
75+
suspicious_xor_used_as_pow = "warn"
76+
unused_self = "warn"
77+
used_underscore_binding = "warn"
78+
while_float = "warn"

apps/pyth-lazer-agent/README.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# pyth-lazer-agent
2+
3+
pyth-lazer-agent is intended to be run by Lazer publishers analogous to [pyth-agent](https://github.com/pyth-network/pyth-agent)
4+
for pythnet publishers. Currently it retains [the existing Lazer publishing interface](https://github.com/pyth-network/pyth-examples/tree/main/lazer/publisher),
5+
but will batch and sign transactions before publishing them to Lazer.
6+
7+
## Keypair
8+
9+
You will need to generate an ed25519 keypair and provide the pubkey to the Lazer team. `solana-keygen` is the recommended utility.
10+
```bash
11+
solana-keygen new -o /path/to/keypair.json
12+
solana-keygen pubkey /path/to/keypair.json
13+
```
14+
15+
pyth-lazer-agent will need to configure access to this keypair file to sign transactions.
16+
17+
## Build and run
18+
19+
### From source
20+
Please check [rust-toolchain](rust-toolchain.toml) to see the version of Rust needed to build (currently 1.88).
21+
You will also need SSL and CA certificates. `cargo build` should then work as usual.
22+
23+
### Docker
24+
See the included [Dockerfile](Dockerfile) to build an image yourself.
25+
26+
### Container
27+
We also publish images to the [GitHub Container Registry](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry#pulling-container-images).
28+
The latest will be available at `ghcr.io/pyth-network/pyth-lazer-agent:latest`.
29+
30+
## Configure
31+
The agent takes a single `--config` CLI option, pointing at
32+
`config/config.toml` by default. Configuration is currently minimal:
33+
34+
```toml
35+
relayer_urls = ["ws://relayer-0.pyth-lazer.dourolabs.app/v1/transaction", "ws://relayer-0.pyth-lazer.dourolabs.app/v1/transaction"]
36+
publish_keypair_path = "/path/to/keypair.json"
37+
authorization_token = "your_token"
38+
listen_address = "0.0.0.0:8910"
39+
publish_interval_duration = "25ms"
40+
```
41+
42+
- `relayers_urls`: The Lazer team will provide these.
43+
- `publish_keypair_path`: The keypair file generated with `solana-keygen` or similar.
44+
- `authorization_token`: The Lazer team will provide this or instruct that it can be omitted.
45+
- `listen_address`: The local port the agent will be listening on; can be anything you want.
46+
- `publisher_interval`: The agent will batch and send transaction bundles at this interval. The Lazer team will provide guidance here.
47+
48+
## Publish
49+
50+
Please use the `/v1/publisher` or `/v2/publisher` endpoints and the corresponding `PriceFeedDataV1` and `PriceFeedDataV2`
51+
schemas as defined in [the sdk](https://github.com/pyth-network/pyth-crosschain/blob/main/lazer/sdk/rust/protocol/src/publisher.rs).

apps/pyth-lazer-agent/clippy.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
allow-unwrap-in-tests = true
2+
allow-expect-in-tests = true
3+
allow-indexing-slicing-in-tests = true
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
[toolchain]
2-
channel = "1.87.0"
2+
channel = "1.88.0"
33
profile = "minimal"
44
components = ["rustfmt", "clippy"]

apps/pyth-lazer-agent/src/lazer_publisher.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,12 @@ impl LazerPublisher {
4949
.context("Failed to create signing key from keypair")
5050
}
5151

52+
#[allow(clippy::panic, reason = "can't run agent without keypair")]
5253
pub async fn new(config: &Config) -> Self {
5354
let signing_key = match Self::load_signing_key(&config.publish_keypair_path) {
5455
Ok(signing_key) => signing_key,
5556
Err(e) => {
5657
tracing::error!("Failed to load signing key: {e:?}");
57-
// Can't proceed on key failure
5858
panic!("Failed to load signing key: {e:?}");
5959
}
6060
};

apps/pyth-lazer-agent/src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ struct Cli {
2222

2323
#[tokio::main]
2424
async fn main() -> anyhow::Result<()> {
25+
#[allow(clippy::expect_used, reason = "application can fail on invalid RUST_LOG")]
2526
tracing_subscriber::fmt()
2627
.with_env_filter(
2728
EnvFilter::builder()

apps/pyth-lazer-agent/src/publisher_handle.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ async fn try_handle_publisher(
6969
// in the inner loop.
7070
let receive = async { ws_receiver.receive(&mut receive_buf).await };
7171
pin!(receive);
72-
#[allow(clippy::never_loop)] // false positive
72+
#[allow(clippy::never_loop, reason = "false positive")]
7373
loop {
7474
select! {
7575
_result = &mut receive => {
@@ -88,7 +88,9 @@ async fn try_handle_publisher(
8888
) {
8989
Ok((data, _)) => {
9090
let source_timestamp = MessageField::some(Timestamp {
91+
#[allow(clippy::cast_possible_wrap, reason = "Unix seconds won't wrap any time soon")]
9192
seconds: (data.source_timestamp_us.0 / 1_000_000) as i64,
93+
#[allow(clippy::cast_possible_truncation, reason = "this value will always be less than one billion")]
9294
nanos: (data.source_timestamp_us.0 % 1_000_000 * 1000) as i32,
9395
special_fields: Default::default(),
9496
});
@@ -131,7 +133,9 @@ async fn try_handle_publisher(
131133
) {
132134
Ok((data, _)) => {
133135
let source_timestamp = MessageField::some(Timestamp {
136+
#[allow(clippy::cast_possible_wrap, reason = "Unix seconds won't wrap any time soon")]
134137
seconds: (data.source_timestamp_us.0 / 1_000_000) as i64,
138+
#[allow(clippy::cast_possible_truncation, reason = "this value will always be less than one billion")]
135139
nanos: (data.source_timestamp_us.0 % 1_000_000 * 1000) as i32,
136140
special_fields: Default::default(),
137141
});

0 commit comments

Comments
 (0)