refactored example programs

wip


wip


example program cleanup


example programs cleanup
This commit is contained in:
Conner Gallagher 2022-05-18 15:00:17 -06:00
parent 0796ca4b4f
commit 37a21ee6f6
95 changed files with 7939 additions and 1747 deletions

View File

@ -1,4 +0,0 @@
lib
dist
node_modules
scripts

View File

@ -3,6 +3,7 @@
"es2020": true,
"node": true
},
"ignorePatterns": ["**/*/node_modules", "**/*/lib", "**/*/dist"],
"root": true,
"extends": [
"airbnb-typescript/base",

2
.gitignore vendored
View File

@ -21,12 +21,14 @@ programs/**/target
Cargo.lock
.anchor
target
.crates
# Misc
.keypairs
secrets
*-keypair*.json
.archive
*-error.log
# Root level jsons ignored
job-directory/*.json

27
Anchor.toml Normal file
View File

@ -0,0 +1,27 @@
[provider]
cluster = "devnet"
wallet = "../payer-keypair.json"
# wallet = "~/.config/solana/id.json"
[programs.localnet]
anchor_feed_parser = "H7frfaL4ZjRW6NAyBvuGgsi9P2G1CgVgqFqzFSDS521f"
anchor_vrf_parser = "HWCUJF1GgCrS1fWNyJdWSBEVNXtdjRwQy7HohdQ5n31o"
# spl_feed_parser = "9dqf4Z9oKRJ6TDGHWyfArV7VtcFNsZWz1wZwWWQmWPHW"
[programs.devnet]
anchor_feed_parser = "H7frfaL4ZjRW6NAyBvuGgsi9P2G1CgVgqFqzFSDS521f"
anchor_vrf_parser = "HWCUJF1GgCrS1fWNyJdWSBEVNXtdjRwQy7HohdQ5n31o"
# spl_feed_parser = "9dqf4Z9oKRJ6TDGHWyfArV7VtcFNsZWz1wZwWWQmWPHW"
[registry]
url = "https://anchor.projectserum.com"
[scripts]
test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 programs/*/tests/**/*.test.ts"
[test.validator]
url="https://api.devnet.solana.com"
[[testnet.validator.clone]]
address="GvDMxPzN1sCj7L26YDK2HnMRXEQmQ2aemov8YBtPS7vR" # sbv2 SOL/USD Feed

6
Cargo.toml Normal file
View File

@ -0,0 +1,6 @@
[workspace]
members = [
"programs/anchor-feed-parser",
"programs/anchor-vrf-parser",
"programs/spl-feed-parser",
]

View File

@ -2408,6 +2408,18 @@ OPTIONS
--queueAuthority=queueAuthority alternative keypair to use for queue authority
--vrfKeypair=vrfKeypair filesystem path of existing keypair to use for VRF Account
EXAMPLES
sbv2 vrf:create 9WZ59yz95bd3XwJxDPVE2PjvVWmSy9WM1NgGD2Hqsohw --keypair ../payer-keypair.json -v --enable
--queueAuthority queue-authority-keypair.json --callbackPid 6MLk7G54uHZ7JuzNxpBAVENANrgM9BZ51pKkzGwPYBCE --ixData
"[145,72,9,94,61,97,126,106]" -a "{"pubkey": "HpQoFL5kxPp2JCFvjsVTvBd7navx4THLefUU68SXAyd6","isSigner":
false,"isWritable": true}" -a "{"pubkey": "8VdBtS8ufkXMCa6Yr9E4KVCfX2inVZVwU4KGg2CL1q7P","isSigner":
false,"isWritable": false}"
sbv2 vrf:create 9WZ59yz95bd3XwJxDPVE2PjvVWmSy9WM1NgGD2Hqsohw --keypair ../payer-keypair.json -v --enable
--queueAuthority oracle-keypair.json --callbackPid 6MLk7G54uHZ7JuzNxpBAVENANrgM9BZ51pKkzGwPYBCE --ixData
"[145,72,9,94,61,97,126,106]" -a "{"pubkey": "HYKi1grticLXPe5vqapUHhm976brwqRob8vqRnWMKWL5","isSigner":
false,"isWritable": true}" -a "{"pubkey": "6vG9QLMgSvsfjvSpDxWfZ2MGPYGzEYoBxviLG7cr4go","isSigner":
false,"isWritable": false}"
```
_See code: [src/commands/vrf/create/index.ts](https://github.com/switchboard-xyz/switchboard-v2/blob/v0.1.18/src/commands/vrf/create/index.ts)_

View File

@ -35,7 +35,7 @@ export default class VrfPrint extends BaseCommand {
publicKey: args.vrfKey,
});
this.logger.log(await prettyPrintVrf(vrfAccount));
this.logger.log(await prettyPrintVrf(vrfAccount, undefined, true));
}
async catch(error) {

View File

@ -61,6 +61,11 @@ export default class VrfCreate extends BaseCommand {
},
];
static examples = [
'sbv2 vrf:create 9WZ59yz95bd3XwJxDPVE2PjvVWmSy9WM1NgGD2Hqsohw --keypair ../payer-keypair.json -v --enable --queueAuthority queue-authority-keypair.json --callbackPid 6MLk7G54uHZ7JuzNxpBAVENANrgM9BZ51pKkzGwPYBCE --ixData "[145,72,9,94,61,97,126,106]" -a "{"pubkey": "HpQoFL5kxPp2JCFvjsVTvBd7navx4THLefUU68SXAyd6","isSigner": false,"isWritable": true}" -a "{"pubkey": "8VdBtS8ufkXMCa6Yr9E4KVCfX2inVZVwU4KGg2CL1q7P","isSigner": false,"isWritable": false}"',
'sbv2 vrf:create 9WZ59yz95bd3XwJxDPVE2PjvVWmSy9WM1NgGD2Hqsohw --keypair ../payer-keypair.json -v --enable --queueAuthority oracle-keypair.json --callbackPid 6MLk7G54uHZ7JuzNxpBAVENANrgM9BZ51pKkzGwPYBCE --ixData "[145,72,9,94,61,97,126,106]" -a "{"pubkey": "HYKi1grticLXPe5vqapUHhm976brwqRob8vqRnWMKWL5","isSigner": false,"isWritable": true}" -a "{"pubkey": "6vG9QLMgSvsfjvSpDxWfZ2MGPYGzEYoBxviLG7cr4go","isSigner": false,"isWritable": false}"',
];
async run() {
const { args, flags } = this.parse(VrfCreate);
verifyProgramHasPayer(this.program);

View File

@ -7,6 +7,7 @@
"rootDir": "src",
"skipLibCheck": true,
"esModuleInterop": true,
"noEmit": false,
"strict": true
},
"include": ["src/**/*"],

View File

@ -11,8 +11,8 @@ import {
import fs from "fs";
import path from "path";
import toml from "toml";
import { DEFAULT_KEYPAIR } from "../const";
import { NoPayerKeypairProvided } from "../errors";
import { DEFAULT_KEYPAIR } from "./const";
import { NoPayerKeypairProvided } from "./errors";
export function programWallet(program: anchor.Program): Keypair {
return ((program.provider as anchor.AnchorProvider).wallet as NodeWallet)

View File

@ -1 +0,0 @@
export * from "./anchor";

View File

@ -0,0 +1,326 @@
import * as anchor from "@project-serum/anchor";
import * as spl from "@solana/spl-token";
import {
Keypair,
PublicKey,
SystemProgram,
TransactionInstruction,
} from "@solana/web3.js";
import {
AggregatorAccount,
CrankAccount,
JobAccount,
LeaseAccount,
OracleJob,
OracleQueueAccount,
PermissionAccount,
ProgramStateAccount,
SwitchboardDecimal,
} from "@switchboard-xyz/switchboard-v2";
import type Big from "big.js";
interface CopyAggregatorParameters {
authority?: PublicKey;
minOracles?: number;
batchSize?: number;
minJobs?: number;
minUpdateDelay?: number;
forceReportPeriod?: number;
varianceThreshold?: Big;
crankKey?: PublicKey;
}
export async function copyAggregatorTxn(
payerKeypair: Keypair,
sourceAggregatorAccount: AggregatorAccount,
targetQueue: OracleQueueAccount,
params: CopyAggregatorParameters
) {
// load source environment
const sourceAggregator = await sourceAggregatorAccount.loadData();
const sourceJobPubkeys: PublicKey[] = sourceAggregator.jobPubkeysData.slice(
0,
sourceAggregator.jobPubkeysSize
);
const sourceJobAccounts = sourceJobPubkeys.map((publicKey) => {
return new JobAccount({
program: sourceAggregatorAccount.program,
publicKey: publicKey,
});
});
const sourceJobs = await Promise.all(
sourceJobAccounts.map(async (jobAccount) => {
const data = await jobAccount.loadData();
const job = OracleJob.decodeDelimited(data.data);
return { job, data };
})
);
const program = targetQueue.program;
const [programStateAccount, stateBump] =
ProgramStateAccount.fromSeed(program);
const programState = await programStateAccount.loadData();
const queue = await targetQueue.loadData();
const tokenMint = await targetQueue.loadMint();
const tokenWallet = (
await tokenMint.getOrCreateAssociatedAccountInfo(payerKeypair.publicKey)
).address;
const createAccountInstructions: (
| TransactionInstruction
| TransactionInstruction[]
)[] = [];
const createAccountSigners: Keypair[] = [payerKeypair];
const jobAccounts = await Promise.all(
sourceJobs.map(async ({ job, data }) => {
const jobKeypair = Keypair.generate();
createAccountSigners.push(jobKeypair);
const jobData = Buffer.from(
OracleJob.encodeDelimited(
OracleJob.create({
tasks: job.tasks,
})
).finish()
);
const size =
280 + jobData.length + (data.variables?.join("")?.length ?? 0);
createAccountInstructions.push([
SystemProgram.createAccount({
fromPubkey: payerKeypair.publicKey,
newAccountPubkey: jobKeypair.publicKey,
space: size,
lamports:
await this.program.provider.connection.getMinimumBalanceForRentExemption(
size
),
programId: this.program.programId,
}),
await this.program.methods
.jobInit({
name: Buffer.from(data.name),
data: jobData,
variables:
data.variables?.map((item) => Buffer.from("")) ??
new Array<Buffer>(),
authorWallet: payerKeypair.publicKey,
stateBump,
})
.accounts({
job: jobKeypair.publicKey,
authorWallet: tokenWallet,
authority: payerKeypair.publicKey,
programState: programStateAccount.publicKey,
})
// .signers([jobKeypair])
.instruction(),
]);
return new JobAccount({
program: this.program,
publicKey: jobKeypair.publicKey,
});
})
);
const aggregatorKeypair = Keypair.generate();
this.logger.debug(`Aggregator: ${aggregatorKeypair.publicKey}`);
createAccountSigners.push(aggregatorKeypair);
const aggregatorSize = this.program.account.aggregatorAccountData.size;
const permissionAccountSize = this.program.account.permissionAccountData.size;
const [permissionAccount, permissionBump] = PermissionAccount.fromSeed(
this.program,
queue.authority,
targetQueue.publicKey,
aggregatorKeypair.publicKey
);
const aggregatorAccount = new AggregatorAccount({
program: this.program,
publicKey: aggregatorKeypair.publicKey,
});
// Create lease and push to crank
const [leaseAccount, leaseBump] = LeaseAccount.fromSeed(
this.program,
targetQueue,
aggregatorAccount
);
const leaseEscrow = await spl.Token.getAssociatedTokenAddress(
spl.ASSOCIATED_TOKEN_PROGRAM_ID,
spl.TOKEN_PROGRAM_ID,
tokenMint.publicKey,
leaseAccount.publicKey,
true
);
const jobPubkeys: Array<PublicKey> = [];
const jobWallets: Array<PublicKey> = [];
const walletBumps: Array<number> = [];
for (const idx in jobAccounts) {
const [jobWallet, bump] = anchor.utils.publicKey.findProgramAddressSync(
[
payerKeypair.publicKey.toBuffer(),
spl.TOKEN_PROGRAM_ID.toBuffer(),
tokenMint.publicKey.toBuffer(),
],
spl.ASSOCIATED_TOKEN_PROGRAM_ID
);
jobPubkeys.push(jobAccounts[idx].publicKey);
jobWallets.push(jobWallet);
walletBumps.push(bump);
}
createAccountInstructions.push(
[
// allocate aggregator space
SystemProgram.createAccount({
fromPubkey: payerKeypair.publicKey,
newAccountPubkey: aggregatorKeypair.publicKey,
space: aggregatorSize,
lamports:
await this.program.provider.connection.getMinimumBalanceForRentExemption(
aggregatorSize
),
programId: this.program.programId,
}),
// create aggregator
await this.program.methods
.aggregatorInit({
name: sourceAggregator.name,
metadata: sourceAggregator.metadata,
batchSize:
params.batchSize ?? sourceAggregator.oracleRequestBatchSize,
minOracleResults:
params.minOracles ?? sourceAggregator.minOracleResults,
minJobResults: params.minJobs ?? sourceAggregator.minJobResults,
minUpdateDelaySeconds:
params.minUpdateDelay ?? sourceAggregator.minUpdateDelaySeconds,
varianceThreshold: params.varianceThreshold
? SwitchboardDecimal.fromBig(params.varianceThreshold)
: sourceAggregator.varianceThreshold,
forceReportPeriod:
params.forceReportPeriod ?? sourceAggregator.forceReportPeriod,
stateBump,
})
.accounts({
aggregator: aggregatorKeypair.publicKey,
authority: payerKeypair.publicKey,
queue: targetQueue.publicKey,
authorWallet: tokenWallet,
programState: programStateAccount.publicKey,
})
.instruction(),
// create permissions
await this.program.methods
.permissionInit({})
.accounts({
permission: permissionAccount.publicKey,
authority: queue.authority,
granter: targetQueue.publicKey,
grantee: aggregatorKeypair.publicKey,
payer: payerKeypair.publicKey,
systemProgram: SystemProgram.programId,
})
.instruction(),
payerKeypair.publicKey.equals(queue.authority)
? await this.program.methods
.permissionSet({
permission: { permitOracleQueueUsage: null },
enable: true,
})
.accounts({
permission: permissionAccount.publicKey,
authority: queue.authority,
})
.instruction()
: undefined,
spl.Token.createAssociatedTokenAccountInstruction(
spl.ASSOCIATED_TOKEN_PROGRAM_ID,
spl.TOKEN_PROGRAM_ID,
tokenMint.publicKey,
leaseEscrow,
leaseAccount.publicKey,
payerKeypair.publicKey
),
await this.program.methods
.leaseInit({
loadAmount: new anchor.BN(0),
stateBump,
leaseBump,
withdrawAuthority: payerKeypair.publicKey,
walletBumps: Buffer.from([]),
})
.accounts({
programState: programStateAccount.publicKey,
lease: leaseAccount.publicKey,
queue: targetQueue.publicKey,
aggregator: aggregatorAccount.publicKey,
systemProgram: SystemProgram.programId,
funder: tokenWallet,
payer: payerKeypair.publicKey,
tokenProgram: spl.TOKEN_PROGRAM_ID,
escrow: leaseEscrow,
owner: payerKeypair.publicKey,
mint: tokenMint.publicKey,
})
// .remainingAccounts(
// jobPubkeys.concat(jobWallets).map((pubkey: PublicKey) => {
// return { isSigner: false, isWritable: true, pubkey };
// })
// )
.instruction(),
params.crankKey
? await this.program.methods
.crankPush({
stateBump,
permissionBump,
})
.accounts({
crank: new PublicKey(params.crankKey),
aggregator: aggregatorAccount.publicKey,
oracleQueue: targetQueue.publicKey,
queueAuthority: queue.authority,
permission: permissionAccount.publicKey,
lease: leaseAccount.publicKey,
escrow: leaseEscrow,
programState: programStateAccount.publicKey,
dataBuffer: (
await new CrankAccount({
program: this.program,
publicKey: new PublicKey(params.crankKey),
}).loadData()
).dataBuffer,
})
.instruction()
: undefined,
].filter((item) => item)
);
const finalInstructions: (
| TransactionInstruction
| TransactionInstruction[]
)[] = [];
finalInstructions.push(
...(await Promise.all(
jobAccounts.map(async (jobAccount) => {
return this.program.methods
.aggregatorAddJob({
weight: 1,
})
.accounts({
aggregator: aggregatorKeypair.publicKey,
authority: payerKeypair.publicKey,
job: jobAccount.publicKey,
})
.instruction();
})
))
);
return "";
}

View File

@ -1,9 +1,9 @@
export * from "./anchor";
export * from "./async";
export * from "./big";
export * from "./const";
export * from "./date";
export * from "./errors";
export * from "./math";
export * from "./nonce";
export * from "./print";
export * from "./solana";

View File

@ -0,0 +1,98 @@
import * as anchor from "@project-serum/anchor";
import {
Keypair,
PublicKey,
SystemProgram,
TransactionInstruction,
} from "@solana/web3.js";
import {
OracleJob,
ProgramStateAccount,
programWallet,
} from "@switchboard-xyz/switchboard-v2";
export interface SwitchboardInstructionResult {
ixns: (TransactionInstruction | Promise<TransactionInstruction>)[];
signers: Keypair[];
}
export class SwitchboardTransaction {
program: anchor.Program;
payerKeypair: Keypair;
programStateAccount: ProgramStateAccount;
// programState: Promise<any>;
// programMint: Promise<spl.Token>;
stateBump: number;
constructor(program: anchor.Program) {
this.program = program;
this.payerKeypair = programWallet(program);
const [programStateAccount, stateBump] =
ProgramStateAccount.fromSeed(program);
this.programStateAccount = programStateAccount;
this.stateBump = stateBump;
// this.programState = programStateAccount.loadData();
// this.programMint = programStateAccount.getTokenMint();
}
createInitJobInstruction(
job: OracleJob,
rentExemption: number,
authorWallet: PublicKey,
params: {
name?: string;
metadata?: string;
authority?: PublicKey;
expiration?: anchor.BN;
variables?: string[];
}
): SwitchboardInstructionResult {
const jobKeypair = Keypair.generate();
const jobData = Buffer.from(
OracleJob.encodeDelimited(
OracleJob.create({
tasks: job.tasks,
})
).finish()
);
const size =
280 + jobData.length + (params.variables?.join("")?.length ?? 0);
const ixns: (TransactionInstruction | Promise<TransactionInstruction>)[] = [
SystemProgram.createAccount({
fromPubkey: this.payerKeypair.publicKey,
newAccountPubkey: jobKeypair.publicKey,
space: size,
lamports: rentExemption,
programId: this.program.programId,
}),
this.program.methods
.jobInit({
name: Buffer.from(params.name ?? ""),
data: jobData,
variables:
params.variables?.map((item) => Buffer.from("")) ??
new Array<Buffer>(),
stateBump: this.stateBump,
})
.accounts({
job: jobKeypair.publicKey,
authorWallet: authorWallet,
authority: this.payerKeypair.publicKey,
programState: this.programStateAccount.publicKey,
})
// .signers([jobKeypair])
.instruction(),
];
return {
ixns,
signers: [jobKeypair],
};
}
}

View File

@ -1 +0,0 @@
export * from "./big";

View File

@ -65,6 +65,8 @@ export const toPermissionString = (
return "PERMIT_ORACLE_HEARTBEAT";
case SwitchboardPermissionValue.PERMIT_ORACLE_QUEUE_USAGE:
return "PERMIT_ORACLE_QUEUE_USAGE";
case SwitchboardPermissionValue.PERMIT_VRF_REQUESTS:
return "PERMIT_VRF_REQUESTS";
default:
return "NONE";
}

View File

@ -1,6 +1,7 @@
/* eslint-disable @typescript-eslint/no-shadow */
/* eslint-disable @typescript-eslint/no-var-requires */
import * as anchor from "@project-serum/anchor";
import type NodeWallet from "@project-serum/anchor/dist/cjs/nodewallet";
import * as spl from "@solana/spl-token";
import { Keypair, PublicKey } from "@solana/web3.js";
import * as sbv2 from "@switchboard-xyz/switchboard-v2";
@ -13,9 +14,9 @@ import { DEFAULT_PUBKEY, promiseWithTimeout } from "../";
export interface ISwitchboardTestContext {
program: anchor.Program;
mint: spl.Token;
tokenWallet: PublicKey;
payerTokenWallet: PublicKey;
queue: sbv2.OracleQueueAccount;
oracle: sbv2.OracleAccount;
oracle?: sbv2.OracleAccount;
}
export class SwitchboardTestContext implements ISwitchboardTestContext {
@ -23,16 +24,16 @@ export class SwitchboardTestContext implements ISwitchboardTestContext {
mint: spl.Token;
tokenWallet: PublicKey;
payerTokenWallet: PublicKey;
queue: sbv2.OracleQueueAccount;
oracle: sbv2.OracleAccount;
oracle?: sbv2.OracleAccount;
constructor(ctx: ISwitchboardTestContext) {
this.program = ctx.program;
this.mint = ctx.mint;
this.tokenWallet = ctx.tokenWallet;
this.payerTokenWallet = ctx.payerTokenWallet;
this.queue = ctx.queue;
this.oracle = ctx.oracle;
}
@ -52,6 +53,65 @@ export class SwitchboardTestContext implements ISwitchboardTestContext {
);
}
static async loadDevnetQueue(
provider: anchor.AnchorProvider,
queueKey = "F8ce7MsckeZAbAGmxjJNetxYXQa9mKr9nnrC3qKubyYy"
) {
const payerKeypair = (provider.wallet as NodeWallet).payer;
let program: anchor.Program;
try {
program = await sbv2.loadSwitchboardProgram(
"devnet",
provider.connection,
payerKeypair
);
} catch (error) {
throw new Error(
`Failed to load the SBV2 program for the given cluster, ${error.message}`
);
}
let queue: sbv2.OracleQueueAccount;
let queueData: any;
try {
queue = new sbv2.OracleQueueAccount({
program,
publicKey: new PublicKey(queueKey),
});
queueData = await queue.loadData();
if (queueData.queue.length < 1) {
throw new Error(`OracleQueue has no active oracles heartbeating`);
}
} catch (error) {
throw new Error(
`Failed to load the SBV2 queue for the given cluster, ${error.message}`
);
}
let mint: spl.Token;
try {
mint = await queue.loadMint();
} catch (error) {
throw new Error(
`Failed to load the SBV2 mint for the given cluster, ${error.message}`
);
}
let payerTokenWallet: PublicKey;
try {
payerTokenWallet = (
await mint.getOrCreateAssociatedAccountInfo(payerKeypair.publicKey)
).address;
} catch (error) {
throw new Error(
`Failed to load the SBV2 mint for the given cluster, ${error.message}`
);
}
return new SwitchboardTestContext({
program,
queue,
mint,
payerTokenWallet,
});
}
// public static async depositSwitchboardWallet(
// program: anchor.Program,
// wallet: PublicKey,
@ -141,8 +201,11 @@ export class SwitchboardTestContext implements ISwitchboardTestContext {
program: switchboardProgram,
publicKey: SWITCHBOARD_QUEUE,
});
const queueData = await queue.loadData();
if (queueData.queue.length < 1) {
throw new Error(`OracleQueue has no active oracles heartbeating`);
}
// TODO: Check oracle is heartbeating when context starts
let oracle: sbv2.OracleAccount;
if (process.env.ORACLE) {
const SWITCHBOARD_ORACLE = new PublicKey(process.env.ORACLE);
@ -156,14 +219,13 @@ export class SwitchboardTestContext implements ISwitchboardTestContext {
sbv2.ProgramStateAccount.fromSeed(switchboardProgram);
const switchboardMint = await switchboardProgramState.getTokenMint();
const tokenWallet = await SwitchboardTestContext.createSwitchboardWallet(
switchboardProgram
);
const payerTokenWallet =
await SwitchboardTestContext.createSwitchboardWallet(switchboardProgram);
const context: ISwitchboardTestContext = {
program: switchboardProgram,
mint: switchboardMint,
tokenWallet,
payerTokenWallet,
queue,
oracle,
};
@ -187,7 +249,7 @@ export class SwitchboardTestContext implements ISwitchboardTestContext {
minRequiredOracleResults: 1,
minUpdateDelaySeconds: 5,
queueAccount: this.queue,
authorWallet: this.tokenWallet,
authorWallet: this.payerTokenWallet,
}
);
@ -216,7 +278,7 @@ export class SwitchboardTestContext implements ISwitchboardTestContext {
// create lease contract
const leaseAccount = await sbv2.LeaseAccount.create(this.program, {
aggregatorAccount,
funder: this.tokenWallet,
funder: this.payerTokenWallet,
funderAuthority: payerKeypair,
loadAmount: new anchor.BN(0),
oracleQueueAccount: this.queue,
@ -225,7 +287,7 @@ export class SwitchboardTestContext implements ISwitchboardTestContext {
// create and add job account
const staticJob = await sbv2.JobAccount.create(this.program, {
name: Buffer.from(`Value ${value}`),
authority: this.tokenWallet,
authority: this.payerTokenWallet,
data: Buffer.from(
sbv2.OracleJob.encodeDelimited(
sbv2.OracleJob.create({
@ -245,7 +307,7 @@ export class SwitchboardTestContext implements ISwitchboardTestContext {
// open new round and request new result
await aggregatorAccount.openRound({
oracleQueueAccount: this.queue,
payoutWallet: this.tokenWallet,
payoutWallet: this.payerTokenWallet,
});
return aggregatorAccount;
@ -339,7 +401,7 @@ export class SwitchboardTestContext implements ISwitchboardTestContext {
await aggregatorAccount.openRound({
oracleQueueAccount: this.queue,
payoutWallet: this.tokenWallet,
payoutWallet: this.payerTokenWallet,
});
await updatedValuePromise;

View File

@ -10,7 +10,9 @@
"skipLibCheck": true,
"esModuleInterop": true,
"noImplicitReturns": false,
"importsNotUsedAsValues": "preserve",
"strict": false,
"noEmit": false,
"emitDeclarationOnly": false,
"paths": {
"@switchboard-xyz/switchboard-v2": ["../ts"]

View File

@ -32,9 +32,16 @@
},
"devDependencies": {
"@gallynaut/rawrtools": "^0.0.1",
"@types/chai": "^4.3.1",
"@types/mocha": "^9.1.1",
"anchor-client-gen": "^0.24.0",
"chai": "^4.3.6",
"lerna": "^4.0.0",
"mocha": "^10.0.0",
"npm-run-all": "^4.1.5",
"shelljs": "^0.8.5",
"shx": "^0.3.4",
"ts-mocha": "^10.0.0",
"ts-node": "^10.7.0",
"typedoc": "^0.22.15",
"typescript": "^4.6.3"

View File

@ -1,6 +0,0 @@
.anchor
.DS_Store
target
**/*.rs.bk
node_modules

View File

@ -1,20 +0,0 @@
[features]
seeds = false
[programs.localnet]
anchor_feed_parser = "3Y2v9gVaFAKTDqcxxs8oSRWV8K9ctkCB8yiC6KA4sFz5"
[registry]
url = "https://anchor.projectserum.com"
[provider]
cluster = "localnet"
wallet = "../../../payer-keypair.json"
[scripts]
test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"
# Clone devnet SOL/USD feed
[test.validator]
url = "https://api.devnet.solana.com"
[[test.validator.clone]]
address="GvDMxPzN1sCj7L26YDK2HnMRXEQmQ2aemov8YBtPS7vR"

View File

@ -1,4 +1,22 @@
[workspace]
members = [
"programs/*"
]
[package]
name = "anchor-feed-parser"
version = "0.1.0"
description = "Created with Anchor"
edition = "2018"
[lib]
crate-type = ["cdylib", "lib"]
name = "anchor_feed_parser"
[features]
no-entrypoint = []
no-idl = []
no-log-ix-name = []
cpi = ["no-entrypoint"]
default = []
[dependencies]
switchboard-v2 = { path = "../../libraries/rs" }
# switchboard-v2 = "^0.1.10"
anchor-lang = "^0.24.2"
solana-program = "~1.9.13"

View File

@ -0,0 +1,690 @@
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

@ -0,0 +1,52 @@
import { PROGRAM_ID } from "../programId"
import * as anchor from "./anchor"
export function fromCode(code: number): anchor.AnchorError | null {
return 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): 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

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

View File

@ -0,0 +1,16 @@
import { PublicKey, TransactionInstruction } from "@solana/web3.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import { PROGRAM_ID } from "../programId"
export interface ReadResultAccounts {
aggregator: PublicKey
}
export function readResult(accounts: ReadResultAccounts) {
const keys = [
{ pubkey: accounts.aggregator, isSigner: false, isWritable: false },
]
const identifier = Buffer.from([130, 229, 115, 203, 180, 191, 240, 90])
const data = identifier
const ix = new TransactionInstruction({ keys, programId: PROGRAM_ID, data })
return ix
}

View File

@ -0,0 +1,9 @@
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(
"H7frfaL4ZjRW6NAyBvuGgsi9P2G1CgVgqFqzFSDS521f"
)
// 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

@ -8,23 +8,15 @@
"directory": "programs/anchor-feed-parser"
},
"scripts": {
"generate:api": "ts-node solita",
"build": "anchor build && yarn run generate:api && yarn run pid",
"pid": "shx echo \"\n\nPROGRAM ID: \"$(solana-keygen pubkey target/deploy/anchor_feed_parser-keypair.json) \"\n\nUpdate Anchor.toml and src/lib.rs with your PID above.\" || exit 0",
"lint": "eslint --ext .js,.json,.ts 'src/**' --fix",
"test": "anchor test",
"anchor:test": "anchor test --skip-local-validator"
"build": "echo \"For workspace anchor-feed-parser, run 'anchor build' from the project root\" && exit 0",
"lint": "eslint --ext .js,.json,.ts 'src/**' --fix"
},
"dependencies": {
"@metaplex-foundation/beet": "^0.1.0",
"@metaplex-foundation/beet-solana": "^0.1.1",
"@metaplex-foundation/solita": "^0.2.1",
"@project-serum/anchor": "^0.24.2",
"@switchboard-xyz/switchboard-v2": "^0.0.95",
"@solana/web3.js": "^1.37.1"
"@solana/web3.js": "^1.37.1",
"@switchboard-xyz/switchboard-v2": "^0.0.95"
},
"devDependencies": {
"@metaplex-foundation/solita": "^0.2.1",
"@types/chai": "^4.3.0",
"@types/mocha": "^9.1.0",
"chai": "^4.3.4",

View File

@ -1,21 +0,0 @@
[package]
name = "anchor-feed-parser"
version = "0.1.0"
description = "Created with Anchor"
edition = "2018"
[lib]
crate-type = ["cdylib", "lib"]
name = "anchor_feed_parser"
[features]
no-entrypoint = []
no-idl = []
no-log-ix-name = []
cpi = ["no-entrypoint"]
default = []
[dependencies]
anchor-lang = "^0.24.2"
switchboard-v2 = "^0.1.10"
solana-program = "~1.9.13"

View File

@ -1,52 +0,0 @@
const PROGRAM_NAME = "anchor_feed_parser";
const PROGRAM_ID = "3Y2v9gVaFAKTDqcxxs8oSRWV8K9ctkCB8yiC6KA4sFz5";
import { Solita } from "@metaplex-foundation/solita";
import { spawn } from "child_process";
import { writeFile } from "fs/promises";
import * as path from "path";
const programDir = path.join(__dirname, "..");
const generatedIdlDir = path.join(__dirname, "..", "target", "idl");
const generatedSDKDir = path.join(__dirname, "..", "src", "generated");
const anchor = spawn("anchor", ["build", "--idl", generatedIdlDir], {
cwd: programDir,
})
.on("error", (err) => {
console.error(err);
// @ts-ignore this err does have a code
if (err.code === "ENOENT") {
console.error(
"Ensure that `anchor` is installed and in your path, see:\n https://project-serum.github.io/anchor/getting-started/installation.html#install-anchor\n"
);
}
process.exit(1);
})
.on("exit", () => {
console.log(
"IDL written to: %s",
path.join(generatedIdlDir, `${PROGRAM_NAME}.json`)
);
generateTypeScriptSDK();
});
anchor.stdout.on("data", (buf) => console.log(buf.toString("utf8")));
anchor.stderr.on("data", (buf) => console.error(buf.toString("utf8")));
async function generateTypeScriptSDK() {
console.error("Generating TypeScript SDK to %s", generatedSDKDir);
const generatedIdlPath = path.join(generatedIdlDir, `${PROGRAM_NAME}.json`);
const idl = require(generatedIdlPath);
if (idl.metadata?.address == null) {
idl.metadata = { ...idl.metadata, address: PROGRAM_ID };
await writeFile(generatedIdlPath, JSON.stringify(idl, null, 2));
}
const gen = new Solita(idl, { formatCode: true });
await gen.renderAndWriteTo(generatedSDKDir);
console.error("Success!");
process.exit(0);
}

View File

@ -1,58 +0,0 @@
/* eslint-disable unicorn/no-process-exit */
/* eslint-disable @typescript-eslint/ban-ts-comment */
/* eslint-disable unicorn/prevent-abbreviations */
/* eslint-disable unicorn/prefer-module */
const PROGRAM_NAME = "anchor_feed_parser";
const PROGRAM_ID = "3Y2v9gVaFAKTDqcxxs8oSRWV8K9ctkCB8yiC6KA4sFz5";
import { Solita } from "@metaplex-foundation/solita";
import { spawn } from "child_process";
import { writeFile } from "fs/promises";
import path from "path";
const programDir = path.join(__dirname, "programs");
const generatedIdlDir = path.join(__dirname, "target", "idl");
const generatedSDKDir = path.join(__dirname, "src", "generated");
const anchor = spawn("anchor", ["build", "--idl", generatedIdlDir], {
cwd: programDir,
})
.on("error", (err) => {
console.error(err);
// @ts-ignore this err does have a code
if (err.code === "ENOENT") {
console.error(
"Ensure that `anchor` is installed and in your path, see:\n https://project-serum.github.io/anchor/getting-started/installation.html#install-anchor\n"
);
}
process.exit(1);
})
.on("exit", () => {
console.log(
"IDL written to: %s",
path.join(generatedIdlDir, `${PROGRAM_NAME}.json`)
);
generateTypeScriptSDK();
});
anchor.stdout.on("data", (buf) => console.log(buf.toString("utf8")));
anchor.stderr.on("data", (buf) => console.error(buf.toString("utf8")));
async function generateTypeScriptSDK() {
console.error("Generating TypeScript SDK to %s", generatedSDKDir);
const generatedIdlPath = path.join(generatedIdlDir, `${PROGRAM_NAME}.json`);
// eslint-disable-next-line @typescript-eslint/no-var-requires
const idl = require(generatedIdlPath);
if (idl.metadata?.address == undefined) {
idl.metadata = { ...idl.metadata, address: PROGRAM_ID };
await writeFile(generatedIdlPath, JSON.stringify(idl, undefined, 2));
}
const gen = new Solita(idl, { formatCode: true });
await gen.renderAndWriteTo(generatedSDKDir);
console.error("Success!");
process.exit(0);
}
export {};

View File

@ -1,18 +0,0 @@
import { PublicKey } from '@solana/web3.js'
export * from './instructions'
/**
* Program address
*
* @category constants
* @category generated
*/
export const PROGRAM_ADDRESS = '3Y2v9gVaFAKTDqcxxs8oSRWV8K9ctkCB8yiC6KA4sFz5'
/**
* Program publick key
*
* @category constants
* @category generated
*/
export const PROGRAM_ID = new PublicKey(PROGRAM_ADDRESS)

View File

@ -1 +0,0 @@
export * from './readResult';

View File

@ -1,69 +0,0 @@
/**
* This code was GENERATED using the solita package.
* Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality.
*
* See: https://github.com/metaplex-foundation/solita
*/
import * as beet from '@metaplex-foundation/beet'
import * as web3 from '@solana/web3.js'
/**
* @category Instructions
* @category ReadResult
* @category generated
*/
const readResultStruct = new beet.BeetArgsStruct<{
instructionDiscriminator: number[] /* size: 8 */
}>(
[['instructionDiscriminator', beet.uniformFixedSizeArray(beet.u8, 8)]],
'ReadResultInstructionArgs'
)
/**
* Accounts required by the _readResult_ instruction
* @category Instructions
* @category ReadResult
* @category generated
*/
export type ReadResultInstructionAccounts = {
aggregator: web3.PublicKey
}
const readResultInstructionDiscriminator = [
130, 229, 115, 203, 180, 191, 240, 90,
]
/**
* Creates a _ReadResult_ instruction.
*
* @param accounts that will be accessed while the instruction is processed
*
* @category Instructions
* @category ReadResult
* @category generated
*/
export function createReadResultInstruction(
accounts: ReadResultInstructionAccounts
) {
const { aggregator } = accounts
const [data] = readResultStruct.serialize({
instructionDiscriminator: readResultInstructionDiscriminator,
})
const keys: web3.AccountMeta[] = [
{
pubkey: aggregator,
isWritable: false,
isSigner: false,
},
]
const ix = new web3.TransactionInstruction({
programId: new web3.PublicKey(
'3Y2v9gVaFAKTDqcxxs8oSRWV8K9ctkCB8yiC6KA4sFz5'
),
keys,
data,
})
return ix
}

View File

@ -1 +0,0 @@
export * from "./generated";

View File

@ -3,7 +3,7 @@ use anchor_lang::prelude::*;
use std::convert::TryInto;
pub use switchboard_v2::AggregatorAccountData;
declare_id!("3Y2v9gVaFAKTDqcxxs8oSRWV8K9ctkCB8yiC6KA4sFz5");
declare_id!("H7frfaL4ZjRW6NAyBvuGgsi9P2G1CgVgqFqzFSDS521f");
#[derive(Accounts)]
pub struct ReadResult<'info> {

View File

@ -2,32 +2,30 @@ import type { Program } from "@project-serum/anchor";
import * as anchor from "@project-serum/anchor";
import { PublicKey } from "@solana/web3.js";
import { SwitchboardTestContext } from "@switchboard-xyz/switchboard-v2";
import { createReadResultInstruction } from "../src";
import type { AnchorFeedParser } from "../target/types/anchor_feed_parser";
import type { AnchorFeedParser } from "../../../target/types/anchor_feed_parser";
const sleep = (ms: number): Promise<any> =>
new Promise((s) => setTimeout(s, ms));
// Anchor.toml will copy this to localnet when we start our tests
const DEFAULT_SOL_USD_FEED = new PublicKey(
"GvDMxPzN1sCj7L26YDK2HnMRXEQmQ2aemov8YBtPS7vR"
);
console.log("checking1");
describe("anchor-feed-parser", () => {
const provider = anchor.AnchorProvider.env();
anchor.setProvider(provider);
anchor.setProvider(anchor.AnchorProvider.env());
const program = anchor.workspace
const feedParserProgram = anchor.workspace
.AnchorFeedParser as Program<AnchorFeedParser>;
const provider = feedParserProgram.provider as anchor.AnchorProvider;
let aggregatorKey: PublicKey;
const connection = new anchor.web3.Connection(
provider.connection.rpcEndpoint,
{ commitment: "finalized" }
);
before(async () => {
const accountInfo = await connection.getAccountInfo(DEFAULT_SOL_USD_FEED);
console.log("checking");
const accountInfo = await provider.connection.getAccountInfo(
DEFAULT_SOL_USD_FEED
);
if (accountInfo) {
aggregatorKey = DEFAULT_SOL_USD_FEED;
return;
@ -52,21 +50,10 @@ describe("anchor-feed-parser", () => {
});
it("Read SOL/USD Feed", async () => {
const instruction = createReadResultInstruction({
aggregator: aggregatorKey,
});
const transaction = new anchor.web3.Transaction();
transaction.add(instruction);
const tx = await provider.sendAndConfirm(transaction);
// // Using Anchor Program to send transaction
// const tx = await program.rpc.readResult({
// accounts: {
// aggregator: aggregatorKey,
// },
// });
const tx = await feedParserProgram.methods
.readResult()
.accounts({ aggregator: aggregatorKey })
.rpc();
// wait for RPC
await sleep(2000);

View File

@ -6,12 +6,11 @@
"lib": ["es2015"],
"module": "commonjs",
"target": "es6",
"noEmit": true,
"esModuleInterop": true,
"paths": {
"@switchboard-xyz/switchboard-v2": ["../../libraries/ts"]
}
},
"include": ["tests/**/*"],
"exclude": ["target"],
"references": [{ "path": "../../libraries/ts" }]
}

View File

@ -1,6 +0,0 @@
.anchor
.DS_Store
target
**/*.rs.bk
node_modules

View File

@ -1,14 +0,0 @@
[programs.localnet]
anchor_vrf_parser = "FAnbznqZvZ7eijxQ6mKPoyDdM33o8cdM6wsUZtv2dFib"
[registry]
url = "https://anchor.projectserum.com"
[provider]
cluster = "devnet"
wallet = "../../../payer-keypair.json"
# cluster = "devnet"
# wallet = "secrets/payer-keypair.json"
[scripts]
test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.test.ts"

View File

@ -1,4 +1,24 @@
[workspace]
members = [
"programs/*"
]
[package]
name = "anchor-vrf-parser"
version = "0.1.0"
description = "Created with Anchor"
edition = "2018"
[lib]
crate-type = ["cdylib", "lib"]
name = "anchor_vrf_parser"
[features]
no-entrypoint = []
no-idl = []
no-log-ix-name = []
cpi = ["no-entrypoint"]
default = []
[dependencies]
switchboard-v2 = { path = "../../libraries/rs" }
# switchboard-v2 = "^0.1.10"
anchor-lang = "^0.24.2"
anchor-spl = "^0.24.2"
solana-program = "~1.9.13"
bytemuck = "1.7.2"

View File

@ -0,0 +1,134 @@
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,
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

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

View File

@ -0,0 +1,690 @@
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

@ -0,0 +1,60 @@
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

@ -0,0 +1,57 @@
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

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

View File

@ -0,0 +1,39 @@
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

@ -0,0 +1,60 @@
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

@ -0,0 +1,18 @@
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

@ -0,0 +1,9 @@
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(
"HWCUJF1GgCrS1fWNyJdWSBEVNXtdjRwQy7HohdQ5n31o"
)
// 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

@ -0,0 +1,51 @@
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

@ -0,0 +1,61 @@
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

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

View File

@ -8,25 +8,14 @@
"directory": "programs/anchor-vrf-parser"
},
"scripts": {
"generate:api": "ts-node solita",
"pid": "shx echo \"\n\nPROGRAM ID: \"$(solana-keygen pubkey target/deploy/anchor_vrf_parser-keypair.json) \"\n\nUpdate Anchor.toml, src/lib.rs, and solita.ts with your PID above.\" || exit 0",
"setup:authority": "run-s create:authority airdrop:authority",
"setup:switchboard": "sbv2 localnet:env --keypair secrets/payer-keypair.json",
"create:authority": "shx find secrets/payer-keypair.json || solana-keygen new -s --no-bip39-passphrase --outfile secrets/payer-keypair.json",
"airdrop": "solana airdrop 1 secrets/payer-keypair.json",
"airdrop:authority": "run-s airdrop && run-s airdrop && run-s airdrop && run-s airdrop || true",
"build": "rm -rf lib && tsc -p tsconfig.json",
"lint": "eslint --ext .js,.json,.ts 'src/**' --fix",
"anchor:test": "anchor test --skip-local-validator",
"test": "echo \"For workspace anchor-vrf-parser, use the anchor:test script\" && exit 0"
"build": "echo \"For workspace anchor-vrf-parser, run 'anchor build' from the project root\" && exit 0",
"lint": "eslint --ext .js,.json,.ts 'src/**' --fix"
},
"dependencies": {
"@metaplex-foundation/beet": "^0.1.0",
"@metaplex-foundation/beet-solana": "^0.1.1",
"@metaplex-foundation/solita": "^0.2.1",
"@project-serum/anchor": "^0.24.2",
"@solana/spl-token": "^0.1.8",
"@solana/web3.js": "^1.33.0",
"@solana/web3.js": "^1.42.0",
"@switchboard-xyz/sbv2-utils": "^0.0.10",
"@switchboard-xyz/switchboard-v2": "^0.0.95",
"chalk": "^4.1.2",
"child_process": "^1.0.2",

View File

@ -1,23 +0,0 @@
[package]
name = "anchor-vrf-parser"
version = "0.1.0"
description = "Created with Anchor"
edition = "2018"
[lib]
crate-type = ["cdylib", "lib"]
name = "anchor_vrf_parser"
[features]
no-entrypoint = []
no-idl = []
no-log-ix-name = []
cpi = ["no-entrypoint"]
default = []
[dependencies]
anchor-lang = "^0.24.2"
anchor-spl = "^0.24.2"
solana-program = "~1.9.13"
switchboard-v2 = "^0.1.10"
bytemuck = "1.7.2"

View File

@ -1,55 +0,0 @@
const PROGRAM_NAME = "anchor_vrf_parser";
const PROGRAM_ID = "7PoPs442NYqZwfrFhMuVDTzpWfaZi8dCtRFwqydnj5Gt";
import { Solita } from "@metaplex-foundation/solita";
import { spawn } from "child_process";
import { writeFile } from "fs/promises";
import * as path from "path";
const programDir = path.join(__dirname, "..");
// console.log(`programDir ${programDir}`);
const generatedIdlDir = path.join(__dirname, "..", "target", "idl");
// console.log(`generatedIdlDir ${generatedIdlDir}`);
const generatedSDKDir = path.join(__dirname, "..", "src", "generated");
// console.log(`generatedSDKDir ${generatedSDKDir}`);
const anchor = spawn("anchor", ["build", "--idl", generatedIdlDir], {
cwd: programDir,
})
.on("error", (err) => {
console.error(err);
// @ts-ignore this err does have a code
if (err.code === "ENOENT") {
console.error(
"Ensure that `anchor` is installed and in your path, see:\n https://project-serum.github.io/anchor/getting-started/installation.html#install-anchor\n"
);
}
process.exit(1);
})
.on("exit", () => {
console.log(
"IDL written to: %s",
path.join(generatedIdlDir, `${PROGRAM_NAME}.json`)
);
generateTypeScriptSDK();
});
anchor.stdout.on("data", (buf) => console.log(buf.toString("utf8")));
anchor.stderr.on("data", (buf) => console.error(buf.toString("utf8")));
async function generateTypeScriptSDK() {
console.error("Generating TypeScript SDK to %s", generatedSDKDir);
const generatedIdlPath = path.join(generatedIdlDir, `${PROGRAM_NAME}.json`);
const idl = require(generatedIdlPath);
if (idl.metadata?.address == null) {
idl.metadata = { ...idl.metadata, address: PROGRAM_ID };
await writeFile(generatedIdlPath, JSON.stringify(idl, null, 2));
}
const gen = new Solita(idl, { formatCode: true });
await gen.renderAndWriteTo(generatedSDKDir);
console.error("Success!");
process.exit(0);
}

View File

@ -1,58 +0,0 @@
/* eslint-disable unicorn/no-process-exit */
/* eslint-disable @typescript-eslint/ban-ts-comment */
/* eslint-disable unicorn/prevent-abbreviations */
/* eslint-disable unicorn/prefer-module */
const PROGRAM_NAME = "anchor_vrf_parser";
const PROGRAM_ID = "FAnbznqZvZ7eijxQ6mKPoyDdM33o8cdM6wsUZtv2dFib";
import { Solita } from "@metaplex-foundation/solita";
import { spawn } from "child_process";
import { writeFile } from "fs/promises";
import path from "path";
const programDir = path.join(__dirname, "programs");
const generatedIdlDir = path.join(__dirname, "target", "idl");
const generatedSDKDir = path.join(__dirname, "src", "generated");
const anchor = spawn("anchor", ["build", "--idl", generatedIdlDir], {
cwd: programDir,
})
.on("error", (err) => {
console.error(err);
// @ts-ignore this err does have a code
if (err.code === "ENOENT") {
console.error(
"Ensure that `anchor` is installed and in your path, see:\n https://project-serum.github.io/anchor/getting-started/installation.html#install-anchor\n"
);
}
process.exit(1);
})
.on("exit", () => {
console.log(
"IDL written to: %s",
path.join(generatedIdlDir, `${PROGRAM_NAME}.json`)
);
generateTypeScriptSDK();
});
anchor.stdout.on("data", (buf) => console.log(buf.toString("utf8")));
anchor.stderr.on("data", (buf) => console.error(buf.toString("utf8")));
async function generateTypeScriptSDK() {
console.error("Generating TypeScript SDK to %s", generatedSDKDir);
const generatedIdlPath = path.join(generatedIdlDir, `${PROGRAM_NAME}.json`);
// eslint-disable-next-line @typescript-eslint/no-var-requires
const idl = require(generatedIdlPath);
if (idl.metadata?.address == undefined) {
idl.metadata = { ...idl.metadata, address: PROGRAM_ID };
await writeFile(generatedIdlPath, JSON.stringify(idl, undefined, 2));
}
const gen = new Solita(idl, { formatCode: true });
await gen.renderAndWriteTo(generatedSDKDir);
console.error("Success!");
process.exit(0);
}
export {};

View File

@ -13,6 +13,8 @@ pub struct UpdateResult<'info> {
impl UpdateResult<'_> {
pub fn validate(&self, _ctx: &Context<Self>) -> Result<()> {
// We should check VRF account passed is equal to the pubkey stored in our client state
// But skipping so we can re-use this program instruction for CI testing
Ok(())
}

View File

@ -1,39 +0,0 @@
import * as anchor from "@project-serum/anchor";
import type { PublicKey } from "@solana/web3.js";
import type { Callback } from "@switchboard-xyz/switchboard-v2";
export function getVrfClientFromSeed(
program: anchor.Program,
vrfPubkey: PublicKey,
authority: PublicKey
): [PublicKey, number] {
const [statePubkey, stateBump] =
anchor.utils.publicKey.findProgramAddressSync(
[Buffer.from("STATE"), vrfPubkey.toBytes(), authority.toBytes()],
program.programId
);
return [statePubkey, stateBump];
}
export function getVrfClientCallback(
vrfClientProgram: anchor.Program,
clientKey: PublicKey,
vrfKey: PublicKey
): Callback {
const vrfIxCoder = new anchor.BorshInstructionCoder(vrfClientProgram.idl);
const callback: Callback = {
programId: vrfClientProgram.programId,
accounts: [
// ensure all accounts in updateResult are populated
{ pubkey: clientKey, isSigner: false, isWritable: true },
{ pubkey: vrfKey, isSigner: false, isWritable: false },
],
ixData: vrfIxCoder.encode("updateResult", ""), // pass any params for instruction here
};
return callback;
}
// export async function createVrfClient(
// switchboardProgram: anchor.Program,
// vrfKeypair: Keypair
// ): Promise<VrfClient> {}

View File

@ -1,179 +0,0 @@
/**
* This code was GENERATED using the solita package.
* Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality.
*
* See: https://github.com/metaplex-foundation/solita
*/
import * as beet from "@metaplex-foundation/beet";
import * as beetSolana from "@metaplex-foundation/beet-solana";
import * as web3 from "@solana/web3.js";
/**
* Arguments used to create {@link VrfClient}
* @category Accounts
* @category generated
*/
export type VrfClientArgs = {
bump: number;
maxResult: beet.bignum;
resultBuffer: number[] /* size: 32 */;
result: beet.bignum;
lastTimestamp: beet.bignum;
authority: web3.PublicKey;
vrf: web3.PublicKey;
};
const vrfClientDiscriminator = [230, 174, 157, 153, 51, 18, 230, 163];
/**
* Holds the data for the {@link VrfClient} Account and provides de/serialization
* functionality for that data
*
* @category Accounts
* @category generated
*/
export class VrfClient implements VrfClientArgs {
private constructor(
readonly bump: number,
readonly maxResult: beet.bignum,
readonly resultBuffer: number[] /* size: 32 */,
readonly result: beet.bignum,
readonly lastTimestamp: beet.bignum,
readonly authority: web3.PublicKey,
readonly vrf: web3.PublicKey
) {}
/**
* Creates a {@link VrfClient} instance from the provided args.
*/
static fromArgs(args: VrfClientArgs) {
return new VrfClient(
args.bump,
args.maxResult,
args.resultBuffer,
args.result,
args.lastTimestamp,
args.authority,
args.vrf
);
}
/**
* Deserializes the {@link VrfClient} from the data of the provided {@link web3.AccountInfo}.
* @returns a tuple of the account data and the offset up to which the buffer was read to obtain it.
*/
static fromAccountInfo(
accountInfo: web3.AccountInfo<Buffer>,
offset = 0
): [VrfClient, number] {
return VrfClient.deserialize(accountInfo.data, offset);
}
/**
* Retrieves the account info from the provided address and deserializes
* the {@link VrfClient} from its data.
*
* @throws Error if no account info is found at the address or if deserialization fails
*/
static async fromAccountAddress(
connection: web3.Connection,
address: web3.PublicKey
): Promise<VrfClient> {
const accountInfo = await connection.getAccountInfo(address);
if (accountInfo == null) {
throw new Error(`Unable to find VrfClient account at ${address}`);
}
return VrfClient.fromAccountInfo(accountInfo, 0)[0];
}
/**
* Deserializes the {@link VrfClient} from the provided data Buffer.
* @returns a tuple of the account data and the offset up to which the buffer was read to obtain it.
*/
static deserialize(buf: Buffer, offset = 0): [VrfClient, number] {
return vrfClientBeet.deserialize(buf, offset);
}
/**
* Serializes the {@link VrfClient} into a Buffer.
* @returns a tuple of the created Buffer and the offset up to which the buffer was written to store it.
*/
serialize(): [Buffer, number] {
return vrfClientBeet.serialize({
accountDiscriminator: vrfClientDiscriminator,
...this,
});
}
/**
* Returns the byteSize of a {@link Buffer} holding the serialized data of
* {@link VrfClient}
*/
static get byteSize() {
return vrfClientBeet.byteSize;
}
/**
* Fetches the minimum balance needed to exempt an account holding
* {@link VrfClient} data from rent
*
* @param connection used to retrieve the rent exemption information
*/
static async getMinimumBalanceForRentExemption(
connection: web3.Connection,
commitment?: web3.Commitment
): Promise<number> {
return connection.getMinimumBalanceForRentExemption(
VrfClient.byteSize,
commitment
);
}
/**
* Determines if the provided {@link Buffer} has the correct byte size to
* hold {@link VrfClient} data.
*/
static hasCorrectByteSize(buf: Buffer, offset = 0) {
return buf.byteLength - offset === VrfClient.byteSize;
}
/**
* Returns a readable version of {@link VrfClient} properties
* and can be used to convert to JSON and/or logging
*/
pretty() {
return {
bump: this.bump,
maxResult: this.maxResult,
resultBuffer: this.resultBuffer,
result: this.result,
lastTimestamp: this.lastTimestamp,
authority: this.authority.toBase58(),
vrf: this.vrf.toBase58(),
};
}
}
/**
* @category Accounts
* @category generated
*/
export const vrfClientBeet = new beet.BeetStruct<
VrfClient,
VrfClientArgs & {
accountDiscriminator: number[] /* size: 8 */;
}
>(
[
["accountDiscriminator", beet.uniformFixedSizeArray(beet.u8, 8)],
["bump", beet.u8],
["maxResult", beet.u64],
["resultBuffer", beet.uniformFixedSizeArray(beet.u8, 32)],
["result", beet.u128],
["lastTimestamp", beet.i64],
["authority", beetSolana.publicKey],
["vrf", beetSolana.publicKey],
],
VrfClient.fromArgs,
"VrfClient"
);

View File

@ -1 +0,0 @@
export * from "./VrfClient";

View File

@ -1,135 +0,0 @@
/**
* This code was GENERATED using the solita package.
* Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality.
*
* See: https://github.com/metaplex-foundation/solita
*/
type ErrorWithCode = Error & { code: number };
type MaybeErrorWithCode = ErrorWithCode | null | undefined;
const createErrorFromCodeLookup: Map<number, () => ErrorWithCode> = new Map();
const createErrorFromNameLookup: Map<string, () => ErrorWithCode> = new Map();
/**
* InvalidSwitchboardVrfAccount: 'Not a valid Switchboard VRF account'
*
* @category Errors
* @category generated
*/
export class InvalidSwitchboardVrfAccountError extends Error {
readonly code: number = 0x1770;
readonly name: string = "InvalidSwitchboardVrfAccount";
constructor() {
super("Not a valid Switchboard VRF account");
if (typeof Error.captureStackTrace === "function") {
Error.captureStackTrace(this, InvalidSwitchboardVrfAccountError);
}
}
}
createErrorFromCodeLookup.set(
0x1770,
() => new InvalidSwitchboardVrfAccountError()
);
createErrorFromNameLookup.set(
"InvalidSwitchboardVrfAccount",
() => new InvalidSwitchboardVrfAccountError()
);
/**
* MaxResultExceedsMaximum: 'The max result must not exceed u64'
*
* @category Errors
* @category generated
*/
export class MaxResultExceedsMaximumError extends Error {
readonly code: number = 0x1771;
readonly name: string = "MaxResultExceedsMaximum";
constructor() {
super("The max result must not exceed u64");
if (typeof Error.captureStackTrace === "function") {
Error.captureStackTrace(this, MaxResultExceedsMaximumError);
}
}
}
createErrorFromCodeLookup.set(0x1771, () => new MaxResultExceedsMaximumError());
createErrorFromNameLookup.set(
"MaxResultExceedsMaximum",
() => new MaxResultExceedsMaximumError()
);
/**
* EmptyCurrentRoundResult: 'Current round result is empty'
*
* @category Errors
* @category generated
*/
export class EmptyCurrentRoundResultError extends Error {
readonly code: number = 0x1772;
readonly name: string = "EmptyCurrentRoundResult";
constructor() {
super("Current round result is empty");
if (typeof Error.captureStackTrace === "function") {
Error.captureStackTrace(this, EmptyCurrentRoundResultError);
}
}
}
createErrorFromCodeLookup.set(0x1772, () => new EmptyCurrentRoundResultError());
createErrorFromNameLookup.set(
"EmptyCurrentRoundResult",
() => new EmptyCurrentRoundResultError()
);
/**
* InvalidAuthorityError: 'Invalid authority account provided.'
*
* @category Errors
* @category generated
*/
export class InvalidAuthorityErrorError extends Error {
readonly code: number = 0x1773;
readonly name: string = "InvalidAuthorityError";
constructor() {
super("Invalid authority account provided.");
if (typeof Error.captureStackTrace === "function") {
Error.captureStackTrace(this, InvalidAuthorityErrorError);
}
}
}
createErrorFromCodeLookup.set(0x1773, () => new InvalidAuthorityErrorError());
createErrorFromNameLookup.set(
"InvalidAuthorityError",
() => new InvalidAuthorityErrorError()
);
/**
* Attempts to resolve a custom program error from the provided error code.
* @category Errors
* @category generated
*/
export function errorFromCode(code: number): MaybeErrorWithCode {
const createError = createErrorFromCodeLookup.get(code);
return createError != null ? createError() : null;
}
/**
* Attempts to resolve a custom program error from the provided error name, i.e. 'Unauthorized'.
* @category Errors
* @category generated
*/
export function errorFromName(name: string): MaybeErrorWithCode {
const createError = createErrorFromNameLookup.get(name);
return createError != null ? createError() : null;
}

View File

@ -1,21 +0,0 @@
import { PublicKey } from "@solana/web3.js";
export * from "./accounts";
export * from "./errors";
export * from "./instructions";
export * from "./types";
/**
* Program address
*
* @category constants
* @category generated
*/
export const PROGRAM_ADDRESS = "FAnbznqZvZ7eijxQ6mKPoyDdM33o8cdM6wsUZtv2dFib";
/**
* Program publick key
*
* @category constants
* @category generated
*/
export const PROGRAM_ID = new PublicKey(PROGRAM_ADDRESS);

View File

@ -1,3 +0,0 @@
export * from "./initState";
export * from "./requestResult";
export * from "./updateResult";

View File

@ -1,107 +0,0 @@
/**
* This code was GENERATED using the solita package.
* Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality.
*
* See: https://github.com/metaplex-foundation/solita
*/
import * as beet from "@metaplex-foundation/beet";
import * as web3 from "@solana/web3.js";
import { InitStateParams, initStateParamsBeet } from "../types/InitStateParams";
/**
* @category Instructions
* @category InitState
* @category generated
*/
export type InitStateInstructionArgs = {
params: InitStateParams;
};
/**
* @category Instructions
* @category InitState
* @category generated
*/
const initStateStruct = new beet.BeetArgsStruct<
InitStateInstructionArgs & {
instructionDiscriminator: number[] /* size: 8 */;
}
>(
[
["instructionDiscriminator", beet.uniformFixedSizeArray(beet.u8, 8)],
["params", initStateParamsBeet],
],
"InitStateInstructionArgs"
);
/**
* Accounts required by the _initState_ instruction
* @category Instructions
* @category InitState
* @category generated
*/
export type InitStateInstructionAccounts = {
state: web3.PublicKey;
authority: web3.PublicKey;
payer: web3.PublicKey;
vrf: web3.PublicKey;
};
const initStateInstructionDiscriminator = [124, 213, 73, 136, 80, 37, 141, 54];
/**
* Creates a _InitState_ instruction.
*
* @param accounts that will be accessed while the instruction is processed
* @param args to provide as instruction data to the program
*
* @category Instructions
* @category InitState
* @category generated
*/
export function createInitStateInstruction(
accounts: InitStateInstructionAccounts,
args: InitStateInstructionArgs
) {
const { state, authority, payer, vrf } = accounts;
const [data] = initStateStruct.serialize({
instructionDiscriminator: initStateInstructionDiscriminator,
...args,
});
const keys: web3.AccountMeta[] = [
{
pubkey: state,
isWritable: true,
isSigner: false,
},
{
pubkey: authority,
isWritable: false,
isSigner: false,
},
{
pubkey: payer,
isWritable: true,
isSigner: true,
},
{
pubkey: vrf,
isWritable: false,
isSigner: false,
},
{
pubkey: web3.SystemProgram.programId,
isWritable: false,
isSigner: false,
},
];
const ix = new web3.TransactionInstruction({
programId: new web3.PublicKey(
"FAnbznqZvZ7eijxQ6mKPoyDdM33o8cdM6wsUZtv2dFib"
),
keys,
data,
});
return ix;
}

View File

@ -1,181 +0,0 @@
/**
* This code was GENERATED using the solita package.
* Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality.
*
* See: https://github.com/metaplex-foundation/solita
*/
import * as beet from "@metaplex-foundation/beet";
import * as splToken from "@solana/spl-token";
import * as web3 from "@solana/web3.js";
import {
RequestResultParams,
requestResultParamsBeet,
} from "../types/RequestResultParams";
/**
* @category Instructions
* @category RequestResult
* @category generated
*/
export type RequestResultInstructionArgs = {
params: RequestResultParams;
};
/**
* @category Instructions
* @category RequestResult
* @category generated
*/
const requestResultStruct = new beet.BeetArgsStruct<
RequestResultInstructionArgs & {
instructionDiscriminator: number[] /* size: 8 */;
}
>(
[
["instructionDiscriminator", beet.uniformFixedSizeArray(beet.u8, 8)],
["params", requestResultParamsBeet],
],
"RequestResultInstructionArgs"
);
/**
* Accounts required by the _requestResult_ instruction
* @category Instructions
* @category RequestResult
* @category generated
*/
export type RequestResultInstructionAccounts = {
state: web3.PublicKey;
authority: web3.PublicKey;
switchboardProgram: web3.PublicKey;
vrf: web3.PublicKey;
oracleQueue: web3.PublicKey;
queueAuthority: web3.PublicKey;
dataBuffer: web3.PublicKey;
permission: web3.PublicKey;
escrow: web3.PublicKey;
payerWallet: web3.PublicKey;
payerAuthority: web3.PublicKey;
recentBlockhashes: web3.PublicKey;
programState: web3.PublicKey;
};
const requestResultInstructionDiscriminator = [
52, 47, 170, 99, 27, 80, 113, 141,
];
/**
* Creates a _RequestResult_ instruction.
*
* @param accounts that will be accessed while the instruction is processed
* @param args to provide as instruction data to the program
*
* @category Instructions
* @category RequestResult
* @category generated
*/
export function createRequestResultInstruction(
accounts: RequestResultInstructionAccounts,
args: RequestResultInstructionArgs
) {
const {
state,
authority,
switchboardProgram,
vrf,
oracleQueue,
queueAuthority,
dataBuffer,
permission,
escrow,
payerWallet,
payerAuthority,
recentBlockhashes,
programState,
} = accounts;
const [data] = requestResultStruct.serialize({
instructionDiscriminator: requestResultInstructionDiscriminator,
...args,
});
const keys: web3.AccountMeta[] = [
{
pubkey: state,
isWritable: true,
isSigner: false,
},
{
pubkey: authority,
isWritable: false,
isSigner: true,
},
{
pubkey: switchboardProgram,
isWritable: false,
isSigner: false,
},
{
pubkey: vrf,
isWritable: true,
isSigner: false,
},
{
pubkey: oracleQueue,
isWritable: true,
isSigner: false,
},
{
pubkey: queueAuthority,
isWritable: false,
isSigner: false,
},
{
pubkey: dataBuffer,
isWritable: false,
isSigner: false,
},
{
pubkey: permission,
isWritable: true,
isSigner: false,
},
{
pubkey: escrow,
isWritable: true,
isSigner: false,
},
{
pubkey: payerWallet,
isWritable: true,
isSigner: false,
},
{
pubkey: payerAuthority,
isWritable: false,
isSigner: true,
},
{
pubkey: recentBlockhashes,
isWritable: false,
isSigner: false,
},
{
pubkey: programState,
isWritable: false,
isSigner: false,
},
{
pubkey: splToken.TOKEN_PROGRAM_ID,
isWritable: false,
isSigner: false,
},
];
const ix = new web3.TransactionInstruction({
programId: new web3.PublicKey(
"FAnbznqZvZ7eijxQ6mKPoyDdM33o8cdM6wsUZtv2dFib"
),
keys,
data,
});
return ix;
}

View File

@ -1,73 +0,0 @@
/**
* This code was GENERATED using the solita package.
* Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality.
*
* See: https://github.com/metaplex-foundation/solita
*/
import * as beet from "@metaplex-foundation/beet";
import * as web3 from "@solana/web3.js";
/**
* @category Instructions
* @category UpdateResult
* @category generated
*/
const updateResultStruct = new beet.BeetArgsStruct<{
instructionDiscriminator: number[] /* size: 8 */;
}>(
[["instructionDiscriminator", beet.uniformFixedSizeArray(beet.u8, 8)]],
"UpdateResultInstructionArgs"
);
/**
* Accounts required by the _updateResult_ instruction
* @category Instructions
* @category UpdateResult
* @category generated
*/
export type UpdateResultInstructionAccounts = {
state: web3.PublicKey;
vrf: web3.PublicKey;
};
const updateResultInstructionDiscriminator = [145, 72, 9, 94, 61, 97, 126, 106];
/**
* Creates a _UpdateResult_ instruction.
*
* @param accounts that will be accessed while the instruction is processed
*
* @category Instructions
* @category UpdateResult
* @category generated
*/
export function createUpdateResultInstruction(
accounts: UpdateResultInstructionAccounts
) {
const { state, vrf } = accounts;
const [data] = updateResultStruct.serialize({
instructionDiscriminator: updateResultInstructionDiscriminator,
});
const keys: web3.AccountMeta[] = [
{
pubkey: state,
isWritable: true,
isSigner: false,
},
{
pubkey: vrf,
isWritable: false,
isSigner: false,
},
];
const ix = new web3.TransactionInstruction({
programId: new web3.PublicKey(
"FAnbznqZvZ7eijxQ6mKPoyDdM33o8cdM6wsUZtv2dFib"
),
keys,
data,
});
return ix;
}

View File

@ -1,20 +0,0 @@
/**
* This code was GENERATED using the solita package.
* Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality.
*
* See: https://github.com/metaplex-foundation/solita
*/
import * as beet from "@metaplex-foundation/beet";
export type InitStateParams = {
maxResult: beet.bignum;
};
/**
* @category userTypes
* @category generated
*/
export const initStateParamsBeet = new beet.BeetArgsStruct<InitStateParams>(
[["maxResult", beet.u64]],
"InitStateParams"
);

View File

@ -1,25 +0,0 @@
/**
* This code was GENERATED using the solita package.
* Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality.
*
* See: https://github.com/metaplex-foundation/solita
*/
import * as beet from "@metaplex-foundation/beet";
export type RequestResultParams = {
permissionBump: number;
switchboardStateBump: number;
};
/**
* @category userTypes
* @category generated
*/
export const requestResultParamsBeet =
new beet.BeetArgsStruct<RequestResultParams>(
[
["permissionBump", beet.u8],
["switchboardStateBump", beet.u8],
],
"RequestResultParams"
);

View File

@ -1,2 +0,0 @@
export * from "./InitStateParams";
export * from "./RequestResultParams";

View File

@ -1,2 +0,0 @@
export * from "./api";
export * from "./generated";

View File

@ -4,7 +4,7 @@ pub use actions::*;
pub use anchor_lang::prelude::*;
use anchor_spl::token::TokenAccount;
declare_id!("FAnbznqZvZ7eijxQ6mKPoyDdM33o8cdM6wsUZtv2dFib");
declare_id!("HWCUJF1GgCrS1fWNyJdWSBEVNXtdjRwQy7HohdQ5n31o");
const MAX_RESULT: u64 = u64::MAX;

View File

@ -1,205 +0,0 @@
import * as anchor from "@project-serum/anchor";
import NodeWallet from "@project-serum/anchor/dist/cjs/nodewallet";
import * as spl from "@solana/spl-token";
import {
PublicKey,
SystemProgram,
SYSVAR_RECENT_BLOCKHASHES_PUBKEY,
} from "@solana/web3.js";
import {
loadSwitchboardProgram,
OracleQueueAccount,
PermissionAccount,
ProgramStateAccount,
SwitchboardPermission,
VrfAccount,
} from "@switchboard-xyz/switchboard-v2";
import chai from "chai";
import "mocha";
import { getVrfClientCallback, getVrfClientFromSeed } from "../src/api";
import { VrfClient } from "../src/generated";
import type { AnchorVrfParser } from "../target/types/anchor_vrf_parser";
import { promiseWithTimeout } from "./test-utils";
const expect = chai.expect;
describe("creates a vrf account on the devnet permissionless queue", async () => {
anchor.setProvider(anchor.AnchorProvider.env());
const vrfClientProgram = anchor.workspace
.AnchorVrfParser as anchor.Program<AnchorVrfParser>;
const payer = (
(vrfClientProgram.provider as anchor.AnchorProvider).wallet as NodeWallet
).payer;
const vrfSecret = anchor.web3.Keypair.generate();
// create state account but dont send instruction
// need public key for VRF CPI
const [vrfClientKey, vrfClientBump] = getVrfClientFromSeed(
vrfClientProgram as any,
vrfSecret.publicKey,
payer.publicKey // client state authority
);
const vrfClientCallback = getVrfClientCallback(
vrfClientProgram as any,
vrfClientKey,
vrfSecret.publicKey
);
it("Creates a vrfClient account", async () => {
let switchboardProgram: anchor.Program;
try {
switchboardProgram = await loadSwitchboardProgram(
"devnet",
vrfClientProgram.provider.connection,
payer
);
} catch {
console.log(`might not be connected to devnet - test exiting`);
return;
}
// override queue
const queue = new OracleQueueAccount({
program: switchboardProgram,
publicKey: new PublicKey("F8ce7MsckeZAbAGmxjJNetxYXQa9mKr9nnrC3qKubyYy"),
});
const { unpermissionedVrfEnabled, authority, dataBuffer } =
await queue.loadData();
// Create Switchboard VRF and Permission account
const vrfAccount = await VrfAccount.create(switchboardProgram, {
queue,
callback: vrfClientCallback,
authority: vrfClientKey, // vrf authority
keypair: vrfSecret,
});
const { escrow } = await vrfAccount.loadData();
console.log(`Created VRF Account: ${vrfAccount.publicKey}`);
const permissionAccount = await PermissionAccount.create(
switchboardProgram,
{
authority,
granter: queue.publicKey,
grantee: vrfAccount.publicKey,
}
);
console.log(`Created Permission Account: ${permissionAccount.publicKey}`);
// If queue requires permissions to use VRF, check the correct authority was provided
if (!unpermissionedVrfEnabled) {
if (!payer.publicKey.equals(authority)) {
throw new Error(
`queue requires PERMIT_VRF_REQUESTS and wrong queue authority provided`
);
}
await permissionAccount.set({
authority: payer,
permission: SwitchboardPermission.PERMIT_VRF_REQUESTS,
enable: true,
});
console.log(`Set VRF Permissions`);
}
// Create VRF Client account
await vrfClientProgram.rpc.initState(
{
maxResult: new anchor.BN(1),
},
{
accounts: {
state: vrfClientKey,
vrf: vrfAccount.publicKey,
payer: payer.publicKey,
authority: payer.publicKey,
systemProgram: SystemProgram.programId,
},
}
);
console.log(`Created VrfClient Account: ${vrfClientKey}`);
// Get required switchboard accounts
const [programStateAccount, programStateBump] =
ProgramStateAccount.fromSeed(switchboardProgram);
const [permissionKey, permissionBump] = PermissionAccount.fromSeed(
switchboardProgram,
authority,
queue.publicKey,
vrfAccount.publicKey
);
const switchboardMint = await programStateAccount.getTokenMint();
const payerTokenAccount =
await switchboardMint.getOrCreateAssociatedAccountInfo(payer.publicKey);
// Request randomness
console.log(`Sending RequestRandomness instruction`);
const requestTxn = await vrfClientProgram.rpc.requestResult(
{
switchboardStateBump: programStateBump,
permissionBump,
},
{
accounts: {
state: vrfClientKey,
authority: payer.publicKey,
switchboardProgram: switchboardProgram.programId,
vrf: vrfAccount.publicKey,
oracleQueue: queue.publicKey,
queueAuthority: authority,
dataBuffer,
permission: permissionAccount.publicKey,
escrow,
payerWallet: payerTokenAccount.address,
payerAuthority: payer.publicKey,
recentBlockhashes: SYSVAR_RECENT_BLOCKHASHES_PUBKEY,
programState: programStateAccount.publicKey,
tokenProgram: spl.TOKEN_PROGRAM_ID,
},
signers: [payer, payer],
}
);
const vrfClientAccountDecoder = new anchor.BorshAccountsCoder(
vrfClientProgram.idl
);
let ws: number;
const waitForEventPromise = new Promise(
(resolve: (result: anchor.BN) => void) => {
ws = vrfClientProgram.addEventListener(
"VrfClientResultUpdated",
async (event: any, slot: number) => {
console.log("VrfClientResultUpdated invoked");
resolve(event.result as anchor.BN);
}
);
}
);
const awaitResult = await promiseWithTimeout(
30_000,
waitForEventPromise
).finally(() => {
try {
vrfClientProgram.provider.connection.removeAccountChangeListener(ws);
} catch {}
});
if (!awaitResult) {
throw new Error(`failed to get a VRF result`);
}
console.log(JSON.stringify(awaitResult, undefined, 2));
const vrfClient = await VrfClient.fromAccountAddress(
vrfClientProgram.provider.connection,
vrfClientKey
);
console.log(`VrfClient Result: ${vrfClient.result}`);
});
});

View File

@ -1,17 +0,0 @@
export const sleep = (ms: number): Promise<any> =>
new Promise((s) => setTimeout(s, ms));
export async function promiseWithTimeout<T>(
ms: number,
promise: Promise<T>,
timeoutError = new Error("timeoutError")
): Promise<T> {
// create a promise that rejects in milliseconds
const timeout = new Promise<never>((_, reject) => {
setTimeout(() => {
reject(timeoutError);
}, ms);
});
return Promise.race<T>([promise, timeout]);
}

View File

@ -1,58 +1,95 @@
import * as anchor from "@project-serum/anchor";
import NodeWallet from "@project-serum/anchor/dist/cjs/nodewallet";
import type NodeWallet from "@project-serum/anchor/dist/cjs/nodewallet";
import * as spl from "@solana/spl-token";
import {
AccountInfo,
Context,
PublicKey,
SystemProgram,
SYSVAR_RECENT_BLOCKHASHES_PUBKEY,
} from "@solana/web3.js";
import {
OracleAccount,
promiseWithTimeout,
SwitchboardTestContext,
} from "@switchboard-xyz/sbv2-utils";
import {
Callback,
PermissionAccount,
ProgramStateAccount,
SwitchboardPermission,
SwitchboardTestContext,
VrfAccount,
} from "@switchboard-xyz/switchboard-v2";
import chai from "chai";
import "mocha";
import { getVrfClientCallback, getVrfClientFromSeed } from "../src/api";
import { VrfClient } from "../src/generated";
import type { AnchorVrfParser } from "../target/types/anchor_vrf_parser";
import { promiseWithTimeout } from "./test-utils";
import type { AnchorVrfParser } from "../../../target/types/anchor_vrf_parser";
const expect = chai.expect;
interface VrfClientState {
bump: number;
maxResult: anchor.BN;
resultBuffer: number[];
result: anchor.BN;
lastTimestamp: anchor.BN;
authority: PublicKey;
vrf: PublicKey;
}
describe("vrfClient test", async () => {
anchor.setProvider(anchor.AnchorProvider.env());
const vrfClientProgram = anchor.workspace
.AnchorVrfParser as anchor.Program<AnchorVrfParser>;
const payer = (
(vrfClientProgram.provider as anchor.AnchorProvider).wallet as NodeWallet
).payer;
const provider = vrfClientProgram.provider as anchor.AnchorProvider;
const payer = (provider.wallet as NodeWallet).payer;
let switchboard: SwitchboardTestContext;
const vrfSecret = anchor.web3.Keypair.generate();
// create state account but dont send instruction
// need public key for VRF CPI
const [vrfClientKey, vrfClientBump] = getVrfClientFromSeed(
vrfClientProgram as any,
vrfSecret.publicKey,
payer.publicKey // client state authority
);
const [vrfClientKey, vrfClientBump] =
anchor.utils.publicKey.findProgramAddressSync(
[
Buffer.from("STATE"),
vrfSecret.publicKey.toBytes(),
payer.publicKey.toBytes(),
],
vrfClientProgram.programId
);
const vrfClientCallback = getVrfClientCallback(
vrfClientProgram as any,
vrfClientKey,
vrfSecret.publicKey
);
const vrfIxCoder = new anchor.BorshInstructionCoder(vrfClientProgram.idl);
const vrfClientCallback: Callback = {
programId: vrfClientProgram.programId,
accounts: [
// ensure all accounts in updateResult are populated
{ pubkey: vrfClientKey, isSigner: false, isWritable: true },
{ pubkey: vrfSecret.publicKey, isSigner: false, isWritable: false },
],
ixData: vrfIxCoder.encode("updateResult", ""), // pass any params for instruction here
};
before(async () => {
// First, attempt to load the switchboard devnet PID
try {
switchboard = await SwitchboardTestContext.loadDevnetQueue(provider);
console.log("devnet detected");
return;
} catch (error) {
console.log(error);
}
// If exists, try to load the devnet permissionless queue
// If fails, fallback to looking for a local env file
try {
switchboard = await SwitchboardTestContext.loadFromEnv(provider);
console.log("localnet detected");
return;
} catch (error) {
console.log(error);
}
// If fails, throw error
// TODO: Add try catch block to check devnet environment accounts
switchboard = await SwitchboardTestContext.loadFromEnv(
vrfClientProgram.provider as anchor.AnchorProvider
throw new Error(
`Failed to load the SwitchboardTestContext from devnet or from a switchboard.env file`
);
});
@ -129,85 +166,77 @@ describe("vrfClient test", async () => {
// Request randomness
console.log(`Sending RequestRandomness instruction`);
const requestTxn = await vrfClientProgram.rpc.requestResult(
{
const requestTxn = await vrfClientProgram.methods
.requestResult({
switchboardStateBump: programStateBump,
permissionBump,
},
{
accounts: {
state: vrfClientKey,
authority: payer.publicKey,
switchboardProgram: switchboard.program.programId,
vrf: vrfAccount.publicKey,
oracleQueue: queue.publicKey,
queueAuthority: authority,
dataBuffer,
permission: permissionAccount.publicKey,
escrow,
payerWallet: payerTokenAccount.address,
payerAuthority: payer.publicKey,
recentBlockhashes: SYSVAR_RECENT_BLOCKHASHES_PUBKEY,
programState: programStateAccount.publicKey,
tokenProgram: spl.TOKEN_PROGRAM_ID,
},
signers: [payer, payer],
}
);
})
.accounts({
state: vrfClientKey,
authority: payer.publicKey,
switchboardProgram: switchboard.program.programId,
vrf: vrfAccount.publicKey,
oracleQueue: queue.publicKey,
queueAuthority: authority,
dataBuffer,
permission: permissionAccount.publicKey,
escrow,
payerWallet: payerTokenAccount.address,
payerAuthority: payer.publicKey,
recentBlockhashes: SYSVAR_RECENT_BLOCKHASHES_PUBKEY,
programState: programStateAccount.publicKey,
tokenProgram: spl.TOKEN_PROGRAM_ID,
})
.signers([payer, payer])
.rpc();
const vrfClientAccountDecoder = new anchor.BorshAccountsCoder(
const vrfClientAccountCoder = new anchor.BorshAccountsCoder(
vrfClientProgram.idl
);
let ws: number;
const waitToCrankPromise = new Promise(
(resolve: (result: string[]) => void) => {
ws = switchboard.program.addEventListener(
"VrfProveEvent",
async (event: any, slot: number) => {
console.log("VrfProveEvent invoked");
if (!vrfSecret.publicKey.equals(event.vrfPubkey)) {
console.log(`not the same vrfKey`);
return;
// watch VrfClientState for a populated result
let ws: number | undefined = undefined;
const waitForResultPromise = new Promise(
(
resolve: (result: anchor.BN) => void,
reject: (reason: string) => void
) => {
try {
ws = vrfClientProgram.provider.connection.onAccountChange(
vrfClientKey,
async (accountInfo: AccountInfo<Buffer>, context: Context) => {
const clientState: VrfClientState = vrfClientAccountCoder.decode(
"VrfClient",
accountInfo.data
);
if (clientState.result.gt(new anchor.BN(0))) {
resolve(clientState.result);
}
}
const vrf = await vrfAccount.loadData();
const round = vrf.builders[0];
if (round.status.statusVerifying) {
console.log(`Ready to turn the crank`);
const oracle = new OracleAccount({
program: switchboard.program,
publicKey: round.producer,
});
const txns = await vrfAccount.verify(oracle);
resolve(txns);
}
}
);
);
} catch (error: any) {
reject(error);
}
}
);
const awaitResult = await promiseWithTimeout(
20_000,
waitToCrankPromise
).finally(() => {
try {
vrfClientProgram.provider.connection.removeAccountChangeListener(ws);
} catch {}
});
if (!awaitResult) {
let result: anchor.BN;
try {
result = await promiseWithTimeout(30_000, waitForResultPromise);
} catch (error) {
throw error;
} finally {
if (ws) {
await vrfClientProgram.provider.connection.removeAccountChangeListener(
ws
);
}
}
if (!result) {
throw new Error(`failed to get a VRF result`);
}
console.log(JSON.stringify(awaitResult, undefined, 2));
const vrfClient = await VrfClient.fromAccountAddress(
vrfClientProgram.provider.connection,
vrfClientKey
);
console.log(`VrfClient Result: ${vrfClient.result}`);
console.log(`VrfClient Result: ${result}`);
});
});

View File

@ -9,16 +9,20 @@
"types": ["mocha", "chai", "node"],
"typeRoots": ["./node_modules/@types"],
"lib": ["es2015"],
"outDir": "lib",
"module": "commonjs",
"target": "es6",
"esModuleInterop": true,
"importsNotUsedAsValues": "remove",
"noEmit": true,
"paths": {
"@switchboard-xyz/switchboard-v2": ["../../libraries/ts"]
"@switchboard-xyz/switchboard-v2": ["../../libraries/ts"],
"@switchboard-xyz/sbv2-utils": ["../../libraries/sbv2-utils"]
}
},
"include": ["src/**/*"],
"include": ["client/**/*"],
"exclude": ["target", "lib"],
"references": [{ "path": "../../libraries/ts" }]
"references": [
{ "path": "../../libraries/ts" },
{ "path": "../../libraries/sbv2-utils" }
]
}

View File

@ -1,6 +0,0 @@
.anchor
.DS_Store
target
**/*.rs.bk
node_modules

View File

@ -3,12 +3,15 @@ name = "spl-feed-parser"
version = "0.1.0"
edition = "2018"
[lib]
crate-type = ["cdylib", "lib"]
name = "spl_feed_parser"
[features]
no-entrypoint = []
[dependencies]
switchboard-v2 = "^0.1.10"
switchboard-v2 = { path = "../../libraries/rs" }
# switchboard-v2 = "^0.1.10"
solana-program = "~1.9.13"
[lib]
crate-type = ["cdylib", "lib"]

View File

@ -8,13 +8,15 @@
"directory": "programs/spl-feed-parser"
},
"scripts": {
"build": "cargo build-bpf --manifest-path=Cargo.toml",
"build": "echo \"For workspace spl-feed-parser, run 'anchor build' from the project root\" && exit 0",
"build:bpf": "cargo build-bpf --manifest-path=Cargo.toml",
"deploy": "solana program deploy target/deploy/spl_feed_parser.so",
"anchor:test": "echo \"No anchor:test script for spl-feed-parser\" && exit 0",
"test": "echo \"For workspace spl-feed-parser, use the anchor:test script\" && exit 0"
},
"dependencies": {
"@solana/web3.js": "^1.37.1"
"@project-serum/anchor": "^0.24.2",
"@solana/web3.js": "^1.37.1",
"@switchboard-xyz/switchboard-v2": "^0.0.97"
},
"devDependencies": {
"@types/chai": "^4.3.0",

View File

@ -0,0 +1,54 @@
import type { Program } from "@project-serum/anchor";
import * as anchor from "@project-serum/anchor";
import { PublicKey } from "@solana/web3.js";
import { SwitchboardTestContext } from "@switchboard-xyz/switchboard-v2";
import type { AnchorFeedParser } from "../../../target/types/anchor_feed_parser";
const sleep = (ms: number): Promise<any> =>
new Promise((s) => setTimeout(s, ms));
// Anchor.toml will copy this to localnet when we start our tests
const DEFAULT_SOL_USD_FEED = new PublicKey(
"GvDMxPzN1sCj7L26YDK2HnMRXEQmQ2aemov8YBtPS7vR"
);
describe("anchor-feed-parser", () => {
anchor.setProvider(anchor.AnchorProvider.env());
const feedParserProgram = anchor.workspace
.AnchorFeedParser as Program<AnchorFeedParser>;
const provider = feedParserProgram.provider as anchor.AnchorProvider;
let aggregatorKey: PublicKey;
before(async () => {
const accountInfo = await provider.connection.getAccountInfo(
DEFAULT_SOL_USD_FEED
);
if (accountInfo) {
aggregatorKey = DEFAULT_SOL_USD_FEED;
return;
}
// create an aggregator
try {
const switchboard = await SwitchboardTestContext.loadFromEnv(provider);
const staticFeed = await switchboard.createStaticFeed(100);
if (!staticFeed.publicKey) {
throw new Error("failed to read aggregatorKey");
}
aggregatorKey = staticFeed.publicKey;
console.log(`created aggregator ${aggregatorKey}`);
await sleep(2000);
} catch (error) {
console.error(error);
throw new Error(
`failed to load switchboard aggregator or switchboard.env`
);
}
});
it("Read SOL/USD Feed", async () => {
return;
});
});

View File

@ -1,2 +0,0 @@
// TODO: Add mocha test
export {};

View File

@ -7,11 +7,12 @@
"module": "commonjs",
"target": "es6",
"esModuleInterop": true,
"noEmit": true,
"paths": {
"@switchboard-xyz/switchboard-v2": ["../../libraries/ts"]
}
},
"include": ["tests/**/*"],
"include": ["oldtests/**/**/*"],
"exclude": ["target"],
"references": [{ "path": "../../libraries/ts" }]
}

View File

@ -0,0 +1,159 @@
#!/usr/bin/env node
/* eslint-disable @typescript-eslint/no-var-requires */
/* eslint-disable import/no-extraneous-dependencies */
const shell = require("shelljs");
const { exec, spawn, execSync, spawnSync } = require("child_process");
const web3 = require("@solana/web3.js");
const fs = require("fs");
const path = require("path");
const projectRoot = path.join(__dirname, "..");
const targetDir = path.join(projectRoot, "target");
const idlDir = path.join(targetDir, "idl");
const anchorToml = path.join(projectRoot, "Anchor.toml");
const anchorClientGen = path.join(
projectRoot,
"node_modules",
".bin",
"anchor-client-gen"
);
const shx = path.join(projectRoot, "node_modules", ".bin", "shx");
const anchorVrfKeypairPath = path.join(
targetDir,
"deploy",
"anchor_vrf_parser-keypair.json"
);
const anchorFeedKeypairPath = path.join(
targetDir,
"deploy",
"anchor_feed_parser-keypair.json"
);
const splFeedKeypairPath = path.join(
targetDir,
"deploy",
"spl_feed_parser-keypair.json"
);
async function main() {
shell.cd(projectRoot);
if (!shell.which("solana")) {
shell.echo(
"Sorry, this script requires 'solana' to be installed in your $PATH"
);
shell.exit(1);
}
if (!shell.which("anchor")) {
shell.echo(
"Sorry, this script requires 'anchor' to be installed in your $PATH"
);
shell.exit(1);
}
if (!fs.existsSync(path.join(targetDir, "deploy"))) {
shell.echo("Missing program deploy keypairs, building projects");
const anchorBuildSpawn = spawn("anchor", ["build"]);
anchorBuildSpawn.stdout.on("data", function (msg) {
console.log(msg.toString());
});
await new Promise((resolve) => {
anchorBuildSpawn.on("close", resolve);
});
}
const anchorVrfParserPid = web3.Keypair.fromSecretKey(
new Uint8Array(JSON.parse(fs.readFileSync(anchorVrfKeypairPath, "utf8")))
).publicKey;
const anchorFeedParserPid = web3.Keypair.fromSecretKey(
new Uint8Array(JSON.parse(fs.readFileSync(anchorFeedKeypairPath, "utf8")))
).publicKey;
const splFeedParserPid = web3.Keypair.fromSecretKey(
new Uint8Array(JSON.parse(fs.readFileSync(splFeedKeypairPath, "utf8")))
).publicKey;
// REPLACE ANCHOR-VRF-PROGRAM IDS
console.log(`Anchor VRF Parser PID: ${anchorVrfParserPid}`);
shell.sed(
"-i",
/declare_id!(.*);/,
`declare_id!("${anchorVrfParserPid.toString()}");`,
path.join(projectRoot, "programs", "anchor-vrf-parser", "src", "lib.rs")
);
shell.sed(
"-i",
/anchor_vrf_parser = "(.*)"/,
`anchor_vrf_parser = "${anchorVrfParserPid.toString()}"`,
anchorToml
);
console.log(`Anchor Feed Parser PID: ${anchorFeedParserPid}`);
shell.sed(
"-i",
/declare_id!(.*);/,
`declare_id!("${anchorFeedParserPid.toString()}");`,
path.join(projectRoot, "programs", "anchor-feed-parser", "src", "lib.rs")
);
shell.sed(
"-i",
/anchor_feed_parser = "(.*)"/,
`anchor_feed_parser = "${anchorFeedParserPid.toString()}"`,
anchorToml
);
console.log(`SPL Feed Parser PID: ${splFeedParserPid}`);
shell.sed(
"-i",
/declare_id!(.*);/,
`declare_id!("${splFeedParserPid.toString()}");`,
path.join(projectRoot, "programs", "spl-feed-parser", "src", "lib.rs")
);
shell.sed(
"-i",
/spl_feed_parser = "(.*)"/,
`spl_feed_parser = "${splFeedParserPid.toString()}"`,
anchorToml
);
// Build Anchor APIs
const vrfClientPath = path.join(
projectRoot,
"programs",
"anchor-vrf-parser",
"client"
);
shell.rm("-rf", vrfClientPath);
fs.mkdirSync(vrfClientPath, { recursive: true });
execSync(
`node ${anchorClientGen} ${path.join(
idlDir,
"anchor_vrf_parser.json"
)} ${vrfClientPath} --program-id ${anchorVrfParserPid.toString()}`
);
const feedClientPath = path.join(
projectRoot,
"programs",
"anchor-feed-parser",
"client"
);
shell.rm("-rf", feedClientPath);
fs.mkdirSync(feedClientPath, { recursive: true });
execSync(
`node ${anchorClientGen} ${path.join(
idlDir,
"anchor_feed_parser.json"
)} ${feedClientPath} --program-id ${anchorFeedParserPid.toString()}`
);
}
main()
.then(() => {
// console.log("Executed successfully");
})
.catch((err) => {
console.error(err);
});

4766
switchboard_v2.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -52,6 +52,7 @@
"types": [
"node",
"mocha",
"chai",
"long"
] /* Specify type package names to be included without being referenced in a source file. */,
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
@ -71,7 +72,7 @@
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */
// "outDir": "./", /* Specify an output folder for all emitted files. */
// "removeComments": true, /* Disable emitting comments. */
// "noEmit": true, /* Disable emitting files from a compilation. */
"noEmit": true /* Disable emitting files from a compilation. */,
"importHelpers": true /* Allow importing helper functions from tslib once per project, instead of including them per-file. */,
"importsNotUsedAsValues": "error" /* Specify emit/checking behavior for imports that are only used for types */,
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */

View File

@ -5,82 +5,82 @@ title: Errors
## Anchor Errors
See [@project-serum/anchor/src/error.ts#L53](https://github.com/project-serum/anchor/blob/HEAD/ts/src/error.ts#L53) for a list of built-in Anchor errors.
See [docs.rs/anchor-lang/latest/anchor_lang/error](https://docs.rs/anchor-lang/latest/anchor_lang/error/enum.ErrorCode.html) for a list of built-in Anchor errors.
## Switchboard Errors
| Code | Hex | Name | Message |
| ---- | ------ | -------------------------------- | --------------------------------------------------------------------------- |
| 6000 | 0x0x1770 | ArrayOperationError | Illegal operation on a Switchboard array. |
| 6001 | 0x0x1771 | QueueOperationError | Illegal operation on a Switchboard queue. |
| 6002 | 0x0x1772 | IncorrectProgramOwnerError | An account required to be owned by the program has a different owner. |
| 6003 | 0x0x1773 | InvalidAggregatorRound | Aggregator is not currently populated with a valid round. |
| 6004 | 0x0x1774 | TooManyAggregatorJobs | Aggregator cannot fit any more jobs. |
| 6005 | 0x0x1775 | AggregatorCurrentRoundClosed | Aggregator's current round is closed. No results are being accepted. |
| 6006 | 0x0x1776 | AggregatorInvalidSaveResult | Aggregator received an invalid save result instruction. |
| 6007 | 0x0x1777 | InvalidStrDecimalConversion | Failed to convert string to decimal format. |
| 6008 | 0x0x1778 | AccountLoaderMissingSignature | AccountLoader account is missing a required signature. |
| 6009 | 0x0x1779 | MissingRequiredSignature | Account is missing a required signature. |
| 6010 | 0x0x177a | ArrayOverflowError | The attempted action will overflow a zero-copy account array. |
| 6011 | 0x0x177b | ArrayUnderflowError | The attempted action will underflow a zero-copy account array. |
| 6012 | 0x0x177c | PubkeyNotFoundError | The queried public key was not found. |
| 6013 | 0x0x177d | AggregatorIllegalRoundOpenCall | Aggregator round open called too early. |
| 6014 | 0x0x177e | AggregatorIllegalRoundCloseCall | Aggregator round close called too early. |
| 6015 | 0x0x177f | AggregatorClosedError | Aggregator is closed. Illegal action. |
| 6016 | 0x0x1780 | IllegalOracleIdxError | Illegal oracle index. |
| 6017 | 0x0x1781 | OracleAlreadyRespondedError | The provided oracle has already responded this round. |
| 6018 | 0x0x1782 | ProtoDeserializeError | Failed to deserialize protocol buffer. |
| 6019 | 0x0x1783 | UnauthorizedStateUpdateError | Unauthorized program state modification attempted. |
| 6020 | 0x0x1784 | MissingOracleAccountsError | Not enough oracle accounts provided to closeRounds. |
| 6021 | 0x0x1785 | OracleMismatchError | An unexpected oracle account was provided for the transaction. |
| 6022 | 0x0x1786 | CrankMaxCapacityError | Attempted to push to a Crank that's at capacity |
| Code | Hex | Name | Message |
| ---- | -------- | -------------------------------- | --------------------------------------------------------------------------- |
| 6000 | 0x0x1770 | ArrayOperationError | Illegal operation on a Switchboard array. |
| 6001 | 0x0x1771 | QueueOperationError | Illegal operation on a Switchboard queue. |
| 6002 | 0x0x1772 | IncorrectProgramOwnerError | An account required to be owned by the program has a different owner. |
| 6003 | 0x0x1773 | InvalidAggregatorRound | Aggregator is not currently populated with a valid round. |
| 6004 | 0x0x1774 | TooManyAggregatorJobs | Aggregator cannot fit any more jobs. |
| 6005 | 0x0x1775 | AggregatorCurrentRoundClosed | Aggregator's current round is closed. No results are being accepted. |
| 6006 | 0x0x1776 | AggregatorInvalidSaveResult | Aggregator received an invalid save result instruction. |
| 6007 | 0x0x1777 | InvalidStrDecimalConversion | Failed to convert string to decimal format. |
| 6008 | 0x0x1778 | AccountLoaderMissingSignature | AccountLoader account is missing a required signature. |
| 6009 | 0x0x1779 | MissingRequiredSignature | Account is missing a required signature. |
| 6010 | 0x0x177a | ArrayOverflowError | The attempted action will overflow a zero-copy account array. |
| 6011 | 0x0x177b | ArrayUnderflowError | The attempted action will underflow a zero-copy account array. |
| 6012 | 0x0x177c | PubkeyNotFoundError | The queried public key was not found. |
| 6013 | 0x0x177d | AggregatorIllegalRoundOpenCall | Aggregator round open called too early. |
| 6014 | 0x0x177e | AggregatorIllegalRoundCloseCall | Aggregator round close called too early. |
| 6015 | 0x0x177f | AggregatorClosedError | Aggregator is closed. Illegal action. |
| 6016 | 0x0x1780 | IllegalOracleIdxError | Illegal oracle index. |
| 6017 | 0x0x1781 | OracleAlreadyRespondedError | The provided oracle has already responded this round. |
| 6018 | 0x0x1782 | ProtoDeserializeError | Failed to deserialize protocol buffer. |
| 6019 | 0x0x1783 | UnauthorizedStateUpdateError | Unauthorized program state modification attempted. |
| 6020 | 0x0x1784 | MissingOracleAccountsError | Not enough oracle accounts provided to closeRounds. |
| 6021 | 0x0x1785 | OracleMismatchError | An unexpected oracle account was provided for the transaction. |
| 6022 | 0x0x1786 | CrankMaxCapacityError | Attempted to push to a Crank that's at capacity |
| 6023 | 0x0x1787 | AggregatorLeaseInsufficientFunds | Aggregator update call attempted but attached lease has insufficient funds. |
| 6024 | 0x0x1788 | IncorrectTokenAccountMint | The provided token account does not point to the Switchboard token mint. |
| 6025 | 0x0x1789 | InvalidEscrowAccount | An invalid escrow account was provided. |
| 6026 | 0x0x178a | CrankEmptyError | Crank empty. Pop failed. |
| 6027 | 0x0x178b | PdaDeriveError | Failed to derive a PDA from the provided seed. |
| 6028 | 0x0x178c | AggregatorAccountNotFound | Aggregator account missing from provided account list. |
| 6029 | 0x0x178d | PermissionAccountNotFound | Permission account missing from provided account list. |
| 6030 | 0x0x178e | LeaseAccountDeriveFailure | Failed to derive a lease account. |
| 6031 | 0x0x178f | PermissionAccountDeriveFailure | Failed to derive a permission account. |
| 6032 | 0x0x1790 | EscrowAccountNotFound | Escrow account missing from provided account list. |
| 6033 | 0x0x1791 | LeaseAccountNotFound | Lease account missing from provided account list. |
| 6034 | 0x0x1792 | DecimalConversionError | Decimal conversion method failed. |
| 6035 | 0x0x1793 | PermissionDenied | Permission account is missing required flags for the given action. |
| 6036 | 0x0x1794 | QueueAtCapacity | Oracle queue is at lease capacity. |
| 6037 | 0x0x1795 | ExcessiveCrankRowsError | Data feed is already pushed on a crank. |
| 6038 | 0x0x1796 | AggregatorLockedError | Aggregator is locked, no setting modifications or job additions allowed. |
| 6039 | 0x0x1797 | AggregatorInvalidBatchSizeError | Aggregator invalid batch size. |
| 6040 | 0x0x1798 | AggregatorJobChecksumMismatch | Oracle provided an incorrect aggregator job checksum. |
| 6041 | 0x0x1799 | IntegerOverflowError | An integer overflow occurred. |
| 6042 | 0x0x179a | InvalidUpdatePeriodError | Minimum update period is 5 seconds. |
| 6043 | 0x0x179b | NoResultsError | Aggregator round evaluation attempted with no results. |
| 6044 | 0x0x179c | InvalidExpirationError | An expiration constraint was broken. |
| 6045 | 0x0x179d | InsufficientStakeError | An account provided insufficient stake for action. |
| 6046 | 0x0x179e | LeaseInactiveError | The provided lease account is not active. |
| 6047 | 0x0x179f | NoAggregatorJobsFound | No jobs are currently included in the aggregator. |
| 6048 | 0x0x17a0 | IntegerUnderflowError | An integer underflow occurred. |
| 6049 | 0x0x17a1 | OracleQueueMismatch | An invalid oracle queue account was provided. |
| 6050 | 0x0x17a2 | OracleWalletMismatchError | An unexpected oracle wallet account was provided for the transaction. |
| 6051 | 0x0x17a3 | InvalidBufferAccountError | An invalid buffer account was provided. |
| 6052 | 0x0x17a4 | InsufficientOracleQueueError | Insufficient oracle queue size. |
| 6053 | 0x0x17a5 | InvalidAuthorityError | Invalid authority account provided. |
| 6054 | 0x0x17a6 | InvalidTokenAccountMintError | A provided token wallet is associated with an incorrect mint. |
| 6055 | 0x0x17a7 | ExcessiveLeaseWithdrawlError | You must leave enough funds to perform at least 1 update in the lease. |
| 6056 | 0x0x17a8 | InvalideHistoryAccountError | Invalid history account provided. |
| 6057 | 0x0x17a9 | InvalidLeaseAccountEscrowError | Invalid lease account escrow. |
| 6058 | 0x0x17aa | InvalidCrankAccountError | Invalid crank provided. |
| 6059 | 0x0x17ab | CrankNoElementsReadyError | No elements ready to be popped. |
| 6060 | 0x0x17ac | IndexOutOfBoundsError | Index out of bounds |
| 6061 | 0x0x17ad | VrfInvalidRequestError | Invalid vrf request params |
| 6062 | 0x0x17ae | VrfInvalidProofSubmissionError | Vrf proof failed to verify |
| 6063 | 0x0x17af | VrfVerifyError | Error in verifying vrf proof. |
| 6064 | 0x0x17b0 | VrfCallbackError | Vrf callback function failed. |
| 6065 | 0x0x17b1 | VrfCallbackParamsError | Invalid vrf callback params provided. |
| 6066 | 0x0x17b2 | VrfCallbackAlreadyCalledError | Vrf callback has already been triggered. |
| 6067 | 0x0x17b3 | VrfInvalidPubkeyError | The provided pubkey is invalid to use in ecvrf proofs |
| 6068 | 0x0x17b4 | VrfTooManyVerifyCallsError | Number of required verify calls exceeded |
| 6069 | 0x0x17b5 | VrfRequestAlreadyLaunchedError | Vrf request is already pending |
| 6070 | 0x0x17b6 | VrfInsufficientVerificationError | Insufficient amount of proofs collected for VRF callback |
| 6071 | 0x0x17b7 | InvalidVrfProducerError | An incorrect oracle attempted to submit a proof |
| 6072 | 0x0x17b8 | NoopError | Noop error |
| 6024 | 0x0x1788 | IncorrectTokenAccountMint | The provided token account does not point to the Switchboard token mint. |
| 6025 | 0x0x1789 | InvalidEscrowAccount | An invalid escrow account was provided. |
| 6026 | 0x0x178a | CrankEmptyError | Crank empty. Pop failed. |
| 6027 | 0x0x178b | PdaDeriveError | Failed to derive a PDA from the provided seed. |
| 6028 | 0x0x178c | AggregatorAccountNotFound | Aggregator account missing from provided account list. |
| 6029 | 0x0x178d | PermissionAccountNotFound | Permission account missing from provided account list. |
| 6030 | 0x0x178e | LeaseAccountDeriveFailure | Failed to derive a lease account. |
| 6031 | 0x0x178f | PermissionAccountDeriveFailure | Failed to derive a permission account. |
| 6032 | 0x0x1790 | EscrowAccountNotFound | Escrow account missing from provided account list. |
| 6033 | 0x0x1791 | LeaseAccountNotFound | Lease account missing from provided account list. |
| 6034 | 0x0x1792 | DecimalConversionError | Decimal conversion method failed. |
| 6035 | 0x0x1793 | PermissionDenied | Permission account is missing required flags for the given action. |
| 6036 | 0x0x1794 | QueueAtCapacity | Oracle queue is at lease capacity. |
| 6037 | 0x0x1795 | ExcessiveCrankRowsError | Data feed is already pushed on a crank. |
| 6038 | 0x0x1796 | AggregatorLockedError | Aggregator is locked, no setting modifications or job additions allowed. |
| 6039 | 0x0x1797 | AggregatorInvalidBatchSizeError | Aggregator invalid batch size. |
| 6040 | 0x0x1798 | AggregatorJobChecksumMismatch | Oracle provided an incorrect aggregator job checksum. |
| 6041 | 0x0x1799 | IntegerOverflowError | An integer overflow occurred. |
| 6042 | 0x0x179a | InvalidUpdatePeriodError | Minimum update period is 5 seconds. |
| 6043 | 0x0x179b | NoResultsError | Aggregator round evaluation attempted with no results. |
| 6044 | 0x0x179c | InvalidExpirationError | An expiration constraint was broken. |
| 6045 | 0x0x179d | InsufficientStakeError | An account provided insufficient stake for action. |
| 6046 | 0x0x179e | LeaseInactiveError | The provided lease account is not active. |
| 6047 | 0x0x179f | NoAggregatorJobsFound | No jobs are currently included in the aggregator. |
| 6048 | 0x0x17a0 | IntegerUnderflowError | An integer underflow occurred. |
| 6049 | 0x0x17a1 | OracleQueueMismatch | An invalid oracle queue account was provided. |
| 6050 | 0x0x17a2 | OracleWalletMismatchError | An unexpected oracle wallet account was provided for the transaction. |
| 6051 | 0x0x17a3 | InvalidBufferAccountError | An invalid buffer account was provided. |
| 6052 | 0x0x17a4 | InsufficientOracleQueueError | Insufficient oracle queue size. |
| 6053 | 0x0x17a5 | InvalidAuthorityError | Invalid authority account provided. |
| 6054 | 0x0x17a6 | InvalidTokenAccountMintError | A provided token wallet is associated with an incorrect mint. |
| 6055 | 0x0x17a7 | ExcessiveLeaseWithdrawlError | You must leave enough funds to perform at least 1 update in the lease. |
| 6056 | 0x0x17a8 | InvalideHistoryAccountError | Invalid history account provided. |
| 6057 | 0x0x17a9 | InvalidLeaseAccountEscrowError | Invalid lease account escrow. |
| 6058 | 0x0x17aa | InvalidCrankAccountError | Invalid crank provided. |
| 6059 | 0x0x17ab | CrankNoElementsReadyError | No elements ready to be popped. |
| 6060 | 0x0x17ac | IndexOutOfBoundsError | Index out of bounds |
| 6061 | 0x0x17ad | VrfInvalidRequestError | Invalid vrf request params |
| 6062 | 0x0x17ae | VrfInvalidProofSubmissionError | Vrf proof failed to verify |
| 6063 | 0x0x17af | VrfVerifyError | Error in verifying vrf proof. |
| 6064 | 0x0x17b0 | VrfCallbackError | Vrf callback function failed. |
| 6065 | 0x0x17b1 | VrfCallbackParamsError | Invalid vrf callback params provided. |
| 6066 | 0x0x17b2 | VrfCallbackAlreadyCalledError | Vrf callback has already been triggered. |
| 6067 | 0x0x17b3 | VrfInvalidPubkeyError | The provided pubkey is invalid to use in ecvrf proofs |
| 6068 | 0x0x17b4 | VrfTooManyVerifyCallsError | Number of required verify calls exceeded |
| 6069 | 0x0x17b5 | VrfRequestAlreadyLaunchedError | Vrf request is already pending |
| 6070 | 0x0x17b6 | VrfInsufficientVerificationError | Insufficient amount of proofs collected for VRF callback |
| 6071 | 0x0x17b7 | InvalidVrfProducerError | An incorrect oracle attempted to submit a proof |
| 6072 | 0x0x17b8 | NoopError | Noop error |

View File

@ -11,7 +11,7 @@
"scripts": {
"docusaurus": "docusaurus",
"start": "docusaurus start",
"build": "echo \"Use 'npm run build:site' to build the docusaurus project\" && exit 0",
"build": "For workspace website, run 'yarn docs:build' from the project root",
"build:site": "docusaurus build --out-dir public",
"swizzle": "docusaurus swizzle",
"deploy": "docusaurus build --out-dir public && docusaurus deploy --out-dir public",

188
yarn.lock
View File

@ -2846,38 +2846,6 @@
resolved "https://registry.npmjs.org/@mdx-js/util/-/util-1.6.22.tgz"
integrity sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA==
"@metaplex-foundation/beet-solana@^0.1.1":
version "0.1.1"
resolved "https://registry.npmjs.org/@metaplex-foundation/beet-solana/-/beet-solana-0.1.1.tgz"
integrity sha512-QV2DbxjaJWLkMvn12OC09g+r7a6R0uNwf8msYuOUSw4cG7amXzvFb7s0bh4IxY3Rk8/0ma0PfKi/FEdC7Hi4Pg==
dependencies:
"@metaplex-foundation/beet" ">=0.1.0"
"@solana/web3.js" "^1.31.0"
"@metaplex-foundation/beet@>=0.1.0", "@metaplex-foundation/beet@^0.1.0":
version "0.1.0"
resolved "https://registry.npmjs.org/@metaplex-foundation/beet/-/beet-0.1.0.tgz"
integrity sha512-6SKV0Tp1+onU1vjBA26wvgPIKpxhnYINNpnpxvBpK9Cl8dNfz5+sfdx6opaKcljpCSaRpQqHfdtEn6qlYVCO8A==
dependencies:
ansicolors "^0.3.2"
bn.js "^5.2.0"
debug "^4.3.3"
"@metaplex-foundation/solita@^0.2.1":
version "0.2.1"
resolved "https://registry.npmjs.org/@metaplex-foundation/solita/-/solita-0.2.1.tgz"
integrity sha512-dEC5g2/9MK9io+sglYmItjmmERkw/yKqQNEPHac5aW/QFQRdzRySggulE0UbCiuVegqwIKMEPxqOKf4/w7n86A==
dependencies:
"@metaplex-foundation/beet" "^0.1.0"
"@metaplex-foundation/beet-solana" "^0.1.1"
"@solana/web3.js" "^1.36.0"
camelcase "^6.2.1"
debug "^4.3.3"
js-sha256 "^0.9.0"
prettier "^2.5.1"
snake-case "^3.0.4"
spok "^1.4.3"
"@mui/base@5.0.0-alpha.78":
version "5.0.0-alpha.78"
resolved "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.78.tgz"
@ -3571,9 +3539,9 @@
snake-case "^3.0.4"
toml "^3.0.0"
"@project-serum/anchor@^0.24.2":
"@project-serum/anchor@^0.24.1", "@project-serum/anchor@^0.24.2":
version "0.24.2"
resolved "https://registry.npmjs.org/@project-serum/anchor/-/anchor-0.24.2.tgz"
resolved "https://registry.npmjs.org/@project-serum/anchor/-/anchor-0.24.2.tgz#a3c52a99605c80735f446ca9b3a4885034731004"
integrity sha512-0/718g8/DnEuwAidUwh5wLYphUYXhUbiClkuRNhvNoa+1Y8a4g2tJyxoae+emV+PG/Gikd/QUBNMkIcimiIRTA==
dependencies:
"@project-serum/borsh" "^0.2.5"
@ -3917,7 +3885,7 @@
tweetnacl "^1.0.0"
ws "^7.0.0"
"@solana/web3.js@^1.10.0", "@solana/web3.js@^1.17.0", "@solana/web3.js@^1.20.0", "@solana/web3.js@^1.21.0", "@solana/web3.js@^1.22.0", "@solana/web3.js@^1.24.1", "@solana/web3.js@^1.31.0", "@solana/web3.js@^1.32.0", "@solana/web3.js@^1.33.0", "@solana/web3.js@^1.35.1", "@solana/web3.js@^1.36.0", "@solana/web3.js@^1.37.1":
"@solana/web3.js@^1.10.0", "@solana/web3.js@^1.17.0", "@solana/web3.js@^1.20.0", "@solana/web3.js@^1.21.0", "@solana/web3.js@^1.22.0", "@solana/web3.js@^1.24.1", "@solana/web3.js@^1.32.0", "@solana/web3.js@^1.33.0", "@solana/web3.js@^1.35.1", "@solana/web3.js@^1.36.0", "@solana/web3.js@^1.37.1":
version "1.37.1"
resolved "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.37.1.tgz"
integrity sha512-1zm1blRU6ANb8bOfONibKkNKoMyzE1e0Z88MagyRLF1AmfHc+18lFvqxSQKUdazLMHcioZ28h+GfyAaeCT63iA==
@ -3981,6 +3949,28 @@
superstruct "^0.14.2"
tweetnacl "^1.0.0"
"@solana/web3.js@^1.42.0":
version "1.42.0"
resolved "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.42.0.tgz#296e4bbab1fbfc198b3e9c3d94016c3876eb6a2c"
integrity sha512-QqGh5DWzrgsWRx4sCPDQIm3390b7buPR16tZI61slQaQwJ2ymrSXPQCe4PPTJEIlzGjCV3dkn2vpT2R32BfK2Q==
dependencies:
"@babel/runtime" "^7.12.5"
"@ethersproject/sha2" "^5.5.0"
"@solana/buffer-layout" "^4.0.0"
"@solana/buffer-layout-utils" "^0.2.0"
bn.js "^5.0.0"
borsh "^0.7.0"
bs58 "^4.0.1"
buffer "6.0.1"
cross-fetch "^3.1.4"
fast-stable-stringify "^1.0.0"
jayson "^3.4.4"
js-sha3 "^0.8.0"
rpc-websockets "^7.4.2"
secp256k1 "^4.0.2"
superstruct "^0.14.2"
tweetnacl "^1.0.0"
"@svgr/babel-plugin-add-jsx-attribute@^5.4.0":
version "5.4.0"
resolved "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-5.4.0.tgz"
@ -4275,6 +4265,16 @@
resolved "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz"
integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==
"@ts-morph/common@~0.12.3":
version "0.12.3"
resolved "https://registry.npmjs.org/@ts-morph/common/-/common-0.12.3.tgz#a96e250217cd30e480ab22ec6a0ebbe65fd784ff"
integrity sha512-4tUmeLyXJnJWvTFOKtcNJ1yh0a3SsTLi2MUoyj8iUNznFRN1ZquaNe7Oukqrnki2FzZkm0J9adCNLDZxUzvj+w==
dependencies:
fast-glob "^3.2.7"
minimatch "^3.0.4"
mkdirp "^1.0.4"
path-browserify "^1.0.1"
"@tsconfig/docusaurus@^1.0.4":
version "1.0.5"
resolved "https://registry.npmjs.org/@tsconfig/docusaurus/-/docusaurus-1.0.5.tgz"
@ -4473,9 +4473,9 @@
resolved "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz"
integrity sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==
"@types/mocha@^9.0.0", "@types/mocha@^9.1.0":
"@types/mocha@^9.0.0", "@types/mocha@^9.1.0", "@types/mocha@^9.1.1":
version "9.1.1"
resolved "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.1.tgz"
resolved "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.1.tgz#e7c4f1001eefa4b8afbd1eee27a237fee3bf29c4"
integrity sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw==
"@types/node@*", "@types/node@>=12.12.47", "@types/node@>=13.7.0", "@types/node@^17.0.23", "@types/node@^17.0.25", "@types/node@^17.0.5":
@ -5119,6 +5119,22 @@ algoliasearch@^4.0.0, algoliasearch@^4.13.0:
"@algolia/requester-node-http" "4.13.0"
"@algolia/transporter" "4.13.0"
anchor-client-gen@^0.24.0:
version "0.24.0"
resolved "https://registry.npmjs.org/anchor-client-gen/-/anchor-client-gen-0.24.0.tgz#25aebebf93a7d6032866fff821260158338f06c4"
integrity sha512-FGGPrvek3l2mNXmU1fmFR09QIUR4bi8PlcM+pqRBox5GonOkR6UQ3Z1+NlVvEaW3CQMxfHxHTyWFEEPZPmpD2A==
dependencies:
"@project-serum/anchor" "^0.24.1"
"@project-serum/borsh" "^0.2.5"
"@solana/web3.js" "^1.36.0"
bn.js "^5.1.2"
camelcase "^5.3.1"
commander "^9.0.0"
js-sha256 "^0.9.0"
prettier "^2.5.1"
snake-case "^3.0.4"
ts-morph "^13.0.3"
ansi-align@^3.0.0, ansi-align@^3.0.1:
version "3.0.1"
resolved "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz"
@ -5192,7 +5208,7 @@ ansi-styles@^6.1.0:
resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.1.0.tgz"
integrity sha512-VbqNsoz55SYGczauuup0MFUyXNQviSpFTj1RQtFzmQLk18qbVSpTFFGMT293rmDaQuKCT6InmbuEyUne4mTuxQ==
ansicolors@^0.3.2, ansicolors@~0.3.2:
ansicolors@~0.3.2:
version "0.3.2"
resolved "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz"
integrity sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=
@ -5973,7 +5989,7 @@ camelcase@^5.0.0, camelcase@^5.3.1:
resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz"
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
camelcase@^6.0.0, camelcase@^6.2.0, camelcase@^6.2.1:
camelcase@^6.0.0, camelcase@^6.2.0:
version "6.3.0"
resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz"
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
@ -6354,6 +6370,13 @@ coa@^2.0.2:
chalk "^2.4.1"
q "^1.1.2"
code-block-writer@^11.0.0:
version "11.0.0"
resolved "https://registry.npmjs.org/code-block-writer/-/code-block-writer-11.0.0.tgz#5956fb186617f6740e2c3257757fea79315dd7d4"
integrity sha512-GEqWvEWWsOvER+g9keO4ohFoD3ymwyCnqY3hoTr7GZipYFwEhMHJw+TtV0rfgRhNImM6QWZGO2XYjlJVyYT62w==
dependencies:
tslib "2.3.1"
code-point-at@^1.0.0:
version "1.1.0"
resolved "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz"
@ -6480,7 +6503,7 @@ commander@^8.3.0:
resolved "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz"
integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==
commander@^9.1.0:
commander@^9.0.0, commander@^9.1.0:
version "9.2.0"
resolved "https://registry.npmjs.org/commander/-/commander-9.2.0.tgz"
integrity sha512-e2i4wANQiSXgnrBlIatyHtP1odfUp0BbV5Y5nEGbxtIrStkEOAAzCUirvLBNXHLr7kwLvJl6V+4V3XV9x7Wd9w==
@ -7104,7 +7127,7 @@ debug@2.6.9, debug@^2.6.0, debug@^2.6.9:
dependencies:
ms "2.0.0"
debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3:
debug@4, debug@4.3.4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3:
version "4.3.4"
resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
@ -11372,6 +11395,13 @@ minimatch@4.2.1:
dependencies:
brace-expansion "^1.1.7"
minimatch@5.0.1, minimatch@^5.0.1:
version "5.0.1"
resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz"
integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==
dependencies:
brace-expansion "^2.0.1"
minimatch@^3.0.4, minimatch@^3.1.2:
version "3.1.2"
resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz"
@ -11379,13 +11409,6 @@ minimatch@^3.0.4, minimatch@^3.1.2:
dependencies:
brace-expansion "^1.1.7"
minimatch@^5.0.1:
version "5.0.1"
resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz"
integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==
dependencies:
brace-expansion "^2.0.1"
minimist-options@4.1.0:
version "4.1.0"
resolved "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz"
@ -11503,6 +11526,34 @@ mkdirp@^0.5.1, mkdirp@^0.5.5, mkdirp@~0.5.1:
dependencies:
minimist "^1.2.6"
mocha@^10.0.0:
version "10.0.0"
resolved "https://registry.npmjs.org/mocha/-/mocha-10.0.0.tgz#205447d8993ec755335c4b13deba3d3a13c4def9"
integrity sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA==
dependencies:
"@ungap/promise-all-settled" "1.1.2"
ansi-colors "4.1.1"
browser-stdout "1.3.1"
chokidar "3.5.3"
debug "4.3.4"
diff "5.0.0"
escape-string-regexp "4.0.0"
find-up "5.0.0"
glob "7.2.0"
he "1.2.0"
js-yaml "4.1.0"
log-symbols "4.1.0"
minimatch "5.0.1"
ms "2.1.3"
nanoid "3.3.3"
serialize-javascript "6.0.0"
strip-json-comments "3.1.1"
supports-color "8.1.1"
workerpool "6.2.1"
yargs "16.2.0"
yargs-parser "20.2.4"
yargs-unparser "2.0.0"
mocha@^9.0.3, mocha@^9.1.1, mocha@^9.1.3, mocha@^9.2.2:
version "9.2.2"
resolved "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz"
@ -11609,6 +11660,11 @@ nanoid@3.3.1, nanoid@^3.3.1:
resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz"
integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==
nanoid@3.3.3:
version "3.3.3"
resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25"
integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==
natural-compare@^1.4.0:
version "1.4.0"
resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz"
@ -12565,6 +12621,11 @@ password-prompt@^1.1.2:
ansi-escapes "^3.1.0"
cross-spawn "^6.0.5"
path-browserify@^1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd"
integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==
path-exists@^3.0.0:
version "3.0.0"
resolved "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz"
@ -14395,7 +14456,7 @@ shell-quote@^1.6.1, shell-quote@^1.7.3:
shelljs@^0.8.5:
version "0.8.5"
resolved "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz"
resolved "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c"
integrity sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==
dependencies:
glob "^7.0.0"
@ -14682,13 +14743,6 @@ split@^1.0.0:
dependencies:
through "2"
spok@^1.4.3:
version "1.4.3"
resolved "https://registry.npmjs.org/spok/-/spok-1.4.3.tgz"
integrity sha512-5wFGctwrk638aDs+44u99kohxFNByUq2wo0uShQ9yqxSmsxqx7zKbMo1Busy4s7stZQXU+PhJ/BlVf2XWFEGIw==
dependencies:
ansicolors "~0.3.2"
sprintf-js@~1.0.2:
version "1.0.3"
resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz"
@ -15380,6 +15434,15 @@ trough@^1.0.0:
resolved "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz"
integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==
ts-mocha@^10.0.0:
version "10.0.0"
resolved "https://registry.npmjs.org/ts-mocha/-/ts-mocha-10.0.0.tgz#41a8d099ac90dbbc64b06976c5025ffaebc53cb9"
integrity sha512-VRfgDO+iiuJFlNB18tzOfypJ21xn2xbuZyDvJvqpTbWgkAgD17ONGr8t+Tl8rcBtOBdjXp5e/Rk+d39f7XBHRw==
dependencies:
ts-node "7.0.1"
optionalDependencies:
tsconfig-paths "^3.5.0"
ts-mocha@^9.0.2:
version "9.0.2"
resolved "https://registry.npmjs.org/ts-mocha/-/ts-mocha-9.0.2.tgz"
@ -15389,6 +15452,14 @@ ts-mocha@^9.0.2:
optionalDependencies:
tsconfig-paths "^3.5.0"
ts-morph@^13.0.3:
version "13.0.3"
resolved "https://registry.npmjs.org/ts-morph/-/ts-morph-13.0.3.tgz#c0c51d1273ae2edb46d76f65161eb9d763444c1d"
integrity sha512-pSOfUMx8Ld/WUreoSzvMFQG5i9uEiWIsBYjpU9+TTASOeUa89j5HykomeqVULm1oqWtBdleI3KEFRLrlA3zGIw==
dependencies:
"@ts-morph/common" "~0.12.3"
code-block-writer "^11.0.0"
ts-node@7.0.1:
version "7.0.1"
resolved "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz"
@ -16350,6 +16421,11 @@ workerpool@6.2.0:
resolved "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz"
integrity sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==
workerpool@6.2.1:
version "6.2.1"
resolved "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343"
integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==
wrap-ansi@^6.2.0:
version "6.2.0"
resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz"