Skip to content

Commit 3f35fc1

Browse files
feat(lazer/sui): initialize (#2964)
* feat(lazer/sui): init lazer sui contract * feat(lazer/sui): init structs and basic example * feat(lazer/sui): add setters, ctors * feat(lazer/sui): readme, cleanup * fix(lazer/sui): make setters package private * fix(lazer/sui): add funding_rate_interval, address review comments * fix(lazer/sui): lock down ctors * test(lazer/sui): fix
1 parent cd8e3ff commit 3f35fc1

File tree

11 files changed

+912
-0
lines changed

11 files changed

+912
-0
lines changed

lazer/contracts/sui/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
build/*
2+
.trace
3+
.coverage*

lazer/contracts/sui/Move.lock

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# @generated by Move, please check-in and do not edit manually.
2+
3+
[move]
4+
version = 3
5+
manifest_digest = "DD0B86B0E012F788977D2224EA46B39395FCF48AB7DAE200E70E6E12F9445868"
6+
deps_digest = "F9B494B64F0615AED0E98FC12A85B85ECD2BC5185C22D30E7F67786BB52E507C"
7+
dependencies = [
8+
{ id = "Bridge", name = "Bridge" },
9+
{ id = "MoveStdlib", name = "MoveStdlib" },
10+
{ id = "Sui", name = "Sui" },
11+
{ id = "SuiSystem", name = "SuiSystem" },
12+
]
13+
14+
[[move.package]]
15+
id = "Bridge"
16+
source = { git = "https://github.com/MystenLabs/sui.git", rev = "b448b1d971bd6c1aac8ef4eee4305943806d5d5b", subdir = "crates/sui-framework/packages/bridge" }
17+
18+
dependencies = [
19+
{ id = "MoveStdlib", name = "MoveStdlib" },
20+
{ id = "Sui", name = "Sui" },
21+
{ id = "SuiSystem", name = "SuiSystem" },
22+
]
23+
24+
[[move.package]]
25+
id = "MoveStdlib"
26+
source = { git = "https://github.com/MystenLabs/sui.git", rev = "b448b1d971bd6c1aac8ef4eee4305943806d5d5b", subdir = "crates/sui-framework/packages/move-stdlib" }
27+
28+
[[move.package]]
29+
id = "Sui"
30+
source = { git = "https://github.com/MystenLabs/sui.git", rev = "b448b1d971bd6c1aac8ef4eee4305943806d5d5b", subdir = "crates/sui-framework/packages/sui-framework" }
31+
32+
dependencies = [
33+
{ id = "MoveStdlib", name = "MoveStdlib" },
34+
]
35+
36+
[[move.package]]
37+
id = "SuiSystem"
38+
source = { git = "https://github.com/MystenLabs/sui.git", rev = "b448b1d971bd6c1aac8ef4eee4305943806d5d5b", subdir = "crates/sui-framework/packages/sui-system" }
39+
40+
dependencies = [
41+
{ id = "MoveStdlib", name = "MoveStdlib" },
42+
{ id = "Sui", name = "Sui" },
43+
]
44+
45+
[move.toolchain-version]
46+
compiler-version = "1.53.2"
47+
edition = "2024.beta"
48+
flavor = "sui"

lazer/contracts/sui/Move.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[package]
2+
name = "pyth_lazer"
3+
edition = "2024.beta"
4+
5+
[dependencies]
6+
7+
[addresses]
8+
pyth_lazer = "0x0"
9+
10+
[dev-dependencies]
11+
12+
[dev-addresses]

lazer/contracts/sui/README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
## Pyth Lazer Sui Contract
2+
3+
`pyth_lazer` is a Sui package that allows consumers to easily parse and verify cryptographically signed price feed data from the Pyth Network's high-frequency Lazer protocol for use on-chain.
4+
5+
This package is built using the Move language and Sui framework.
6+
7+
### Build, test, deploy
8+
9+
Install Sui CLI and build the project:
10+
11+
```shell
12+
brew install sui
13+
sui move build
14+
```
15+
16+
Run tests:
17+
18+
```shell
19+
sui move test
20+
sui move test test_parse_and_verify_le_ecdsa_update # run a specific test
21+
```
22+
23+
Deploy:
24+
25+
TODO
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
module pyth_lazer::channel;
2+
3+
public enum Channel has copy, drop {
4+
Invalid,
5+
RealTime,
6+
FixedRate50ms,
7+
FixedRate200ms,
8+
}
9+
10+
/// Create a new Invalid channel
11+
public fun new_invalid(): Channel {
12+
Channel::Invalid
13+
}
14+
15+
/// Create a new RealTime channel
16+
public fun new_real_time(): Channel {
17+
Channel::RealTime
18+
}
19+
20+
/// Create a new FixedRate50ms channel
21+
public fun new_fixed_rate_50ms(): Channel {
22+
Channel::FixedRate50ms
23+
}
24+
25+
/// Create a new FixedRate200ms channel
26+
public fun new_fixed_rate_200ms(): Channel {
27+
Channel::FixedRate200ms
28+
}
29+
30+
/// Check if the channel is Invalid
31+
public fun is_invalid(channel: &Channel): bool {
32+
match (channel) {
33+
Channel::Invalid => true,
34+
_ => false,
35+
}
36+
}
37+
38+
/// Check if the channel is RealTime
39+
public fun is_real_time(channel: &Channel): bool {
40+
match (channel) {
41+
Channel::RealTime => true,
42+
_ => false,
43+
}
44+
}
45+
46+
/// Check if the channel is FixedRate50ms
47+
public fun is_fixed_rate_50ms(channel: &Channel): bool {
48+
match (channel) {
49+
Channel::FixedRate50ms => true,
50+
_ => false,
51+
}
52+
}
53+
54+
/// Check if the channel is FixedRate200ms
55+
public fun is_fixed_rate_200ms(channel: &Channel): bool {
56+
match (channel) {
57+
Channel::FixedRate200ms => true,
58+
_ => false,
59+
}
60+
}
61+
62+
/// Get the update interval in milliseconds for fixed rate channels, returns 0 for non-fixed rate channels
63+
public fun get_update_interval_ms(channel: &Channel): u64 {
64+
match (channel) {
65+
Channel::FixedRate50ms => 50,
66+
Channel::FixedRate200ms => 200,
67+
_ => 0,
68+
}
69+
}

lazer/contracts/sui/sources/feed.move

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
module pyth_lazer::feed;
2+
3+
use pyth_lazer::i16::I16;
4+
use pyth_lazer::i64::I64;
5+
6+
/// The feed struct is based on the Lazer rust protocol definition defined here:
7+
/// https://github.com/pyth-network/pyth-crosschain/blob/main/lazer/sdk/rust/protocol/src/payload.rs
8+
///
9+
/// Some fields in Lazer are optional, as in Lazer might return None for them due to some conditions (for example,
10+
/// not having enough publishers to calculate the price) and that is why they are represented as Option<Option<T>>.
11+
/// The first Option<T> is for the existence of the field within the update data and the second Option<T> is for the
12+
/// value of the field.
13+
public struct Feed has copy, drop {
14+
/// Unique identifier for the price feed (e.g., 1 for BTC/USD, 2 for ETH/USD)
15+
feed_id: u32,
16+
/// Current aggregate price from all publishers
17+
price: Option<Option<I64>>,
18+
/// Best bid price available across all publishers
19+
best_bid_price: Option<Option<I64>>,
20+
/// Best ask price available across all publishers
21+
best_ask_price: Option<Option<I64>>,
22+
/// Number of publishers contributing to this price feed
23+
publisher_count: Option<u16>,
24+
/// Price exponent (typically negative, e.g., -8 means divide price by 10^8)
25+
exponent: Option<I16>,
26+
/// Confidence interval representing price uncertainty
27+
confidence: Option<Option<I64>>,
28+
/// Funding rate for derivative products (e.g., perpetual futures)
29+
funding_rate: Option<Option<I64>>,
30+
/// Timestamp when the funding rate was last updated
31+
funding_timestamp: Option<Option<u64>>,
32+
/// How often the funding rate and funding payments are calculated, in microseconds
33+
funding_rate_interval: Option<Option<u64>>,
34+
}
35+
36+
/// Create a new Feed with the specified parameters
37+
public(package) fun new(
38+
feed_id: u32,
39+
price: Option<Option<I64>>,
40+
best_bid_price: Option<Option<I64>>,
41+
best_ask_price: Option<Option<I64>>,
42+
publisher_count: Option<u16>,
43+
exponent: Option<I16>,
44+
confidence: Option<Option<I64>>,
45+
funding_rate: Option<Option<I64>>,
46+
funding_timestamp: Option<Option<u64>>,
47+
funding_rate_interval: Option<Option<u64>>,
48+
): Feed {
49+
Feed {
50+
feed_id,
51+
price,
52+
best_bid_price,
53+
best_ask_price,
54+
publisher_count,
55+
exponent,
56+
confidence,
57+
funding_rate,
58+
funding_timestamp,
59+
funding_rate_interval
60+
}
61+
}
62+
63+
/// Get the feed ID
64+
public fun feed_id(feed: &Feed): u32 {
65+
feed.feed_id
66+
}
67+
68+
/// Get the price
69+
public fun price(feed: &Feed): Option<Option<I64>> {
70+
feed.price
71+
}
72+
73+
/// Get the best bid price
74+
public fun best_bid_price(feed: &Feed): Option<Option<I64>> {
75+
feed.best_bid_price
76+
}
77+
78+
/// Get the best ask price
79+
public fun best_ask_price(feed: &Feed): Option<Option<I64>> {
80+
feed.best_ask_price
81+
}
82+
83+
/// Get the publisher count
84+
public fun publisher_count(feed: &Feed): Option<u16> {
85+
feed.publisher_count
86+
}
87+
88+
/// Get the exponent
89+
public fun exponent(feed: &Feed): Option<I16> {
90+
feed.exponent
91+
}
92+
93+
/// Get the confidence interval
94+
public fun confidence(feed: &Feed): Option<Option<I64>> {
95+
feed.confidence
96+
}
97+
98+
/// Get the funding rate
99+
public fun funding_rate(feed: &Feed): Option<Option<I64>> {
100+
feed.funding_rate
101+
}
102+
103+
/// Get the funding timestamp
104+
public fun funding_timestamp(feed: &Feed): Option<Option<u64>> {
105+
feed.funding_timestamp
106+
}
107+
108+
/// Get the funding rate interval
109+
public fun funding_rate_interval(feed: &Feed): Option<Option<u64>> {
110+
feed.funding_rate_interval
111+
}
112+
113+
/// Set the feed ID
114+
public(package) fun set_feed_id(feed: &mut Feed, feed_id: u32) {
115+
feed.feed_id = feed_id;
116+
}
117+
118+
/// Set the price
119+
public(package) fun set_price(feed: &mut Feed, price: Option<Option<I64>>) {
120+
feed.price = price;
121+
}
122+
123+
/// Set the best bid price
124+
public(package) fun set_best_bid_price(feed: &mut Feed, best_bid_price: Option<Option<I64>>) {
125+
feed.best_bid_price = best_bid_price;
126+
}
127+
128+
/// Set the best ask price
129+
public(package) fun set_best_ask_price(feed: &mut Feed, best_ask_price: Option<Option<I64>>) {
130+
feed.best_ask_price = best_ask_price;
131+
}
132+
133+
/// Set the publisher count
134+
public(package) fun set_publisher_count(feed: &mut Feed, publisher_count: Option<u16>) {
135+
feed.publisher_count = publisher_count;
136+
}
137+
138+
/// Set the exponent
139+
public(package) fun set_exponent(feed: &mut Feed, exponent: Option<I16>) {
140+
feed.exponent = exponent;
141+
}
142+
143+
/// Set the confidence interval
144+
public(package) fun set_confidence(feed: &mut Feed, confidence: Option<Option<I64>>) {
145+
feed.confidence = confidence;
146+
}
147+
148+
/// Set the funding rate
149+
public(package) fun set_funding_rate(feed: &mut Feed, funding_rate: Option<Option<I64>>) {
150+
feed.funding_rate = funding_rate;
151+
}
152+
153+
/// Set the funding timestamp
154+
public(package) fun set_funding_timestamp(feed: &mut Feed, funding_timestamp: Option<Option<u64>>) {
155+
feed.funding_timestamp = funding_timestamp;
156+
}
157+
158+
/// Set the funding rate interval
159+
public(package) fun set_funding_rate_interval(feed: &mut Feed, funding_rate_interval: Option<Option<u64>>) {
160+
feed.funding_rate_interval = funding_rate_interval;
161+
}

0 commit comments

Comments
 (0)