Merge branch 'fix-create-agg-cli' into main
This commit is contained in:
commit
7d56377292
100
cli/README.md
100
cli/README.md
|
@ -13,7 +13,6 @@ npm install -g @switchboard-xyz/switchboardv2-cli
|
|||
|
||||
<!-- commands -->
|
||||
* [`sbv2 aggregator:add:job AGGREGATORKEY`](#sbv2-aggregatoraddjob-aggregatorkey)
|
||||
* [`sbv2 aggregator:create QUEUEKEY`](#sbv2-aggregatorcreate-queuekey)
|
||||
* [`sbv2 aggregator:create:copy AGGREGATORSOURCE`](#sbv2-aggregatorcreatecopy-aggregatorsource)
|
||||
* [`sbv2 aggregator:create:json DEFINITIONFILE`](#sbv2-aggregatorcreatejson-definitionfile)
|
||||
* [`sbv2 aggregator:lock AGGREGATORKEY`](#sbv2-aggregatorlock-aggregatorkey)
|
||||
|
@ -36,6 +35,7 @@ npm install -g @switchboard-xyz/switchboardv2-cli
|
|||
* [`sbv2 crank:push CRANKKEY AGGREGATORKEY`](#sbv2-crankpush-crankkey-aggregatorkey)
|
||||
* [`sbv2 crank:turn CRANKKEY`](#sbv2-crankturn-crankkey)
|
||||
* [`sbv2 help [COMMAND]`](#sbv2-help-command)
|
||||
* [`sbv2 job:create JOBDEFINITION`](#sbv2-jobcreate-jobdefinition)
|
||||
* [`sbv2 job:create:copy JOBSOURCE`](#sbv2-jobcreatecopy-jobsource)
|
||||
* [`sbv2 job:create:json DEFINITIONFILE`](#sbv2-jobcreatejson-definitionfile)
|
||||
* [`sbv2 job:create:template TEMPLATE ID`](#sbv2-jobcreatetemplate-template-id)
|
||||
|
@ -125,57 +125,6 @@ EXAMPLE
|
|||
|
||||
_See code: [src/commands/aggregator/add/job.ts](https://github.com/switchboard-xyz/switchboard-v2/blob/v0.1.26/src/commands/aggregator/add/job.ts)_
|
||||
|
||||
## `sbv2 aggregator:create QUEUEKEY`
|
||||
|
||||
create an aggregator account
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ sbv2 aggregator:create QUEUEKEY
|
||||
|
||||
ARGUMENTS
|
||||
QUEUEKEY public key of the oracle queue account to create aggregator for
|
||||
|
||||
OPTIONS
|
||||
-a, --authority=authority alternate keypair that is the authority for the aggregator
|
||||
-h, --help show CLI help
|
||||
-j, --job=job filesystem path to job definition file
|
||||
|
||||
-k, --keypair=keypair keypair that will pay for onchain transactions. defaults to new account
|
||||
authority if no alternate authority provided
|
||||
|
||||
-s, --silent suppress cli prompts
|
||||
|
||||
-u, --rpcUrl=rpcUrl alternate RPC url
|
||||
|
||||
-v, --verbose log everything
|
||||
|
||||
--batchSize=batchSize number of oracles requested for each open round call
|
||||
|
||||
--force skip job confirmation
|
||||
|
||||
--forceReportPeriod=forceReportPeriod Number of seconds for which, even if the variance threshold is not passed,
|
||||
accept new responses from oracles.
|
||||
|
||||
--mainnetBeta WARNING: use mainnet-beta solana cluster
|
||||
|
||||
--minJobs=minJobs number of jobs that must respond before an oracle responds
|
||||
|
||||
--minOracles=minOracles number of oracles that must respond before a value is accepted on-chain
|
||||
|
||||
--newQueue=newQueue public key of the new oracle queue
|
||||
|
||||
--programId=programId alternative Switchboard program ID to interact with
|
||||
|
||||
--updateInterval=updateInterval set an aggregator's minimum update delay
|
||||
|
||||
--varianceThreshold=varianceThreshold percentage change between a previous accepted result and the next round before
|
||||
an oracle reports a value on-chain. Used to conserve lease cost during low
|
||||
volatility
|
||||
```
|
||||
|
||||
_See code: [src/commands/aggregator/create/index.ts](https://github.com/switchboard-xyz/switchboard-v2/blob/v0.1.26/src/commands/aggregator/create/index.ts)_
|
||||
|
||||
## `sbv2 aggregator:create:copy AGGREGATORSOURCE`
|
||||
|
||||
copy an aggregator account to a new oracle queue
|
||||
|
@ -203,8 +152,12 @@ OPTIONS
|
|||
|
||||
--batchSize=batchSize override source aggregator's oracleRequestBatchSize
|
||||
|
||||
--copyJobs create copy of job accounts instead of referincing existing job account
|
||||
|
||||
--crankKey=crankKey public key of the crank to push aggregator to
|
||||
|
||||
--enable set permissions to PERMIT_ORACLE_QUEUE_USAGE
|
||||
|
||||
--force skip job confirmation
|
||||
|
||||
--forceReportPeriod=forceReportPeriod override source aggregator's forceReportPeriod
|
||||
|
@ -219,9 +172,9 @@ OPTIONS
|
|||
|
||||
--programId=programId alternative Switchboard program ID to interact with
|
||||
|
||||
--queueKey=queueKey (required) public key of the queue to create aggregator for
|
||||
--queueAuthority=queueAuthority alternative keypair to use for queue authority
|
||||
|
||||
--sourceCluster=devnet|mainnet-beta alternative solana cluster to copy source aggregator from
|
||||
--queueKey=queueKey (required) public key of the queue to create aggregator for
|
||||
|
||||
--varianceThreshold=varianceThreshold override source aggregator's varianceThreshold
|
||||
|
||||
|
@ -959,6 +912,39 @@ OPTIONS
|
|||
|
||||
_See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v5.1.12/src/commands/help.ts)_
|
||||
|
||||
## `sbv2 job:create JOBDEFINITION`
|
||||
|
||||
create a buffer relayer account
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ sbv2 job:create JOBDEFINITION
|
||||
|
||||
ARGUMENTS
|
||||
JOBDEFINITION filesystem path to job definition
|
||||
|
||||
OPTIONS
|
||||
-a, --authority=authority alternate keypair that will be the aggregator authority
|
||||
-h, --help show CLI help
|
||||
|
||||
-k, --keypair=keypair keypair that will pay for onchain transactions. defaults to new account authority if no
|
||||
alternate authority provided
|
||||
|
||||
-n, --name=name name of the buffer account
|
||||
|
||||
-s, --silent suppress cli prompts
|
||||
|
||||
-u, --rpcUrl=rpcUrl alternate RPC url
|
||||
|
||||
-v, --verbose log everything
|
||||
|
||||
--mainnetBeta WARNING: use mainnet-beta solana cluster
|
||||
|
||||
--programId=programId alternative Switchboard program ID to interact with
|
||||
```
|
||||
|
||||
_See code: [src/commands/job/create/index.ts](https://github.com/switchboard-xyz/switchboard-v2/blob/v0.1.26/src/commands/job/create/index.ts)_
|
||||
|
||||
## `sbv2 job:create:copy JOBSOURCE`
|
||||
|
||||
copy a job account
|
||||
|
@ -2153,8 +2139,8 @@ ARGUMENTS
|
|||
OPTIONS
|
||||
-h, --help show CLI help
|
||||
|
||||
-k, --keypair=keypair keypair that will pay for onchain transactions. defaults to new account authority if no
|
||||
alternate authority provided
|
||||
-k, --keypair=keypair keypair that will pay for onchain transactions. defaults to new account authority if
|
||||
no alternate authority provided
|
||||
|
||||
-n, --name=name name of the crank for easier identification
|
||||
|
||||
|
@ -2170,6 +2156,8 @@ OPTIONS
|
|||
|
||||
--programId=programId alternative Switchboard program ID to interact with
|
||||
|
||||
--queueAuthority=queueAuthority alternative keypair to use for queue authority
|
||||
|
||||
EXAMPLE
|
||||
$ sbv2 queue:add:crank 5aYuxRdcB9GpWrEXVMBQp2R5uf94uoBiFdMEBwcmHuU4 -k ../authority-keypair.json -n crank-1
|
||||
```
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
/* eslint-disable unicorn/no-process-exit */
|
||||
/* eslint-disable no-process-exit */
|
||||
import Command, { flags } from "@oclif/command";
|
||||
import { Input } from "@oclif/parser";
|
||||
import * as anchor from "@project-serum/anchor";
|
||||
|
@ -146,6 +144,7 @@ abstract class BaseCommand extends Command {
|
|||
if (this.verbose) {
|
||||
this.logger.log("verbose logging enabled");
|
||||
}
|
||||
|
||||
this.logger.debug(chalk.underline(chalk.blue("## Config".padEnd(16))));
|
||||
this.logger.debug(
|
||||
`${chalk.yellow("cluster:")} ${chalk.blue(this.cluster)}`
|
||||
|
@ -166,10 +165,12 @@ abstract class BaseCommand extends Command {
|
|||
if (message) {
|
||||
logger.info(chalk.red(`${FAILED_ICON}${message}`));
|
||||
}
|
||||
|
||||
if (error.message) {
|
||||
const messageLines = error.message.split("\n");
|
||||
logger.error(messageLines[0]);
|
||||
}
|
||||
|
||||
if (this.verbose) {
|
||||
console.error(error);
|
||||
}
|
||||
|
@ -209,7 +210,6 @@ abstract class BaseCommand extends Command {
|
|||
loadConfig(): void {
|
||||
const configPath = path.join(this.config.configDir, "config.json");
|
||||
if (fs.existsSync(configPath)) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const userConfig: CliConfig = JSON.parse(
|
||||
fs.readFileSync(configPath, "utf-8")
|
||||
);
|
||||
|
@ -240,6 +240,7 @@ abstract class BaseCommand extends Command {
|
|||
this.saveConfig(newConfig);
|
||||
break;
|
||||
}
|
||||
|
||||
case "mainnet-rpc": {
|
||||
const newConfig = {
|
||||
...this.cliConfig,
|
||||
|
@ -251,6 +252,7 @@ abstract class BaseCommand extends Command {
|
|||
this.saveConfig(newConfig);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
this.logger.warn("not implemented yet");
|
||||
}
|
||||
|
@ -274,15 +276,17 @@ abstract class BaseCommand extends Command {
|
|||
// Converts a string to a tokenAmount
|
||||
// If a decimal is found, it will be normalized using 9 decimal places
|
||||
getTokenAmount(value: string, decimals = 9): anchor.BN {
|
||||
if (isNaN(Number(value))) {
|
||||
throw new Error("tokenAmount must be an integer or decimal");
|
||||
if (Number.isNaN(Number(value))) {
|
||||
throw new TypeError("tokenAmount must be an integer or decimal");
|
||||
}
|
||||
|
||||
if (value.split(".").length > 1) {
|
||||
const float = new Big(value);
|
||||
const scale = BigUtils.safePow(new Big(10), decimals);
|
||||
const tokenAmount = BigUtils.safeMul(float, scale);
|
||||
return new anchor.BN(tokenAmount.toFixed(0));
|
||||
}
|
||||
|
||||
return new anchor.BN(value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,12 +81,14 @@ export default class AggregatorAddJob extends BaseCommand {
|
|||
if (flags.jobDefinition) {
|
||||
this.jobDefinition = JSON.parse(flags.jobDefinition, pubKeyReviver);
|
||||
}
|
||||
|
||||
if (flags.jobKey) {
|
||||
this.jobAccount = new JobAccount({
|
||||
program: this.program,
|
||||
publicKey: new PublicKey(flags.jobKey),
|
||||
});
|
||||
}
|
||||
|
||||
if (!this.jobDefinition && !this.jobAccount) {
|
||||
throw new Error("need to provide --jobDefinition or --jobKey");
|
||||
}
|
||||
|
@ -95,6 +97,7 @@ export default class AggregatorAddJob extends BaseCommand {
|
|||
if (fs.existsSync(flags.outputFile) && !flags.force) {
|
||||
throw new OutputFileExistsNoForce(flags.outputFile);
|
||||
}
|
||||
|
||||
this.outputFile = flags.outputFile;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable unicorn/no-array-push-push */
|
||||
import { flags } from "@oclif/command";
|
||||
import * as anchor from "@project-serum/anchor";
|
||||
import * as spl from "@solana/spl-token";
|
||||
|
@ -9,6 +10,7 @@ import {
|
|||
TransactionInstruction,
|
||||
} from "@solana/web3.js";
|
||||
import {
|
||||
packAndSend,
|
||||
prettyPrintAggregator,
|
||||
promiseWithTimeout,
|
||||
} from "@switchboard-xyz/sbv2-utils";
|
||||
|
@ -17,7 +19,6 @@ import {
|
|||
CrankAccount,
|
||||
JobAccount,
|
||||
LeaseAccount,
|
||||
loadSwitchboardProgram,
|
||||
OracleJob,
|
||||
OracleQueueAccount,
|
||||
PermissionAccount,
|
||||
|
@ -28,8 +29,9 @@ import {
|
|||
import Big from "big.js";
|
||||
import BaseCommand from "../../../BaseCommand";
|
||||
import { verifyProgramHasPayer } from "../../../utils";
|
||||
import { packAndSend } from "../../../utils/transaction";
|
||||
|
||||
// TODO: Fix command so it accepts a feed authority flag
|
||||
// TODO: Add flag that skips job creation
|
||||
export default class AggregatorCreateCopy extends BaseCommand {
|
||||
static description = "copy an aggregator account to a new oracle queue";
|
||||
|
||||
|
@ -70,11 +72,21 @@ export default class AggregatorCreateCopy extends BaseCommand {
|
|||
description: "public key of the crank to push aggregator to",
|
||||
required: false,
|
||||
}),
|
||||
sourceCluster: flags.string({
|
||||
description: "alternative solana cluster to copy source aggregator from",
|
||||
required: false,
|
||||
options: ["devnet", "mainnet-beta"],
|
||||
enable: flags.boolean({
|
||||
description: "set permissions to PERMIT_ORACLE_QUEUE_USAGE",
|
||||
}),
|
||||
queueAuthority: flags.string({
|
||||
description: "alternative keypair to use for queue authority",
|
||||
}),
|
||||
copyJobs: flags.boolean({
|
||||
description:
|
||||
"create copy of job accounts instead of referincing existing job account",
|
||||
}),
|
||||
// sourceCluster: flags.string({
|
||||
// description: "alternative solana cluster to copy source aggregator from",
|
||||
// required: false,
|
||||
// options: ["devnet", "mainnet-beta"],
|
||||
// }),
|
||||
};
|
||||
|
||||
static args = [
|
||||
|
@ -97,20 +109,24 @@ export default class AggregatorCreateCopy extends BaseCommand {
|
|||
const { args, flags } = this.parse(AggregatorCreateCopy);
|
||||
|
||||
const payerKeypair = programWallet(this.program);
|
||||
const feedAuthority = await this.loadAuthority(flags.authority);
|
||||
const queueAuthority = await this.loadAuthority(flags.queueAuthority);
|
||||
|
||||
const sourceProgram = !flags.sourceCluster
|
||||
? this.program
|
||||
: flags.sourceCluster === "devnet" ||
|
||||
flags.sourceCluster === "mainnet-beta"
|
||||
? await loadSwitchboardProgram(
|
||||
flags.sourceCluster,
|
||||
undefined,
|
||||
payerKeypair
|
||||
)
|
||||
: undefined;
|
||||
// const sourceProgram = !flags.sourceCluster
|
||||
// ? this.program
|
||||
// : flags.sourceCluster === "devnet" ||
|
||||
// flags.sourceCluster === "mainnet-beta"
|
||||
// ? await loadSwitchboardProgram(
|
||||
// flags.sourceCluster,
|
||||
// undefined,
|
||||
// payerKeypair
|
||||
// )
|
||||
// : undefined;
|
||||
const sourceProgram = this.program;
|
||||
if (sourceProgram === undefined) {
|
||||
throw new Error(`Invalid sourceAggregatorCluster ${flags.sourceCluster}`);
|
||||
throw new Error(`Invalid sourceAggregatorCluster`);
|
||||
}
|
||||
|
||||
const sourceAggregatorAccount = new AggregatorAccount({
|
||||
program: sourceProgram,
|
||||
publicKey: args.aggregatorSource,
|
||||
|
@ -126,14 +142,6 @@ export default class AggregatorCreateCopy extends BaseCommand {
|
|||
return new JobAccount({ program: sourceProgram, 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 [programStateAccount, stateBump] = ProgramStateAccount.fromSeed(
|
||||
this.program
|
||||
);
|
||||
|
@ -153,67 +161,17 @@ export default class AggregatorCreateCopy extends BaseCommand {
|
|||
| 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 createAccountSigners: Keypair[] = [
|
||||
payerKeypair,
|
||||
feedAuthority,
|
||||
queueAuthority,
|
||||
];
|
||||
|
||||
// Create Aggregator & Permissions
|
||||
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,
|
||||
|
@ -240,23 +198,6 @@ export default class AggregatorCreateCopy extends BaseCommand {
|
|||
true
|
||||
);
|
||||
|
||||
const jobPubkeys: Array<PublicKey> = [];
|
||||
const jobWallets: Array<PublicKey> = [];
|
||||
const walletBumps: Array<number> = [];
|
||||
for (let 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
|
||||
|
@ -291,7 +232,7 @@ export default class AggregatorCreateCopy extends BaseCommand {
|
|||
})
|
||||
.accounts({
|
||||
aggregator: aggregatorKeypair.publicKey,
|
||||
authority: payerKeypair.publicKey,
|
||||
authority: feedAuthority.publicKey,
|
||||
queue: queueAccount.publicKey,
|
||||
authorWallet: tokenWallet,
|
||||
programState: programStateAccount.publicKey,
|
||||
|
@ -309,18 +250,23 @@ export default class AggregatorCreateCopy extends BaseCommand {
|
|||
systemProgram: SystemProgram.programId,
|
||||
})
|
||||
.instruction(),
|
||||
payerKeypair.publicKey.equals(queue.authority)
|
||||
flags.enable && queueAuthority.publicKey.equals(queue.authority)
|
||||
? await this.program.methods
|
||||
.permissionSet({
|
||||
permission: { permitOracleQueueUsage: null },
|
||||
permission: { permitOracleQueueUsage: undefined },
|
||||
enable: true,
|
||||
})
|
||||
.accounts({
|
||||
permission: permissionAccount.publicKey,
|
||||
authority: queue.authority,
|
||||
authority: queueAuthority.publicKey,
|
||||
})
|
||||
.instruction()
|
||||
: undefined,
|
||||
].filter((item) => item)
|
||||
);
|
||||
|
||||
createAccountInstructions.push(
|
||||
[
|
||||
spl.Token.createAssociatedTokenAccountInstruction(
|
||||
spl.ASSOCIATED_TOKEN_PROGRAM_ID,
|
||||
spl.TOKEN_PROGRAM_ID,
|
||||
|
@ -334,7 +280,7 @@ export default class AggregatorCreateCopy extends BaseCommand {
|
|||
loadAmount: new anchor.BN(0),
|
||||
stateBump,
|
||||
leaseBump,
|
||||
withdrawAuthority: payerKeypair.publicKey,
|
||||
withdrawAuthority: feedAuthority.publicKey,
|
||||
walletBumps: Buffer.from([]),
|
||||
})
|
||||
.accounts({
|
||||
|
@ -364,7 +310,7 @@ export default class AggregatorCreateCopy extends BaseCommand {
|
|||
})
|
||||
.accounts({
|
||||
crank: new PublicKey(flags.crankKey),
|
||||
aggregator: aggregatorAccount.publicKey,
|
||||
aggregator: aggregatorKeypair.publicKey,
|
||||
oracleQueue: queueAccount.publicKey,
|
||||
queueAuthority: queue.authority,
|
||||
permission: permissionAccount.publicKey,
|
||||
|
@ -383,54 +329,116 @@ export default class AggregatorCreateCopy extends BaseCommand {
|
|||
].filter((item) => item)
|
||||
);
|
||||
|
||||
const finalInstructions: (
|
||||
| TransactionInstruction
|
||||
| TransactionInstruction[]
|
||||
)[] = [];
|
||||
const createJobIxns = flags.copyJobs
|
||||
? // create job account copies
|
||||
await Promise.all(
|
||||
sourceJobAccounts.map(async (jobAccount) => {
|
||||
const jobKeypair = Keypair.generate();
|
||||
createAccountSigners.push(jobKeypair); // add signers
|
||||
|
||||
finalInstructions.push(
|
||||
...(await Promise.all(
|
||||
jobAccounts.map(async (jobAccount) => {
|
||||
return this.program.methods
|
||||
const job = await jobAccount.loadData();
|
||||
const data = await jobAccount.loadData();
|
||||
const jobData = Buffer.from(
|
||||
OracleJob.encodeDelimited(
|
||||
OracleJob.create({
|
||||
tasks: job.tasks,
|
||||
})
|
||||
).finish()
|
||||
);
|
||||
|
||||
const size =
|
||||
280 + jobData.length + (data.variables?.join("")?.length ?? 0);
|
||||
|
||||
return [
|
||||
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: feedAuthority.publicKey,
|
||||
programState: programStateAccount.publicKey,
|
||||
})
|
||||
.signers([feedAuthority])
|
||||
.instruction(),
|
||||
await this.program.methods
|
||||
.aggregatorAddJob({
|
||||
weight: 1,
|
||||
})
|
||||
.accounts({
|
||||
aggregator: aggregatorKeypair.publicKey,
|
||||
authority: payerKeypair.publicKey,
|
||||
authority: feedAuthority.publicKey,
|
||||
job: jobAccount.publicKey,
|
||||
})
|
||||
.instruction(),
|
||||
];
|
||||
})
|
||||
)
|
||||
: // add job by pubkey
|
||||
await Promise.all(
|
||||
sourceJobAccounts.map(async (jobAccount) => {
|
||||
const addJobIxn = await this.program.methods
|
||||
.aggregatorAddJob({
|
||||
weight: 1,
|
||||
})
|
||||
.accounts({
|
||||
aggregator: aggregatorKeypair.publicKey,
|
||||
authority: feedAuthority.publicKey,
|
||||
job: jobAccount.publicKey,
|
||||
})
|
||||
.instruction();
|
||||
return addJobIxn;
|
||||
})
|
||||
))
|
||||
);
|
||||
|
||||
const createAccountSignatures = packAndSend(
|
||||
this.program,
|
||||
createAccountInstructions,
|
||||
finalInstructions,
|
||||
[createAccountInstructions, createJobIxns],
|
||||
createAccountSigners,
|
||||
payerKeypair.publicKey
|
||||
);
|
||||
).catch((error) => {
|
||||
throw error;
|
||||
});
|
||||
|
||||
let aggInitWs: number;
|
||||
const aggInitPromise = new Promise((resolve: (result: boolean) => void) => {
|
||||
const aggInitPromise = new Promise((resolve: (result: any) => void) => {
|
||||
aggInitWs = this.program.provider.connection.onAccountChange(
|
||||
aggregatorAccount.publicKey,
|
||||
aggregatorKeypair.publicKey,
|
||||
(accountInfo: AccountInfo<Buffer>, slot) => {
|
||||
resolve(true);
|
||||
const aggData = new anchor.BorshAccountsCoder(
|
||||
this.program.idl
|
||||
).decode("AggregatorAccountData", accountInfo.data);
|
||||
resolve(aggData);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
const awaitResult = await promiseWithTimeout(
|
||||
22_000,
|
||||
aggInitPromise
|
||||
).finally(() => {
|
||||
const result = await promiseWithTimeout(45_000, aggInitPromise).finally(
|
||||
() => {
|
||||
try {
|
||||
this.program.provider.connection.removeAccountChangeListener(aggInitWs);
|
||||
this.program.provider.connection.removeAccountChangeListener(
|
||||
aggInitWs
|
||||
);
|
||||
} catch {}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
if (this.silent) {
|
||||
console.log(aggregatorAccount.publicKey.toString());
|
||||
|
@ -438,13 +446,7 @@ export default class AggregatorCreateCopy extends BaseCommand {
|
|||
}
|
||||
|
||||
this.logger.info(
|
||||
await prettyPrintAggregator(
|
||||
aggregatorAccount,
|
||||
undefined,
|
||||
true,
|
||||
true,
|
||||
true
|
||||
)
|
||||
await prettyPrintAggregator(aggregatorAccount, result, true, true, true)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,16 +1,41 @@
|
|||
import { flags } from "@oclif/command";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
import * as anchor from "@project-serum/anchor";
|
||||
import * as spl from "@solana/spl-token";
|
||||
import {
|
||||
AccountInfo,
|
||||
Keypair,
|
||||
PublicKey,
|
||||
SystemProgram,
|
||||
TransactionInstruction,
|
||||
} from "@solana/web3.js";
|
||||
import {
|
||||
packAndSend,
|
||||
prettyPrintAggregator,
|
||||
promiseWithTimeout,
|
||||
sleep,
|
||||
} from "@switchboard-xyz/sbv2-utils";
|
||||
import {
|
||||
AggregatorAccount,
|
||||
CrankAccount,
|
||||
JobAccount,
|
||||
LeaseAccount,
|
||||
OracleJob,
|
||||
OracleQueueAccount,
|
||||
PermissionAccount,
|
||||
ProgramStateAccount,
|
||||
programWallet,
|
||||
SwitchboardDecimal,
|
||||
} from "@switchboard-xyz/switchboard-v2";
|
||||
import Big from "big.js";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import BaseCommand from "../../../BaseCommand";
|
||||
import { verifyProgramHasPayer } from "../../../utils";
|
||||
|
||||
// TODO: Finish
|
||||
export default class AggregatorCreate extends BaseCommand {
|
||||
static hidden = true;
|
||||
|
||||
static description = "create an aggregator account";
|
||||
|
||||
static flags = {
|
||||
|
@ -20,7 +45,20 @@ export default class AggregatorCreate extends BaseCommand {
|
|||
char: "a",
|
||||
description: "alternate keypair that is the authority for the aggregator",
|
||||
}),
|
||||
forceReportPeriod: flags.string({
|
||||
crankKey: flags.string({
|
||||
description: "public key of the crank to join",
|
||||
}),
|
||||
enable: flags.boolean({
|
||||
description: "set permissions to PERMIT_ORACLE_QUEUE_USAGE",
|
||||
}),
|
||||
queueAuthority: flags.string({
|
||||
description: "alternative keypair to use for queue authority",
|
||||
}),
|
||||
name: flags.string({
|
||||
char: "n",
|
||||
description: "name of the aggregator",
|
||||
}),
|
||||
forceReportPeriod: flags.integer({
|
||||
description:
|
||||
"Number of seconds for which, even if the variance threshold is not passed, accept new responses from oracles.",
|
||||
}),
|
||||
|
@ -34,9 +72,6 @@ export default class AggregatorCreate extends BaseCommand {
|
|||
description:
|
||||
"number of oracles that must respond before a value is accepted on-chain",
|
||||
}),
|
||||
newQueue: flags.string({
|
||||
description: "public key of the new oracle queue",
|
||||
}),
|
||||
updateInterval: flags.string({
|
||||
description: "set an aggregator's minimum update delay",
|
||||
}),
|
||||
|
@ -66,19 +101,41 @@ export default class AggregatorCreate extends BaseCommand {
|
|||
const { args, flags } = this.parse(AggregatorCreate);
|
||||
|
||||
const payerKeypair = programWallet(this.program);
|
||||
const feedAuthority = await this.loadAuthority(flags.authority);
|
||||
const queueAuthority = await this.loadAuthority(flags.queueAuthority);
|
||||
|
||||
const [programStateAccount, stateBump] = ProgramStateAccount.fromSeed(
|
||||
this.program
|
||||
);
|
||||
const queueAccount = new OracleQueueAccount({
|
||||
program: this.program,
|
||||
publicKey: args.queueKey,
|
||||
});
|
||||
const queue = await queueAccount.loadData();
|
||||
const switchTokenMint = await queueAccount.loadMint();
|
||||
const payerTokenWallet = (
|
||||
const tokenWallet = (
|
||||
await switchTokenMint.getOrCreateAssociatedAccountInfo(
|
||||
payerKeypair.publicKey
|
||||
)
|
||||
).address;
|
||||
|
||||
const jobs = flags.job.map((jobDefinition) => {
|
||||
const createAccountInstructions: (
|
||||
| TransactionInstruction
|
||||
| TransactionInstruction[]
|
||||
)[] = [];
|
||||
const createAccountSigners: Keypair[] = [
|
||||
payerKeypair,
|
||||
feedAuthority,
|
||||
queueAuthority,
|
||||
];
|
||||
|
||||
// Create Job Accounts
|
||||
const createJobs = flags.job
|
||||
? await Promise.all(
|
||||
flags.job.map(
|
||||
async (
|
||||
jobDefinition
|
||||
): Promise<[TransactionInstruction, Keypair]> => {
|
||||
const jobJson = JSON.parse(
|
||||
fs.readFileSync(
|
||||
jobDefinition.startsWith("/")
|
||||
|
@ -90,6 +147,9 @@ export default class AggregatorCreate extends BaseCommand {
|
|||
if (!jobJson || !("tasks" in jobJson)) {
|
||||
throw new Error("job definition missing tasks");
|
||||
}
|
||||
|
||||
const jobKeypair = anchor.web3.Keypair.generate();
|
||||
|
||||
const data = Buffer.from(
|
||||
OracleJob.encodeDelimited(
|
||||
OracleJob.create({
|
||||
|
@ -97,7 +157,251 @@ export default class AggregatorCreate extends BaseCommand {
|
|||
})
|
||||
).finish()
|
||||
);
|
||||
|
||||
const createJobIxn = await this.program.methods
|
||||
.jobInit({
|
||||
name: Buffer.from("").slice(0, 32),
|
||||
data: data,
|
||||
variables: new Array<Buffer>(),
|
||||
authorWallet: payerKeypair.publicKey,
|
||||
stateBump,
|
||||
})
|
||||
.accounts({
|
||||
job: jobKeypair.publicKey,
|
||||
authorWallet: tokenWallet,
|
||||
authority: feedAuthority.publicKey,
|
||||
programState: programStateAccount.publicKey,
|
||||
})
|
||||
.signers([feedAuthority])
|
||||
.instruction();
|
||||
|
||||
return [createJobIxn, jobKeypair];
|
||||
}
|
||||
)
|
||||
)
|
||||
: [];
|
||||
createAccountInstructions.push(createJobs.map((index) => index[0]));
|
||||
createAccountSigners.push(...createJobs.map((index) => index[1]));
|
||||
const jobAccounts = createJobs
|
||||
.map((index) => index[1])
|
||||
.map((jobKeypair) => {
|
||||
return new JobAccount({
|
||||
program: this.program,
|
||||
publicKey: jobKeypair.publicKey,
|
||||
keypair: jobKeypair,
|
||||
});
|
||||
});
|
||||
|
||||
// Create Aggregator Account
|
||||
const aggregatorKeypair = anchor.web3.Keypair.generate();
|
||||
const aggregatorSize = this.program.account.aggregatorAccountData.size;
|
||||
const aggregatorAccount = new AggregatorAccount({
|
||||
program: this.program,
|
||||
publicKey: aggregatorKeypair.publicKey,
|
||||
});
|
||||
const [permissionAccount, permissionBump] = PermissionAccount.fromSeed(
|
||||
this.program,
|
||||
queue.authority,
|
||||
queueAccount.publicKey,
|
||||
aggregatorKeypair.publicKey
|
||||
);
|
||||
createAccountInstructions.push(
|
||||
[
|
||||
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: Buffer.from(flags.name ?? "").slice(0, 32),
|
||||
metadata: Buffer.from("").slice(0, 64),
|
||||
batchSize: flags.batchSize ?? 1,
|
||||
minOracleResults: flags.minOracles ?? 1,
|
||||
minJobResults: flags.minJobs ?? 1,
|
||||
minUpdateDelaySeconds: flags.updateInterval ?? 30,
|
||||
varianceThreshold: flags.varianceThreshold
|
||||
? SwitchboardDecimal.fromBig(new Big(flags.varianceThreshold))
|
||||
: SwitchboardDecimal.fromBig(new Big(0)),
|
||||
forceReportPeriod: flags.forceReportPeriod ?? 0,
|
||||
stateBump,
|
||||
})
|
||||
.accounts({
|
||||
aggregator: aggregatorKeypair.publicKey,
|
||||
authority: feedAuthority.publicKey,
|
||||
queue: queueAccount.publicKey,
|
||||
authorWallet: tokenWallet,
|
||||
programState: programStateAccount.publicKey,
|
||||
})
|
||||
.instruction(),
|
||||
await this.program.methods
|
||||
.permissionInit({})
|
||||
.accounts({
|
||||
permission: permissionAccount.publicKey,
|
||||
authority: queue.authority,
|
||||
granter: queueAccount.publicKey,
|
||||
grantee: aggregatorKeypair.publicKey,
|
||||
payer: payerKeypair.publicKey,
|
||||
systemProgram: SystemProgram.programId,
|
||||
})
|
||||
.instruction(),
|
||||
flags.enable && queueAuthority.publicKey.equals(queue.authority)
|
||||
? await this.program.methods
|
||||
.permissionSet({
|
||||
permission: { permitOracleQueueUsage: undefined },
|
||||
enable: true,
|
||||
})
|
||||
.accounts({
|
||||
permission: permissionAccount.publicKey,
|
||||
authority: queueAuthority.publicKey,
|
||||
})
|
||||
.instruction()
|
||||
: undefined,
|
||||
].filter((item) => item)
|
||||
);
|
||||
createAccountSigners.push(aggregatorKeypair);
|
||||
|
||||
// Create Lease Account
|
||||
// Add to crank if applicable
|
||||
const [leaseAccount, leaseBump] = LeaseAccount.fromSeed(
|
||||
this.program,
|
||||
queueAccount,
|
||||
aggregatorAccount
|
||||
);
|
||||
const leaseEscrow = await spl.Token.getAssociatedTokenAddress(
|
||||
spl.ASSOCIATED_TOKEN_PROGRAM_ID,
|
||||
spl.TOKEN_PROGRAM_ID,
|
||||
switchTokenMint.publicKey,
|
||||
leaseAccount.publicKey,
|
||||
true
|
||||
);
|
||||
createAccountInstructions.push(
|
||||
[
|
||||
spl.Token.createAssociatedTokenAccountInstruction(
|
||||
spl.ASSOCIATED_TOKEN_PROGRAM_ID,
|
||||
spl.TOKEN_PROGRAM_ID,
|
||||
switchTokenMint.publicKey,
|
||||
leaseEscrow,
|
||||
leaseAccount.publicKey,
|
||||
payerKeypair.publicKey
|
||||
),
|
||||
await this.program.methods
|
||||
.leaseInit({
|
||||
loadAmount: new anchor.BN(0),
|
||||
stateBump,
|
||||
leaseBump,
|
||||
withdrawAuthority: feedAuthority.publicKey,
|
||||
walletBumps: Buffer.from([]),
|
||||
})
|
||||
.accounts({
|
||||
programState: programStateAccount.publicKey,
|
||||
lease: leaseAccount.publicKey,
|
||||
queue: queueAccount.publicKey,
|
||||
aggregator: aggregatorAccount.publicKey,
|
||||
systemProgram: SystemProgram.programId,
|
||||
funder: tokenWallet,
|
||||
payer: payerKeypair.publicKey,
|
||||
tokenProgram: spl.TOKEN_PROGRAM_ID,
|
||||
escrow: leaseEscrow,
|
||||
owner: payerKeypair.publicKey,
|
||||
mint: switchTokenMint.publicKey,
|
||||
})
|
||||
// .remainingAccounts(
|
||||
// jobPubkeys.concat(jobWallets).map((pubkey: PublicKey) => {
|
||||
// return { isSigner: false, isWritable: true, pubkey };
|
||||
// })
|
||||
// )
|
||||
.instruction(),
|
||||
flags.crankKey
|
||||
? await this.program.methods
|
||||
.crankPush({
|
||||
stateBump,
|
||||
permissionBump,
|
||||
})
|
||||
.accounts({
|
||||
crank: new PublicKey(flags.crankKey),
|
||||
aggregator: aggregatorKeypair.publicKey,
|
||||
oracleQueue: queueAccount.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(flags.crankKey),
|
||||
}).loadData()
|
||||
).dataBuffer,
|
||||
})
|
||||
.instruction()
|
||||
: undefined,
|
||||
].filter((item) => item)
|
||||
);
|
||||
|
||||
// Add Job Accounts
|
||||
const addJobIxns = await Promise.all(
|
||||
jobAccounts.map(async (job) => {
|
||||
return this.program.methods
|
||||
.aggregatorAddJob({
|
||||
weight: 1,
|
||||
})
|
||||
.accounts({
|
||||
aggregator: aggregatorKeypair.publicKey,
|
||||
authority: feedAuthority.publicKey,
|
||||
job: job.publicKey,
|
||||
})
|
||||
.instruction();
|
||||
})
|
||||
);
|
||||
|
||||
const createAccountSignatures = packAndSend(
|
||||
this.program,
|
||||
[createAccountInstructions, addJobIxns],
|
||||
createAccountSigners,
|
||||
payerKeypair.publicKey
|
||||
).catch((error) => {
|
||||
throw error;
|
||||
});
|
||||
|
||||
let aggInitWs: number;
|
||||
const aggInitPromise = new Promise((resolve: (result: any) => void) => {
|
||||
aggInitWs = this.program.provider.connection.onAccountChange(
|
||||
aggregatorKeypair.publicKey,
|
||||
(accountInfo: AccountInfo<Buffer>, slot) => {
|
||||
const aggData = new anchor.BorshAccountsCoder(
|
||||
this.program.idl
|
||||
).decode("AggregatorAccountData", accountInfo.data);
|
||||
resolve(aggData);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
const result = await promiseWithTimeout(45_000, aggInitPromise).finally(
|
||||
() => {
|
||||
try {
|
||||
this.program.provider.connection.removeAccountChangeListener(
|
||||
aggInitWs
|
||||
);
|
||||
} catch {}
|
||||
}
|
||||
);
|
||||
|
||||
if (this.silent) {
|
||||
console.log(aggregatorAccount.publicKey.toString());
|
||||
}
|
||||
|
||||
await sleep(2500);
|
||||
|
||||
this.logger.info(
|
||||
await prettyPrintAggregator(aggregatorAccount, result, true, true, true)
|
||||
);
|
||||
}
|
||||
|
||||
async catch(error) {
|
||||
|
|
|
@ -70,18 +70,17 @@ export default class JsonCreateAggregator extends BaseCommand {
|
|||
if (!fs.existsSync(definitionFile)) {
|
||||
throw new Error("input file does not exist");
|
||||
}
|
||||
let aggregatorDefinition: fromAggregatorJSON = JSON.parse(
|
||||
|
||||
const aggregatorDefinition: fromAggregatorJSON = JSON.parse(
|
||||
fs.readFileSync(definitionFile, "utf-8"),
|
||||
pubKeyReviver
|
||||
);
|
||||
|
||||
if (flags.outputFile) {
|
||||
if (fs.existsSync(flags.outputFile) && !flags.force) {
|
||||
if (flags.outputFile && fs.existsSync(flags.outputFile) && !flags.force) {
|
||||
throw new Error(
|
||||
"output file exists. Run the command with '--force' to overwrite it"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let authority = programWallet(this.program);
|
||||
if (flags.authority) {
|
||||
|
@ -91,6 +90,7 @@ export default class JsonCreateAggregator extends BaseCommand {
|
|||
if (!aggregatorDefinition.queuePublicKey && !flags.queueKey) {
|
||||
throw new Error("you must provide a --queueKey to create aggregator for");
|
||||
}
|
||||
|
||||
const queueAccount = new OracleQueueAccount({
|
||||
program: this.program,
|
||||
publicKey: aggregatorDefinition.queuePublicKey
|
||||
|
@ -173,6 +173,7 @@ export default class JsonCreateAggregator extends BaseCommand {
|
|||
jobs.push(account);
|
||||
}
|
||||
}
|
||||
|
||||
for await (const job of jobs) {
|
||||
await aggregatorAccount.addJob(job, authority);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
import { flags } from "@oclif/command";
|
||||
import { prettyPrintJob } from "@switchboard-xyz/sbv2-utils";
|
||||
import {
|
||||
JobAccount,
|
||||
OracleJob,
|
||||
programWallet,
|
||||
} from "@switchboard-xyz/switchboard-v2";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import BaseCommand from "../../../BaseCommand";
|
||||
import { verifyProgramHasPayer } from "../../../utils";
|
||||
|
||||
export default class JobCreate extends BaseCommand {
|
||||
static description = "create a buffer relayer account";
|
||||
|
||||
static flags = {
|
||||
...BaseCommand.flags,
|
||||
authority: flags.string({
|
||||
char: "a",
|
||||
description: "alternate keypair that will be the aggregator authority",
|
||||
}),
|
||||
name: flags.string({
|
||||
char: "n",
|
||||
description: "name of the buffer account",
|
||||
}),
|
||||
};
|
||||
|
||||
static args = [
|
||||
{
|
||||
name: "jobDefinition",
|
||||
required: true,
|
||||
description: "filesystem path to job definition",
|
||||
},
|
||||
];
|
||||
|
||||
async run() {
|
||||
verifyProgramHasPayer(this.program);
|
||||
const { args, flags } = this.parse(JobCreate);
|
||||
const payerKeypair = programWallet(this.program);
|
||||
const authority = await this.loadAuthority(flags.authority);
|
||||
|
||||
const jobDefinitionPath = args.jobDefinition.startsWith("/")
|
||||
? args.jobDefinition
|
||||
: path.join(process.cwd(), args.jobDefinition);
|
||||
if (!fs.existsSync(jobDefinitionPath)) {
|
||||
throw new Error(`jobDefinitionPath does not exist, ${jobDefinitionPath}`);
|
||||
}
|
||||
|
||||
const oracleJob = OracleJob.create(
|
||||
JSON.parse(fs.readFileSync(jobDefinitionPath, "utf-8"))
|
||||
);
|
||||
if (!("tasks" in oracleJob)) {
|
||||
throw new Error("Must provide tasks in job definition");
|
||||
}
|
||||
|
||||
const data = Buffer.from(
|
||||
OracleJob.encodeDelimited(
|
||||
OracleJob.create({
|
||||
tasks: oracleJob.tasks,
|
||||
})
|
||||
).finish()
|
||||
);
|
||||
console.log(`DATA: [${data.join(",")}]`);
|
||||
const jobAccount = await JobAccount.create(this.program, {
|
||||
authority: authority.publicKey,
|
||||
name: flags.name ? Buffer.from(flags.name) : Buffer.from(""),
|
||||
data,
|
||||
});
|
||||
|
||||
if (this.silent) {
|
||||
this.logger.info(jobAccount.publicKey.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
const job = await jobAccount.loadData();
|
||||
this.logger.info(await prettyPrintJob(jobAccount, job));
|
||||
|
||||
console.log(`DATA: [${job.data.join(",")}]`);
|
||||
}
|
||||
|
||||
async catch(error) {
|
||||
super.catch(error, "failed to create buffer relayer account");
|
||||
}
|
||||
}
|
|
@ -64,11 +64,19 @@ export default class OracleCreate extends BaseCommand {
|
|||
const { args, flags } = this.parse(OracleCreate);
|
||||
verifyProgramHasPayer(this.program);
|
||||
const payerKeypair = programWallet(this.program);
|
||||
const signers: Keypair[] = [payerKeypair];
|
||||
|
||||
const authorityKeypair = await this.loadAuthority(flags.authority);
|
||||
// if (!payerKeypair.publicKey.equals(authorityKeypair.publicKey)) {
|
||||
// signers.push(authorityKeypair);
|
||||
// }
|
||||
|
||||
const queueAuthority: Keypair = flags.queueAuthority
|
||||
? await loadKeypair(flags.queueAuthority)
|
||||
: payerKeypair;
|
||||
if (!payerKeypair.publicKey.equals(queueAuthority.publicKey)) {
|
||||
signers.push(queueAuthority);
|
||||
}
|
||||
|
||||
const queueAccount = new OracleQueueAccount({
|
||||
program: this.program,
|
||||
|
@ -82,6 +90,7 @@ export default class OracleCreate extends BaseCommand {
|
|||
);
|
||||
|
||||
const tokenWalletKeypair = anchor.web3.Keypair.generate();
|
||||
signers.push(tokenWalletKeypair);
|
||||
const [oracleAccount, oracleBump] = OracleAccount.fromSeed(
|
||||
this.program,
|
||||
queueAccount,
|
||||
|
@ -92,7 +101,7 @@ export default class OracleCreate extends BaseCommand {
|
|||
|
||||
const [permissionAccount, permissionBump] = PermissionAccount.fromSeed(
|
||||
this.program,
|
||||
authorityKeypair.publicKey,
|
||||
queue.authority,
|
||||
queueAccount.publicKey,
|
||||
oracleAccount.publicKey
|
||||
);
|
||||
|
@ -137,7 +146,7 @@ export default class OracleCreate extends BaseCommand {
|
|||
.permissionInit({})
|
||||
.accounts({
|
||||
permission: permissionAccount.publicKey,
|
||||
authority: authorityKeypair.publicKey,
|
||||
authority: queue.authority,
|
||||
granter: queueAccount.publicKey,
|
||||
grantee: oracleAccount.publicKey,
|
||||
payer: payerKeypair.publicKey,
|
||||
|
@ -152,9 +161,11 @@ export default class OracleCreate extends BaseCommand {
|
|||
`Invalid queue authority, received ${queueAuthority.publicKey}, expected ${queue.authority}`
|
||||
);
|
||||
}
|
||||
|
||||
createOracleTxn.add(
|
||||
await this.program.methods
|
||||
.permissionSet({
|
||||
// eslint-disable-next-line unicorn/no-null
|
||||
permission: { permitOracleHeartbeat: null },
|
||||
enable: true,
|
||||
})
|
||||
|
@ -168,7 +179,7 @@ export default class OracleCreate extends BaseCommand {
|
|||
|
||||
const signature = await this.program.provider.sendAndConfirm(
|
||||
createOracleTxn,
|
||||
[payerKeypair, authorityKeypair, tokenWalletKeypair]
|
||||
signers
|
||||
);
|
||||
const oracleData = await oracleAccount.loadData();
|
||||
|
||||
|
@ -176,6 +187,7 @@ export default class OracleCreate extends BaseCommand {
|
|||
console.log(oracleAccount.publicKey.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
this.logger.log(
|
||||
`${chalk.green(`${CHECK_ICON}Oracle account created successfully`)}`
|
||||
);
|
||||
|
|
|
@ -57,12 +57,14 @@ export default class PermissionSet extends BaseCommand {
|
|||
authorityKey = data.authority;
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
throw new Error(
|
||||
`Granter should be a OracleQueueAccount, received ${granterAccountType}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const authority = await this.loadAuthority(flags.authority, authorityKey);
|
||||
|
||||
// check and load grantees account type, and assign permissions based on type
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
/* eslint-disable unicorn/import-style */
|
||||
import { flags } from "@oclif/command";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
import {
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
import { flags } from "@oclif/command";
|
||||
import { Keypair, PublicKey } from "@solana/web3.js";
|
||||
import { OracleQueueAccount } from "@switchboard-xyz/switchboard-v2";
|
||||
import * as anchor from "@project-serum/anchor";
|
||||
import { PublicKey, SystemProgram } from "@solana/web3.js";
|
||||
import {
|
||||
prettyPrintCrank,
|
||||
verifyProgramHasPayer,
|
||||
} from "@switchboard-xyz/sbv2-utils";
|
||||
import {
|
||||
CrankAccount,
|
||||
OracleQueueAccount,
|
||||
programWallet,
|
||||
} from "@switchboard-xyz/switchboard-v2";
|
||||
import chalk from "chalk";
|
||||
import { fromCrankJSON } from "../../../accounts";
|
||||
import { CrankClass } from "../../../accounts/crank/crank";
|
||||
import BaseCommand from "../../../BaseCommand";
|
||||
import { CHECK_ICON } from "../../../utils";
|
||||
|
||||
export default class QueueAddCrank extends BaseCommand {
|
||||
queueAccount: OracleQueueAccount;
|
||||
|
||||
crankDefinition: fromCrankJSON;
|
||||
|
||||
queueAuthority: Keypair | undefined = undefined;
|
||||
|
||||
static description = "add a crank to an existing oracle queue";
|
||||
|
||||
static flags = {
|
||||
|
@ -26,10 +27,9 @@ export default class QueueAddCrank extends BaseCommand {
|
|||
char: "r",
|
||||
description: "maximum number of rows a crank can support",
|
||||
}),
|
||||
// authority: flags.string({
|
||||
// char: "a",
|
||||
// description: "alternate keypair that is the authority for oracle queue",
|
||||
// }),
|
||||
queueAuthority: flags.string({
|
||||
description: "alternative keypair to use for queue authority",
|
||||
}),
|
||||
};
|
||||
|
||||
static args = [
|
||||
|
@ -46,41 +46,72 @@ export default class QueueAddCrank extends BaseCommand {
|
|||
// "$ sbv2 queue:add:crank 5aYuxRdcB9GpWrEXVMBQp2R5uf94uoBiFdMEBwcmHuU4 -k ../payer-keypair.json -a ../authority-keypair.json",
|
||||
];
|
||||
|
||||
async init() {
|
||||
await super.init();
|
||||
async run() {
|
||||
const { args, flags } = this.parse(QueueAddCrank);
|
||||
|
||||
this.queueAccount = new OracleQueueAccount({
|
||||
program: this.program,
|
||||
publicKey: args.queueKey,
|
||||
});
|
||||
|
||||
// TODO: Not implemented yet
|
||||
// if (flags.authority) {
|
||||
// this.queueAuthority = await loadKeypair(flags.authority);
|
||||
// }
|
||||
verifyProgramHasPayer(this.program);
|
||||
const payerKeypair = programWallet(this.program);
|
||||
|
||||
if (flags.maxRows < 0) {
|
||||
throw new Error("max rows must be a positive number");
|
||||
}
|
||||
|
||||
this.crankDefinition = {
|
||||
name: flags.name || "",
|
||||
maxRows: flags.maxRows || undefined,
|
||||
};
|
||||
}
|
||||
const maxRows = flags.maxRows;
|
||||
|
||||
async run() {
|
||||
const crank = await CrankClass.fromJSON(
|
||||
this.context,
|
||||
this.crankDefinition,
|
||||
this.queueAccount
|
||||
const queueAccount = new OracleQueueAccount({
|
||||
program: this.program,
|
||||
publicKey: args.queueKey,
|
||||
});
|
||||
const queue = await queueAccount.loadData();
|
||||
|
||||
const queueAuthority = await this.loadAuthority(
|
||||
flags.queueAuthority,
|
||||
queue.authority
|
||||
);
|
||||
|
||||
const crankKeypair = anchor.web3.Keypair.generate();
|
||||
const bufferKeypair = anchor.web3.Keypair.generate();
|
||||
const crankSize = this.program.account.crankAccountData.size;
|
||||
const bufferSize = maxRows * 40 + 8;
|
||||
const signature = await this.program.methods
|
||||
.crankInit({
|
||||
name: (flags.name ? Buffer.from(flags.name) : Buffer.from("")).slice(
|
||||
0,
|
||||
32
|
||||
),
|
||||
metadata: Buffer.from("").slice(0, 64),
|
||||
crankSize: maxRows,
|
||||
})
|
||||
.accounts({
|
||||
crank: crankKeypair.publicKey,
|
||||
queue: queueAccount.publicKey,
|
||||
buffer: bufferKeypair.publicKey,
|
||||
systemProgram: SystemProgram.programId,
|
||||
payer: payerKeypair.publicKey,
|
||||
})
|
||||
.signers([crankKeypair, bufferKeypair])
|
||||
.preInstructions([
|
||||
anchor.web3.SystemProgram.createAccount({
|
||||
fromPubkey: payerKeypair.publicKey,
|
||||
newAccountPubkey: bufferKeypair.publicKey,
|
||||
space: bufferSize,
|
||||
lamports:
|
||||
await this.program.provider.connection.getMinimumBalanceForRentExemption(
|
||||
bufferSize
|
||||
),
|
||||
programId: this.program.programId,
|
||||
}),
|
||||
])
|
||||
.rpc();
|
||||
|
||||
const crankAccount = new CrankAccount({
|
||||
program: this.program,
|
||||
publicKey: crankKeypair.publicKey,
|
||||
});
|
||||
|
||||
if (this.silent) {
|
||||
console.log(crank.account.publicKey.toString());
|
||||
console.log(crankKeypair.publicKey.toString());
|
||||
} else {
|
||||
this.logger.log(crank.prettyPrint());
|
||||
this.logger.log(await prettyPrintCrank(crankAccount));
|
||||
this.logger.log(
|
||||
`${chalk.green(`${CHECK_ICON}Crank created successfully\r\n`)}`
|
||||
);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* eslint-disable unicorn/prevent-abbreviations */
|
||||
/* eslint-disable complexity */
|
||||
/* eslint-disable unicorn/new-for-builtins */
|
||||
import { flags } from "@oclif/command";
|
||||
import * as anchor from "@project-serum/anchor";
|
||||
|
@ -102,7 +102,7 @@ export default class QueueCreate extends BaseCommand {
|
|||
verifyProgramHasPayer(this.program);
|
||||
const { flags, args } = this.parse(QueueCreate);
|
||||
const payerKeypair = programWallet(this.program);
|
||||
const signers: Keypair[] = [];
|
||||
const signers: Keypair[] = [payerKeypair];
|
||||
|
||||
const outputPath =
|
||||
flags.outputFile === undefined
|
||||
|
@ -119,6 +119,7 @@ export default class QueueCreate extends BaseCommand {
|
|||
if (!authorityKeypair.publicKey.equals(payerKeypair.publicKey)) {
|
||||
signers.push(authorityKeypair);
|
||||
}
|
||||
|
||||
const [programStateAccount, stateBump] = ProgramStateAccount.fromSeed(
|
||||
this.program
|
||||
);
|
||||
|
@ -186,18 +187,6 @@ export default class QueueCreate extends BaseCommand {
|
|||
this.logger.debug(chalkString("OracleQueue", queueKeypair.publicKey));
|
||||
this.logger.debug(chalkString("OracleBuffer", queueBuffer.publicKey));
|
||||
|
||||
const crankKeypair = anchor.web3.Keypair.generate();
|
||||
const crankBuffer = anchor.web3.Keypair.generate();
|
||||
const crankSize = flags.crankSize ? flags.crankSize * 40 + 8 : 0;
|
||||
|
||||
this.logger.debug(chalkString("CrankAccount", crankKeypair.publicKey));
|
||||
this.logger.debug(chalkString("CrankBuffer", crankBuffer.publicKey));
|
||||
|
||||
const crankAccount = new CrankAccount({
|
||||
program: this.program,
|
||||
publicKey: crankKeypair.publicKey,
|
||||
});
|
||||
|
||||
setupQueueTxns.push(
|
||||
anchor.web3.SystemProgram.createAccount({
|
||||
fromPubkey: payerKeypair.publicKey,
|
||||
|
@ -238,7 +227,25 @@ export default class QueueCreate extends BaseCommand {
|
|||
payer: payerKeypair.publicKey,
|
||||
mint: tokenMint.publicKey,
|
||||
})
|
||||
.instruction(),
|
||||
.instruction()
|
||||
);
|
||||
signers.push(queueKeypair, queueBuffer);
|
||||
|
||||
let crankAccount: CrankAccount | undefined;
|
||||
if (flags.crankSize) {
|
||||
const crankKeypair = anchor.web3.Keypair.generate();
|
||||
const crankBuffer = anchor.web3.Keypair.generate();
|
||||
const crankSize = flags.crankSize ? flags.crankSize * 40 + 8 : 0;
|
||||
|
||||
this.logger.debug(chalkString("CrankAccount", crankKeypair.publicKey));
|
||||
this.logger.debug(chalkString("CrankBuffer", crankBuffer.publicKey));
|
||||
crankAccount = new CrankAccount({
|
||||
program: this.program,
|
||||
publicKey: crankKeypair.publicKey,
|
||||
});
|
||||
signers.push(crankKeypair, crankBuffer);
|
||||
|
||||
setupQueueTxns.push(
|
||||
anchor.web3.SystemProgram.createAccount({
|
||||
fromPubkey: payerKeypair.publicKey,
|
||||
newAccountPubkey: crankBuffer.publicKey,
|
||||
|
@ -264,7 +271,7 @@ export default class QueueCreate extends BaseCommand {
|
|||
})
|
||||
.instruction()
|
||||
);
|
||||
signers.push(queueKeypair, queueBuffer, crankKeypair, crankBuffer);
|
||||
}
|
||||
|
||||
const finalTransactions: (
|
||||
| TransactionInstruction
|
||||
|
@ -272,7 +279,7 @@ export default class QueueCreate extends BaseCommand {
|
|||
)[] = [];
|
||||
|
||||
const oracleAccounts = await Promise.all(
|
||||
Array.from(Array(flags.numOracles).keys()).map(async (n) => {
|
||||
[...Array(flags.numOracles).keys()].map(async (n) => {
|
||||
const name = `Oracle-${n + 1}`;
|
||||
const tokenWalletKeypair = anchor.web3.Keypair.generate();
|
||||
const [oracleAccount, oracleBump] = OracleAccount.fromSeed(
|
||||
|
@ -340,6 +347,7 @@ export default class QueueCreate extends BaseCommand {
|
|||
.instruction(),
|
||||
await this.program.methods
|
||||
.permissionSet({
|
||||
// eslint-disable-next-line unicorn/no-null
|
||||
permission: { permitOracleHeartbeat: null },
|
||||
enable: true,
|
||||
})
|
||||
|
@ -386,13 +394,17 @@ export default class QueueCreate extends BaseCommand {
|
|||
name: flags.name,
|
||||
queueAccount: queueKeypair.publicKey.toString(),
|
||||
queueSize: flags.queueSize,
|
||||
queueReward: Number.parseInt(flags.reward),
|
||||
minStake: Number.parseInt(flags.minStake),
|
||||
queueReward: Number.parseInt(flags.reward, 10),
|
||||
minStake: Number.parseInt(flags.minStake, 10),
|
||||
oracleTimeout: flags.oracleTimeout,
|
||||
crankAccounts: [
|
||||
// crankAccount === undefined ? undefined :
|
||||
crankAccounts:
|
||||
crankAccount === undefined
|
||||
? undefined
|
||||
: [
|
||||
{
|
||||
name: "Crank",
|
||||
crankAccount: crankKeypair.publicKey.toString(),
|
||||
crankAccount: crankAccount.publicKey.toString(),
|
||||
maxRows: flags.crankSize,
|
||||
},
|
||||
],
|
||||
|
|
|
@ -60,7 +60,9 @@ export const loadGoogleSecretKeypair = async (
|
|||
const client = new SecretManagerServiceClient();
|
||||
|
||||
const [accessResponse] = await client.accessSecretVersion({
|
||||
name: secretPath,
|
||||
name: secretPath.includes("/versions/")
|
||||
? secretPath
|
||||
: `${secretPath}/versions/latest`,
|
||||
});
|
||||
|
||||
const secrets = accessResponse?.payload.data;
|
||||
|
@ -91,6 +93,7 @@ export const loadKeypair = async (
|
|||
const keypair = loadKeypairFs(keypairPath);
|
||||
return keypair;
|
||||
} catch {}
|
||||
|
||||
try {
|
||||
const keypair = await loadGoogleSecretKeypair(keypairPath);
|
||||
return keypair;
|
||||
|
@ -100,6 +103,7 @@ export const loadKeypair = async (
|
|||
} else if ("secretPath" in keypairPath) {
|
||||
return loadGoogleSecretKeypair(keypairPath.secretPath);
|
||||
}
|
||||
|
||||
throw new InvalidKeypairProvided(keypairPath);
|
||||
};
|
||||
|
||||
|
@ -140,5 +144,6 @@ export const loadKeypairWithDescriptor = async (
|
|||
};
|
||||
return [keypair, descriptor];
|
||||
}
|
||||
|
||||
throw new InvalidKeypairProvided(keypairPath);
|
||||
};
|
||||
|
|
|
@ -31,11 +31,12 @@ export async function packAndSend(
|
|||
).wallet.signAllTransactions(signedTransactions);
|
||||
|
||||
for (let k = 0; k < packedTransactions.length; k += 1) {
|
||||
const tx = signedTxs[k];
|
||||
const rawTx = tx!.serialize();
|
||||
const tx = signedTxs[k]!;
|
||||
const rawTx = tx.serialize();
|
||||
signatures.push(
|
||||
sendAndConfirmRawTransaction(program.provider.connection, rawTx, {
|
||||
maxRetries: 10,
|
||||
commitment: "processed",
|
||||
})
|
||||
.then((sig) => {
|
||||
return sig;
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
"scripts": {
|
||||
"docgen": "yarn build && npx typedoc",
|
||||
"build:protos": "pbjs -t static-module -o src/protos/index.js ../protos/*.proto && pbts -o src/protos/index.d.ts src/protos/index.js",
|
||||
"build:cjs:protos": "shx mkdir -p lib/cjs/protos; pbjs -t static-module -w commonjs -o lib/cjs/protos/index.js ../protos/*.proto && pbts -o lib/cjs/protos/index.d.ts lib/cjs/protos/index.js",
|
||||
"build:cjs:protos": "shx mkdir -p lib/cjs/protos; pbjs -t static-module -o lib/cjs/protos/index.js ../protos/*.proto && pbts -o lib/cjs/protos/index.d.ts lib/cjs/protos/index.js",
|
||||
"build:esm:protos": "shx mkdir -p lib/esm/protos; pbjs -t static-module -o lib/esm/protos/index.js ../protos/*.proto && pbts -o lib/esm/protos/index.d.ts lib/esm/protos/index.js",
|
||||
"build:cjs": "shx rm -rf lib/cjs && tsc -p tsconfig.cjs.json && shx echo '{\"type\": \"commonjs\"}' > lib/cjs/package.json && yarn build:cjs:protos",
|
||||
"build:esm": "shx rm -rf lib/esm && tsc -p tsconfig.esm.json && shx echo '{\"type\": \"module\"}' > lib/esm/package.json && yarn build:esm:protos",
|
||||
|
@ -43,6 +43,7 @@
|
|||
"@project-serum/anchor": "^0.24.2",
|
||||
"@solana/spl-governance": "^0.0.34",
|
||||
"@switchboard-xyz/eslint-config": "^0.1.1",
|
||||
"@switchboard-xyz/switchboard-api": "^0.2.201",
|
||||
"assert": "^2.0.0",
|
||||
"big.js": "^6.1.1",
|
||||
"bs58": "^4.0.1",
|
||||
|
@ -65,12 +66,5 @@
|
|||
"shx": "^0.3.4",
|
||||
"typedoc": "^0.22.13",
|
||||
"typescript": "^4.2.4"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "@switchboard-xyz",
|
||||
"rules": {
|
||||
"no-return-await": "off",
|
||||
"quotes": "off"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,11 +18,12 @@ import {
|
|||
TransactionInstruction,
|
||||
TransactionSignature,
|
||||
} from "@solana/web3.js";
|
||||
// eslint-disable-next-line import/extensions
|
||||
// import { OracleJob } from "./protos/index.js";
|
||||
import { OracleJob } from "@switchboard-xyz/switchboard-api";
|
||||
import assert from "assert";
|
||||
import Big from "big.js";
|
||||
import * as crypto from "crypto";
|
||||
// eslint-disable-next-line import/extensions
|
||||
import { OracleJob } from "./protos/index.js";
|
||||
const assert = require("assert");
|
||||
|
||||
/**
|
||||
* Switchboard Devnet Program ID
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
"docs:build:sbv2-utils": "yarn workspace @switchboard-xyz/sbv2-utils docgen",
|
||||
"docs:build:cli": "node ./tools/scripts/generate-cli-docs.js",
|
||||
"docs:build:site": "yarn workspace website build:site",
|
||||
"docs:build:tasks": "protoc --proto_path=../switchboard-core/protos --doc_out=website/api --doc_opt=markdown,_tasks.md ../switchboard-core/protos/job_schemas.proto",
|
||||
"docs:build:tasks": "protoc --proto_path=./libraries/protos --doc_out=website/api --doc_opt=markdown,_tasks.md ./libraries/protos/job_schemas.proto",
|
||||
"docs:build": "run-s docs:build:ts docs:build:sbv2-lite docs:build:sbv2-utils docs:build:cli docs:build:site",
|
||||
"docs:deploy": "yarn workspace website deploy",
|
||||
"gen:idl": "rawrtools gen:anchor SW1TCH7qEPTdLsDHRgPuMQjbQxKdH2aBStViMFnt64f -o website/idl -p /idl",
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
# Protocol Documentation
|
||||
|
||||
<a name="top"></a>
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [job_schemas.proto](#job_schemas.proto)
|
||||
|
||||
- [JobPosting](#.JobPosting)
|
||||
- [JobResult](#.JobResult)
|
||||
- [OracleJob](#.OracleJob)
|
||||
- [OracleJob.AddTask](#.OracleJob.AddTask)
|
||||
- [OracleJob.AnchorFetchTask](#.OracleJob.AnchorFetchTask)
|
||||
- [OracleJob.CacheTask](#.OracleJob.CacheTask)
|
||||
- [OracleJob.ConditionalTask](#.OracleJob.ConditionalTask)
|
||||
- [OracleJob.DefiKingdomsTask](#.OracleJob.DefiKingdomsTask)
|
||||
- [OracleJob.DefiKingdomsTask.Token](#.OracleJob.DefiKingdomsTask.Token)
|
||||
|
@ -28,6 +27,7 @@
|
|||
- [OracleJob.MedianTask](#.OracleJob.MedianTask)
|
||||
- [OracleJob.MultiplyTask](#.OracleJob.MultiplyTask)
|
||||
- [OracleJob.OracleTask](#.OracleJob.OracleTask)
|
||||
- [OracleJob.PancakeswapExchangeRateTask](#.OracleJob.PancakeswapExchangeRateTask)
|
||||
- [OracleJob.PerpMarketTask](#.OracleJob.PerpMarketTask)
|
||||
- [OracleJob.PowTask](#.OracleJob.PowTask)
|
||||
- [OracleJob.RegexExtractTask](#.OracleJob.RegexExtractTask)
|
||||
|
@ -36,6 +36,7 @@
|
|||
- [OracleJob.SplTokenParseTask](#.OracleJob.SplTokenParseTask)
|
||||
- [OracleJob.SubtractTask](#.OracleJob.SubtractTask)
|
||||
- [OracleJob.SushiswapExchangeRateTask](#.OracleJob.SushiswapExchangeRateTask)
|
||||
- [OracleJob.SysclockOffsetTask](#.OracleJob.SysclockOffsetTask)
|
||||
- [OracleJob.Task](#.OracleJob.Task)
|
||||
- [OracleJob.TpsTask](#.OracleJob.TpsTask)
|
||||
- [OracleJob.TwapTask](#.OracleJob.TwapTask)
|
||||
|
@ -44,376 +45,589 @@
|
|||
- [OracleJob.WebsocketTask](#.OracleJob.WebsocketTask)
|
||||
- [OracleJob.XStepPriceTask](#.OracleJob.XStepPriceTask)
|
||||
|
||||
- [OracleJob.CacheTask.Method](#.OracleJob.CacheTask.Method)
|
||||
- [OracleJob.HttpTask.Method](#.OracleJob.HttpTask.Method)
|
||||
- [OracleJob.JsonParseTask.AggregationMethod](#.OracleJob.JsonParseTask.AggregationMethod)
|
||||
- [OracleJob.LendingRateTask.Field](#.OracleJob.LendingRateTask.Field)
|
||||
|
||||
- [Scalar Value Types](#scalar-value-types)
|
||||
|
||||
<a name="job_schemas.proto"></a>
|
||||
|
||||
|
||||
<a name="job_schemas.proto"></a>
|
||||
<p align="right"><a href="#top">Top</a></p>
|
||||
|
||||
## job_schemas.proto
|
||||
|
||||
|
||||
|
||||
<a name=".JobPosting"></a>
|
||||
|
||||
### JobPosting
|
||||
|
||||
The schema Oracle nodes receive when they are notified to fulfill a job.
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----------------------- | ----------------- | -------- | ------------------------------------------------ |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| aggregator_state_pubkey | [bytes](#bytes) | optional | Pubkey of the aggregator to fulfill the job for. |
|
||||
| node_pubkeys | [bytes](#bytes) | repeated | The pubkey of the nodes this job is assigned to. |
|
||||
| slot | [uint64](#uint64) | optional | Slot number of the job posting. |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".JobResult"></a>
|
||||
|
||||
### JobResult
|
||||
|
||||
This schema Oracle nodes respond with when fulfilling a job.
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----------- | --------------- | -------- | ----------------------------------------------------------------- |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| node_pubkey | [bytes](#bytes) | optional | The public key of the responding node. |
|
||||
| result | double | optional | The median value of the jobs the node has fulfilled successfully. |
|
||||
| result | [double](#double) | optional | The median value of the jobs the node has fulfilled successfully. |
|
||||
| error | [bool](#bool) | optional | True if the node failed to decide on an answer to the job. |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob"></a>
|
||||
|
||||
### OracleJob
|
||||
Represnts a list of tasks to be performed by a switchboard oracle.
|
||||
|
||||
Represents a list of tasks to be performed by a switchboard oracle.
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | --------------------------------- | -------- | ------------------------------------------------- |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| tasks | [OracleJob.Task](#OracleJob.Task) | repeated | The chain of tasks to perform for this OracleJob. |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.AddTask"></a>
|
||||
|
||||
### OracleJob.AddTask
|
||||
|
||||
This task will add a numerical input by a scalar value or by another
|
||||
aggregate.
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----------------- | ----------------------- | -------- | -------------------------------------------------------------------------------- |
|
||||
| scalar | double | optional | Specifies a scalar to add by. |
|
||||
| aggregator_pubkey | string | optional | Specifies an aggregator to add by. |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| scalar | [double](#double) | optional | Specifies a scalar to add by. |
|
||||
| aggregator_pubkey | [string](#string) | optional | Specifies an aggregator to add by. |
|
||||
| job | [OracleJob](#OracleJob) | optional | A job whose result is computed before adding our numerical input by that result. |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.AnchorFetchTask"></a>
|
||||
|
||||
### OracleJob.AnchorFetchTask
|
||||
|
||||
Load a parse an Anchor based solana account.
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| --------------- | ------ | -------- | --------------------------------------- |
|
||||
| program_id | string | optional | Owning program of the account to parse. |
|
||||
| account_address | string | optional | The account to parse. |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| program_id | [string](#string) | optional | Owning program of the account to parse. |
|
||||
| account_address | [string](#string) | optional | The account to parse. |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.CacheTask"></a>
|
||||
|
||||
### OracleJob.CacheTask
|
||||
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| name | [string](#string) | optional | |
|
||||
| method | [OracleJob.CacheTask.Method](#OracleJob.CacheTask.Method) | optional | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.ConditionalTask"></a>
|
||||
|
||||
### OracleJob.ConditionalTask
|
||||
|
||||
This task will run the `attempt` subtasks in an effort to produce a valid numerical result. If
|
||||
`attempt` fails to produce an acceptable result, `on_failure` subtasks will be run instead.
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ---------- | --------------------------------- | -------- | ----------------------------------------------------------------------------------------------------- |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| attempt | [OracleJob.Task](#OracleJob.Task) | repeated | A list of subtasks to process in an attempt to produce a valid numerical result. |
|
||||
| on_failure | [OracleJob.Task](#OracleJob.Task) | repeated | A list of subtasks that will be run if `attempt` subtasks are unable to produce an acceptable result. |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.DefiKingdomsTask"></a>
|
||||
|
||||
### OracleJob.DefiKingdomsTask
|
||||
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| --------- | --------------------------------------------------------------------- | -------- | ----------- |
|
||||
| provider | string | optional | |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| provider | [string](#string) | optional | |
|
||||
| in_token | [OracleJob.DefiKingdomsTask.Token](#OracleJob.DefiKingdomsTask.Token) | optional | |
|
||||
| out_token | [OracleJob.DefiKingdomsTask.Token](#OracleJob.DefiKingdomsTask.Token) | optional | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.DefiKingdomsTask.Token"></a>
|
||||
|
||||
### OracleJob.DefiKingdomsTask.Token
|
||||
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| -------- | ------ | -------- | ----------- |
|
||||
| address | string | optional | |
|
||||
| decimals | int32 | optional | |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| address | [string](#string) | optional | |
|
||||
| decimals | [int32](#int32) | optional | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.DivideTask"></a>
|
||||
|
||||
### OracleJob.DivideTask
|
||||
|
||||
This task will divide a numerical input by a scalar value or by another
|
||||
aggregate.
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----------------- | ----------------------- | -------- | ---------------------------------------------------------------------------------- |
|
||||
| scalar | double | optional | Specifies a basic scalar denominator to divide by. |
|
||||
| aggregator_pubkey | string | optional | Specifies another aggregator result to divide by. |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| scalar | [double](#double) | optional | Specifies a basic scalar denominator to divide by. |
|
||||
| aggregator_pubkey | [string](#string) | optional | Specifies another aggregator resut to divide by. |
|
||||
| job | [OracleJob](#OracleJob) | optional | A job whose result is computed before dividing our numerical input by that result. |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.HttpTask"></a>
|
||||
|
||||
### OracleJob.HttpTask
|
||||
|
||||
The adapter will report the text body of a successful HTTP request to the specified url,
|
||||
or return an error if the response status code is greater than or equal to 400.
|
||||
@return string representation of it's output.
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ------- | ------------------------------------------------------- | -------- | ----------------------------------------------------------- |
|
||||
| url | string | optional | A string containing the URL to direct this HTTP request to. |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| url | [string](#string) | optional | A string containing the URL to direct this HTTP request to. |
|
||||
| method | [OracleJob.HttpTask.Method](#OracleJob.HttpTask.Method) | optional | The type of HTTP request to make. |
|
||||
| headers | [OracleJob.HttpTask.Header](#OracleJob.HttpTask.Header) | repeated | A list of headers to add to this HttpTask. |
|
||||
| body | string | optional | A stringified body (if any) to add to this HttpTask. |
|
||||
| body | [string](#string) | optional | A stringified body (if any) to add to this HttpTask. |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.HttpTask.Header"></a>
|
||||
|
||||
### OracleJob.HttpTask.Header
|
||||
|
||||
An object that represents a header to add to an HTTP request.
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ------ | -------- | ----------- |
|
||||
| key | string | optional | |
|
||||
| value | string | optional | |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| key | [string](#string) | optional | |
|
||||
| value | [string](#string) | optional | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.JsonParseTask"></a>
|
||||
|
||||
### OracleJob.JsonParseTask
|
||||
|
||||
The adapter walks the path specified and returns the value found at that result. If returning
|
||||
JSON data from the HttpGet or HttpPost adapters, you must use this adapter to parse the
|
||||
response.
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ------------------ | --------------------------------------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------- |
|
||||
| path | string | optional | JSONPath formatted path to the element. https://t.ly/uLtw https://www.npmjs.com/package/jsonpath-plus |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| path | [string](#string) | optional | JSONPath formatted path to the element. https://t.ly/uLtw https://www.npmjs.com/package/jsonpath-plus |
|
||||
| aggregation_method | [OracleJob.JsonParseTask.AggregationMethod](#OracleJob.JsonParseTask.AggregationMethod) | optional | The technique that will be used to aggregate the results if walking the specified path returns multiple numerical results. |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.JupiterSwapTask"></a>
|
||||
|
||||
### OracleJob.JupiterSwapTask
|
||||
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----------------- | ------ | -------- | ----------- |
|
||||
| in_token_address | string | optional | |
|
||||
| out_token_address | string | optional | |
|
||||
| base_amount | double | optional | |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| in_token_address | [string](#string) | optional | |
|
||||
| out_token_address | [string](#string) | optional | |
|
||||
| base_amount | [double](#double) | optional | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.LendingRateTask"></a>
|
||||
|
||||
### OracleJob.LendingRateTask
|
||||
|
||||
Fetch the lending rates for various Solana protocols
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ---------- | ------------------------------------------------------------------- | -------- | ------------------------------------------------------------- |
|
||||
| protocol | string | optional | 01, apricot, francium, jet, larix, mango, port, solend, tulip |
|
||||
| asset_mint | string | optional | A token mint address supported by the chosen protocol |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| protocol | [string](#string) | optional | 01, apricot, francium, jet, larix, mango, port, solend, tulip |
|
||||
| asset_mint | [string](#string) | optional | A token mint address supported by the chosen protocol |
|
||||
| field | [OracleJob.LendingRateTask.Field](#OracleJob.LendingRateTask.Field) | optional | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.LpExchangeRateTask"></a>
|
||||
|
||||
### OracleJob.LpExchangeRateTask
|
||||
|
||||
Fetch the current swap price for a given liquidity pool
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ---------------------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------- |
|
||||
| in_token_address | string | optional | Not Used |
|
||||
| out_token_address | string | optional | Not Used |
|
||||
| mercurial_pool_address | string | optional | Mercurial finance pool address. A full list can be found here: https://github.com/mercurial-finance/stable-swap-n-pool-js |
|
||||
| saber_pool_address | string | optional | Saber pool address. A full list can be found here: https://github.com/saber-hq/saber-registry-dist |
|
||||
| orca_pool_token_mint_address | string | optional | Orca pool address. A full list can be found here: https://www.orca.so/pools |
|
||||
| raydium_pool_address | string | optional | The Raydium liquidity pool ammId. A full list can be found here: https://sdk.raydium.io/liquidity/mainnet.json |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| in_token_address | [string](#string) | optional | Not Used |
|
||||
| out_token_address | [string](#string) | optional | Not Used |
|
||||
| mercurial_pool_address | [string](#string) | optional | Mercurial finance pool address. A full list can be found here: https://github.com/mercurial-finance/stable-swap-n-pool-js |
|
||||
| saber_pool_address | [string](#string) | optional | Saber pool address. A full list can be found here: https://github.com/saber-hq/saber-registry-dist |
|
||||
| orca_pool_token_mint_address | [string](#string) | optional | Orca pool address. A full list can be found here: https://www.orca.so/pools |
|
||||
| raydium_pool_address | [string](#string) | optional | The Raydium liquidity pool ammId. A full list can be found here: https://sdk.raydium.io/liquidity/mainnet.json |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.LpTokenPriceTask"></a>
|
||||
|
||||
### OracleJob.LpTokenPriceTask
|
||||
|
||||
Fetch LP token price info from a number of supported exchanges.
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ---------------------- | ----------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| mercurial_pool_address | string | optional | Mercurial finance pool address. A full list can be found here: https://github.com/mercurial-finance/stable-swap-n-pool-js |
|
||||
| saber_pool_address | string | optional | Saber pool address. A full list can be found here: https://github.com/saber-hq/saber-registry-dist |
|
||||
| orca_pool_address | string | optional | Orca pool address. A full list can be found here: https://www.orca.so/pools |
|
||||
| raydium_pool_address | string | optional | The Raydium liquidity pool ammId. A full list can be found here: https://sdk.raydium.io/liquidity/mainnet.json |
|
||||
| price_feed_addresses | string | repeated | A list of Switchboard aggregator accounts used to calculate the fair LP price. This ensures the price is based on the previous round to mitigate flash loan price manipulation. |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| mercurial_pool_address | [string](#string) | optional | Mercurial finance pool address. A full list can be found here: https://github.com/mercurial-finance/stable-swap-n-pool-js |
|
||||
| saber_pool_address | [string](#string) | optional | Saber pool address. A full list can be found here: https://github.com/saber-hq/saber-registry-dist |
|
||||
| orca_pool_address | [string](#string) | optional | Orca pool address. A full list can be found here: https://www.orca.so/pools |
|
||||
| raydium_pool_address | [string](#string) | optional | The Raydium liquidity pool ammId. A full list can be found here: https://sdk.raydium.io/liquidity/mainnet.json |
|
||||
| price_feed_addresses | [string](#string) | repeated | A list of Switchboard aggregator accounts used to calculate the fair LP price. This ensures the price is based on the previous round to mitigate flash loan price manipulation. |
|
||||
| price_feed_jobs | [OracleJob](#OracleJob) | repeated | |
|
||||
| use_fair_price | [bool](#bool) | optional | If enabled and price_feed_addresses provided, the oracle will calculate the fair LP price based on the liquidity pool reserves. See our blog post for more information: https://switchboardxyz.medium.com/fair-lp-token-oracles-94a457c50239 |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.MangoPerpMarketTask"></a>
|
||||
|
||||
### OracleJob.MangoPerpMarketTask
|
||||
|
||||
Fetch the current price for a Mango perpetual market
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ------------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| perp_market_address | string | optional | Mainnet address for a mango perpetual market. A full list can be found here: https://github.com/blockworks-foundation/mango-client-v3/blob/main/src/ids.json |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| perp_market_address | [string](#string) | optional | Mainnet address for a mango perpetual market. A full list can be found here: https://github.com/blockworks-foundation/mango-client-v3/blob/main/src/ids.json |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.MaxTask"></a>
|
||||
|
||||
### OracleJob.MaxTask
|
||||
|
||||
Returns the maximum value of all the results returned by the provided subtasks and subjobs.
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | --------------------------------- | -------- | ------------------------------------------------------------------ |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| tasks | [OracleJob.Task](#OracleJob.Task) | repeated | A list of subtasks to process and produce a list of result values. |
|
||||
| jobs | [OracleJob](#OracleJob) | repeated | A list of subjobs to process and produce a list of result values. |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.MeanTask"></a>
|
||||
|
||||
### OracleJob.MeanTask
|
||||
|
||||
Returns the mean of all the results returned by the provided subtasks and subjobs.
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | --------------------------------- | -------- | ------------------------------------------------------------------ |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| tasks | [OracleJob.Task](#OracleJob.Task) | repeated | A list of subtasks to process and produce a list of result values. |
|
||||
| jobs | [OracleJob](#OracleJob) | repeated | A list of subjobs to process and produce a list of result values. |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.MedianTask"></a>
|
||||
|
||||
### OracleJob.MedianTask
|
||||
|
||||
Returns the median of all the results returned by the provided subtasks and subjobs. Nested
|
||||
tasks must return a Number.
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----------------------- | --------------------------------- | -------- | ------------------------------------------------------------------ |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| tasks | [OracleJob.Task](#OracleJob.Task) | repeated | A list of subtasks to process and produce a list of result values. |
|
||||
| jobs | [OracleJob](#OracleJob) | repeated | A list of subjobs to process and produce a list of result values. |
|
||||
| min_successful_required | int32 | optional | |
|
||||
| min_successful_required | [int32](#int32) | optional | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.MultiplyTask"></a>
|
||||
|
||||
### OracleJob.MultiplyTask
|
||||
|
||||
This task will multiply a numerical input by a scalar value or by another
|
||||
aggregate.
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----------------- | ----------------------- | -------- | ------------------------------------------------------------------------------------- |
|
||||
| scalar | double | optional | Specifies a scalar to multiply by. |
|
||||
| aggregator_pubkey | string | optional | Specifies an aggregator to multiply by. |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| scalar | [double](#double) | optional | Specifies a scalar to multiply by. |
|
||||
| aggregator_pubkey | [string](#string) | optional | Specifies an aggregator to multiply by. |
|
||||
| job | [OracleJob](#OracleJob) | optional | A job whose result is computed before multiplying our numerical input by that result. |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.OracleTask"></a>
|
||||
|
||||
### OracleJob.OracleTask
|
||||
|
||||
Fetch the current price of a Solana oracle protocol
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| -------------------------------- | ------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| switchboard_address | string | optional | Mainnet address of a Switchboard V2 feed. Switchboard is decentralized and allows anyone to build their own feed. A small subset of feeds is available here: https://switchboard.xyz/explorer |
|
||||
| pyth_address | string | optional | Mainnet address for a Pyth feed. A full list can be found here: https://pyth.network/markets/ |
|
||||
| chainlink_address | string | optional | Devnet address for a Chainlink feed. A full list can be found here: https://docs.chain.link/docs/solana/data-feeds-solana |
|
||||
| pyth_allowed_confidence_interval | double | optional | Value (as a percentage) that the lower bound confidence interval is of the actual value. Confidence intervals that are larger that this threshold are rejected. |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| switchboard_address | [string](#string) | optional | Mainnet address of a Switchboard V2 feed. Switchboard is decentralized and allows anyone to build their own feed. A small subset of feeds is available here: https://switchboard.xyz/explorer |
|
||||
| pyth_address | [string](#string) | optional | Mainnet address for a Pyth feed. A full list can be found here: https://pyth.network/markets/ |
|
||||
| chainlink_address | [string](#string) | optional | Devnet address for a Chainlink feed. A full list can be found here: https://docs.chain.link/docs/solana/data-feeds-solana |
|
||||
| pyth_allowed_confidence_interval | [double](#double) | optional | Value (as a percentage) that the lower bound confidence interval is of the actual value. Confidence intervals that are larger that this treshold are rejected. |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.PancakeswapExchangeRateTask"></a>
|
||||
|
||||
### OracleJob.PancakeswapExchangeRateTask
|
||||
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| in_token_address | [string](#string) | optional | |
|
||||
| out_token_address | [string](#string) | optional | |
|
||||
| in_token_amount | [double](#double) | optional | |
|
||||
| slippage | [double](#double) | optional | |
|
||||
| provider | [string](#string) | optional | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.PerpMarketTask"></a>
|
||||
|
||||
### OracleJob.PerpMarketTask
|
||||
|
||||
Fetch the current price of a perpetual market
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| -------------------- | ------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| mango_market_address | string | optional | Market address for a mango perpetual market. A full list can be found here: https://github.com/blockworks-foundation/mango-client-v3/blob/main/src/ids.json |
|
||||
| drift_market_address | string | optional | Market address for a drift perpetual market. A full list can be found here: https://github.com/drift-labs/protocol-v1/blob/master/sdk/src/constants/markets.ts |
|
||||
| zeta_market_address | string | optional | Market address for a zeta perpetual market. |
|
||||
| zo_market_address | string | optional | Market address for a 01 protocol perpetual market. |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| mango_market_address | [string](#string) | optional | Market address for a mango perpetual market. A full list can be found here: https://github.com/blockworks-foundation/mango-client-v3/blob/main/src/ids.json |
|
||||
| drift_market_address | [string](#string) | optional | Market address for a drift perpetual market. A full list can be found here: https://github.com/drift-labs/protocol-v1/blob/master/sdk/src/constants/markets.ts |
|
||||
| zeta_market_address | [string](#string) | optional | Market address for a zeta perpetual market. |
|
||||
| zo_market_address | [string](#string) | optional | Market address for a 01 protocol perpetual market. |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.PowTask"></a>
|
||||
|
||||
### OracleJob.PowTask
|
||||
|
||||
Take the power of the working value.
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----------------- | ------ | -------- | ---------------------------------------------------------------- |
|
||||
| scalar | double | optional | Take the working value to the exponent of value. |
|
||||
| aggregator_pubkey | string | optional | Take the working value to the exponent of the aggregators value. |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| scalar | [double](#double) | optional | Take the working value to the exponent of value. |
|
||||
| aggregator_pubkey | [string](#string) | optional | Take the working value to the exponent of the aggregators value. |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.RegexExtractTask"></a>
|
||||
|
||||
### OracleJob.RegexExtractTask
|
||||
|
||||
Find a pattern within a string of a previous task and extract a group number.
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ------------ | ------ | -------- | ------------------------ |
|
||||
| pattern | string | optional | Regex pattern to find. |
|
||||
| group_number | int32 | optional | Group number to extract. |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| pattern | [string](#string) | optional | Regex pattern to find. |
|
||||
| group_number | [int32](#int32) | optional | Group number to extract. |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.SerumSwapTask"></a>
|
||||
|
||||
### OracleJob.SerumSwapTask
|
||||
|
||||
Fetch the latest swap price on Serum's orderbook
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ------------------ | ------ | -------- | -------------------------------------- |
|
||||
| serum_pool_address | string | optional | The serum pool to fetch swap price for |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| serum_pool_address | [string](#string) | optional | The serum pool to fetch swap price for |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.SplStakePoolTask"></a>
|
||||
|
||||
### OracleJob.SplStakePoolTask
|
||||
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ------ | ------ | -------- | ----------------------------------- |
|
||||
| pubkey | string | optional | The pubkey of the SPL Stake Pool.`` |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| pubkey | [string](#string) | optional | The pubkey of the SPL Stake Pool.`` |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.SplTokenParseTask"></a>
|
||||
|
||||
### OracleJob.SplTokenParseTask
|
||||
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| --------------------- | ------ | -------- | ----------- |
|
||||
| token_account_address | string | optional | |
|
||||
| mint_address | string | optional | |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| token_account_address | [string](#string) | optional | |
|
||||
| mint_address | [string](#string) | optional | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.SubtractTask"></a>
|
||||
|
||||
### OracleJob.SubtractTask
|
||||
|
||||
This task will subtract a numerical input by a scalar value or by another
|
||||
aggregate.
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----------------- | ----------------------- | -------- | ------------------------------------------------------------------------------------- |
|
||||
| scalar | double | optional | Specifies a scalar to subtract by. |
|
||||
| aggregator_pubkey | string | optional | Specifies an aggregator to subtract by. |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| scalar | [double](#double) | optional | Specifies a scalar to subtract by. |
|
||||
| aggregator_pubkey | [string](#string) | optional | Specifies an aggregator to subtract by. |
|
||||
| job | [OracleJob](#OracleJob) | optional | A job whose result is computed before subtracting our numerical input by that result. |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.SushiswapExchangeRateTask"></a>
|
||||
|
||||
### OracleJob.SushiswapExchangeRateTask
|
||||
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----------------- | ------ | -------- | ----------- |
|
||||
| in_token_address | string | optional | |
|
||||
| out_token_address | string | optional | |
|
||||
| in_token_amount | uint32 | optional | |
|
||||
| slippage | double | optional | |
|
||||
| provider | string | optional | |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| in_token_address | [string](#string) | optional | |
|
||||
| out_token_address | [string](#string) | optional | |
|
||||
| in_token_amount | [double](#double) | optional | |
|
||||
| slippage | [double](#double) | optional | |
|
||||
| provider | [string](#string) | optional | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.SysclockOffsetTask"></a>
|
||||
|
||||
### OracleJob.SysclockOffsetTask
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.Task"></a>
|
||||
|
||||
### OracleJob.Task
|
||||
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ---------------------------- | --------------------------------------------------------------------------- | -------- | ----------- |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| http_task | [OracleJob.HttpTask](#OracleJob.HttpTask) | optional | |
|
||||
| json_parse_task | [OracleJob.JsonParseTask](#OracleJob.JsonParseTask) | optional | |
|
||||
| median_task | [OracleJob.MedianTask](#OracleJob.MedianTask) | optional | |
|
||||
|
@ -445,108 +659,177 @@ aggregate.
|
|||
| spl_token_parse_task | [OracleJob.SplTokenParseTask](#OracleJob.SplTokenParseTask) | optional | |
|
||||
| uniswap_exchange_rate_task | [OracleJob.UniswapExchangeRateTask](#OracleJob.UniswapExchangeRateTask) | optional | |
|
||||
| sushiswap_exchange_rate_task | [OracleJob.SushiswapExchangeRateTask](#OracleJob.SushiswapExchangeRateTask) | optional | |
|
||||
| pancakeswap_exchange_rate_task | [OracleJob.PancakeswapExchangeRateTask](#OracleJob.PancakeswapExchangeRateTask) | optional | |
|
||||
| cache_task | [OracleJob.CacheTask](#OracleJob.CacheTask) | optional | |
|
||||
| sysclock_offset_task | [OracleJob.SysclockOffsetTask](#OracleJob.SysclockOffsetTask) | optional | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.TpsTask"></a>
|
||||
|
||||
### OracleJob.TpsTask
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.TwapTask"></a>
|
||||
|
||||
### OracleJob.TwapTask
|
||||
|
||||
Takes a twap over a set period for a certain aggregator.
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| -------------------------- | ------------- | -------- | -------------------------------------------------------------------- |
|
||||
| aggregator_pubkey | string | optional | The target aggregator for the TWAP. |
|
||||
| period | int32 | optional | Period, in seconds, the twap should account for |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| aggregator_pubkey | [string](#string) | optional | The target aggregator for the TWAP. |
|
||||
| period | [int32](#int32) | optional | Period, in seconds, the twap should account for |
|
||||
| weight_by_propagation_time | [bool](#bool) | optional | Weight samples by their propagation time |
|
||||
| min_samples | uint32 | optional | Minimum number of samples in the history to calculate a valid result |
|
||||
| ending_unix_timestamp | int32 | optional | Ending unix timestamp to collect values up to |
|
||||
| min_samples | [uint32](#uint32) | optional | Minimum number of samples in the history to calculate a valid result |
|
||||
| ending_unix_timestamp | [int32](#int32) | optional | Ending unix timestamp to collect values up to |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.UniswapExchangeRateTask"></a>
|
||||
|
||||
### OracleJob.UniswapExchangeRateTask
|
||||
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----------------- | ------ | -------- | ----------- |
|
||||
| in_token_address | string | optional | |
|
||||
| out_token_address | string | optional | |
|
||||
| in_token_amount | uint32 | optional | |
|
||||
| slippage | double | optional | |
|
||||
| provider | string | optional | |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| in_token_address | [string](#string) | optional | |
|
||||
| out_token_address | [string](#string) | optional | |
|
||||
| in_token_amount | [double](#double) | optional | |
|
||||
| slippage | [double](#double) | optional | |
|
||||
| provider | [string](#string) | optional | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.ValueTask"></a>
|
||||
|
||||
### OracleJob.ValueTask
|
||||
|
||||
Returns a specified value.
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----------------- | ------ | -------- | ----------------------------------------------- |
|
||||
| value | double | optional | The value that will be returned from this task. |
|
||||
| aggregator_pubkey | string | optional | Specifies an aggregator to pull the value of. |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| value | [double](#double) | optional | The value that will be returned from this task. |
|
||||
| aggregator_pubkey | [string](#string) | optional | Specifies an aggregatorr to pull the value of. |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.WebsocketTask"></a>
|
||||
|
||||
### OracleJob.WebsocketTask
|
||||
|
||||
Opens and maintains a websocket for light speed data retrieval.
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| -------------------- | ------ | -------- | --------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| url | string | optional | The websocket url. |
|
||||
| subscription | string | optional | The websocket message to notify of a new subscription. |
|
||||
| max_data_age_seconds | int32 | optional | Minimum amount of time required between when the horses are taking out. |
|
||||
| filter | string | optional | Incoming message JSONPath filter. Example: "$[?(@.channel == 'ticker' && @.market == 'BTC/USD')]" |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| url | [string](#string) | optional | The websocket url. |
|
||||
| subscription | [string](#string) | optional | The websocket message to notify of a new subscription. |
|
||||
| max_data_age_seconds | [int32](#int32) | optional | Minimum amount of time required between when the horses are taking out. |
|
||||
| filter | [string](#string) | optional | Incoming message JSONPath filter. Example: "$[?(@.channel == 'ticker' && @.market == 'BTC/USD')]" |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.XStepPriceTask"></a>
|
||||
|
||||
### OracleJob.XStepPriceTask
|
||||
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ---------------------- | --------------------------------------------- | -------- | ---------------------------------------------------------------------- |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| step_job | [OracleJob.MedianTask](#OracleJob.MedianTask) | optional | median task containing the job definitions to fetch the STEP/USD price |
|
||||
| step_aggregator_pubkey | string | optional | existing aggregator pubkey for STEP/USD |
|
||||
| step_aggregator_pubkey | [string](#string) | optional | existing aggregator pubkey for STEP/USD |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.CacheTask.Method"></a>
|
||||
|
||||
### OracleJob.CacheTask.Method
|
||||
|
||||
|
||||
| Name | Number | Description |
|
||||
| ---- | ------ | ----------- |
|
||||
| METHOD_GET | 0 | |
|
||||
| METHOD_SET | 1 | |
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.HttpTask.Method"></a>
|
||||
|
||||
### OracleJob.HttpTask.Method
|
||||
|
||||
An enumeration representing the types of HTTP requests available to make.
|
||||
|
||||
| Name | Number | Description |
|
||||
| -------------- | ------ | -------------------------------------------- |
|
||||
| METHOD_UNKNOWN | 0 | Unset HTTP method will default to METHOD_GET |
|
||||
| ---- | ------ | ----------- |
|
||||
| METHOD_UNKOWN | 0 | Unset HTTP method will default to METHOD_GET |
|
||||
| METHOD_GET | 1 | Perform an HTTP 'GET' request. |
|
||||
| METHOD_POST | 2 | Perform an HTTP 'POST' request. |
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.JsonParseTask.AggregationMethod"></a>
|
||||
|
||||
### OracleJob.JsonParseTask.AggregationMethod
|
||||
|
||||
The methods of combining a list of numerical results.
|
||||
|
||||
| Name | Number | Description |
|
||||
| ---- | ------ | -------------------------------------- |
|
||||
| ---- | ------ | ----------- |
|
||||
| NONE | 0 | |
|
||||
| MIN | 1 | Grab the minimum value of the results. |
|
||||
| MAX | 2 | Grab the maximum value of the results. |
|
||||
| SUM | 3 | Sum up all of the results. |
|
||||
|
||||
|
||||
|
||||
<a name=".OracleJob.LendingRateTask.Field"></a>
|
||||
|
||||
### OracleJob.LendingRateTask.Field
|
||||
|
||||
|
||||
| Name | Number | Description |
|
||||
| ------------------ | ------ | -------------------- |
|
||||
| ---- | ------ | ----------- |
|
||||
| FIELD_DEPOSIT_RATE | 0 | deposit lending rate |
|
||||
| FIELD_BORROW_RATE | 1 | borrow lending rate |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Scalar Value Types
|
||||
|
||||
| .proto Type | Notes | C++ | Java | Python | Go | C# | PHP | Ruby |
|
||||
| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- | ------ | ---------- | ----------- | ------- | ---------- | -------------- | ------------------------------ |
|
||||
| ----------- | ----- | --- | ---- | ------ | -- | -- | --- | ---- |
|
||||
| <a name="double" /> double | | double | double | float | float64 | double | float | Float |
|
||||
| <a name="float" /> float | | float | float | float | float32 | float | float | Float |
|
||||
| <a name="int32" /> int32 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) |
|
||||
|
@ -562,3 +845,4 @@ The methods of combining a list of numerical results.
|
|||
| <a name="bool" /> bool | | bool | boolean | boolean | bool | bool | boolean | TrueClass/FalseClass |
|
||||
| <a name="string" /> string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode | string | string | string | String (UTF-8) |
|
||||
| <a name="bytes" /> bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str | []byte | ByteString | string | String (ASCII-8BIT) |
|
||||
|
||||
|
|
|
@ -41,6 +41,6 @@ You will need to manually add:
|
|||
- BACKUP_MAINNET_RPC
|
||||
- ORACLE_KEY
|
||||
- GRAFANA_HOSTNAME
|
||||
- GRAFANA_PASSWORD
|
||||
- GRAFANA_ADMIN_PASSWORD
|
||||
- GRAFANA_TLS_CRT
|
||||
- GRAFANA_TLS_KEY
|
||||
|
|
|
@ -187,7 +187,7 @@ You will need to collect the following environment variables to inject into the
|
|||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GRAFANA_PASSWORD</td>
|
||||
<td>GRAFANA_ADMIN_PASSWORD</td>
|
||||
<td>
|
||||
<b>
|
||||
<u>Optional</u>
|
||||
|
|
|
@ -32,6 +32,6 @@ When the necessary keys and CSR are generated, head over to [gethttpsforfree.com
|
|||
Your `PROJECTNAME.env` file should now contain
|
||||
|
||||
- GRAFANA_HOSTNAME
|
||||
- GRAFANA_PASSWORD (You can set this to whatever value you want)
|
||||
- GRAFANA_ADMIN_PASSWORD (You can set this to whatever value you want)
|
||||
- GRAFANA_TLS_CRT
|
||||
- GRAFANA_TLS_KEY
|
||||
|
|
|
@ -180,6 +180,6 @@ You will need to manually add:
|
|||
- BACKUP_MAINNET_RPC
|
||||
- ORACLE_KEY
|
||||
- GRAFANA_HOSTNAME
|
||||
- GRAFANA_PASSWORD
|
||||
- GRAFANA_ADMIN_PASSWORD
|
||||
- GRAFANA_TLS_CRT
|
||||
- GRAFANA_TLS_KEY
|
||||
|
|
|
@ -207,7 +207,7 @@ You will need to collect the following environment variables to inject into the
|
|||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GRAFANA_PASSWORD</td>
|
||||
<td>GRAFANA_ADMIN_PASSWORD</td>
|
||||
<td>
|
||||
<b>
|
||||
<u>Optional</u>
|
||||
|
@ -287,7 +287,7 @@ You will need to manually add:
|
|||
- BACKUP_MAINNET_RPC
|
||||
- ORACLE_KEY
|
||||
- GRAFANA_HOSTNAME
|
||||
- GRAFANA_PASSWORD
|
||||
- GRAFANA_ADMIN_PASSWORD
|
||||
- GRAFANA_TLS_CRT
|
||||
- GRAFANA_TLS_KEY
|
||||
|
||||
|
@ -469,7 +469,7 @@ You will need to manually add:
|
|||
- BACKUP_MAINNET_RPC
|
||||
- ORACLE_KEY
|
||||
- GRAFANA_HOSTNAME
|
||||
- GRAFANA_PASSWORD
|
||||
- GRAFANA_ADMIN_PASSWORD
|
||||
- GRAFANA_TLS_CRT
|
||||
- GRAFANA_TLS_KEY
|
||||
|
||||
|
@ -502,7 +502,7 @@ When the necessary keys and CSR are generated, head over to [gethttpsforfree.com
|
|||
Your `PROJECTNAME.env` file should now contain
|
||||
|
||||
- GRAFANA_HOSTNAME
|
||||
- GRAFANA_PASSWORD (You can set this to whatever value you want)
|
||||
- GRAFANA_ADMIN_PASSWORD (You can set this to whatever value you want)
|
||||
- GRAFANA_TLS_CRT
|
||||
- GRAFANA_TLS_KEY
|
||||
|
||||
|
|
30
yarn.lock
30
yarn.lock
|
@ -4668,6 +4668,18 @@
|
|||
"@svgr/plugin-jsx" "^6.2.1"
|
||||
"@svgr/plugin-svgo" "^6.2.0"
|
||||
|
||||
"@switchboard-xyz/switchboard-api@^0.2.201":
|
||||
version "0.2.201"
|
||||
resolved "https://registry.npmjs.org/@switchboard-xyz/switchboard-api/-/switchboard-api-0.2.201.tgz#d082206d521d24dbcdeb06a77e6637a56ab883eb"
|
||||
integrity sha512-hlxgeYmO6dbOEcmQzT1SqRxdiCFyVOMpyW4HFPgmPKT0+wSVkjsLc+BKkMGYPDaO0sWMLTJrj0FGhhTsrqd8Mg==
|
||||
dependencies:
|
||||
"@solana/web3.js" "^1.17.0"
|
||||
form-data "^4.0.0"
|
||||
protobufjs "^6.10.2"
|
||||
rpc-websockets "^7.4.12"
|
||||
typedoc "^0.22.15"
|
||||
ws "^7.4.6"
|
||||
|
||||
"@szmarczak/http-timer@^1.1.2":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz"
|
||||
|
@ -6884,7 +6896,7 @@ combine-promises@^1.1.0:
|
|||
resolved "https://registry.npmjs.org/combine-promises/-/combine-promises-1.1.0.tgz"
|
||||
integrity sha512-ZI9jvcLDxqwaXEixOhArm3r7ReIivsXkpbyEWyeOhzz1QS0iSgBPnWvEqvIQtYyamGCYA88gFhmUrs9hrrQ0pg==
|
||||
|
||||
combined-stream@^1.0.6, combined-stream@~1.0.6:
|
||||
combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6:
|
||||
version "1.0.8"
|
||||
resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz"
|
||||
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
|
||||
|
@ -9169,6 +9181,15 @@ fork-ts-checker-webpack-plugin@^6.5.0:
|
|||
semver "^7.3.2"
|
||||
tapable "^1.0.0"
|
||||
|
||||
form-data@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
|
||||
integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
|
||||
dependencies:
|
||||
asynckit "^0.4.0"
|
||||
combined-stream "^1.0.8"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
form-data@~2.3.2:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz"
|
||||
|
@ -14600,7 +14621,7 @@ rimraf@^3.0.0, rimraf@^3.0.2:
|
|||
dependencies:
|
||||
glob "^7.1.3"
|
||||
|
||||
rpc-websockets@^7.4.2:
|
||||
rpc-websockets@^7.4.12, rpc-websockets@^7.4.2:
|
||||
version "7.4.18"
|
||||
resolved "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-7.4.18.tgz"
|
||||
integrity sha512-bVu+4qM5CkGVlTqJa6FaAxLbb5uRnyH4te7yjFvoCzbnif7PT4BcvXtNTprHlNvsH+/StB81zUQicxMrUrIomA==
|
||||
|
@ -16894,6 +16915,11 @@ ws@^7.0.0, ws@^7.3.1, ws@^7.4.5:
|
|||
resolved "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz"
|
||||
integrity sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==
|
||||
|
||||
ws@^7.4.6:
|
||||
version "7.5.8"
|
||||
resolved "https://registry.npmjs.org/ws/-/ws-7.5.8.tgz#ac2729881ab9e7cbaf8787fe3469a48c5c7f636a"
|
||||
integrity sha512-ri1Id1WinAX5Jqn9HejiGb8crfRio0Qgu8+MtL36rlTA6RLsMdWt1Az/19A2Qij6uSHUMphEFaTKa4WG+UNHNw==
|
||||
|
||||
ws@^8.4.2, ws@^8.5.0:
|
||||
version "8.5.0"
|
||||
resolved "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz"
|
||||
|
|
Loading…
Reference in New Issue