gmsol_sdk/client/ops/
oracle.rs1use std::{future::Future, ops::Deref};
2
3use gmsol_programs::gmsol_store::{
4 accounts::Oracle,
5 client::{accounts, args},
6};
7use gmsol_solana_utils::transaction_builder::TransactionBuilder;
8use gmsol_utils::oracle::PriceProviderKind;
9use solana_sdk::{
10 pubkey::Pubkey, signer::Signer, system_instruction::create_account, system_program,
11};
12
13pub trait OracleOps<C> {
15 fn initialize_oracle<'a>(
17 &'a self,
18 store: &Pubkey,
19 oracle: &'a dyn Signer,
20 authority: Option<&Pubkey>,
21 ) -> impl Future<Output = crate::Result<(TransactionBuilder<'a, C>, Pubkey)>>;
22
23 fn initialize_price_feed(
25 &self,
26 store: &Pubkey,
27 index: u16,
28 provider: PriceProviderKind,
29 token: &Pubkey,
30 feed_id: &Pubkey,
31 ) -> (TransactionBuilder<C>, Pubkey);
32
33 #[cfg(feature = "gmsol-chainlink-datastreams")]
35 fn update_price_feed_with_chainlink(
36 &self,
37 store: &Pubkey,
38 price_feed: &Pubkey,
39 chainlink: &Pubkey,
40 access_controller: &Pubkey,
41 signed_report: &[u8],
42 ) -> crate::Result<TransactionBuilder<C>>;
43}
44
45impl<C: Deref<Target = impl Signer> + Clone> OracleOps<C> for crate::Client<C> {
46 async fn initialize_oracle<'a>(
47 &'a self,
48 store: &Pubkey,
49 oracle: &'a dyn Signer,
50 authority: Option<&Pubkey>,
51 ) -> crate::Result<(TransactionBuilder<'a, C>, Pubkey)> {
52 let payer = self.payer();
53 let oracle_address = oracle.pubkey();
54
55 let size = 8 + std::mem::size_of::<Oracle>();
56 let lamports = self
57 .store_program()
58 .rpc()
59 .get_minimum_balance_for_rent_exemption(size)
60 .await
61 .map_err(crate::Error::custom)?;
62 let create = create_account(
63 &payer,
64 &oracle_address,
65 lamports,
66 size as u64,
67 self.store_program_id(),
68 );
69
70 let builder = self
71 .store_transaction()
72 .pre_instruction(create, false)
73 .anchor_accounts(accounts::InitializeOracle {
74 payer,
75 authority: authority.copied().unwrap_or(payer),
76 store: *store,
77 oracle: oracle_address,
78 system_program: system_program::ID,
79 })
80 .anchor_args(args::InitializeOracle {})
81 .signer(oracle);
82 Ok((builder, oracle_address))
83 }
84
85 fn initialize_price_feed(
86 &self,
87 store: &Pubkey,
88 index: u16,
89 provider: PriceProviderKind,
90 token: &Pubkey,
91 feed_id: &Pubkey,
92 ) -> (TransactionBuilder<C>, Pubkey) {
93 let authority = self.payer();
94 let price_feed = self.find_price_feed_address(store, &authority, index, provider, token);
95 let rpc = self
96 .store_transaction()
97 .anchor_accounts(accounts::InitializePriceFeed {
98 authority,
99 store: *store,
100 price_feed,
101 system_program: system_program::ID,
102 })
103 .anchor_args(args::InitializePriceFeed {
104 index,
105 provider: provider.into(),
106 token: *token,
107 feed_id: *feed_id,
108 });
109 (rpc, price_feed)
110 }
111
112 #[cfg(feature = "gmsol-chainlink-datastreams")]
113 fn update_price_feed_with_chainlink(
114 &self,
115 store: &Pubkey,
116 price_feed: &Pubkey,
117 chainlink: &Pubkey,
118 access_controller: &Pubkey,
119 signed_report: &[u8],
120 ) -> crate::Result<TransactionBuilder<C>> {
121 use gmsol_chainlink_datastreams::utils::{
122 find_config_account_pda, find_verifier_account_pda, Compressor,
123 };
124
125 let authority = self.payer();
126 let verifier_account = find_verifier_account_pda(chainlink);
127 let config_account = find_config_account_pda(signed_report, chainlink);
128 Ok(self
129 .store_transaction()
130 .anchor_accounts(accounts::UpdatePriceFeedWithChainlink {
131 authority,
132 store: *store,
133 verifier_account,
134 access_controller: *access_controller,
135 config_account,
136 price_feed: *price_feed,
137 chainlink: *chainlink,
138 })
139 .anchor_args(args::UpdatePriceFeedWithChainlink {
140 compressed_report: Compressor::compress(signed_report)
141 .map_err(crate::Error::custom)?,
142 }))
143 }
144}