Skip to content

Commit 5a51547

Browse files
committed
feat: add dynamic pricing based on staleness
This commit adds dynamic (exponential) pricing based on staleness of the feeds that the publishers publish. This feature, combined with the recent fees for the price updates causes the spike on fee to last some time before going away.
1 parent a723612 commit 5a51547

File tree

10 files changed

+251
-86
lines changed

10 files changed

+251
-86
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "pyth-agent"
3-
version = "2.2.0"
3+
version = "2.3.0"
44
edition = "2021"
55

66
[[bin]]

config/config.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,16 @@ key_store.mapping_key = "RelevantOracleMappingAddress"
8383
# calculated based on the network previous prioritization fees.
8484
# exporter.dynamic_compute_unit_pricing_enabled = false
8585

86+
# Maximum total compute unit fee paid for a single transaction. Defaults to 0.001 SOL. This
87+
# is a safety measure while using dynamic compute price to prevent the exporter from paying
88+
# too much for a single transaction. The default is 10**12 micro lamports (0.001 SOL).
89+
# exporter.maximum_total_compute_fee_micro_lamports = 1000000000000
90+
91+
# Maximum slot gap between the current slot and the oldest slot amongst all the accounts in
92+
# the batch. This is used to calculate the dynamic price per compute unit. When the slot gap
93+
# reaches this number we will use the maximum total_compute_fee for the transaction.
94+
# exporter.maximum_slot_gap_for_dynamic_compute_unit_price = 25
95+
8696
# Duration of the interval with which to poll the status of transactions.
8797
# It is recommended to set this to a value close to exporter.publish_interval_duration
8898
# exporter.transaction_monitor.poll_interval_duration = "4s"

src/agent.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@
1010
| +--------+ +----------+ | | +----------+ +--------+ |
1111
| | Oracle | | Exporter | | | | Exporter | | Oracle | |
1212
| +--------+ +----------+ | | +----------+ +--------+ |
13-
| | ^ ^ | | ^ ^ | |
14-
+------|--------------|--|-------+ +-----|--|-------------|---------+
15-
| | | | | | +------------------------+
16-
| +--------|---------------|---------+ | | Pythd Websocket API |
17-
| | Local Store | |<---------------+-------+ +------+ |
18-
| +--------|---------------|---------+ | | | |<--|JRPC | |
19-
v | | | v | |Adapter| | WS | |
13+
| | ^ ^ ^ | | ^ ^ ^ | |
14+
+------|-----------|--|--|-------+ +-----|--|--|----------|---------+
15+
| | | | | | | | +------------------------+
16+
| +--|-----|---------------|-----|---+ | | Pythd Websocket API |
17+
| | | Local Store | | |<---------------+-------+ +------+ |
18+
| +--|-----|---------------|-----|---+ | | | |<--|JRPC | |
19+
v | | | | | v | |Adapter| | WS | |
2020
+--------------------|---------------|--------|-----------+ | | |-->|Server| |
2121
| | Global Store | | |---->+-------+ +------+ |
2222
+--------------------|---------------|--------|-----------+ | ^ | |
@@ -39,7 +39,8 @@ Publisher data write path:
3939
- The Adapter then transforms this into the Pyth SDK data structures and sends it to the Local Store.
4040
- The Local Store holds the latest price data the user has submitted for each price feed.
4141
- The Exporters periodically query the Local Store for the latest user-submitted data,
42-
and send it to the RPC node.
42+
and send it to the RPC node. They query the Global Store to get the on-chain status to dynamically
43+
adjust the compute unit price (if enabled).
4344
4445
Publisher data read path:
4546
- The Oracles continually fetch data from the RPC node, and pass this to the Global Store.
@@ -128,7 +129,9 @@ impl Agent {
128129
// Spawn the primary network
129130
jhs.extend(network::spawn_network(
130131
self.config.primary_network.clone(),
132+
network::Network::Primary,
131133
local_store_tx.clone(),
134+
global_store_lookup_tx.clone(),
132135
primary_oracle_updates_tx,
133136
primary_keypair_loader_tx,
134137
logger.new(o!("primary" => true)),
@@ -138,7 +141,9 @@ impl Agent {
138141
if let Some(config) = &self.config.secondary_network {
139142
jhs.extend(network::spawn_network(
140143
config.clone(),
144+
network::Network::Secondary,
141145
local_store_tx.clone(),
146+
global_store_lookup_tx.clone(),
142147
secondary_oracle_updates_tx,
143148
secondary_keypair_loader_tx,
144149
logger.new(o!("primary" => false)),

src/agent/dashboard.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ impl MetricsServer {
5656

5757
self.global_store_lookup_tx
5858
.send(Lookup::LookupAllAccountsData {
59+
network: super::solana::network::Network::Primary,
5960
result_tx: global_data_tx,
6061
})
6162
.await?;

src/agent/pythd/adapter.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,10 @@ impl Adapter {
359359
async fn lookup_all_accounts_data(&self) -> Result<AllAccountsData> {
360360
let (result_tx, result_rx) = oneshot::channel();
361361
self.global_store_lookup_tx
362-
.send(global::Lookup::LookupAllAccountsData { result_tx })
362+
.send(global::Lookup::LookupAllAccountsData {
363+
network: solana::network::Network::Primary,
364+
result_tx,
365+
})
363366
.await?;
364367
result_rx.await?
365368
}

src/agent/solana.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ pub mod network {
3636
},
3737
};
3838

39+
#[derive(Clone, Copy, Serialize, Deserialize, Debug)]
40+
pub enum Network {
41+
Primary,
42+
Secondary,
43+
}
44+
3945
pub fn default_rpc_url() -> String {
4046
"http://localhost:8899".to_string()
4147
}
@@ -72,9 +78,11 @@ pub mod network {
7278

7379
pub fn spawn_network(
7480
config: Config,
81+
network: Network,
7582
local_store_tx: Sender<store::local::Message>,
76-
global_store_update_tx: mpsc::Sender<global::Update>,
77-
keypair_request_tx: mpsc::Sender<KeypairRequest>,
83+
global_store_lookup_tx: Sender<global::Lookup>,
84+
global_store_update_tx: Sender<global::Update>,
85+
keypair_request_tx: Sender<KeypairRequest>,
7886
logger: Logger,
7987
) -> Result<Vec<JoinHandle<()>>> {
8088
// Publisher permissions updates between oracle and exporter
@@ -96,11 +104,13 @@ pub mod network {
96104
// Spawn the Exporter
97105
let exporter_jhs = exporter::spawn_exporter(
98106
config.exporter,
107+
network,
99108
&config.rpc_url,
100109
config.rpc_timeout,
101110
publisher_permissions_rx,
102111
KeyStore::new(config.key_store.clone(), &logger)?,
103112
local_store_tx,
113+
global_store_lookup_tx,
104114
keypair_request_tx,
105115
logger,
106116
)?;

0 commit comments

Comments
 (0)