uprev switchboard deps

wip


wip


wip


wip


fix sleep timer
This commit is contained in:
Conner Gallagher 2022-11-26 15:14:39 -07:00
parent c63b80dc5a
commit 6c3283db30
102 changed files with 48677 additions and 28744 deletions

View File

@ -1,31 +0,0 @@
[workspace]
members = [
"examples/programs/anchor-feed-parser",
"examples/programs/anchor-vrf-parser",
"examples/programs/anchor-buffer-parser",
"examples/programs/native-feed-parser"
]
[provider]
# cluster = "devnet"
cluster = "localnet"
wallet = "../payer-keypair.json"
# wallet = "~/.config/solana/id.json"
[programs.localnet]
anchor_feed_parser = "FnsPs665aBSwJRu2A8wGv6ZT76ipR41kHm4hoA3B1QGh"
anchor_vrf_parser = "HjjRFjCyQH3ne6Gg8Yn3TQafrrYecRrphwLwnh2A26vM"
anchor_buffer_parser = "96punQGZDShZGkzsBa3SsfTxfUnwu4XGpzXbhF7NTgcP"
[registry]
url = "https://anchor.projectserum.com"
[scripts]
test = "yarn run ts-mocha -p ./tsconfig.testing.json -t 1000000 ./examples/programs/*/tests/*.test.ts"
[test.validator]
url="https://api.devnet.solana.com"
[[testnet.validator.clone]]
address="GvDMxPzN1sCj7L26YDK2HnMRXEQmQ2aemov8YBtPS7vR" # sbv2 SOL/USD Feed

View File

@ -18,9 +18,9 @@
"author": "",
"license": "ISC",
"dependencies": {
"@project-serum/anchor": "^0.24.2",
"@project-serum/anchor": "^0.25.0",
"@solana/web3.js": "^1.33.0",
"@switchboard-xyz/switchboard-v2": "^0.0.136",
"@switchboard-xyz/switchboard-v2": "^0.0.165",
"big.js": "^6.1.1"
},
"devDependencies": {

View File

@ -22,11 +22,11 @@
"outDir": "dist",
"rootDir": "src",
"paths": {
"@switchboard-xyz/switchboard-v2": ["../solana.js"]
"@switchboard-xyz/switchboard-v2": ["../switchboard-v2"]
}
},
"include": ["src/**/*"],
"exclude": ["esbuild.js", "dist"],
"references": [{ "path": "../solana.js" }],
"references": [{ "path": "../switchboard-v2" }],
"files": ["src/main.ts"]
}

View File

@ -17,11 +17,11 @@
"test": "echo \"No test script for @switchboard-xyz/v2-feed-walkthrough\" && exit 0"
},
"dependencies": {
"@project-serum/anchor": "^0.24.2",
"@project-serum/anchor": "^0.25.0",
"@solana/spl-token-v2": "npm:@solana/spl-token@^0.2.0",
"@solana/web3.js": "^1.50.1",
"@switchboard-xyz/common": "^2.0.0",
"@switchboard-xyz/switchboard-v2": "^0.0.136",
"@switchboard-xyz/common": "^2.1.7",
"@switchboard-xyz/switchboard-v2": "^0.0.165",
"chalk": "^4.1.2",
"dotenv": "^16.0.1",
"readline-sync": "^1.4.10"

View File

@ -22,12 +22,12 @@
"outDir": "dist",
"rootDir": "src",
"paths": {
"@switchboard-xyz/switchboard-v2": ["../solana.js"],
"@switchboard-xyz/switchboard-v2": ["../switchboard-v2"],
"@solana/spl-token": ["./node_modules/@solana/spl-token"]
}
},
"include": ["src/**/*"],
"exclude": ["esbuild.js", "dist"],
"references": [{ "path": "../solana.js" }],
"references": [{ "path": "../switchboard-v2" }],
"files": ["src/main.ts"]
}

View File

@ -15,10 +15,10 @@
"test": "echo \"No test script for @switchboard-xyz/lease-observer\" && exit 0"
},
"dependencies": {
"@project-serum/anchor": "^0.24.2",
"@project-serum/anchor": "^0.25.0",
"@solana/web3.js": "1.33.0",
"@switchboard-xyz/sbv2-utils": "^0.1.49",
"@switchboard-xyz/switchboard-v2": "^0.0.136",
"@switchboard-xyz/sbv2-utils": "^0.1.53",
"@switchboard-xyz/switchboard-v2": "^0.0.165",
"dotenv": "^16.0.1",
"node-pagerduty": "^1.3.6"
},

View File

@ -25,13 +25,13 @@
"rootDir": "src",
"strict": false,
"paths": {
"@switchboard-xyz/switchboard-v2": ["../solana.js"],
"@switchboard-xyz/switchboard-v2": ["../switchboard-v2"],
"@switchboard-xyz/sbv2-utils": ["../sbv2-utils"],
"@solana/spl-token": ["./node_modules/@solana/spl-token"]
}
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"],
"references": [{ "path": "../solana.js" }, { "path": "../sbv2-utils" }],
"references": [{ "path": "../switchboard-v2" }, { "path": "../sbv2-utils" }],
"files": ["src/main.ts"]
}

View File

@ -39,8 +39,8 @@
"@saberhq/token-utils": "^1.13.32",
"@solana/spl-token-v2": "npm:@solana/spl-token@^0.2.0",
"@solana/web3.js": "^1.66.2",
"@switchboard-xyz/common": "^2.1.3",
"@switchboard-xyz/switchboard-v2": "^0.0.159",
"@switchboard-xyz/common": "^2.1.7",
"@switchboard-xyz/switchboard-v2": "^0.0.165",
"big.js": "^6.2.1",
"bn.js": "^5.2.1",
"chalk": "4",

View File

@ -12,7 +12,7 @@
"repository": {
"type": "git",
"url": "https://github.com/switchboard-xyz/switchboard-v2",
"directory": "javascript/solana.js"
"directory": "javascript/switchboard-v2"
},
"homepage": "https://docs.switchboard.xyz",
"files": [

View File

@ -5,19 +5,18 @@ import * as spl from "@solana/spl-token-v2";
import {
AccountInfo,
AccountMeta,
ComputeBudgetProgram,
clusterApiUrl,
ConfirmOptions,
Connection,
Keypair,
PublicKey,
SYSVAR_INSTRUCTIONS_PUBKEY,
SYSVAR_RECENT_BLOCKHASHES_PUBKEY,
sendAndConfirmTransaction,
Signer,
SystemProgram,
SYSVAR_INSTRUCTIONS_PUBKEY,
SYSVAR_RECENT_BLOCKHASHES_PUBKEY,
Transaction,
TransactionSignature,
clusterApiUrl,
sendAndConfirmTransaction,
} from "@solana/web3.js";
import { OracleJob, SwitchboardDecimal, toUtf8 } from "@switchboard-xyz/common";
import assert from "assert";
@ -825,10 +824,7 @@ export class AggregatorAccount {
* @param aggregator The loaded aggegator schema
* @returns boolean
*/
static async shouldReportValue(
value: Big,
aggregator: any
): Promise<boolean> {
static shouldReportValue(value: Big, aggregator: any): boolean {
if ((aggregator.latestConfirmedRound?.numSuccess ?? 0) === 0) {
return true;
}

View File

@ -1,8 +1,9 @@
### Sbv2 Program Examples
| Package | Description |
| ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| [anchor-feed-parser](./anchor-feed-parser) | Anchor example program demonstrating how to deserialize and read an onchain aggregator account. |
| [native-feed-parser](./native-feed-parser) | Solana Program Library example demonstrating how to deserialize and read an onchain aggregator account. |
| [anchor-vrf-parser](./anchor-vrf-parser) | Anchor example program demonstrating how to deserialize and read an onchain verifiable randomness function (VRF) account. |
| [anchor-buffer-parser](./anchor-buffer-parser) | Anchor example program demonstrating how to deserialize and read an onchain buffer relayer account. |
| Package | Description |
| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- |
| [anchor-feed-parser](./anchor-feed-parser) | Anchor example program demonstrating how to deserialize and read an onchain aggregator account. |
| [native-feed-parser](./native-feed-parser) | Solana Program Library example demonstrating how to deserialize and read an onchain aggregator account. |
| [anchor-history-parser](./anchor-history-parser) | Anchor example program demonstrating how to deserialize and read an onchain aggregator history buffer account. |
| [anchor-vrf-parser](./anchor-vrf-parser) | Anchor example program demonstrating how to deserialize and read an onchain verifiable randomness function (VRF) account. |
| [anchor-buffer-parser](./anchor-buffer-parser) | Anchor example program demonstrating how to deserialize and read an onchain buffer relayer account. |

View File

@ -0,0 +1,7 @@
.anchor
.DS_Store
target
**/*.rs.bk
node_modules
test-ledger
client/

View File

@ -22,5 +22,50 @@ test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 ./tests/*.test.ts"
[test.validator]
url="https://api.devnet.solana.com"
[test]
startup_wait = 10000
[[testnet.validator.clone]]
address="GvDMxPzN1sCj7L26YDK2HnMRXEQmQ2aemov8YBtPS7vR" # sbv2 SOL/USD Feed
address="GvDMxPzN1sCj7L26YDK2HnMRXEQmQ2aemov8YBtPS7vR" # sbv2 SOL/USD Feed
# [[test.validator.clone]] # programID
# address = "2TfB33aLaneQb5TNVwyDz3jSZXS6jdW2ARw1Dgf84XCG"
# [[test.validator.clone]] # idlAddress
# address = "CKwZcshn4XDvhaWVH9EXnk3iu19t6t5xP2Sy2pD6TRDp"
# [[test.validator.clone]] # programState
# address = "BYM81n8HvTJuqZU1PmTVcwZ9G8uoji7FKM6EaPkwphPt"
# [[test.validator.clone]] # switchboardVault
# address = "FVLfR6C2ckZhbSwBzZY4CX7YBcddUSge5BNeGQv5eKhy"
# [[test.validator.clone]] # tokenWallet
# address = "98noixB6NnabjgFKw9wgXtqVd9Xg6rmj5kEVMeCHUB5e"
# [[test.validator.clone]] # queue
# address = "AGhkGTuVfSGKYoFcRCUbbPNxhnaWNRXzcAYndyHdNV3V"
# [[test.validator.clone]] # queueAuthority
# address = "AXrbiv8bmcJfscyYWjR8BMFvTUjmx7FSENCjtEx4NxFh"
# [[test.validator.clone]] # queueBuffer
# address = "9SYE1tzHxKvRCYAv1yLLA4iMjk3p3VWiqgZX8v4HNBrw"
# [[test.validator.clone]] # crank
# address = "7xN6FXxJBtPVgrzcAZogvw7kWjz1NQdXmx7hoTVG3abF"
# [[test.validator.clone]] # crankBuffer
# address = "6pANimo6hHXShDcWdNZjsW6cbc2azGhcLGdnCBC4TBi8"
# [[test.validator.clone]] # oracle
# address = "JArZ6Van92SM6VyaARFmstgX2n9TJmLvVBN9ZkwpKH8B"
# [[test.validator.clone]] # oracleAuthority
# address = "AXrbiv8bmcJfscyYWjR8BMFvTUjmx7FSENCjtEx4NxFh"
# [[test.validator.clone]] # oracleEscrow
# address = "3Dm7ZuqNH89QLBuuJbqa4XZfpz8n1pCobP23NtVisQHE"
# [[test.validator.clone]] # oraclePermissions
# address = "GgNZcKzHBtEiLuDeaRAT8SsMTyG5Yzpm4XvetiazkHHW"

View File

@ -16,7 +16,7 @@ cpi = ["no-entrypoint"]
default = []
[dependencies]
# switchboard-v2 = { path = "../../rust/switchboard-v2", features = ["devnet"] }
switchboard-v2 = { version = "^0.1.14", features = ["devnet"] }
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"

View File

@ -1,70 +0,0 @@
import * as borsh from "@project-serum/borsh"; // eslint-disable-line @typescript-eslint/no-unused-vars
import { Connection, PublicKey } from "@solana/web3.js";
import { PROGRAM_ID } from "../programId";
export interface BufferClientFields {}
export interface BufferClientJSON {}
export class BufferClient {
static readonly discriminator = Buffer.from([
142, 182, 89, 69, 9, 66, 10, 86,
]);
static readonly layout = borsh.struct([]);
constructor(fields: BufferClientFields) {}
static async fetch(
c: Connection,
programId: PublicKey,
address: PublicKey
): Promise<BufferClient | null> {
const info = await c.getAccountInfo(address);
if (info === null) {
return null;
}
if (!info.owner.equals(PROGRAM_ID)) {
throw new Error("account doesn't belong to this program");
}
return this.decode(info.data);
}
static async fetchMultiple(
c: Connection,
addresses: PublicKey[]
): Promise<Array<BufferClient | null>> {
const infos = await c.getMultipleAccountsInfo(addresses);
return infos.map((info) => {
if (info === null) {
return null;
}
if (!info.owner.equals(PROGRAM_ID)) {
throw new Error("account doesn't belong to this program");
}
return this.decode(info.data);
});
}
static decode(data: Buffer): BufferClient {
if (!data.slice(0, 8).equals(BufferClient.discriminator)) {
throw new Error("invalid account discriminator");
}
const dec = BufferClient.layout.decode(data.slice(8));
return new BufferClient({});
}
toJSON(): BufferClientJSON {
return {};
}
static fromJSON(obj: BufferClientJSON): BufferClient {
return new BufferClient({});
}
}

View File

@ -1,5 +0,0 @@
export {
BufferClient,
BufferClientFields,
BufferClientJSON,
} from "./BufferClient"

View File

@ -1,690 +0,0 @@
export type AnchorError =
| InstructionMissing
| InstructionFallbackNotFound
| InstructionDidNotDeserialize
| InstructionDidNotSerialize
| IdlInstructionStub
| IdlInstructionInvalidProgram
| ConstraintMut
| ConstraintHasOne
| ConstraintSigner
| ConstraintRaw
| ConstraintOwner
| ConstraintRentExempt
| ConstraintSeeds
| ConstraintExecutable
| ConstraintState
| ConstraintAssociated
| ConstraintAssociatedInit
| ConstraintClose
| ConstraintAddress
| ConstraintZero
| ConstraintTokenMint
| ConstraintTokenOwner
| ConstraintMintMintAuthority
| ConstraintMintFreezeAuthority
| ConstraintMintDecimals
| ConstraintSpace
| RequireViolated
| RequireEqViolated
| RequireKeysEqViolated
| RequireNeqViolated
| RequireKeysNeqViolated
| RequireGtViolated
| RequireGteViolated
| AccountDiscriminatorAlreadySet
| AccountDiscriminatorNotFound
| AccountDiscriminatorMismatch
| AccountDidNotDeserialize
| AccountDidNotSerialize
| AccountNotEnoughKeys
| AccountNotMutable
| AccountOwnedByWrongProgram
| InvalidProgramId
| InvalidProgramExecutable
| AccountNotSigner
| AccountNotSystemOwned
| AccountNotInitialized
| AccountNotProgramData
| AccountNotAssociatedTokenAccount
| AccountSysvarMismatch
| StateInvalidAddress
| DeclaredProgramIdMismatch
| Deprecated
export class InstructionMissing extends Error {
readonly code = 100
readonly name = "InstructionMissing"
readonly msg = "8 byte instruction identifier not provided"
constructor() {
super("100: 8 byte instruction identifier not provided")
}
}
export class InstructionFallbackNotFound extends Error {
readonly code = 101
readonly name = "InstructionFallbackNotFound"
readonly msg = "Fallback functions are not supported"
constructor() {
super("101: Fallback functions are not supported")
}
}
export class InstructionDidNotDeserialize extends Error {
readonly code = 102
readonly name = "InstructionDidNotDeserialize"
readonly msg = "The program could not deserialize the given instruction"
constructor() {
super("102: The program could not deserialize the given instruction")
}
}
export class InstructionDidNotSerialize extends Error {
readonly code = 103
readonly name = "InstructionDidNotSerialize"
readonly msg = "The program could not serialize the given instruction"
constructor() {
super("103: The program could not serialize the given instruction")
}
}
export class IdlInstructionStub extends Error {
readonly code = 1000
readonly name = "IdlInstructionStub"
readonly msg = "The program was compiled without idl instructions"
constructor() {
super("1000: The program was compiled without idl instructions")
}
}
export class IdlInstructionInvalidProgram extends Error {
readonly code = 1001
readonly name = "IdlInstructionInvalidProgram"
readonly msg =
"The transaction was given an invalid program for the IDL instruction"
constructor() {
super(
"1001: The transaction was given an invalid program for the IDL instruction"
)
}
}
export class ConstraintMut extends Error {
readonly code = 2000
readonly name = "ConstraintMut"
readonly msg = "A mut constraint was violated"
constructor() {
super("2000: A mut constraint was violated")
}
}
export class ConstraintHasOne extends Error {
readonly code = 2001
readonly name = "ConstraintHasOne"
readonly msg = "A has_one constraint was violated"
constructor() {
super("2001: A has_one constraint was violated")
}
}
export class ConstraintSigner extends Error {
readonly code = 2002
readonly name = "ConstraintSigner"
readonly msg = "A signer constraint was violated"
constructor() {
super("2002: A signer constraint was violated")
}
}
export class ConstraintRaw extends Error {
readonly code = 2003
readonly name = "ConstraintRaw"
readonly msg = "A raw constraint was violated"
constructor() {
super("2003: A raw constraint was violated")
}
}
export class ConstraintOwner extends Error {
readonly code = 2004
readonly name = "ConstraintOwner"
readonly msg = "An owner constraint was violated"
constructor() {
super("2004: An owner constraint was violated")
}
}
export class ConstraintRentExempt extends Error {
readonly code = 2005
readonly name = "ConstraintRentExempt"
readonly msg = "A rent exemption constraint was violated"
constructor() {
super("2005: A rent exemption constraint was violated")
}
}
export class ConstraintSeeds extends Error {
readonly code = 2006
readonly name = "ConstraintSeeds"
readonly msg = "A seeds constraint was violated"
constructor() {
super("2006: A seeds constraint was violated")
}
}
export class ConstraintExecutable extends Error {
readonly code = 2007
readonly name = "ConstraintExecutable"
readonly msg = "An executable constraint was violated"
constructor() {
super("2007: An executable constraint was violated")
}
}
export class ConstraintState extends Error {
readonly code = 2008
readonly name = "ConstraintState"
readonly msg = "A state constraint was violated"
constructor() {
super("2008: A state constraint was violated")
}
}
export class ConstraintAssociated extends Error {
readonly code = 2009
readonly name = "ConstraintAssociated"
readonly msg = "An associated constraint was violated"
constructor() {
super("2009: An associated constraint was violated")
}
}
export class ConstraintAssociatedInit extends Error {
readonly code = 2010
readonly name = "ConstraintAssociatedInit"
readonly msg = "An associated init constraint was violated"
constructor() {
super("2010: An associated init constraint was violated")
}
}
export class ConstraintClose extends Error {
readonly code = 2011
readonly name = "ConstraintClose"
readonly msg = "A close constraint was violated"
constructor() {
super("2011: A close constraint was violated")
}
}
export class ConstraintAddress extends Error {
readonly code = 2012
readonly name = "ConstraintAddress"
readonly msg = "An address constraint was violated"
constructor() {
super("2012: An address constraint was violated")
}
}
export class ConstraintZero extends Error {
readonly code = 2013
readonly name = "ConstraintZero"
readonly msg = "Expected zero account discriminant"
constructor() {
super("2013: Expected zero account discriminant")
}
}
export class ConstraintTokenMint extends Error {
readonly code = 2014
readonly name = "ConstraintTokenMint"
readonly msg = "A token mint constraint was violated"
constructor() {
super("2014: A token mint constraint was violated")
}
}
export class ConstraintTokenOwner extends Error {
readonly code = 2015
readonly name = "ConstraintTokenOwner"
readonly msg = "A token owner constraint was violated"
constructor() {
super("2015: A token owner constraint was violated")
}
}
export class ConstraintMintMintAuthority extends Error {
readonly code = 2016
readonly name = "ConstraintMintMintAuthority"
readonly msg = "A mint mint authority constraint was violated"
constructor() {
super("2016: A mint mint authority constraint was violated")
}
}
export class ConstraintMintFreezeAuthority extends Error {
readonly code = 2017
readonly name = "ConstraintMintFreezeAuthority"
readonly msg = "A mint freeze authority constraint was violated"
constructor() {
super("2017: A mint freeze authority constraint was violated")
}
}
export class ConstraintMintDecimals extends Error {
readonly code = 2018
readonly name = "ConstraintMintDecimals"
readonly msg = "A mint decimals constraint was violated"
constructor() {
super("2018: A mint decimals constraint was violated")
}
}
export class ConstraintSpace extends Error {
readonly code = 2019
readonly name = "ConstraintSpace"
readonly msg = "A space constraint was violated"
constructor() {
super("2019: A space constraint was violated")
}
}
export class RequireViolated extends Error {
readonly code = 2500
readonly name = "RequireViolated"
readonly msg = "A require expression was violated"
constructor() {
super("2500: A require expression was violated")
}
}
export class RequireEqViolated extends Error {
readonly code = 2501
readonly name = "RequireEqViolated"
readonly msg = "A require_eq expression was violated"
constructor() {
super("2501: A require_eq expression was violated")
}
}
export class RequireKeysEqViolated extends Error {
readonly code = 2502
readonly name = "RequireKeysEqViolated"
readonly msg = "A require_keys_eq expression was violated"
constructor() {
super("2502: A require_keys_eq expression was violated")
}
}
export class RequireNeqViolated extends Error {
readonly code = 2503
readonly name = "RequireNeqViolated"
readonly msg = "A require_neq expression was violated"
constructor() {
super("2503: A require_neq expression was violated")
}
}
export class RequireKeysNeqViolated extends Error {
readonly code = 2504
readonly name = "RequireKeysNeqViolated"
readonly msg = "A require_keys_neq expression was violated"
constructor() {
super("2504: A require_keys_neq expression was violated")
}
}
export class RequireGtViolated extends Error {
readonly code = 2505
readonly name = "RequireGtViolated"
readonly msg = "A require_gt expression was violated"
constructor() {
super("2505: A require_gt expression was violated")
}
}
export class RequireGteViolated extends Error {
readonly code = 2506
readonly name = "RequireGteViolated"
readonly msg = "A require_gte expression was violated"
constructor() {
super("2506: A require_gte expression was violated")
}
}
export class AccountDiscriminatorAlreadySet extends Error {
readonly code = 3000
readonly name = "AccountDiscriminatorAlreadySet"
readonly msg = "The account discriminator was already set on this account"
constructor() {
super("3000: The account discriminator was already set on this account")
}
}
export class AccountDiscriminatorNotFound extends Error {
readonly code = 3001
readonly name = "AccountDiscriminatorNotFound"
readonly msg = "No 8 byte discriminator was found on the account"
constructor() {
super("3001: No 8 byte discriminator was found on the account")
}
}
export class AccountDiscriminatorMismatch extends Error {
readonly code = 3002
readonly name = "AccountDiscriminatorMismatch"
readonly msg = "8 byte discriminator did not match what was expected"
constructor() {
super("3002: 8 byte discriminator did not match what was expected")
}
}
export class AccountDidNotDeserialize extends Error {
readonly code = 3003
readonly name = "AccountDidNotDeserialize"
readonly msg = "Failed to deserialize the account"
constructor() {
super("3003: Failed to deserialize the account")
}
}
export class AccountDidNotSerialize extends Error {
readonly code = 3004
readonly name = "AccountDidNotSerialize"
readonly msg = "Failed to serialize the account"
constructor() {
super("3004: Failed to serialize the account")
}
}
export class AccountNotEnoughKeys extends Error {
readonly code = 3005
readonly name = "AccountNotEnoughKeys"
readonly msg = "Not enough account keys given to the instruction"
constructor() {
super("3005: Not enough account keys given to the instruction")
}
}
export class AccountNotMutable extends Error {
readonly code = 3006
readonly name = "AccountNotMutable"
readonly msg = "The given account is not mutable"
constructor() {
super("3006: The given account is not mutable")
}
}
export class AccountOwnedByWrongProgram extends Error {
readonly code = 3007
readonly name = "AccountOwnedByWrongProgram"
readonly msg =
"The given account is owned by a different program than expected"
constructor() {
super(
"3007: The given account is owned by a different program than expected"
)
}
}
export class InvalidProgramId extends Error {
readonly code = 3008
readonly name = "InvalidProgramId"
readonly msg = "Program ID was not as expected"
constructor() {
super("3008: Program ID was not as expected")
}
}
export class InvalidProgramExecutable extends Error {
readonly code = 3009
readonly name = "InvalidProgramExecutable"
readonly msg = "Program account is not executable"
constructor() {
super("3009: Program account is not executable")
}
}
export class AccountNotSigner extends Error {
readonly code = 3010
readonly name = "AccountNotSigner"
readonly msg = "The given account did not sign"
constructor() {
super("3010: The given account did not sign")
}
}
export class AccountNotSystemOwned extends Error {
readonly code = 3011
readonly name = "AccountNotSystemOwned"
readonly msg = "The given account is not owned by the system program"
constructor() {
super("3011: The given account is not owned by the system program")
}
}
export class AccountNotInitialized extends Error {
readonly code = 3012
readonly name = "AccountNotInitialized"
readonly msg = "The program expected this account to be already initialized"
constructor() {
super("3012: The program expected this account to be already initialized")
}
}
export class AccountNotProgramData extends Error {
readonly code = 3013
readonly name = "AccountNotProgramData"
readonly msg = "The given account is not a program data account"
constructor() {
super("3013: The given account is not a program data account")
}
}
export class AccountNotAssociatedTokenAccount extends Error {
readonly code = 3014
readonly name = "AccountNotAssociatedTokenAccount"
readonly msg = "The given account is not the associated token account"
constructor() {
super("3014: The given account is not the associated token account")
}
}
export class AccountSysvarMismatch extends Error {
readonly code = 3015
readonly name = "AccountSysvarMismatch"
readonly msg = "The given public key does not match the required sysvar"
constructor() {
super("3015: The given public key does not match the required sysvar")
}
}
export class StateInvalidAddress extends Error {
readonly code = 4000
readonly name = "StateInvalidAddress"
readonly msg = "The given state account does not have the correct address"
constructor() {
super("4000: The given state account does not have the correct address")
}
}
export class DeclaredProgramIdMismatch extends Error {
readonly code = 4100
readonly name = "DeclaredProgramIdMismatch"
readonly msg = "The declared program id does not match the actual program id"
constructor() {
super("4100: The declared program id does not match the actual program id")
}
}
export class Deprecated extends Error {
readonly code = 5000
readonly name = "Deprecated"
readonly msg = "The API being used is deprecated and should no longer be used"
constructor() {
super("5000: The API being used is deprecated and should no longer be used")
}
}
export function fromCode(code: number): AnchorError | null {
switch (code) {
case 100:
return new InstructionMissing()
case 101:
return new InstructionFallbackNotFound()
case 102:
return new InstructionDidNotDeserialize()
case 103:
return new InstructionDidNotSerialize()
case 1000:
return new IdlInstructionStub()
case 1001:
return new IdlInstructionInvalidProgram()
case 2000:
return new ConstraintMut()
case 2001:
return new ConstraintHasOne()
case 2002:
return new ConstraintSigner()
case 2003:
return new ConstraintRaw()
case 2004:
return new ConstraintOwner()
case 2005:
return new ConstraintRentExempt()
case 2006:
return new ConstraintSeeds()
case 2007:
return new ConstraintExecutable()
case 2008:
return new ConstraintState()
case 2009:
return new ConstraintAssociated()
case 2010:
return new ConstraintAssociatedInit()
case 2011:
return new ConstraintClose()
case 2012:
return new ConstraintAddress()
case 2013:
return new ConstraintZero()
case 2014:
return new ConstraintTokenMint()
case 2015:
return new ConstraintTokenOwner()
case 2016:
return new ConstraintMintMintAuthority()
case 2017:
return new ConstraintMintFreezeAuthority()
case 2018:
return new ConstraintMintDecimals()
case 2019:
return new ConstraintSpace()
case 2500:
return new RequireViolated()
case 2501:
return new RequireEqViolated()
case 2502:
return new RequireKeysEqViolated()
case 2503:
return new RequireNeqViolated()
case 2504:
return new RequireKeysNeqViolated()
case 2505:
return new RequireGtViolated()
case 2506:
return new RequireGteViolated()
case 3000:
return new AccountDiscriminatorAlreadySet()
case 3001:
return new AccountDiscriminatorNotFound()
case 3002:
return new AccountDiscriminatorMismatch()
case 3003:
return new AccountDidNotDeserialize()
case 3004:
return new AccountDidNotSerialize()
case 3005:
return new AccountNotEnoughKeys()
case 3006:
return new AccountNotMutable()
case 3007:
return new AccountOwnedByWrongProgram()
case 3008:
return new InvalidProgramId()
case 3009:
return new InvalidProgramExecutable()
case 3010:
return new AccountNotSigner()
case 3011:
return new AccountNotSystemOwned()
case 3012:
return new AccountNotInitialized()
case 3013:
return new AccountNotProgramData()
case 3014:
return new AccountNotAssociatedTokenAccount()
case 3015:
return new AccountSysvarMismatch()
case 4000:
return new StateInvalidAddress()
case 4100:
return new DeclaredProgramIdMismatch()
case 5000:
return new Deprecated()
}
return null
}

View File

@ -1,63 +0,0 @@
export type CustomError =
| InvalidSwitchboardAccount
| ExpectedResultMismatch
| StaleBuffer
| StringConversionFailed
export class InvalidSwitchboardAccount extends Error {
readonly code = 6000
readonly name = "InvalidSwitchboardAccount"
readonly msg = "Not a valid Switchboard account"
constructor() {
super("6000: Not a valid Switchboard account")
}
}
export class ExpectedResultMismatch extends Error {
readonly code = 6001
readonly name = "ExpectedResultMismatch"
readonly msg = "Switchboard buffer does not match provided expected_result!"
constructor() {
super("6001: Switchboard buffer does not match provided expected_result!")
}
}
export class StaleBuffer extends Error {
readonly code = 6002
readonly name = "StaleBuffer"
readonly msg =
"Switchboard buffer has not been updated in the last 5 minutes!"
constructor() {
super(
"6002: Switchboard buffer has not been updated in the last 5 minutes!"
)
}
}
export class StringConversionFailed extends Error {
readonly code = 6003
readonly name = "StringConversionFailed"
readonly msg = "Failed to convert the buffer to a string!"
constructor() {
super("6003: Failed to convert the buffer to a string!")
}
}
export function fromCode(code: number): CustomError | null {
switch (code) {
case 6000:
return new InvalidSwitchboardAccount()
case 6001:
return new ExpectedResultMismatch()
case 6002:
return new StaleBuffer()
case 6003:
return new StringConversionFailed()
}
return null
}

View File

@ -1,57 +0,0 @@
import { PROGRAM_ID } from "../programId"
import * as anchor from "./anchor"
import * as custom from "./custom"
export function fromCode(
code: number
): custom.CustomError | anchor.AnchorError | null {
return code >= 6000 ? custom.fromCode(code) : anchor.fromCode(code)
}
function hasOwnProperty<X extends object, Y extends PropertyKey>(
obj: X,
prop: Y
): obj is X & Record<Y, unknown> {
return Object.hasOwnProperty.call(obj, prop)
}
const errorRe = /Program (\w+) failed: custom program error: (\w+)/
export function fromTxError(
err: unknown
): custom.CustomError | anchor.AnchorError | null {
if (
typeof err !== "object" ||
err === null ||
!hasOwnProperty(err, "logs") ||
!Array.isArray(err.logs)
) {
return null
}
let firstMatch: RegExpExecArray | null = null
for (const logLine of err.logs) {
firstMatch = errorRe.exec(logLine)
if (firstMatch !== null) {
break
}
}
if (firstMatch === null) {
return null
}
const [programIdRaw, codeRaw] = firstMatch.slice(1)
if (programIdRaw !== PROGRAM_ID.toString()) {
return null
}
let errorCode: number
try {
errorCode = parseInt(codeRaw, 16)
} catch (parseErr) {
return null
}
return fromCode(errorCode)
}

View File

@ -1 +0,0 @@
export { readResult, ReadResultAccounts, ReadResultArgs } from "./readResult"

View File

@ -1,29 +0,0 @@
import * as borsh from "@project-serum/borsh" // eslint-disable-line @typescript-eslint/no-unused-vars
import { PublicKey, TransactionInstruction } from "@solana/web3.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import { PROGRAM_ID } from "../programId"
import * as types from "../types" // eslint-disable-line @typescript-eslint/no-unused-vars
export interface ReadResultArgs {
params: types.ReadResultParamsFields
}
export interface ReadResultAccounts {
buffer: PublicKey
}
export const layout = borsh.struct([types.ReadResultParams.layout("params")])
export function readResult(args: ReadResultArgs, accounts: ReadResultAccounts) {
const keys = [{ pubkey: accounts.buffer, isSigner: false, isWritable: false }]
const identifier = Buffer.from([130, 229, 115, 203, 180, 191, 240, 90])
const buffer = Buffer.alloc(1000)
const len = layout.encode(
{
params: types.ReadResultParams.toEncodable(args.params),
},
buffer
)
const data = Buffer.concat([identifier, buffer]).slice(0, 8 + len)
const ix = new TransactionInstruction({ keys, programId: PROGRAM_ID, data })
return ix
}

View File

@ -1,9 +0,0 @@
import { PublicKey } from "@solana/web3.js"
// Program ID passed with the cli --program-id flag when running the code generator. Do not edit, it will get overwritten.
export const PROGRAM_ID_CLI = new PublicKey(
"96punQGZDShZGkzsBa3SsfTxfUnwu4XGpzXbhF7NTgcP"
)
// This constant will not get overwritten on subsequent code generations and it's safe to modify it's value.
export const PROGRAM_ID: PublicKey = PROGRAM_ID_CLI

View File

@ -1,55 +0,0 @@
import * as borsh from "@project-serum/borsh"
export interface ReadResultParamsFields {
expectedResult: Array<number> | null
}
export interface ReadResultParamsJSON {
expectedResult: Array<number> | null
}
export class ReadResultParams {
readonly expectedResult: Array<number> | null
constructor(fields: ReadResultParamsFields) {
this.expectedResult = fields.expectedResult
}
static layout(property?: string) {
return borsh.struct(
[borsh.option(borsh.vecU8(), "expectedResult")],
property
)
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
static fromDecoded(obj: any) {
return new ReadResultParams({
expectedResult:
(obj.expectedResult && Array.from(obj.expectedResult)) || null,
})
}
static toEncodable(fields: ReadResultParamsFields) {
return {
expectedResult:
(fields.expectedResult && Buffer.from(fields.expectedResult)) || null,
}
}
toJSON(): ReadResultParamsJSON {
return {
expectedResult: this.expectedResult,
}
}
static fromJSON(obj: ReadResultParamsJSON): ReadResultParams {
return new ReadResultParams({
expectedResult: obj.expectedResult,
})
}
toEncodable() {
return ReadResultParams.toEncodable(this)
}
}

View File

@ -1,5 +0,0 @@
export {
ReadResultParams,
ReadResultParamsFields,
ReadResultParamsJSON,
} from "./ReadResultParams"

File diff suppressed because it is too large Load Diff

View File

@ -12,11 +12,11 @@
"lint": "eslint --ext .js,.json,.ts 'src/**' --fix"
},
"dependencies": {
"@project-serum/anchor": "^0.24.2",
"@solana/web3.js": "^1.42.0",
"@switchboard-xyz/common": "^2.0.0",
"@switchboard-xyz/sbv2-utils": "^0.1.43",
"@switchboard-xyz/switchboard-v2": "^0.0.135",
"@project-serum/anchor": "^0.25.0",
"@solana/web3.js": "^1.66.2",
"@switchboard-xyz/common": "^2.1.7",
"@switchboard-xyz/sbv2-utils": "^0.1.53",
"@switchboard-xyz/switchboard-v2": "^0.0.165",
"node-fetch": "^2.6"
},
"devDependencies": {

View File

@ -28,10 +28,8 @@ pub mod anchor_buffer_parser {
ctx: Context<ReadResult>,
params: ReadResultParams,
) -> anchor_lang::Result<()> {
let buffer_account = &ctx.accounts.buffer;
// load and deserialize buffer
let buffer = BufferRelayerAccountData::new(buffer_account)?;
let buffer = BufferRelayerAccountData::new(&ctx.accounts.buffer)?;
msg!("Buffer account loaded!");

View File

@ -12,8 +12,8 @@ import {
PermissionAccount,
} from "@switchboard-xyz/switchboard-v2";
import fetch from "node-fetch";
import { AnchorBufferParser, IDL } from "../target/types/anchor_buffer_parser";
import { PROGRAM_ID } from "../client/programId";
import { AnchorBufferParser, IDL } from "../target/types/anchor_buffer_parser";
describe("anchor-buffer-parser test", () => {
const provider = anchor.AnchorProvider.env();
@ -41,6 +41,7 @@ describe("anchor-buffer-parser test", () => {
return;
} catch (error: any) {
console.log(`Error: SBV2 Localnet - ${error.message}`);
console.error(error);
}
// If fails, throw error
throw new Error(

View File

@ -9,13 +9,13 @@
"noEmit": true,
"esModuleInterop": true,
"paths": {
"@switchboard-xyz/switchboard-v2": ["../../javascript/solana.js"],
"@switchboard-xyz/switchboard-v2": ["../../javascript/switchboard-v2"],
"@switchboard-xyz/sbv2-utils": ["../../javascript/sbv2-utils"]
}
},
"include": ["tests/**/*", "client/**/*", "./target/types/anchor_feed_parser"],
"references": [
{ "path": "../../javascript/solana.js" },
{ "path": "../../javascript/switchboard-v2" },
{ "path": "../../javascript/sbv2-utils" }
]
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,7 @@
.anchor
.DS_Store
target
**/*.rs.bk
node_modules
test-ledger
client/

View File

@ -3,14 +3,12 @@ members = [
"."
]
[provider]
# cluster = "devnet"
cluster = "localnet"
wallet = "../../../payer-keypair.json"
# wallet = "~/.config/solana/id.json"
[programs.localnet]
anchor_buffer_parser = "FnsPs665aBSwJRu2A8wGv6ZT76ipR41kHm4hoA3B1QGh"
anchor_feed_parser = "5cjAZXFoY4KN1Sq35ZYE72fGdVy8sy5YGpNix1N4rtHY"
[provider]
cluster = "devnet"
wallet = "~/.config/solana/id.json"
[registry]
url = "https://anchor.projectserum.com"
@ -18,9 +16,11 @@ url = "https://anchor.projectserum.com"
[scripts]
test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 ./tests/*.test.ts"
# [test.validator]
# url="https://api.devnet.solana.com"
[test.validator]
url="https://api.devnet.solana.com"
# [test]
# startup_wait = 10000
[[testnet.validator.clone]]
address="GvDMxPzN1sCj7L26YDK2HnMRXEQmQ2aemov8YBtPS7vR" # sbv2 SOL/USD Feed
# [[testnet.validator.clone]]
# address="GvDMxPzN1sCj7L26YDK2HnMRXEQmQ2aemov8YBtPS7vR" # sbv2 SOL/USD Feed

View File

@ -16,8 +16,8 @@ cpi = ["no-entrypoint"]
default = []
[dependencies]
# switchboard-v2 = { path = "../../rust/switchboard-v2", features = ["devnet"] }
switchboard-v2 = { version = "^0.1.14", features = ["devnet"] }
switchboard-v2 = { path = "../../rust/switchboard-v2", features = ["devnet"] }
# switchboard-v2 = { version = "0.1.15", features = ["devnet"] }
anchor-lang = "^0.25.0"
solana-program = "~1.10.29"
bytemuck = "1.7.2"

View File

@ -0,0 +1,8 @@
# Anchor Feed Parser
## Generate the Client
```bash
anchor build
npx anchor-client-gen target/idl/anchor_feed_parser.json client --program-id "$(solana-keygen pubkey target/deploy/anchor_feed_parser-keypair.json)"
```

View File

@ -1,70 +0,0 @@
import * as borsh from "@project-serum/borsh"; // eslint-disable-line @typescript-eslint/no-unused-vars
import { Connection, PublicKey } from "@solana/web3.js";
import { PROGRAM_ID } from "../programId";
export interface FeedClientFields {}
export interface FeedClientJSON {}
export class FeedClient {
static readonly discriminator = Buffer.from([
30, 15, 152, 236, 85, 180, 84, 151,
]);
static readonly layout = borsh.struct([]);
constructor(fields: FeedClientFields) {}
static async fetch(
c: Connection,
programId: PublicKey,
address: PublicKey
): Promise<FeedClient | null> {
const info = await c.getAccountInfo(address);
if (info === null) {
return null;
}
if (!info.owner.equals(PROGRAM_ID)) {
throw new Error("account doesn't belong to this program");
}
return this.decode(info.data);
}
static async fetchMultiple(
c: Connection,
addresses: PublicKey[]
): Promise<Array<FeedClient | null>> {
const infos = await c.getMultipleAccountsInfo(addresses);
return infos.map((info) => {
if (info === null) {
return null;
}
if (!info.owner.equals(PROGRAM_ID)) {
throw new Error("account doesn't belong to this program");
}
return this.decode(info.data);
});
}
static decode(data: Buffer): FeedClient {
if (!data.slice(0, 8).equals(FeedClient.discriminator)) {
throw new Error("invalid account discriminator");
}
const dec = FeedClient.layout.decode(data.slice(8));
return new FeedClient({});
}
toJSON(): FeedClientJSON {
return {};
}
static fromJSON(obj: FeedClientJSON): FeedClient {
return new FeedClient({});
}
}

View File

@ -1 +0,0 @@
export { FeedClient, FeedClientFields, FeedClientJSON } from "./FeedClient"

View File

@ -1,690 +0,0 @@
export type AnchorError =
| InstructionMissing
| InstructionFallbackNotFound
| InstructionDidNotDeserialize
| InstructionDidNotSerialize
| IdlInstructionStub
| IdlInstructionInvalidProgram
| ConstraintMut
| ConstraintHasOne
| ConstraintSigner
| ConstraintRaw
| ConstraintOwner
| ConstraintRentExempt
| ConstraintSeeds
| ConstraintExecutable
| ConstraintState
| ConstraintAssociated
| ConstraintAssociatedInit
| ConstraintClose
| ConstraintAddress
| ConstraintZero
| ConstraintTokenMint
| ConstraintTokenOwner
| ConstraintMintMintAuthority
| ConstraintMintFreezeAuthority
| ConstraintMintDecimals
| ConstraintSpace
| RequireViolated
| RequireEqViolated
| RequireKeysEqViolated
| RequireNeqViolated
| RequireKeysNeqViolated
| RequireGtViolated
| RequireGteViolated
| AccountDiscriminatorAlreadySet
| AccountDiscriminatorNotFound
| AccountDiscriminatorMismatch
| AccountDidNotDeserialize
| AccountDidNotSerialize
| AccountNotEnoughKeys
| AccountNotMutable
| AccountOwnedByWrongProgram
| InvalidProgramId
| InvalidProgramExecutable
| AccountNotSigner
| AccountNotSystemOwned
| AccountNotInitialized
| AccountNotProgramData
| AccountNotAssociatedTokenAccount
| AccountSysvarMismatch
| StateInvalidAddress
| DeclaredProgramIdMismatch
| Deprecated
export class InstructionMissing extends Error {
readonly code = 100
readonly name = "InstructionMissing"
readonly msg = "8 byte instruction identifier not provided"
constructor() {
super("100: 8 byte instruction identifier not provided")
}
}
export class InstructionFallbackNotFound extends Error {
readonly code = 101
readonly name = "InstructionFallbackNotFound"
readonly msg = "Fallback functions are not supported"
constructor() {
super("101: Fallback functions are not supported")
}
}
export class InstructionDidNotDeserialize extends Error {
readonly code = 102
readonly name = "InstructionDidNotDeserialize"
readonly msg = "The program could not deserialize the given instruction"
constructor() {
super("102: The program could not deserialize the given instruction")
}
}
export class InstructionDidNotSerialize extends Error {
readonly code = 103
readonly name = "InstructionDidNotSerialize"
readonly msg = "The program could not serialize the given instruction"
constructor() {
super("103: The program could not serialize the given instruction")
}
}
export class IdlInstructionStub extends Error {
readonly code = 1000
readonly name = "IdlInstructionStub"
readonly msg = "The program was compiled without idl instructions"
constructor() {
super("1000: The program was compiled without idl instructions")
}
}
export class IdlInstructionInvalidProgram extends Error {
readonly code = 1001
readonly name = "IdlInstructionInvalidProgram"
readonly msg =
"The transaction was given an invalid program for the IDL instruction"
constructor() {
super(
"1001: The transaction was given an invalid program for the IDL instruction"
)
}
}
export class ConstraintMut extends Error {
readonly code = 2000
readonly name = "ConstraintMut"
readonly msg = "A mut constraint was violated"
constructor() {
super("2000: A mut constraint was violated")
}
}
export class ConstraintHasOne extends Error {
readonly code = 2001
readonly name = "ConstraintHasOne"
readonly msg = "A has_one constraint was violated"
constructor() {
super("2001: A has_one constraint was violated")
}
}
export class ConstraintSigner extends Error {
readonly code = 2002
readonly name = "ConstraintSigner"
readonly msg = "A signer constraint was violated"
constructor() {
super("2002: A signer constraint was violated")
}
}
export class ConstraintRaw extends Error {
readonly code = 2003
readonly name = "ConstraintRaw"
readonly msg = "A raw constraint was violated"
constructor() {
super("2003: A raw constraint was violated")
}
}
export class ConstraintOwner extends Error {
readonly code = 2004
readonly name = "ConstraintOwner"
readonly msg = "An owner constraint was violated"
constructor() {
super("2004: An owner constraint was violated")
}
}
export class ConstraintRentExempt extends Error {
readonly code = 2005
readonly name = "ConstraintRentExempt"
readonly msg = "A rent exemption constraint was violated"
constructor() {
super("2005: A rent exemption constraint was violated")
}
}
export class ConstraintSeeds extends Error {
readonly code = 2006
readonly name = "ConstraintSeeds"
readonly msg = "A seeds constraint was violated"
constructor() {
super("2006: A seeds constraint was violated")
}
}
export class ConstraintExecutable extends Error {
readonly code = 2007
readonly name = "ConstraintExecutable"
readonly msg = "An executable constraint was violated"
constructor() {
super("2007: An executable constraint was violated")
}
}
export class ConstraintState extends Error {
readonly code = 2008
readonly name = "ConstraintState"
readonly msg = "A state constraint was violated"
constructor() {
super("2008: A state constraint was violated")
}
}
export class ConstraintAssociated extends Error {
readonly code = 2009
readonly name = "ConstraintAssociated"
readonly msg = "An associated constraint was violated"
constructor() {
super("2009: An associated constraint was violated")
}
}
export class ConstraintAssociatedInit extends Error {
readonly code = 2010
readonly name = "ConstraintAssociatedInit"
readonly msg = "An associated init constraint was violated"
constructor() {
super("2010: An associated init constraint was violated")
}
}
export class ConstraintClose extends Error {
readonly code = 2011
readonly name = "ConstraintClose"
readonly msg = "A close constraint was violated"
constructor() {
super("2011: A close constraint was violated")
}
}
export class ConstraintAddress extends Error {
readonly code = 2012
readonly name = "ConstraintAddress"
readonly msg = "An address constraint was violated"
constructor() {
super("2012: An address constraint was violated")
}
}
export class ConstraintZero extends Error {
readonly code = 2013
readonly name = "ConstraintZero"
readonly msg = "Expected zero account discriminant"
constructor() {
super("2013: Expected zero account discriminant")
}
}
export class ConstraintTokenMint extends Error {
readonly code = 2014
readonly name = "ConstraintTokenMint"
readonly msg = "A token mint constraint was violated"
constructor() {
super("2014: A token mint constraint was violated")
}
}
export class ConstraintTokenOwner extends Error {
readonly code = 2015
readonly name = "ConstraintTokenOwner"
readonly msg = "A token owner constraint was violated"
constructor() {
super("2015: A token owner constraint was violated")
}
}
export class ConstraintMintMintAuthority extends Error {
readonly code = 2016
readonly name = "ConstraintMintMintAuthority"
readonly msg = "A mint mint authority constraint was violated"
constructor() {
super("2016: A mint mint authority constraint was violated")
}
}
export class ConstraintMintFreezeAuthority extends Error {
readonly code = 2017
readonly name = "ConstraintMintFreezeAuthority"
readonly msg = "A mint freeze authority constraint was violated"
constructor() {
super("2017: A mint freeze authority constraint was violated")
}
}
export class ConstraintMintDecimals extends Error {
readonly code = 2018
readonly name = "ConstraintMintDecimals"
readonly msg = "A mint decimals constraint was violated"
constructor() {
super("2018: A mint decimals constraint was violated")
}
}
export class ConstraintSpace extends Error {
readonly code = 2019
readonly name = "ConstraintSpace"
readonly msg = "A space constraint was violated"
constructor() {
super("2019: A space constraint was violated")
}
}
export class RequireViolated extends Error {
readonly code = 2500
readonly name = "RequireViolated"
readonly msg = "A require expression was violated"
constructor() {
super("2500: A require expression was violated")
}
}
export class RequireEqViolated extends Error {
readonly code = 2501
readonly name = "RequireEqViolated"
readonly msg = "A require_eq expression was violated"
constructor() {
super("2501: A require_eq expression was violated")
}
}
export class RequireKeysEqViolated extends Error {
readonly code = 2502
readonly name = "RequireKeysEqViolated"
readonly msg = "A require_keys_eq expression was violated"
constructor() {
super("2502: A require_keys_eq expression was violated")
}
}
export class RequireNeqViolated extends Error {
readonly code = 2503
readonly name = "RequireNeqViolated"
readonly msg = "A require_neq expression was violated"
constructor() {
super("2503: A require_neq expression was violated")
}
}
export class RequireKeysNeqViolated extends Error {
readonly code = 2504
readonly name = "RequireKeysNeqViolated"
readonly msg = "A require_keys_neq expression was violated"
constructor() {
super("2504: A require_keys_neq expression was violated")
}
}
export class RequireGtViolated extends Error {
readonly code = 2505
readonly name = "RequireGtViolated"
readonly msg = "A require_gt expression was violated"
constructor() {
super("2505: A require_gt expression was violated")
}
}
export class RequireGteViolated extends Error {
readonly code = 2506
readonly name = "RequireGteViolated"
readonly msg = "A require_gte expression was violated"
constructor() {
super("2506: A require_gte expression was violated")
}
}
export class AccountDiscriminatorAlreadySet extends Error {
readonly code = 3000
readonly name = "AccountDiscriminatorAlreadySet"
readonly msg = "The account discriminator was already set on this account"
constructor() {
super("3000: The account discriminator was already set on this account")
}
}
export class AccountDiscriminatorNotFound extends Error {
readonly code = 3001
readonly name = "AccountDiscriminatorNotFound"
readonly msg = "No 8 byte discriminator was found on the account"
constructor() {
super("3001: No 8 byte discriminator was found on the account")
}
}
export class AccountDiscriminatorMismatch extends Error {
readonly code = 3002
readonly name = "AccountDiscriminatorMismatch"
readonly msg = "8 byte discriminator did not match what was expected"
constructor() {
super("3002: 8 byte discriminator did not match what was expected")
}
}
export class AccountDidNotDeserialize extends Error {
readonly code = 3003
readonly name = "AccountDidNotDeserialize"
readonly msg = "Failed to deserialize the account"
constructor() {
super("3003: Failed to deserialize the account")
}
}
export class AccountDidNotSerialize extends Error {
readonly code = 3004
readonly name = "AccountDidNotSerialize"
readonly msg = "Failed to serialize the account"
constructor() {
super("3004: Failed to serialize the account")
}
}
export class AccountNotEnoughKeys extends Error {
readonly code = 3005
readonly name = "AccountNotEnoughKeys"
readonly msg = "Not enough account keys given to the instruction"
constructor() {
super("3005: Not enough account keys given to the instruction")
}
}
export class AccountNotMutable extends Error {
readonly code = 3006
readonly name = "AccountNotMutable"
readonly msg = "The given account is not mutable"
constructor() {
super("3006: The given account is not mutable")
}
}
export class AccountOwnedByWrongProgram extends Error {
readonly code = 3007
readonly name = "AccountOwnedByWrongProgram"
readonly msg =
"The given account is owned by a different program than expected"
constructor() {
super(
"3007: The given account is owned by a different program than expected"
)
}
}
export class InvalidProgramId extends Error {
readonly code = 3008
readonly name = "InvalidProgramId"
readonly msg = "Program ID was not as expected"
constructor() {
super("3008: Program ID was not as expected")
}
}
export class InvalidProgramExecutable extends Error {
readonly code = 3009
readonly name = "InvalidProgramExecutable"
readonly msg = "Program account is not executable"
constructor() {
super("3009: Program account is not executable")
}
}
export class AccountNotSigner extends Error {
readonly code = 3010
readonly name = "AccountNotSigner"
readonly msg = "The given account did not sign"
constructor() {
super("3010: The given account did not sign")
}
}
export class AccountNotSystemOwned extends Error {
readonly code = 3011
readonly name = "AccountNotSystemOwned"
readonly msg = "The given account is not owned by the system program"
constructor() {
super("3011: The given account is not owned by the system program")
}
}
export class AccountNotInitialized extends Error {
readonly code = 3012
readonly name = "AccountNotInitialized"
readonly msg = "The program expected this account to be already initialized"
constructor() {
super("3012: The program expected this account to be already initialized")
}
}
export class AccountNotProgramData extends Error {
readonly code = 3013
readonly name = "AccountNotProgramData"
readonly msg = "The given account is not a program data account"
constructor() {
super("3013: The given account is not a program data account")
}
}
export class AccountNotAssociatedTokenAccount extends Error {
readonly code = 3014
readonly name = "AccountNotAssociatedTokenAccount"
readonly msg = "The given account is not the associated token account"
constructor() {
super("3014: The given account is not the associated token account")
}
}
export class AccountSysvarMismatch extends Error {
readonly code = 3015
readonly name = "AccountSysvarMismatch"
readonly msg = "The given public key does not match the required sysvar"
constructor() {
super("3015: The given public key does not match the required sysvar")
}
}
export class StateInvalidAddress extends Error {
readonly code = 4000
readonly name = "StateInvalidAddress"
readonly msg = "The given state account does not have the correct address"
constructor() {
super("4000: The given state account does not have the correct address")
}
}
export class DeclaredProgramIdMismatch extends Error {
readonly code = 4100
readonly name = "DeclaredProgramIdMismatch"
readonly msg = "The declared program id does not match the actual program id"
constructor() {
super("4100: The declared program id does not match the actual program id")
}
}
export class Deprecated extends Error {
readonly code = 5000
readonly name = "Deprecated"
readonly msg = "The API being used is deprecated and should no longer be used"
constructor() {
super("5000: The API being used is deprecated and should no longer be used")
}
}
export function fromCode(code: number): AnchorError | null {
switch (code) {
case 100:
return new InstructionMissing()
case 101:
return new InstructionFallbackNotFound()
case 102:
return new InstructionDidNotDeserialize()
case 103:
return new InstructionDidNotSerialize()
case 1000:
return new IdlInstructionStub()
case 1001:
return new IdlInstructionInvalidProgram()
case 2000:
return new ConstraintMut()
case 2001:
return new ConstraintHasOne()
case 2002:
return new ConstraintSigner()
case 2003:
return new ConstraintRaw()
case 2004:
return new ConstraintOwner()
case 2005:
return new ConstraintRentExempt()
case 2006:
return new ConstraintSeeds()
case 2007:
return new ConstraintExecutable()
case 2008:
return new ConstraintState()
case 2009:
return new ConstraintAssociated()
case 2010:
return new ConstraintAssociatedInit()
case 2011:
return new ConstraintClose()
case 2012:
return new ConstraintAddress()
case 2013:
return new ConstraintZero()
case 2014:
return new ConstraintTokenMint()
case 2015:
return new ConstraintTokenOwner()
case 2016:
return new ConstraintMintMintAuthority()
case 2017:
return new ConstraintMintFreezeAuthority()
case 2018:
return new ConstraintMintDecimals()
case 2019:
return new ConstraintSpace()
case 2500:
return new RequireViolated()
case 2501:
return new RequireEqViolated()
case 2502:
return new RequireKeysEqViolated()
case 2503:
return new RequireNeqViolated()
case 2504:
return new RequireKeysNeqViolated()
case 2505:
return new RequireGtViolated()
case 2506:
return new RequireGteViolated()
case 3000:
return new AccountDiscriminatorAlreadySet()
case 3001:
return new AccountDiscriminatorNotFound()
case 3002:
return new AccountDiscriminatorMismatch()
case 3003:
return new AccountDidNotDeserialize()
case 3004:
return new AccountDidNotSerialize()
case 3005:
return new AccountNotEnoughKeys()
case 3006:
return new AccountNotMutable()
case 3007:
return new AccountOwnedByWrongProgram()
case 3008:
return new InvalidProgramId()
case 3009:
return new InvalidProgramExecutable()
case 3010:
return new AccountNotSigner()
case 3011:
return new AccountNotSystemOwned()
case 3012:
return new AccountNotInitialized()
case 3013:
return new AccountNotProgramData()
case 3014:
return new AccountNotAssociatedTokenAccount()
case 3015:
return new AccountSysvarMismatch()
case 4000:
return new StateInvalidAddress()
case 4100:
return new DeclaredProgramIdMismatch()
case 5000:
return new Deprecated()
}
return null
}

View File

@ -1,47 +0,0 @@
export type CustomError =
| InvalidSwitchboardAccount
| StaleFeed
| ConfidenceIntervalExceeded
export class InvalidSwitchboardAccount extends Error {
readonly code = 6000
readonly name = "InvalidSwitchboardAccount"
readonly msg = "Not a valid Switchboard account"
constructor() {
super("6000: Not a valid Switchboard account")
}
}
export class StaleFeed extends Error {
readonly code = 6001
readonly name = "StaleFeed"
readonly msg = "Switchboard feed has not been updated in 5 minutes"
constructor() {
super("6001: Switchboard feed has not been updated in 5 minutes")
}
}
export class ConfidenceIntervalExceeded extends Error {
readonly code = 6002
readonly name = "ConfidenceIntervalExceeded"
readonly msg = "Switchboard feed exceeded provided confidence interval"
constructor() {
super("6002: Switchboard feed exceeded provided confidence interval")
}
}
export function fromCode(code: number): CustomError | null {
switch (code) {
case 6000:
return new InvalidSwitchboardAccount()
case 6001:
return new StaleFeed()
case 6002:
return new ConfidenceIntervalExceeded()
}
return null
}

View File

@ -1,57 +0,0 @@
import { PROGRAM_ID } from "../programId"
import * as anchor from "./anchor"
import * as custom from "./custom"
export function fromCode(
code: number
): custom.CustomError | anchor.AnchorError | null {
return code >= 6000 ? custom.fromCode(code) : anchor.fromCode(code)
}
function hasOwnProperty<X extends object, Y extends PropertyKey>(
obj: X,
prop: Y
): obj is X & Record<Y, unknown> {
return Object.hasOwnProperty.call(obj, prop)
}
const errorRe = /Program (\w+) failed: custom program error: (\w+)/
export function fromTxError(
err: unknown
): custom.CustomError | anchor.AnchorError | null {
if (
typeof err !== "object" ||
err === null ||
!hasOwnProperty(err, "logs") ||
!Array.isArray(err.logs)
) {
return null
}
let firstMatch: RegExpExecArray | null = null
for (const logLine of err.logs) {
firstMatch = errorRe.exec(logLine)
if (firstMatch !== null) {
break
}
}
if (firstMatch === null) {
return null
}
const [programIdRaw, codeRaw] = firstMatch.slice(1)
if (programIdRaw !== PROGRAM_ID.toString()) {
return null
}
let errorCode: number
try {
errorCode = parseInt(codeRaw, 16)
} catch (parseErr) {
return null
}
return fromCode(errorCode)
}

View File

@ -1,26 +0,0 @@
import { Connection, Keypair, PublicKey, Transaction } from "@solana/web3.js";
import fs from "fs";
import { readResult } from "./instructions/readResult";
async function main() {
const payer = Keypair.fromSecretKey(
new Uint8Array(JSON.parse(fs.readFileSync(process.argv[2], "utf8")))
);
const connection = new Connection(
"https://devnet.genesysgo.net",
"confirmed"
);
const ix = readResult(
{ params: { maxConfidenceInterval: null } },
{
aggregator: new PublicKey("8SXvChNYFhRq4EZuZvnhjrB3jJRQCv4k3P4W6hesH3Ee"),
}
);
const tx = new Transaction();
tx.add(ix);
tx.feePayer = payer.publicKey;
const sig = await connection.sendTransaction(tx, [payer]);
console.log(`https://explorer.solana.com/tx/${sig}?cluster=devnet`);
}
(async () => main())();

View File

@ -1 +0,0 @@
export { readResult, ReadResultAccounts, ReadResultArgs } from "./readResult"

View File

@ -1,31 +0,0 @@
import * as borsh from "@project-serum/borsh" // eslint-disable-line @typescript-eslint/no-unused-vars
import { PublicKey, TransactionInstruction } from "@solana/web3.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import { PROGRAM_ID } from "../programId"
import * as types from "../types" // eslint-disable-line @typescript-eslint/no-unused-vars
export interface ReadResultArgs {
params: types.ReadResultParamsFields
}
export interface ReadResultAccounts {
aggregator: PublicKey
}
export const layout = borsh.struct([types.ReadResultParams.layout("params")])
export function readResult(args: ReadResultArgs, accounts: ReadResultAccounts) {
const keys = [
{ pubkey: accounts.aggregator, isSigner: false, isWritable: false },
]
const identifier = Buffer.from([130, 229, 115, 203, 180, 191, 240, 90])
const buffer = Buffer.alloc(1000)
const len = layout.encode(
{
params: types.ReadResultParams.toEncodable(args.params),
},
buffer
)
const data = Buffer.concat([identifier, buffer]).slice(0, 8 + len)
const ix = new TransactionInstruction({ keys, programId: PROGRAM_ID, data })
return ix
}

View File

@ -1,14 +0,0 @@
import { PublicKey } from "@solana/web3.js"
// Program ID defined in the provided IDL. Do not edit, it will get overwritten.
export const PROGRAM_ID_IDL = new PublicKey(
"FnsPs665aBSwJRu2A8wGv6ZT76ipR41kHm4hoA3B1QGh"
)
// Program ID passed with the cli --program-id flag when running the code generator. Do not edit, it will get overwritten.
export const PROGRAM_ID_CLI = new PublicKey(
"FnsPs665aBSwJRu2A8wGv6ZT76ipR41kHm4hoA3B1QGh"
)
// This constant will not get overwritten on subsequent code generations and it's safe to modify it's value.
export const PROGRAM_ID: PublicKey = PROGRAM_ID_CLI

View File

@ -1,53 +0,0 @@
import * as borsh from "@project-serum/borsh"
export interface ReadResultParamsFields {
maxConfidenceInterval: number | null
}
export interface ReadResultParamsJSON {
maxConfidenceInterval: number | null
}
export class ReadResultParams {
readonly maxConfidenceInterval: number | null
constructor(fields: ReadResultParamsFields) {
this.maxConfidenceInterval = fields.maxConfidenceInterval
}
static layout(property?: string) {
return borsh.struct(
[borsh.option(borsh.f64(), "maxConfidenceInterval")],
property
)
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
static fromDecoded(obj: any) {
return new ReadResultParams({
maxConfidenceInterval: obj.maxConfidenceInterval,
})
}
static toEncodable(fields: ReadResultParamsFields) {
return {
maxConfidenceInterval: fields.maxConfidenceInterval,
}
}
toJSON(): ReadResultParamsJSON {
return {
maxConfidenceInterval: this.maxConfidenceInterval,
}
}
static fromJSON(obj: ReadResultParamsJSON): ReadResultParams {
return new ReadResultParams({
maxConfidenceInterval: obj.maxConfidenceInterval,
})
}
toEncodable() {
return ReadResultParams.toEncodable(this)
}
}

View File

@ -1,5 +0,0 @@
export {
ReadResultParams,
ReadResultParamsFields,
ReadResultParamsJSON,
} from "./ReadResultParams"

File diff suppressed because it is too large Load Diff

View File

@ -12,10 +12,10 @@
"lint": "eslint --ext .js,.json,.ts 'src/**' --fix"
},
"dependencies": {
"@project-serum/anchor": "^0.24.2",
"@solana/web3.js": "^1.50.1",
"@switchboard-xyz/sbv2-utils": "^0.1.43",
"@switchboard-xyz/switchboard-v2": "^0.0.135",
"@project-serum/anchor": "^0.25.0",
"@solana/web3.js": "^1.66.2",
"@switchboard-xyz/sbv2-utils": "^0.1.53",
"@switchboard-xyz/switchboard-v2": "^0.0.165",
"fs": "^0.0.1-security"
},
"devDependencies": {

View File

@ -1,19 +1,13 @@
use anchor_lang::prelude::*;
use anchor_lang::solana_program::clock;
// use anchor_lang::{Discriminator, Owner, ZeroCopy};
// use bytemuck::{Pod, Zeroable};
use std::convert::TryInto;
pub use switchboard_v2::{AggregatorAccountData, SwitchboardDecimal, SWITCHBOARD_PROGRAM_ID};
declare_id!("FnsPs665aBSwJRu2A8wGv6ZT76ipR41kHm4hoA3B1QGh");
declare_id!("5cjAZXFoY4KN1Sq35ZYE72fGdVy8sy5YGpNix1N4rtHY");
#[derive(Accounts)]
#[instruction(params: ReadResultParams)]
pub struct ReadResult<'info> {
#[account(
constraint =
*aggregator.to_account_info().owner == SWITCHBOARD_PROGRAM_ID @ FeedErrorCode::InvalidSwitchboardAccount
)]
pub aggregator: AccountLoader<'info, AggregatorAccountData>,
}

View File

@ -3,8 +3,8 @@ import { PublicKey } from "@solana/web3.js";
import { sleep, SwitchboardTestContext } from "@switchboard-xyz/sbv2-utils";
import type { AnchorWallet } from "@switchboard-xyz/switchboard-v2";
import chai from "chai";
import { AnchorFeedParser, IDL } from "../target/types/anchor_feed_parser";
import { PROGRAM_ID } from "../client/programId";
import { AnchorFeedParser, IDL } from "../target/types/anchor_feed_parser";
const expect = chai.expect;
// Anchor.toml will copy this to localnet when we start our tests
@ -31,6 +31,8 @@ describe("anchor-feed-parser test", () => {
let switchboard: SwitchboardTestContext;
let aggregatorKey: PublicKey;
console.log(`rpc: ${feedParserProgram.provider.connection.rpcEndpoint}`);
before(async () => {
try {
switchboard = await SwitchboardTestContext.loadDevnetQueue(
@ -49,7 +51,7 @@ describe("anchor-feed-parser test", () => {
it("Read SOL/USD Feed", async () => {
const signature = await feedParserProgram.methods
.readResult({ maxConfidenceInterval: 0.25 })
.readResult({ maxConfidenceInterval: null })
.accounts({ aggregator: aggregatorKey })
.rpc();

View File

@ -1,20 +1,15 @@
import * as anchor from "@project-serum/anchor";
import { Connection, PublicKey } from "@solana/web3.js";
import { Connection } from "@solana/web3.js";
import { sleep, SwitchboardTestContext } from "@switchboard-xyz/sbv2-utils";
import type {
AggregatorAccount,
AnchorWallet,
} from "@switchboard-xyz/switchboard-v2";
import chai from "chai";
import { AnchorFeedParser, IDL } from "../target/types/anchor_feed_parser";
import { PROGRAM_ID } from "../client/programId";
import { AnchorFeedParser, IDL } from "../target/types/anchor_feed_parser";
const expect = chai.expect;
// Anchor.toml will copy this to localnet when we start our tests
const DEFAULT_SOL_USD_FEED = new PublicKey(
"GvDMxPzN1sCj7L26YDK2HnMRXEQmQ2aemov8YBtPS7vR"
);
describe("anchor-feed-parser test", () => {
const tomlProvider = anchor.AnchorProvider.env();
const provider = new anchor.AnchorProvider(

View File

@ -6,13 +6,13 @@
"noEmit": true,
"esModuleInterop": true,
"paths": {
"@switchboard-xyz/switchboard-v2": ["../../javascript/solana.js"],
"@switchboard-xyz/switchboard-v2": ["../../javascript/switchboard-v2"],
"@switchboard-xyz/sbv2-utils": ["../../javascript/sbv2-utils"]
}
},
"include": ["tests/**/*", "client/**/*", "./target/types/anchor_feed_parser"],
"references": [
{ "path": "../../javascript/solana.js" },
{ "path": "../../javascript/switchboard-v2" },
{ "path": "../../javascript/sbv2-utils" }
]
}

File diff suppressed because it is too large Load Diff

View File

@ -5,3 +5,4 @@ target
**/*.rs.bk
node_modules
test-ledger
client/

View File

@ -20,6 +20,6 @@ overflow-checks = true
[dependencies]
# switchboard-v2 = { path = "../../rust/switchboard-v2", features = ["devnet"] }
switchboard-v2 = { version = "^0.1.14", features = ["devnet"] }
switchboard-v2 = { version = "^0.1.16", features = ["devnet"] }
anchor-lang = "0.25.0"
solana-program = "~1.10.29"

File diff suppressed because it is too large Load Diff

View File

@ -1,22 +1,22 @@
{
"scripts": {
"lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w",
"lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check"
},
"dependencies": {
"@project-serum/anchor": "^0.25.0",
"@switchboard-xyz/common": "^2.0.3",
"@switchboard-xyz/sbv2-utils": "^0.1.49",
"@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"
}
"scripts": {
"lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w",
"lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check"
},
"dependencies": {
"@project-serum/anchor": "^0.25.0",
"@switchboard-xyz/common": "^2.1.7",
"@switchboard-xyz/sbv2-utils": "^0.1.53",
"@switchboard-xyz/switchboard-v2": "^0.0.165"
},
"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"
}
}

View File

@ -1,8 +1,8 @@
use anchor_lang::prelude::*;
use std::convert::TryInto;
pub use switchboard_v2::{
AggregatorAccountData, AggregatorHistoryBuffer, SwitchboardDecimal, SWITCHBOARD_PROGRAM_ID,
};
use std::convert::TryInto;
declare_id!("C7rn1qJkq9FjTwV86RrY5Uih91NgymRVLdJ81rqLNXRS");
@ -10,16 +10,10 @@ declare_id!("C7rn1qJkq9FjTwV86RrY5Uih91NgymRVLdJ81rqLNXRS");
#[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
has_one = history_buffer @ ErrorCode::InvalidHistoryBuffer
)]
pub aggregator: AccountLoader<'info, AggregatorAccountData>,
/// CHECK: Verified by aggregator.history_buffer
#[account(
constraint =
*aggregator.to_account_info().owner == SWITCHBOARD_PROGRAM_ID @ ErrorCode::InvalidSwitchboardAccount
)]
/// CHECK: verified in the aggregator has_one check
pub history_buffer: AccountInfo<'info>,
}
@ -36,17 +30,6 @@ pub mod anchor_history_parser {
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;
@ -57,8 +40,13 @@ pub mod anchor_history_parser {
timestamp = Clock::get()?.unix_timestamp - 3600;
}
let value_at_timestamp: f64 = history_buffer.lower_bound(timestamp).unwrap().value.try_into()?;
let value_at_timestamp: f64 = history_buffer
.lower_bound(timestamp)
.unwrap()
.value
.try_into()?;
msg!("Result {:?}!", value_at_timestamp);
Ok(())
}
}

View File

@ -8,7 +8,7 @@
"target": "es6",
"esModuleInterop": true,
"paths": {
"@switchboard-xyz/switchboard-v2": ["../../javascript/solana.js"],
"@switchboard-xyz/switchboard-v2": ["../../javascript/switchboard-v2"],
"@switchboard-xyz/sbv2-utils": ["../../javascript/sbv2-utils"]
}
},
@ -18,7 +18,7 @@
"./target/types/anchor_history_parser"
],
"references": [
{ "path": "../../javascript/solana.js" },
{ "path": "../../javascript/switchboard-v2" },
{ "path": "../../javascript/sbv2-utils" }
]
}

File diff suppressed because it is too large Load Diff

8
programs/anchor-vrf-parser/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
.anchor
.DS_Store
target
**/*.rs.bk
node_modules
test-ledger
client/

View File

@ -4,13 +4,12 @@ members = [
]
[provider]
# cluster = "devnet"
cluster = "localnet"
wallet = "../../../payer-keypair.json"
# wallet = "~/.config/solana/id.json"
cluster = "devnet"
# cluster = "localnet"
wallet = "~/.config/solana/id.json"
[programs.localnet]
anchor_buffer_parser = "HjjRFjCyQH3ne6Gg8Yn3TQafrrYecRrphwLwnh2A26vM"
anchor_vrf_parser = "HjjRFjCyQH3ne6Gg8Yn3TQafrrYecRrphwLwnh2A26vM"
[registry]
url = "https://anchor.projectserum.com"
@ -18,7 +17,6 @@ url = "https://anchor.projectserum.com"
[scripts]
test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 ./tests/*.test.ts"
[test.validator]
url="https://api.devnet.solana.com"

View File

@ -17,7 +17,7 @@ default = []
[dependencies]
# switchboard-v2 = { path = "../../rust/switchboard-v2", features = ["devnet"] }
switchboard-v2 = { version = "^0.1.14", features = ["devnet"] }
switchboard-v2 = { version = "^0.1.16", features = ["devnet"] }
anchor-lang = "^0.25.0"
anchor-spl = "^0.25.0"
solana-program = "~1.10.29"

View File

@ -4,7 +4,8 @@
/* eslint-disable @typescript-eslint/no-var-requires */
import * as anchor from "@project-serum/anchor";
import * as spl from "@solana/spl-token-v2";
import type {
import {
clusterApiUrl,
Connection,
ParsedTransactionWithMeta,
PublicKey,
@ -19,12 +20,12 @@ const { hideBin } = require("yargs/helpers");
// import { hideBin } from "yargs/helpers";
import fs from "fs";
import path from "path";
import { AnchorVrfParser, IDL } from "../../../target/types/anchor_vrf_parser";
import { AnchorVrfParser, IDL } from "./target/types/anchor_vrf_parser";
import { VrfClient } from "./client/accounts";
import { PROGRAM_ID } from "./client/programId";
const DEFAULT_MAINNET_RPC = "https://ssc-dao.genesysgo.net";
const DEFAULT_DEVNET_RPC = "https://devnet.genesysgo.net";
// const DEFAULT_MAINNET_RPC = "https://ssc-dao.genesysgo.net";
// const DEFAULT_DEVNET_RPC = "https://devnet.genesysgo.net";
const DEFAULT_LOCALNET_RPC = "http://localhost:8899";
const DEFAULT_COMMITMENT = "confirmed";
@ -178,10 +179,11 @@ yargs(hideBin(process.argv))
}
const { vrfClientProgram, switchboardProgram, payer, provider } =
await loadCli(rpcUrl as string, cluster as string);
await loadCli((rpcUrl as string) ?? "", (cluster as string) ?? "");
const vrfClient = await VrfClient.fetch(
provider.connection,
vrfClientProgram.programId,
new anchor.web3.PublicKey(vrfClientKey)
);
if (!vrfClient) {
@ -353,6 +355,7 @@ yargs(hideBin(process.argv))
const vrfClient = await VrfClient.fetch(
provider.connection,
vrfClientProgram.programId,
vrfClientPubkey
);
if (!vrfClient) {
@ -440,8 +443,7 @@ yargs(hideBin(process.argv))
let successes = 0;
let failures = 0;
try {
for await (const i of [...Array(numLoops).keys()]) {
writeStatus(i, numLoops, successes, failures);
for await (const i of Array.from(Array(numLoops).keys())) {
let success = false;
try {
while (true) {
@ -460,10 +462,13 @@ yargs(hideBin(process.argv))
}
}
await awaitCallback(provider.connection, vrfClientPubkey, 45_000)
await awaitCallback(provider.connection, vrfClientPubkey, 90_000)
.then(() => {
success = true;
successes++;
clearStatus();
writeStatus(i, numLoops, successes, failures);
})
.catch(async (error) => {
failures++;
@ -506,11 +511,11 @@ yargs(hideBin(process.argv))
15
),
};
results.push(result);
saveResults(startTime, vrfClientKey, results);
clearStatus();
writeStatus(i, numLoops, successes, failures);
}
} catch (error) {
console.error(`GLOBAL: ${error}`);
@ -543,9 +548,9 @@ yargs(hideBin(process.argv))
function getRpcUrl(cluster: string): string {
switch (cluster) {
case "mainnet-beta":
return DEFAULT_MAINNET_RPC;
return clusterApiUrl("mainnet-beta");
case "devnet":
return DEFAULT_DEVNET_RPC;
return clusterApiUrl("devnet");
case "localnet":
return DEFAULT_LOCALNET_RPC;
default:

View File

@ -1,135 +0,0 @@
import * as borsh from "@project-serum/borsh"; // eslint-disable-line @typescript-eslint/no-unused-vars
import { Connection, PublicKey } from "@solana/web3.js";
import BN from "bn.js"; // eslint-disable-line @typescript-eslint/no-unused-vars
import { PROGRAM_ID } from "../programId";
export interface VrfClientFields {
bump: number;
maxResult: BN;
resultBuffer: Array<number>;
result: BN;
lastTimestamp: BN;
authority: PublicKey;
vrf: PublicKey;
}
export interface VrfClientJSON {
bump: number;
maxResult: string;
resultBuffer: Array<number>;
result: string;
lastTimestamp: string;
authority: string;
vrf: string;
}
export class VrfClient {
readonly bump: number;
readonly maxResult: BN;
readonly resultBuffer: Array<number>;
readonly result: BN;
readonly lastTimestamp: BN;
readonly authority: PublicKey;
readonly vrf: PublicKey;
static readonly discriminator = Buffer.from([
230, 174, 157, 153, 51, 18, 230, 163,
]);
static readonly layout = borsh.struct([
borsh.u8("bump"),
borsh.u64("maxResult"),
borsh.array(borsh.u8(), 32, "resultBuffer"),
borsh.u128("result"),
borsh.i64("lastTimestamp"),
borsh.publicKey("authority"),
borsh.publicKey("vrf"),
]);
constructor(fields: VrfClientFields) {
this.bump = fields.bump;
this.maxResult = fields.maxResult;
this.resultBuffer = fields.resultBuffer;
this.result = fields.result;
this.lastTimestamp = fields.lastTimestamp;
this.authority = fields.authority;
this.vrf = fields.vrf;
}
static async fetch(
c: Connection,
programId: PublicKey,
address: PublicKey
): Promise<VrfClient | null> {
const info = await c.getAccountInfo(address);
if (info === null) {
return null;
}
if (!info.owner.equals(PROGRAM_ID)) {
throw new Error("account doesn't belong to this program");
}
return this.decode(info.data);
}
static async fetchMultiple(
c: Connection,
addresses: PublicKey[]
): Promise<Array<VrfClient | null>> {
const infos = await c.getMultipleAccountsInfo(addresses);
return infos.map((info) => {
if (info === null) {
return null;
}
if (!info.owner.equals(PROGRAM_ID)) {
throw new Error("account doesn't belong to this program");
}
return this.decode(info.data);
});
}
static decode(data: Buffer): VrfClient {
if (!data.slice(0, 8).equals(VrfClient.discriminator)) {
throw new Error("invalid account discriminator");
}
const dec = VrfClient.layout.decode(data.slice(8));
return new VrfClient({
bump: dec.bump,
maxResult: dec.maxResult,
resultBuffer: dec.resultBuffer,
result: dec.result,
lastTimestamp: dec.lastTimestamp,
authority: dec.authority,
vrf: dec.vrf,
});
}
toJSON(): VrfClientJSON {
return {
bump: this.bump,
maxResult: this.maxResult.toString(),
resultBuffer: this.resultBuffer,
result: this.result.toString(),
lastTimestamp: this.lastTimestamp.toString(),
authority: this.authority.toString(),
vrf: this.vrf.toString(),
};
}
static fromJSON(obj: VrfClientJSON): VrfClient {
return new VrfClient({
bump: obj.bump,
maxResult: new BN(obj.maxResult),
resultBuffer: obj.resultBuffer,
result: new BN(obj.result),
lastTimestamp: new BN(obj.lastTimestamp),
authority: new PublicKey(obj.authority),
vrf: new PublicKey(obj.vrf),
});
}
}

View File

@ -1 +0,0 @@
export { VrfClient, VrfClientFields, VrfClientJSON } from "./VrfClient"

View File

@ -1,690 +0,0 @@
export type AnchorError =
| InstructionMissing
| InstructionFallbackNotFound
| InstructionDidNotDeserialize
| InstructionDidNotSerialize
| IdlInstructionStub
| IdlInstructionInvalidProgram
| ConstraintMut
| ConstraintHasOne
| ConstraintSigner
| ConstraintRaw
| ConstraintOwner
| ConstraintRentExempt
| ConstraintSeeds
| ConstraintExecutable
| ConstraintState
| ConstraintAssociated
| ConstraintAssociatedInit
| ConstraintClose
| ConstraintAddress
| ConstraintZero
| ConstraintTokenMint
| ConstraintTokenOwner
| ConstraintMintMintAuthority
| ConstraintMintFreezeAuthority
| ConstraintMintDecimals
| ConstraintSpace
| RequireViolated
| RequireEqViolated
| RequireKeysEqViolated
| RequireNeqViolated
| RequireKeysNeqViolated
| RequireGtViolated
| RequireGteViolated
| AccountDiscriminatorAlreadySet
| AccountDiscriminatorNotFound
| AccountDiscriminatorMismatch
| AccountDidNotDeserialize
| AccountDidNotSerialize
| AccountNotEnoughKeys
| AccountNotMutable
| AccountOwnedByWrongProgram
| InvalidProgramId
| InvalidProgramExecutable
| AccountNotSigner
| AccountNotSystemOwned
| AccountNotInitialized
| AccountNotProgramData
| AccountNotAssociatedTokenAccount
| AccountSysvarMismatch
| StateInvalidAddress
| DeclaredProgramIdMismatch
| Deprecated
export class InstructionMissing extends Error {
readonly code = 100
readonly name = "InstructionMissing"
readonly msg = "8 byte instruction identifier not provided"
constructor() {
super("100: 8 byte instruction identifier not provided")
}
}
export class InstructionFallbackNotFound extends Error {
readonly code = 101
readonly name = "InstructionFallbackNotFound"
readonly msg = "Fallback functions are not supported"
constructor() {
super("101: Fallback functions are not supported")
}
}
export class InstructionDidNotDeserialize extends Error {
readonly code = 102
readonly name = "InstructionDidNotDeserialize"
readonly msg = "The program could not deserialize the given instruction"
constructor() {
super("102: The program could not deserialize the given instruction")
}
}
export class InstructionDidNotSerialize extends Error {
readonly code = 103
readonly name = "InstructionDidNotSerialize"
readonly msg = "The program could not serialize the given instruction"
constructor() {
super("103: The program could not serialize the given instruction")
}
}
export class IdlInstructionStub extends Error {
readonly code = 1000
readonly name = "IdlInstructionStub"
readonly msg = "The program was compiled without idl instructions"
constructor() {
super("1000: The program was compiled without idl instructions")
}
}
export class IdlInstructionInvalidProgram extends Error {
readonly code = 1001
readonly name = "IdlInstructionInvalidProgram"
readonly msg =
"The transaction was given an invalid program for the IDL instruction"
constructor() {
super(
"1001: The transaction was given an invalid program for the IDL instruction"
)
}
}
export class ConstraintMut extends Error {
readonly code = 2000
readonly name = "ConstraintMut"
readonly msg = "A mut constraint was violated"
constructor() {
super("2000: A mut constraint was violated")
}
}
export class ConstraintHasOne extends Error {
readonly code = 2001
readonly name = "ConstraintHasOne"
readonly msg = "A has_one constraint was violated"
constructor() {
super("2001: A has_one constraint was violated")
}
}
export class ConstraintSigner extends Error {
readonly code = 2002
readonly name = "ConstraintSigner"
readonly msg = "A signer constraint was violated"
constructor() {
super("2002: A signer constraint was violated")
}
}
export class ConstraintRaw extends Error {
readonly code = 2003
readonly name = "ConstraintRaw"
readonly msg = "A raw constraint was violated"
constructor() {
super("2003: A raw constraint was violated")
}
}
export class ConstraintOwner extends Error {
readonly code = 2004
readonly name = "ConstraintOwner"
readonly msg = "An owner constraint was violated"
constructor() {
super("2004: An owner constraint was violated")
}
}
export class ConstraintRentExempt extends Error {
readonly code = 2005
readonly name = "ConstraintRentExempt"
readonly msg = "A rent exemption constraint was violated"
constructor() {
super("2005: A rent exemption constraint was violated")
}
}
export class ConstraintSeeds extends Error {
readonly code = 2006
readonly name = "ConstraintSeeds"
readonly msg = "A seeds constraint was violated"
constructor() {
super("2006: A seeds constraint was violated")
}
}
export class ConstraintExecutable extends Error {
readonly code = 2007
readonly name = "ConstraintExecutable"
readonly msg = "An executable constraint was violated"
constructor() {
super("2007: An executable constraint was violated")
}
}
export class ConstraintState extends Error {
readonly code = 2008
readonly name = "ConstraintState"
readonly msg = "A state constraint was violated"
constructor() {
super("2008: A state constraint was violated")
}
}
export class ConstraintAssociated extends Error {
readonly code = 2009
readonly name = "ConstraintAssociated"
readonly msg = "An associated constraint was violated"
constructor() {
super("2009: An associated constraint was violated")
}
}
export class ConstraintAssociatedInit extends Error {
readonly code = 2010
readonly name = "ConstraintAssociatedInit"
readonly msg = "An associated init constraint was violated"
constructor() {
super("2010: An associated init constraint was violated")
}
}
export class ConstraintClose extends Error {
readonly code = 2011
readonly name = "ConstraintClose"
readonly msg = "A close constraint was violated"
constructor() {
super("2011: A close constraint was violated")
}
}
export class ConstraintAddress extends Error {
readonly code = 2012
readonly name = "ConstraintAddress"
readonly msg = "An address constraint was violated"
constructor() {
super("2012: An address constraint was violated")
}
}
export class ConstraintZero extends Error {
readonly code = 2013
readonly name = "ConstraintZero"
readonly msg = "Expected zero account discriminant"
constructor() {
super("2013: Expected zero account discriminant")
}
}
export class ConstraintTokenMint extends Error {
readonly code = 2014
readonly name = "ConstraintTokenMint"
readonly msg = "A token mint constraint was violated"
constructor() {
super("2014: A token mint constraint was violated")
}
}
export class ConstraintTokenOwner extends Error {
readonly code = 2015
readonly name = "ConstraintTokenOwner"
readonly msg = "A token owner constraint was violated"
constructor() {
super("2015: A token owner constraint was violated")
}
}
export class ConstraintMintMintAuthority extends Error {
readonly code = 2016
readonly name = "ConstraintMintMintAuthority"
readonly msg = "A mint mint authority constraint was violated"
constructor() {
super("2016: A mint mint authority constraint was violated")
}
}
export class ConstraintMintFreezeAuthority extends Error {
readonly code = 2017
readonly name = "ConstraintMintFreezeAuthority"
readonly msg = "A mint freeze authority constraint was violated"
constructor() {
super("2017: A mint freeze authority constraint was violated")
}
}
export class ConstraintMintDecimals extends Error {
readonly code = 2018
readonly name = "ConstraintMintDecimals"
readonly msg = "A mint decimals constraint was violated"
constructor() {
super("2018: A mint decimals constraint was violated")
}
}
export class ConstraintSpace extends Error {
readonly code = 2019
readonly name = "ConstraintSpace"
readonly msg = "A space constraint was violated"
constructor() {
super("2019: A space constraint was violated")
}
}
export class RequireViolated extends Error {
readonly code = 2500
readonly name = "RequireViolated"
readonly msg = "A require expression was violated"
constructor() {
super("2500: A require expression was violated")
}
}
export class RequireEqViolated extends Error {
readonly code = 2501
readonly name = "RequireEqViolated"
readonly msg = "A require_eq expression was violated"
constructor() {
super("2501: A require_eq expression was violated")
}
}
export class RequireKeysEqViolated extends Error {
readonly code = 2502
readonly name = "RequireKeysEqViolated"
readonly msg = "A require_keys_eq expression was violated"
constructor() {
super("2502: A require_keys_eq expression was violated")
}
}
export class RequireNeqViolated extends Error {
readonly code = 2503
readonly name = "RequireNeqViolated"
readonly msg = "A require_neq expression was violated"
constructor() {
super("2503: A require_neq expression was violated")
}
}
export class RequireKeysNeqViolated extends Error {
readonly code = 2504
readonly name = "RequireKeysNeqViolated"
readonly msg = "A require_keys_neq expression was violated"
constructor() {
super("2504: A require_keys_neq expression was violated")
}
}
export class RequireGtViolated extends Error {
readonly code = 2505
readonly name = "RequireGtViolated"
readonly msg = "A require_gt expression was violated"
constructor() {
super("2505: A require_gt expression was violated")
}
}
export class RequireGteViolated extends Error {
readonly code = 2506
readonly name = "RequireGteViolated"
readonly msg = "A require_gte expression was violated"
constructor() {
super("2506: A require_gte expression was violated")
}
}
export class AccountDiscriminatorAlreadySet extends Error {
readonly code = 3000
readonly name = "AccountDiscriminatorAlreadySet"
readonly msg = "The account discriminator was already set on this account"
constructor() {
super("3000: The account discriminator was already set on this account")
}
}
export class AccountDiscriminatorNotFound extends Error {
readonly code = 3001
readonly name = "AccountDiscriminatorNotFound"
readonly msg = "No 8 byte discriminator was found on the account"
constructor() {
super("3001: No 8 byte discriminator was found on the account")
}
}
export class AccountDiscriminatorMismatch extends Error {
readonly code = 3002
readonly name = "AccountDiscriminatorMismatch"
readonly msg = "8 byte discriminator did not match what was expected"
constructor() {
super("3002: 8 byte discriminator did not match what was expected")
}
}
export class AccountDidNotDeserialize extends Error {
readonly code = 3003
readonly name = "AccountDidNotDeserialize"
readonly msg = "Failed to deserialize the account"
constructor() {
super("3003: Failed to deserialize the account")
}
}
export class AccountDidNotSerialize extends Error {
readonly code = 3004
readonly name = "AccountDidNotSerialize"
readonly msg = "Failed to serialize the account"
constructor() {
super("3004: Failed to serialize the account")
}
}
export class AccountNotEnoughKeys extends Error {
readonly code = 3005
readonly name = "AccountNotEnoughKeys"
readonly msg = "Not enough account keys given to the instruction"
constructor() {
super("3005: Not enough account keys given to the instruction")
}
}
export class AccountNotMutable extends Error {
readonly code = 3006
readonly name = "AccountNotMutable"
readonly msg = "The given account is not mutable"
constructor() {
super("3006: The given account is not mutable")
}
}
export class AccountOwnedByWrongProgram extends Error {
readonly code = 3007
readonly name = "AccountOwnedByWrongProgram"
readonly msg =
"The given account is owned by a different program than expected"
constructor() {
super(
"3007: The given account is owned by a different program than expected"
)
}
}
export class InvalidProgramId extends Error {
readonly code = 3008
readonly name = "InvalidProgramId"
readonly msg = "Program ID was not as expected"
constructor() {
super("3008: Program ID was not as expected")
}
}
export class InvalidProgramExecutable extends Error {
readonly code = 3009
readonly name = "InvalidProgramExecutable"
readonly msg = "Program account is not executable"
constructor() {
super("3009: Program account is not executable")
}
}
export class AccountNotSigner extends Error {
readonly code = 3010
readonly name = "AccountNotSigner"
readonly msg = "The given account did not sign"
constructor() {
super("3010: The given account did not sign")
}
}
export class AccountNotSystemOwned extends Error {
readonly code = 3011
readonly name = "AccountNotSystemOwned"
readonly msg = "The given account is not owned by the system program"
constructor() {
super("3011: The given account is not owned by the system program")
}
}
export class AccountNotInitialized extends Error {
readonly code = 3012
readonly name = "AccountNotInitialized"
readonly msg = "The program expected this account to be already initialized"
constructor() {
super("3012: The program expected this account to be already initialized")
}
}
export class AccountNotProgramData extends Error {
readonly code = 3013
readonly name = "AccountNotProgramData"
readonly msg = "The given account is not a program data account"
constructor() {
super("3013: The given account is not a program data account")
}
}
export class AccountNotAssociatedTokenAccount extends Error {
readonly code = 3014
readonly name = "AccountNotAssociatedTokenAccount"
readonly msg = "The given account is not the associated token account"
constructor() {
super("3014: The given account is not the associated token account")
}
}
export class AccountSysvarMismatch extends Error {
readonly code = 3015
readonly name = "AccountSysvarMismatch"
readonly msg = "The given public key does not match the required sysvar"
constructor() {
super("3015: The given public key does not match the required sysvar")
}
}
export class StateInvalidAddress extends Error {
readonly code = 4000
readonly name = "StateInvalidAddress"
readonly msg = "The given state account does not have the correct address"
constructor() {
super("4000: The given state account does not have the correct address")
}
}
export class DeclaredProgramIdMismatch extends Error {
readonly code = 4100
readonly name = "DeclaredProgramIdMismatch"
readonly msg = "The declared program id does not match the actual program id"
constructor() {
super("4100: The declared program id does not match the actual program id")
}
}
export class Deprecated extends Error {
readonly code = 5000
readonly name = "Deprecated"
readonly msg = "The API being used is deprecated and should no longer be used"
constructor() {
super("5000: The API being used is deprecated and should no longer be used")
}
}
export function fromCode(code: number): AnchorError | null {
switch (code) {
case 100:
return new InstructionMissing()
case 101:
return new InstructionFallbackNotFound()
case 102:
return new InstructionDidNotDeserialize()
case 103:
return new InstructionDidNotSerialize()
case 1000:
return new IdlInstructionStub()
case 1001:
return new IdlInstructionInvalidProgram()
case 2000:
return new ConstraintMut()
case 2001:
return new ConstraintHasOne()
case 2002:
return new ConstraintSigner()
case 2003:
return new ConstraintRaw()
case 2004:
return new ConstraintOwner()
case 2005:
return new ConstraintRentExempt()
case 2006:
return new ConstraintSeeds()
case 2007:
return new ConstraintExecutable()
case 2008:
return new ConstraintState()
case 2009:
return new ConstraintAssociated()
case 2010:
return new ConstraintAssociatedInit()
case 2011:
return new ConstraintClose()
case 2012:
return new ConstraintAddress()
case 2013:
return new ConstraintZero()
case 2014:
return new ConstraintTokenMint()
case 2015:
return new ConstraintTokenOwner()
case 2016:
return new ConstraintMintMintAuthority()
case 2017:
return new ConstraintMintFreezeAuthority()
case 2018:
return new ConstraintMintDecimals()
case 2019:
return new ConstraintSpace()
case 2500:
return new RequireViolated()
case 2501:
return new RequireEqViolated()
case 2502:
return new RequireKeysEqViolated()
case 2503:
return new RequireNeqViolated()
case 2504:
return new RequireKeysNeqViolated()
case 2505:
return new RequireGtViolated()
case 2506:
return new RequireGteViolated()
case 3000:
return new AccountDiscriminatorAlreadySet()
case 3001:
return new AccountDiscriminatorNotFound()
case 3002:
return new AccountDiscriminatorMismatch()
case 3003:
return new AccountDidNotDeserialize()
case 3004:
return new AccountDidNotSerialize()
case 3005:
return new AccountNotEnoughKeys()
case 3006:
return new AccountNotMutable()
case 3007:
return new AccountOwnedByWrongProgram()
case 3008:
return new InvalidProgramId()
case 3009:
return new InvalidProgramExecutable()
case 3010:
return new AccountNotSigner()
case 3011:
return new AccountNotSystemOwned()
case 3012:
return new AccountNotInitialized()
case 3013:
return new AccountNotProgramData()
case 3014:
return new AccountNotAssociatedTokenAccount()
case 3015:
return new AccountSysvarMismatch()
case 4000:
return new StateInvalidAddress()
case 4100:
return new DeclaredProgramIdMismatch()
case 5000:
return new Deprecated()
}
return null
}

View File

@ -1,60 +0,0 @@
export type CustomError =
| InvalidSwitchboardVrfAccount
| MaxResultExceedsMaximum
| EmptyCurrentRoundResult
| InvalidAuthorityError
export class InvalidSwitchboardVrfAccount extends Error {
readonly code = 6000
readonly name = "InvalidSwitchboardVrfAccount"
readonly msg = "Not a valid Switchboard VRF account"
constructor() {
super("6000: Not a valid Switchboard VRF account")
}
}
export class MaxResultExceedsMaximum extends Error {
readonly code = 6001
readonly name = "MaxResultExceedsMaximum"
readonly msg = "The max result must not exceed u64"
constructor() {
super("6001: The max result must not exceed u64")
}
}
export class EmptyCurrentRoundResult extends Error {
readonly code = 6002
readonly name = "EmptyCurrentRoundResult"
readonly msg = "Current round result is empty"
constructor() {
super("6002: Current round result is empty")
}
}
export class InvalidAuthorityError extends Error {
readonly code = 6003
readonly name = "InvalidAuthorityError"
readonly msg = "Invalid authority account provided."
constructor() {
super("6003: Invalid authority account provided.")
}
}
export function fromCode(code: number): CustomError | null {
switch (code) {
case 6000:
return new InvalidSwitchboardVrfAccount()
case 6001:
return new MaxResultExceedsMaximum()
case 6002:
return new EmptyCurrentRoundResult()
case 6003:
return new InvalidAuthorityError()
}
return null
}

View File

@ -1,57 +0,0 @@
import { PROGRAM_ID } from "../programId"
import * as anchor from "./anchor"
import * as custom from "./custom"
export function fromCode(
code: number
): custom.CustomError | anchor.AnchorError | null {
return code >= 6000 ? custom.fromCode(code) : anchor.fromCode(code)
}
function hasOwnProperty<X extends object, Y extends PropertyKey>(
obj: X,
prop: Y
): obj is X & Record<Y, unknown> {
return Object.hasOwnProperty.call(obj, prop)
}
const errorRe = /Program (\w+) failed: custom program error: (\w+)/
export function fromTxError(
err: unknown
): custom.CustomError | anchor.AnchorError | null {
if (
typeof err !== "object" ||
err === null ||
!hasOwnProperty(err, "logs") ||
!Array.isArray(err.logs)
) {
return null
}
let firstMatch: RegExpExecArray | null = null
for (const logLine of err.logs) {
firstMatch = errorRe.exec(logLine)
if (firstMatch !== null) {
break
}
}
if (firstMatch === null) {
return null
}
const [programIdRaw, codeRaw] = firstMatch.slice(1)
if (programIdRaw !== PROGRAM_ID.toString()) {
return null
}
let errorCode: number
try {
errorCode = parseInt(codeRaw, 16)
} catch (parseErr) {
return null
}
return fromCode(errorCode)
}

View File

@ -1,7 +0,0 @@
export { initState, InitStateAccounts, InitStateArgs } from "./initState"
export {
requestResult,
RequestResultAccounts,
RequestResultArgs,
} from "./requestResult"
export { updateResult, UpdateResultAccounts } from "./updateResult"

View File

@ -1,39 +0,0 @@
import * as borsh from "@project-serum/borsh" // eslint-disable-line @typescript-eslint/no-unused-vars
import { PublicKey, TransactionInstruction } from "@solana/web3.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import { PROGRAM_ID } from "../programId"
import * as types from "../types" // eslint-disable-line @typescript-eslint/no-unused-vars
export interface InitStateArgs {
params: types.InitStateParamsFields
}
export interface InitStateAccounts {
state: PublicKey
authority: PublicKey
payer: PublicKey
vrf: PublicKey
systemProgram: PublicKey
}
export const layout = borsh.struct([types.InitStateParams.layout("params")])
export function initState(args: InitStateArgs, accounts: InitStateAccounts) {
const keys = [
{ pubkey: accounts.state, isSigner: false, isWritable: true },
{ pubkey: accounts.authority, isSigner: false, isWritable: false },
{ pubkey: accounts.payer, isSigner: true, isWritable: true },
{ pubkey: accounts.vrf, isSigner: false, isWritable: false },
{ pubkey: accounts.systemProgram, isSigner: false, isWritable: false },
]
const identifier = Buffer.from([124, 213, 73, 136, 80, 37, 141, 54])
const buffer = Buffer.alloc(1000)
const len = layout.encode(
{
params: types.InitStateParams.toEncodable(args.params),
},
buffer
)
const data = Buffer.concat([identifier, buffer]).slice(0, 8 + len)
const ix = new TransactionInstruction({ keys, programId: PROGRAM_ID, data })
return ix
}

View File

@ -1,60 +0,0 @@
import * as borsh from "@project-serum/borsh" // eslint-disable-line @typescript-eslint/no-unused-vars
import { PublicKey, TransactionInstruction } from "@solana/web3.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import { PROGRAM_ID } from "../programId"
import * as types from "../types" // eslint-disable-line @typescript-eslint/no-unused-vars
export interface RequestResultArgs {
params: types.RequestResultParamsFields
}
export interface RequestResultAccounts {
state: PublicKey
authority: PublicKey
switchboardProgram: PublicKey
vrf: PublicKey
oracleQueue: PublicKey
queueAuthority: PublicKey
dataBuffer: PublicKey
permission: PublicKey
escrow: PublicKey
payerWallet: PublicKey
payerAuthority: PublicKey
recentBlockhashes: PublicKey
programState: PublicKey
tokenProgram: PublicKey
}
export const layout = borsh.struct([types.RequestResultParams.layout("params")])
export function requestResult(
args: RequestResultArgs,
accounts: RequestResultAccounts
) {
const keys = [
{ pubkey: accounts.state, isSigner: false, isWritable: true },
{ pubkey: accounts.authority, isSigner: true, isWritable: false },
{ pubkey: accounts.switchboardProgram, isSigner: false, isWritable: false },
{ pubkey: accounts.vrf, isSigner: false, isWritable: true },
{ pubkey: accounts.oracleQueue, isSigner: false, isWritable: true },
{ pubkey: accounts.queueAuthority, isSigner: false, isWritable: false },
{ pubkey: accounts.dataBuffer, isSigner: false, isWritable: false },
{ pubkey: accounts.permission, isSigner: false, isWritable: true },
{ pubkey: accounts.escrow, isSigner: false, isWritable: true },
{ pubkey: accounts.payerWallet, isSigner: false, isWritable: true },
{ pubkey: accounts.payerAuthority, isSigner: true, isWritable: false },
{ pubkey: accounts.recentBlockhashes, isSigner: false, isWritable: false },
{ pubkey: accounts.programState, isSigner: false, isWritable: false },
{ pubkey: accounts.tokenProgram, isSigner: false, isWritable: false },
]
const identifier = Buffer.from([52, 47, 170, 99, 27, 80, 113, 141])
const buffer = Buffer.alloc(1000)
const len = layout.encode(
{
params: types.RequestResultParams.toEncodable(args.params),
},
buffer
)
const data = Buffer.concat([identifier, buffer]).slice(0, 8 + len)
const ix = new TransactionInstruction({ keys, programId: PROGRAM_ID, data })
return ix
}

View File

@ -1,18 +0,0 @@
import { PublicKey, TransactionInstruction } from "@solana/web3.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import { PROGRAM_ID } from "../programId"
export interface UpdateResultAccounts {
state: PublicKey
vrf: PublicKey
}
export function updateResult(accounts: UpdateResultAccounts) {
const keys = [
{ pubkey: accounts.state, isSigner: false, isWritable: true },
{ pubkey: accounts.vrf, isSigner: false, isWritable: false },
]
const identifier = Buffer.from([145, 72, 9, 94, 61, 97, 126, 106])
const data = identifier
const ix = new TransactionInstruction({ keys, programId: PROGRAM_ID, data })
return ix
}

View File

@ -1,9 +0,0 @@
import { PublicKey } from "@solana/web3.js"
// Program ID passed with the cli --program-id flag when running the code generator. Do not edit, it will get overwritten.
export const PROGRAM_ID_CLI = new PublicKey(
"HjjRFjCyQH3ne6Gg8Yn3TQafrrYecRrphwLwnh2A26vM"
)
// This constant will not get overwritten on subsequent code generations and it's safe to modify it's value.
export const PROGRAM_ID: PublicKey = PROGRAM_ID_CLI

View File

@ -1,51 +0,0 @@
import * as borsh from "@project-serum/borsh"
import BN from "bn.js" // eslint-disable-line @typescript-eslint/no-unused-vars
export interface InitStateParamsFields {
maxResult: BN
}
export interface InitStateParamsJSON {
maxResult: string
}
export class InitStateParams {
readonly maxResult: BN
constructor(fields: InitStateParamsFields) {
this.maxResult = fields.maxResult
}
static layout(property?: string) {
return borsh.struct([borsh.u64("maxResult")], property)
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
static fromDecoded(obj: any) {
return new InitStateParams({
maxResult: obj.maxResult,
})
}
static toEncodable(fields: InitStateParamsFields) {
return {
maxResult: fields.maxResult,
}
}
toJSON(): InitStateParamsJSON {
return {
maxResult: this.maxResult.toString(),
}
}
static fromJSON(obj: InitStateParamsJSON): InitStateParams {
return new InitStateParams({
maxResult: new BN(obj.maxResult),
})
}
toEncodable() {
return InitStateParams.toEncodable(this)
}
}

View File

@ -1,61 +0,0 @@
import * as borsh from "@project-serum/borsh"
export interface RequestResultParamsFields {
permissionBump: number
switchboardStateBump: number
}
export interface RequestResultParamsJSON {
permissionBump: number
switchboardStateBump: number
}
export class RequestResultParams {
readonly permissionBump: number
readonly switchboardStateBump: number
constructor(fields: RequestResultParamsFields) {
this.permissionBump = fields.permissionBump
this.switchboardStateBump = fields.switchboardStateBump
}
static layout(property?: string) {
return borsh.struct(
[borsh.u8("permissionBump"), borsh.u8("switchboardStateBump")],
property
)
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
static fromDecoded(obj: any) {
return new RequestResultParams({
permissionBump: obj.permissionBump,
switchboardStateBump: obj.switchboardStateBump,
})
}
static toEncodable(fields: RequestResultParamsFields) {
return {
permissionBump: fields.permissionBump,
switchboardStateBump: fields.switchboardStateBump,
}
}
toJSON(): RequestResultParamsJSON {
return {
permissionBump: this.permissionBump,
switchboardStateBump: this.switchboardStateBump,
}
}
static fromJSON(obj: RequestResultParamsJSON): RequestResultParams {
return new RequestResultParams({
permissionBump: obj.permissionBump,
switchboardStateBump: obj.switchboardStateBump,
})
}
toEncodable() {
return RequestResultParams.toEncodable(this)
}
}

View File

@ -1,10 +0,0 @@
export {
InitStateParams,
InitStateParamsFields,
InitStateParamsJSON,
} from "./InitStateParams"
export {
RequestResultParams,
RequestResultParamsFields,
RequestResultParamsJSON,
} from "./RequestResultParams"

File diff suppressed because it is too large Load Diff

View File

@ -19,22 +19,21 @@
"@project-serum/borsh": "^0.2.5",
"@solana/spl-token-v2": "npm:@solana/spl-token@^0.2.0",
"@solana/web3.js": "^1.42.0",
"@switchboard-xyz/sbv2-utils": "^0.1.43",
"@switchboard-xyz/switchboard-v2": "^0.0.135",
"@typescript-eslint/eslint-plugin": "^5.44.0",
"@typescript-eslint/parser": "^5.44.0",
"@switchboard-xyz/sbv2-utils": "^0.1.53",
"@switchboard-xyz/switchboard-v2": "^0.0.165",
"chalk": "^4.1.2",
"child_process": "^1.0.2",
"dotenv": "^16.0.1",
"eslint": "^8.28.0",
"yargs": "^17.5.1"
},
"devDependencies": {
"@switchboard-xyz/switchboardv2-cli": "^0.2.14",
"@switchboard-xyz/cli": "^2.0.21",
"@types/chai": "^4.3.0",
"@types/mocha": "^9.0.0",
"@types/node": "^17.0.45",
"@typescript-eslint/eslint-plugin": "^5.44.0",
"@typescript-eslint/parser": "^5.44.0",
"chai": "^4.3.6",
"eslint": "^8.28.0",
"mocha": "^9.0.3",
"npm-run-all": "^4.1.5",
"prettier": "^2.4.1",

View File

@ -42,6 +42,7 @@ describe("anchor-vrf-parser test", () => {
let switchboard: SwitchboardTestContext;
const vrfSecret = anchor.web3.Keypair.generate();
console.log(`VRF Account: ${vrfSecret.publicKey}`);
const [vrfClientKey, vrfClientBump] =
anchor.utils.publicKey.findProgramAddressSync(
@ -101,26 +102,28 @@ describe("anchor-vrf-parser test", () => {
const maxTime = 60000;
const retryCount = 10;
const retryInterval = maxTime / retryCount;
let isReady = false;
const timer = setInterval(async () => {
const queue = await switchboard.queue.loadData();
const oracles = queue.queueData as anchor.web3.PublicKey[];
if (oracles.length) {
console.log(`oracle ready, ${oracles.length}`);
const oracles = queue.queue as anchor.web3.PublicKey[];
if (oracles.length > 0) {
// console.log(`oracle ready, ${oracles.length}`);
isReady = true;
clearTimeout(timer);
} else {
console.log(`oracle not ready, ${oracles.length}`);
// console.log(`oracle not ready, ${oracles.length}`);
}
}, retryInterval);
let n = maxTime / 1000;
while (!isReady && n > 0) {
if (isReady) {
console.log(`finally ready`);
// console.log(`finally ready`);
break;
}
console.log(`still not ready ${n} ...`);
// console.log(`still not ready ${n} ...`);
await sleep(1 * 1000);
--n;
}
@ -206,6 +209,9 @@ describe("anchor-vrf-parser test", () => {
const { escrow } = await vrfAccount.loadData();
// give account time to propagate to oracle RPCs
await sleep(2000);
// Request randomness
await vrfClientProgram.methods.requestResult!({
switchboardStateBump: programStateBump,
@ -235,7 +241,7 @@ describe("anchor-vrf-parser test", () => {
const result = await awaitCallback(
vrfClientProgram.provider.connection,
vrfClientKey,
155_000
45_000
);
console.log(`VrfClient Result: ${result}`);

View File

@ -13,7 +13,7 @@
"strict": false,
"strictNullChecks": false,
"paths": {
"@switchboard-xyz/switchboard-v2": ["../../javascript/solana.js"],
"@switchboard-xyz/switchboard-v2": ["../../javascript/switchboard-v2"],
"@switchboard-xyz/sbv2-utils": ["../../javascript/sbv2-utils"],
"@solana/spl-token": ["./node_modules/@solana/spl-token"]
}
@ -21,7 +21,7 @@
"include": ["tests/**/*", "./cli.ts", "./client/**/*"],
"exclude": ["target", "lib"],
"references": [
{ "path": "../../javascript/solana.js" },
{ "path": "../../javascript/switchboard-v2" },
{ "path": "../../javascript/sbv2-utils" }
]
}

View File

@ -12,6 +12,6 @@ no-entrypoint = []
[dependencies]
# switchboard-v2 = { path = "../../rust/switchboard-v2", features = ["devnet"] }
switchboard-v2 = { version = "^0.1.13", features = ["devnet"] }
switchboard-v2 = { version = "^0.1.16", features = ["devnet"] }
solana-program = "~1.10.29"
anchor-lang = "^0.25.0"

File diff suppressed because it is too large Load Diff

View File

@ -14,10 +14,10 @@
"test": "echo \"For workspace native-feed-parser, use the anchor:test script\" && exit 0"
},
"dependencies": {
"@project-serum/anchor": "^0.24.2",
"@solana/web3.js": "^1.42.0",
"@switchboard-xyz/sbv2-utils": "^0.1.43",
"@switchboard-xyz/switchboard-v2": "^0.0.134"
"@project-serum/anchor": "^0.25.0",
"@solana/web3.js": "^1.66.2",
"@switchboard-xyz/sbv2-utils": "^0.1.53",
"@switchboard-xyz/switchboard-v2": "^0.0.165"
},
"devDependencies": {
"@types/chai": "^4.3.0",

View File

@ -1,5 +1,4 @@
{
"extends": "../../../tsconfig.json",
"compilerOptions": {
"types": ["mocha", "chai"],
"typeRoots": ["./node_modules/@types"],
@ -9,14 +8,13 @@
"esModuleInterop": true,
"noEmit": true,
"paths": {
"@switchboard-xyz/switchboard-v2": ["../../../libraries/ts"],
"@switchboard-xyz/sbv2-utils": ["../../../libraries/sbv2-utils"]
"@switchboard-xyz/switchboard-v2": ["../../javascript/switchboard-v2"],
"@switchboard-xyz/sbv2-utils": ["../../javascript/sbv2-utils"]
}
},
// "include": ["oldtests/**/**/*"],
"exclude": ["target"],
"references": [
{ "path": "../../../libraries/ts" },
{ "path": "../../../libraries/sbv2-utils" }
{ "path": ".../../javascript/switchboard-v2" },
{ "path": "../../javascript/sbv2-utils" }
]
}

File diff suppressed because it is too large Load Diff

View File

@ -47,6 +47,29 @@ pub struct AggregatorRound {
pub errors_fulfilled: [bool; 16],
}
#[derive(Copy, Clone, Debug, AnchorSerialize, AnchorDeserialize, Eq, PartialEq)]
#[repr(u8)]
pub enum AggregatorResolutionMode {
ModeRoundResolution = 0,
ModeSlidingResolution = 1,
}
#[account(zero_copy)]
#[repr(packed)]
pub struct SlidingResultAccountData {
pub data: [SlidingWindowElement; 16],
pub bump: u8,
pub _ebuf: [u8; 512],
}
#[zero_copy]
#[derive(Default)]
#[repr(packed)]
pub struct SlidingWindowElement {
pub oracle_key: Pubkey,
pub value: SwitchboardDecimal,
pub slot: u64,
pub timestamp: i64,
}
// #[zero_copy]
#[account(zero_copy)]
#[repr(packed)]
@ -113,8 +136,11 @@ pub struct AggregatorAccountData {
pub job_weights: [u8; 16],
/// Unix timestamp when the feed was created.
pub creation_timestamp: i64,
/// Use sliding windoe or round based resolution
/// NOTE: This changes result propogation in latest_round_result
pub resolution_mode: AggregatorResolutionMode,
/// Reserved for future info.
pub _ebuf: [u8; 139],
pub _ebuf: [u8; 138],
}
impl AggregatorAccountData {
@ -161,7 +187,12 @@ impl AggregatorAccountData {
/// let decimal: f64 = feed_result.try_into()?;
/// ```
pub fn get_result(&self) -> anchor_lang::Result<SwitchboardDecimal> {
if self.min_oracle_results > self.latest_confirmed_round.num_success {
if self.resolution_mode == AggregatorResolutionMode::ModeSlidingResolution {
return Ok(self.latest_confirmed_round.result);
}
let min_oracle_results = self.min_oracle_results;
let latest_confirmed_round_num_success = self.latest_confirmed_round.num_success;
if min_oracle_results > latest_confirmed_round_num_success {
return Err(SwitchboardError::InvalidAggregatorRound.into());
}
Ok(self.latest_confirmed_round.result)

View File

@ -29,7 +29,8 @@ pub struct BufferRelayerAccountData {
pub result: Vec<u8>,
}
#[derive(Default, Debug, Clone, AnchorSerialize, AnchorDeserialize)]
#[zero_copy]
#[derive(Default, Debug, AnchorSerialize, AnchorDeserialize)]
pub struct BufferRelayerRound {
/// Number of successful responses.
pub num_success: u32,

View File

@ -37,6 +37,8 @@ pub const LEASE_SEED: &[u8] = b"LeaseAccountData";
pub const ORACLE_SEED: &[u8] = b"OracleAccountData";
/// Discriminator used for Switchboard buffer accounts.
pub const BUFFER_DISCRIMINATOR: &[u8] = b"BUFFERxx";
/// Seed used to derive the SlidingWindow PDA.
const SLIDING_RESULT_SEED: &[u8] = b"SlidingResultAccountData";
/// Mainnet program id for Switchboard v2
pub const SWITCHBOARD_V2_MAINNET: Pubkey = pubkey!("SW1TCH7qEPTdLsDHRgPuMQjbQxKdH2aBStViMFnt64f");

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More