I am writing a smart contract that take price values from a switchboard(Oracle Service) save these prices in vec and calculate volatility but everytime I run test on smart contract it reset vector length to zero
#[program]
pub mod volatility {
use super::*;
pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
let volatility_account = &mut ctx.accounts.volatility_account;
volatility_account.total = volatility_account.prices.len() as u64;
msg!("Total Prices {}!", volatility_account.total);
Ok(())
}
pub fn add_price(ctx: Context<AddPrice>) -> Result<()> {
let volatility_account = &mut ctx.accounts.volatility_account;
let feed = &ctx.accounts.aggregator.load()?;
let val: f64 = feed.get_result()?.try_into()?;
volatility_account.prices.push(val);
volatility_account.total = volatility_account.prices.len() as u64;
msg!("Current feed result is {}!", val);
msg!("Total Prices {}!", volatility_account.total);
Ok(())
}
pub fn calculate_volatility(ctx: Context<CalculateVolatility>) -> Result<()> {
let volatility_account = &mut ctx.accounts.volatility_account;
let mut sum: f64 = 0.0;
for price in &volatility_account.prices {
sum = sum + price;
}
let mean = sum / volatility_account.prices.len() as f64;
let mut square_sum: f64 = 0.0;
for price in &volatility_account.prices {
square_sum = square_sum + (price - mean).mul(price - mean);
}
let variance = square_sum / (volatility_account.prices.len() - 1) as f64;
let standard_deviation = f64::sqrt(variance);
let volatility = standard_deviation.mul(f64::sqrt(volatility_account.prices.len() as f64));
volatility_account.volatility = volatility;
msg!("Volatility is {}!", volatility);
msg!("Total Prices {}!", volatility_account.prices.len());
Ok(())
}
}
#[derive(Accounts)]
pub struct Initialize<'info> {
#[account(
init,
payer = user,
space = 200000
)]
pub volatility_account: Account<'info, Volatility>,
#[account(mut)]
pub user: Signer<'info>,
pub system_program: Program<'info, System>,
}
#[derive(Accounts)]
pub struct AddPrice<'info> {
#[account(
constraint =
*aggregator.to_account_info().owner == SWITCHBOARD_PROGRAM_ID @ FeedErrorCode::InvalidSwitchboardAccount
)]
pub aggregator: AccountLoader<'info, AggregatorAccountData>,
#[account(mut)]
pub volatility_account: Account<'info, Volatility>,
}
#[derive(Accounts)]
pub struct CalculateVolatility<'info> {
#[account(mut)]
pub volatility_account: Account<'info, Volatility>,
}
#[account]
pub struct Volatility {
pub prices: Vec<f64>,
pub total: u64,
pub volatility: f64,
}
and test I have written is below
describe("volatility", () => {
// Configure the client to use the local cluster.
const provider = anchor.AnchorProvider.env()
anchor.setProvider(provider);
const BTC_PRICE_FEED = new PublicKey(
"uXp9uaJFFPiQQmPH4UaXTWfeV9M59AvGwNSS6BppbQ3"
);
const PROGRAM_ID = new PublicKey(
"FKLzkEN4iBf9dPFuxUjvVFZGtEqYXLZgdFn9hxa2sKKq"
);
const program = new anchor.Program(
IDL,
PROGRAM_ID,
provider,
new anchor.BorshCoder(IDL)
) as anchor.Program<Volatility>;
const volatilityKeypair = anchor.web3.Keypair.generate();
it("Is initialized!", async () => {
// The Account to create.
// Create the new account and initialize it with the program.
const signature = await program.methods
.initialize()
.accounts({
volatilityAccount: volatilityKeypair.publicKey,
user: provider.wallet.publicKey,
systemProgram: anchor.web3.SystemProgram.programId,
})
.signers([volatilityKeypair])
.rpc();
const logs = await provider.connection.getParsedTransaction(
signature,
"confirmed"
);
console.log(JSON.stringify(logs?.meta?.logMessages, undefined, 2));
});
it("Add 1st price", async () => {
const signature = await program.methods
.addPrice()
.accounts({
aggregator: BTC_PRICE_FEED,
volatilityAccount: volatilityKeypair.publicKey,
})
.rpc();
const logs = await provider.connection.getParsedTransaction(
signature,
"confirmed"
);
console.log(JSON.stringify(logs?.meta?.logMessages, undefined, 2));
});
it("Add 2nd price", async () => {
const signature = await program.methods
.addPrice()
.accounts({
aggregator: BTC_PRICE_FEED,
volatilityAccount: volatilityKeypair.publicKey,
})
.rpc();
const logs = await provider.connection.getParsedTransaction(
signature,
"confirmed"
);
console.log(JSON.stringify(logs?.meta?.logMessages, undefined, 2));
});
it("Add 3rd price", async () => {
const signature = await program.methods
.addPrice()
.accounts({
aggregator: BTC_PRICE_FEED,
volatilityAccount: volatilityKeypair.publicKey,
})
.rpc();
const logs = await provider.connection.getParsedTransaction(
signature,
"confirmed"
);
console.log(JSON.stringify(logs?.meta?.logMessages, undefined, 2));
});
it("Calculate volatility", async () => {
const signature = await program.methods
.calculateVolatility()
.accounts({
volatilityAccount: volatilityKeypair.publicKey,
})
.rpc();
const logs = await provider.connection.getParsedTransaction(
signature,
"confirmed"
);
console.log(JSON.stringify(logs?.meta?.logMessages, undefined, 2));
});
/*it("Can read feed", async () => {
const signature = await program.methods
.readResult({maxConfidenceInterval: 0.25})
.accounts({
aggregator: BTC_PRICE_FEED
})
.rpc();
const logs = await provider.connection.getParsedTransaction(
signature,
"confirmed"
);
console.log(JSON.stringify(logs?.meta?.logMessages, undefined, 2));
});*/
});
Link for github repo Solana Volatility
I want to add functionality when every I call add_price method it update and add new value in price vector and that array will be used in calculate_volatility methods.