Merge branch 'fix-create-agg-cli' into main
This commit is contained in:
commit
7d56377292
116
cli/README.md
116
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
|
||||
|
@ -2151,24 +2137,26 @@ ARGUMENTS
|
|||
QUEUEKEY public key of the oracle queue to create a crank on
|
||||
|
||||
OPTIONS
|
||||
-h, --help show CLI help
|
||||
-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
|
||||
-n, --name=name name of the crank for easier identification
|
||||
|
||||
-r, --maxRows=maxRows maximum number of rows a crank can support
|
||||
-r, --maxRows=maxRows maximum number of rows a crank can support
|
||||
|
||||
-s, --silent suppress cli prompts
|
||||
-s, --silent suppress cli prompts
|
||||
|
||||
-u, --rpcUrl=rpcUrl alternate RPC url
|
||||
-u, --rpcUrl=rpcUrl alternate RPC url
|
||||
|
||||
-v, --verbose log everything
|
||||
-v, --verbose log everything
|
||||
|
||||
--mainnetBeta WARNING: use mainnet-beta solana cluster
|
||||
--mainnetBeta WARNING: use mainnet-beta solana cluster
|
||||
|
||||
--programId=programId alternative Switchboard program ID to interact with
|
||||
--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
|
||||
.aggregatorAddJob({
|
||||
weight: 1,
|
||||
})
|
||||
.accounts({
|
||||
aggregator: aggregatorKeypair.publicKey,
|
||||
authority: payerKeypair.publicKey,
|
||||
job: jobAccount.publicKey,
|
||||
})
|
||||
.instruction();
|
||||
})
|
||||
))
|
||||
);
|
||||
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: 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(() => {
|
||||
try {
|
||||
this.program.provider.connection.removeAccountChangeListener(aggInitWs);
|
||||
} catch {}
|
||||
});
|
||||
const result = await promiseWithTimeout(45_000, aggInitPromise).finally(
|
||||
() => {
|
||||
try {
|
||||
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,38 +101,307 @@ 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 jobJson = JSON.parse(
|
||||
fs.readFileSync(
|
||||
jobDefinition.startsWith("/")
|
||||
? jobDefinition
|
||||
: path.join(process.cwd(), jobDefinition),
|
||||
"utf8"
|
||||
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("/")
|
||||
? jobDefinition
|
||||
: path.join(process.cwd(), jobDefinition),
|
||||
"utf8"
|
||||
)
|
||||
);
|
||||
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({
|
||||
tasks: jobJson.tasks,
|
||||
})
|
||||
).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];
|
||||
}
|
||||
)
|
||||
)
|
||||
);
|
||||
if (!jobJson || !("tasks" in jobJson)) {
|
||||
throw new Error("job definition missing tasks");
|
||||
}
|
||||
const data = Buffer.from(
|
||||
OracleJob.encodeDelimited(
|
||||
OracleJob.create({
|
||||
tasks: jobJson.tasks,
|
||||
: [];
|
||||
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,
|
||||
})
|
||||
).finish()
|
||||
.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,17 +70,16 @@ 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) {
|
||||
throw new Error(
|
||||
"output file exists. Run the command with '--force' to overwrite it"
|
||||
);
|
||||
}
|
||||
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);
|
||||
|
@ -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,33 +227,51 @@ export default class QueueCreate extends BaseCommand {
|
|||
payer: payerKeypair.publicKey,
|
||||
mint: tokenMint.publicKey,
|
||||
})
|
||||
.instruction(),
|
||||
anchor.web3.SystemProgram.createAccount({
|
||||
fromPubkey: payerKeypair.publicKey,
|
||||
newAccountPubkey: crankBuffer.publicKey,
|
||||
space: crankSize,
|
||||
lamports:
|
||||
await this.program.provider.connection.getMinimumBalanceForRentExemption(
|
||||
crankSize
|
||||
),
|
||||
programId: this.program.programId,
|
||||
}),
|
||||
await this.program.methods
|
||||
.crankInit({
|
||||
name: Buffer.from("Crank").slice(0, 32),
|
||||
metadata: Buffer.from("").slice(0, 64),
|
||||
crankSize: flags.crankSize,
|
||||
})
|
||||
.accounts({
|
||||
crank: crankKeypair.publicKey,
|
||||
queue: queueKeypair.publicKey,
|
||||
buffer: crankBuffer.publicKey,
|
||||
systemProgram: SystemProgram.programId,
|
||||
payer: payerKeypair.publicKey,
|
||||
})
|
||||
.instruction()
|
||||
);
|
||||
signers.push(queueKeypair, queueBuffer, crankKeypair, crankBuffer);
|
||||
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,
|
||||
space: crankSize,
|
||||
lamports:
|
||||
await this.program.provider.connection.getMinimumBalanceForRentExemption(
|
||||
crankSize
|
||||
),
|
||||
programId: this.program.programId,
|
||||
}),
|
||||
await this.program.methods
|
||||
.crankInit({
|
||||
name: Buffer.from("Crank").slice(0, 32),
|
||||
metadata: Buffer.from("").slice(0, 64),
|
||||
crankSize: flags.crankSize,
|
||||
})
|
||||
.accounts({
|
||||
crank: crankKeypair.publicKey,
|
||||
queue: queueKeypair.publicKey,
|
||||
buffer: crankBuffer.publicKey,
|
||||
systemProgram: SystemProgram.programId,
|
||||
payer: payerKeypair.publicKey,
|
||||
})
|
||||
.instruction()
|
||||
);
|
||||
}
|
||||
|
||||
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,16 +394,20 @@ 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: [
|
||||
{
|
||||
name: "Crank",
|
||||
crankAccount: crankKeypair.publicKey.toString(),
|
||||
maxRows: flags.crankSize,
|
||||
},
|
||||
],
|
||||
// crankAccount === undefined ? undefined :
|
||||
crankAccounts:
|
||||
crankAccount === undefined
|
||||
? undefined
|
||||
: [
|
||||
{
|
||||
name: "Crank",
|
||||
crankAccount: crankAccount.publicKey.toString(),
|
||||
maxRows: flags.crankSize,
|
||||
},
|
||||
],
|
||||
oracleAccounts: [
|
||||
oracleAccounts.map((oracle) => {
|
||||
return {
|
||||
|
|
|
@ -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",
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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