added anchor-history-parser example
This commit is contained in:
parent
9a08343831
commit
06d4d98cfe
|
@ -0,0 +1,7 @@
|
|||
|
||||
.anchor
|
||||
.DS_Store
|
||||
target
|
||||
**/*.rs.bk
|
||||
node_modules
|
||||
test-ledger
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
.anchor
|
||||
.DS_Store
|
||||
target
|
||||
node_modules
|
||||
dist
|
||||
build
|
||||
test-ledger
|
|
@ -0,0 +1,31 @@
|
|||
[workspace]
|
||||
members = [
|
||||
"."
|
||||
]
|
||||
|
||||
[features]
|
||||
seeds = false
|
||||
[programs.localnet]
|
||||
anchor_history_parser = "C7rn1qJkq9FjTwV86RrY5Uih91NgymRVLdJ81rqLNXRS"
|
||||
|
||||
[registry]
|
||||
url = "https://anchor.projectserum.com"
|
||||
|
||||
[provider]
|
||||
cluster = "devnet"
|
||||
# cluster = "localnet"
|
||||
wallet = "../../../payer-keypair.json"
|
||||
# wallet = "~/.config/solana/id.json"
|
||||
|
||||
|
||||
[scripts]
|
||||
test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.test.ts"
|
||||
|
||||
[test.validator]
|
||||
url="https://api.devnet.solana.com"
|
||||
|
||||
[[testnet.validator.clone]]
|
||||
address="GvDMxPzN1sCj7L26YDK2HnMRXEQmQ2aemov8YBtPS7vR" # sbv2 SOL/USD Feed
|
||||
|
||||
[[testnet.validator.clone]]
|
||||
address="7LLvRhMs73FqcLkA8jvEE1AM2mYZXTmqfUv8GAEurymx" # sbv2 SOL/USD History Buffer
|
|
@ -0,0 +1,25 @@
|
|||
[package]
|
||||
name = "anchor-history-parser"
|
||||
version = "0.1.0"
|
||||
description = "Created with Anchor"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "lib"]
|
||||
name = "anchor_history_parser"
|
||||
|
||||
[features]
|
||||
no-entrypoint = []
|
||||
no-idl = []
|
||||
no-log-ix-name = []
|
||||
cpi = ["no-entrypoint"]
|
||||
default = []
|
||||
|
||||
[profile.release]
|
||||
overflow-checks = true
|
||||
|
||||
[dependencies]
|
||||
# switchboard-v2 = { path = "../../rust/switchboard-v2", features = ["devnet"] }
|
||||
switchboard-v2 = { version = "^0.1.14", features = ["devnet"] }
|
||||
anchor-lang = "0.25.0"
|
||||
solana-program = "~1.10.29"
|
|
@ -0,0 +1,2 @@
|
|||
[target.bpfel-unknown-unknown.dependencies.std]
|
||||
features = []
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"scripts": {
|
||||
"lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w",
|
||||
"lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check"
|
||||
},
|
||||
"dependencies": {
|
||||
"@project-serum/anchor": "^0.25.0",
|
||||
"@switchboard-xyz/switchboard-v2": "^0.0.137"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bn.js": "^5.1.0",
|
||||
"@types/chai": "^4.3.0",
|
||||
"@types/mocha": "^9.0.0",
|
||||
"chai": "^4.3.4",
|
||||
"mocha": "^9.0.3",
|
||||
"prettier": "^2.6.2",
|
||||
"ts-mocha": "^10.0.0",
|
||||
"typescript": "^4.3.5"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
use anchor_lang::prelude::*;
|
||||
pub use switchboard_v2::{
|
||||
AggregatorAccountData, AggregatorHistoryBuffer, SwitchboardDecimal, SWITCHBOARD_PROGRAM_ID,
|
||||
};
|
||||
use std::convert::TryInto;
|
||||
|
||||
declare_id!("C7rn1qJkq9FjTwV86RrY5Uih91NgymRVLdJ81rqLNXRS");
|
||||
|
||||
#[derive(Accounts)]
|
||||
#[instruction(params: ReadHistoryParams)]
|
||||
pub struct ReadHistory<'info> {
|
||||
#[account(
|
||||
has_one = history_buffer @ ErrorCode::InvalidHistoryBuffer,
|
||||
constraint =
|
||||
*aggregator.to_account_info().owner == SWITCHBOARD_PROGRAM_ID @ ErrorCode::InvalidSwitchboardAccount
|
||||
)]
|
||||
pub aggregator: AccountLoader<'info, AggregatorAccountData>,
|
||||
/// CHECK: Verified by aggregator.history_buffer
|
||||
#[account(
|
||||
constraint =
|
||||
*aggregator.to_account_info().owner == SWITCHBOARD_PROGRAM_ID @ ErrorCode::InvalidSwitchboardAccount
|
||||
)]
|
||||
pub history_buffer: AccountInfo<'info>,
|
||||
}
|
||||
|
||||
#[derive(Clone, AnchorSerialize, AnchorDeserialize)]
|
||||
pub struct ReadHistoryParams {
|
||||
pub timestamp: Option<i64>,
|
||||
}
|
||||
|
||||
#[program]
|
||||
pub mod anchor_history_parser {
|
||||
use super::*;
|
||||
|
||||
pub fn read_history(
|
||||
ctx: Context<ReadHistory>,
|
||||
params: ReadHistoryParams,
|
||||
) -> anchor_lang::Result<()> {
|
||||
let aggregator = &ctx.accounts.aggregator.load()?;
|
||||
|
||||
// we validate this in the context but adding here for demonstration purposes
|
||||
if aggregator.history_buffer != ctx.accounts.history_buffer.key() {
|
||||
return Err(error!(ErrorCode::InvalidHistoryBuffer));
|
||||
}
|
||||
|
||||
// demonstration purposes
|
||||
if *ctx.accounts.history_buffer.owner != SWITCHBOARD_PROGRAM_ID {
|
||||
return Err(error!(ErrorCode::InvalidHistoryBuffer));
|
||||
}
|
||||
let history_buffer = AggregatorHistoryBuffer::new(&ctx.accounts.history_buffer)?;
|
||||
|
||||
let timestamp: i64;
|
||||
if let Some(i) = params.timestamp {
|
||||
timestamp = i;
|
||||
} else {
|
||||
// one hour ago
|
||||
timestamp = Clock::get()?.unix_timestamp - 3600;
|
||||
}
|
||||
|
||||
let value_at_timestamp: f64 = history_buffer.lower_bound(timestamp).unwrap().value.try_into()?;
|
||||
msg!("Result {:?}!", value_at_timestamp);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[error_code]
|
||||
#[derive(Eq, PartialEq)]
|
||||
pub enum ErrorCode {
|
||||
#[msg("Not a valid Switchboard account")]
|
||||
InvalidSwitchboardAccount,
|
||||
#[msg("History buffer mismatch")]
|
||||
InvalidHistoryBuffer,
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
import * as anchor from "@project-serum/anchor";
|
||||
import { Program } from "@project-serum/anchor";
|
||||
import {
|
||||
AggregatorAccount,
|
||||
loadSwitchboardProgram,
|
||||
programWallet,
|
||||
} from "@switchboard-xyz/switchboard-v2";
|
||||
import { AnchorHistoryParser } from "../target/types/anchor_history_parser";
|
||||
|
||||
export const AGGREGATOR_PUBKEY: anchor.web3.PublicKey =
|
||||
new anchor.web3.PublicKey("GvDMxPzN1sCj7L26YDK2HnMRXEQmQ2aemov8YBtPS7vR");
|
||||
|
||||
export const HISTORY_BUFFER_PUBKEY: anchor.web3.PublicKey =
|
||||
new anchor.web3.PublicKey("7LLvRhMs73FqcLkA8jvEE1AM2mYZXTmqfUv8GAEurymx");
|
||||
|
||||
export const sleep = (ms: number): Promise<any> =>
|
||||
new Promise((s) => setTimeout(s, ms));
|
||||
|
||||
describe("anchor-history-parser", () => {
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(anchor.AnchorProvider.env());
|
||||
|
||||
const program = anchor.workspace
|
||||
.AnchorHistoryParser as Program<AnchorHistoryParser>;
|
||||
|
||||
it("Reads an aggregator history buffer", async () => {
|
||||
// const ONE_HOUR_AGO: number = Math.floor(Date.now()) - 60 * 60;
|
||||
|
||||
const switchboard = await loadSwitchboardProgram(
|
||||
"devnet",
|
||||
program.provider.connection
|
||||
);
|
||||
const aggregatorAccount = new AggregatorAccount({
|
||||
program: switchboard,
|
||||
publicKey: AGGREGATOR_PUBKEY,
|
||||
});
|
||||
const aggregator = await aggregatorAccount.loadData();
|
||||
|
||||
// TODO: Verify the value in the program logs matches the history samples
|
||||
const history = await aggregatorAccount.loadHistory();
|
||||
|
||||
const tx = await program.methods
|
||||
.readHistory({ timestamp: null })
|
||||
.accounts({
|
||||
aggregator: AGGREGATOR_PUBKEY,
|
||||
historyBuffer: aggregator.historyBuffer,
|
||||
})
|
||||
.rpc();
|
||||
console.log("Your transaction signature", tx);
|
||||
|
||||
await sleep(5000);
|
||||
|
||||
const confirmedTxn = await program.provider.connection.getParsedTransaction(
|
||||
tx,
|
||||
"confirmed"
|
||||
);
|
||||
|
||||
console.log(JSON.stringify(confirmedTxn?.meta?.logMessages, undefined, 2));
|
||||
});
|
||||
});
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"types": ["mocha", "chai"],
|
||||
"typeRoots": ["./node_modules/@types"],
|
||||
"lib": ["es2019", "dom"],
|
||||
"moduleResolution": "node",
|
||||
"module": "commonjs",
|
||||
"target": "es6",
|
||||
"esModuleInterop": true,
|
||||
"paths": {
|
||||
"@switchboard-xyz/switchboard-v2": ["../../javascript/solana.js"],
|
||||
"@switchboard-xyz/sbv2-utils": ["../../javascript/sbv2-utils"]
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"tests/**/*",
|
||||
"client/**/*",
|
||||
"./target/types/anchor_history_parser"
|
||||
],
|
||||
"references": [
|
||||
{ "path": "../../javascript/solana.js" },
|
||||
{ "path": "../../javascript/sbv2-utils" }
|
||||
]
|
||||
}
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue