Skip to main content
Notice removed Draw attention by CommunityBot
Bounty Ended with no winning answer by CommunityBot
Notice added Draw attention by rana_sadam
Bounty Started worth 50 reputation by rana_sadam
Source Link

Smart contract is not persisting vector data in account?

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.