refactored example programs
wip wip example program cleanup example programs cleanup
This commit is contained in:
parent
0796ca4b4f
commit
37a21ee6f6
|
@ -1,4 +0,0 @@
|
|||
lib
|
||||
dist
|
||||
node_modules
|
||||
scripts
|
|
@ -3,6 +3,7 @@
|
|||
"es2020": true,
|
||||
"node": true
|
||||
},
|
||||
"ignorePatterns": ["**/*/node_modules", "**/*/lib", "**/*/dist"],
|
||||
"root": true,
|
||||
"extends": [
|
||||
"airbnb-typescript/base",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -0,0 +1,6 @@
|
|||
[workspace]
|
||||
members = [
|
||||
"programs/anchor-feed-parser",
|
||||
"programs/anchor-vrf-parser",
|
||||
"programs/spl-feed-parser",
|
||||
]
|
|
@ -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)_
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
"rootDir": "src",
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"noEmit": false,
|
||||
"strict": true
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
|
|
|
@ -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)
|
|
@ -1 +0,0 @@
|
|||
export * from "./anchor";
|
|
@ -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 "";
|
||||
}
|
|
@ -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";
|
||||
|
|
|
@ -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],
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
export * from "./big";
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -10,7 +10,9 @@
|
|||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"noImplicitReturns": false,
|
||||
"importsNotUsedAsValues": "preserve",
|
||||
"strict": false,
|
||||
"noEmit": false,
|
||||
"emitDeclarationOnly": false,
|
||||
"paths": {
|
||||
"@switchboard-xyz/switchboard-v2": ["../ts"]
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
|
||||
.anchor
|
||||
.DS_Store
|
||||
target
|
||||
**/*.rs.bk
|
||||
node_modules
|
|
@ -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"
|
|
@ -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"
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export { readResult, ReadResultAccounts } from "./readResult"
|
|
@ -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
|
||||
}
|
|
@ -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
|
|
@ -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",
|
||||
|
|
|
@ -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"
|
|
@ -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);
|
||||
}
|
|
@ -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 {};
|
|
@ -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)
|
|
@ -1 +0,0 @@
|
|||
export * from './readResult';
|
|
@ -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
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
export * from "./generated";
|
|
@ -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> {
|
|
@ -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);
|
||||
|
|
|
@ -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" }]
|
||||
}
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
|
||||
.anchor
|
||||
.DS_Store
|
||||
target
|
||||
**/*.rs.bk
|
||||
node_modules
|
|
@ -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"
|
|
@ -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"
|
||||
|
|
|
@ -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),
|
||||
})
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export { VrfClient, VrfClientFields, VrfClientJSON } from "./VrfClient"
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
export { initState, InitStateAccounts, InitStateArgs } from "./initState"
|
||||
export {
|
||||
requestResult,
|
||||
RequestResultAccounts,
|
||||
RequestResultArgs,
|
||||
} from "./requestResult"
|
||||
export { updateResult, UpdateResultAccounts } from "./updateResult"
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
export {
|
||||
InitStateParams,
|
||||
InitStateParamsFields,
|
||||
InitStateParamsJSON,
|
||||
} from "./InitStateParams"
|
||||
export {
|
||||
RequestResultParams,
|
||||
RequestResultParamsFields,
|
||||
RequestResultParamsJSON,
|
||||
} from "./RequestResultParams"
|
|
@ -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",
|
||||
|
|
|
@ -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"
|
|
@ -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);
|
||||
}
|
|
@ -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 {};
|
|
@ -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(())
|
||||
}
|
||||
|
|
@ -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> {}
|
|
@ -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"
|
||||
);
|
|
@ -1 +0,0 @@
|
|||
export * from "./VrfClient";
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
|
@ -1,3 +0,0 @@
|
|||
export * from "./initState";
|
||||
export * from "./requestResult";
|
||||
export * from "./updateResult";
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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"
|
||||
);
|
|
@ -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"
|
||||
);
|
|
@ -1,2 +0,0 @@
|
|||
export * from "./InitStateParams";
|
||||
export * from "./RequestResultParams";
|
|
@ -1,2 +0,0 @@
|
|||
export * from "./api";
|
||||
export * from "./generated";
|
|
@ -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;
|
||||
|
|
@ -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}`);
|
||||
});
|
||||
});
|
|
@ -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]);
|
||||
}
|
|
@ -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}`);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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" }
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
|
||||
.anchor
|
||||
.DS_Store
|
||||
target
|
||||
**/*.rs.bk
|
||||
node_modules
|
|
@ -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"]
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
});
|
||||
});
|
|
@ -1,2 +0,0 @@
|
|||
// TODO: Add mocha test
|
||||
export {};
|
|
@ -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" }]
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
});
|
File diff suppressed because it is too large
Load Diff
|
@ -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. */
|
||||
|
|
|
@ -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 |
|
||||
|
|
|
@ -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
188
yarn.lock
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue