diff --git a/examples/functions/01_basic_oracle/Anchor.toml b/examples/functions/01_basic_oracle/Anchor.toml index 1dcc1d27c..71528b0f2 100644 --- a/examples/functions/01_basic_oracle/Anchor.toml +++ b/examples/functions/01_basic_oracle/Anchor.toml @@ -14,8 +14,10 @@ basic_oracle = "APWppEwwfddbooTUijn3oAVnQH6jkLDxW4JrTMbBoQXJ" [provider] # cluster = "Localnet" # wallet = "~/.config/solana/id.json" -cluster = "https://api.devnet.solana.com" -wallet = "~/switchboard_environments_v2/devnet/upgrade_authority/upgrade_authority.json" +# cluster = "https://api.devnet.solana.com" +# wallet = "~/switchboard_environments_v2/devnet/upgrade_authority/upgrade_authority.json" +cluster = "https://api.mainnet-beta.solana.com" +wallet = "~/switchboard_environments_v2/mainnet/upgrade_authority/upgrade_authority.json" [scripts] test = "pnpm exec ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" diff --git a/examples/functions/01_basic_oracle/Cargo.lock b/examples/functions/01_basic_oracle/Cargo.lock index 86a29dbcd..4a4d59ff2 100644 --- a/examples/functions/01_basic_oracle/Cargo.lock +++ b/examples/functions/01_basic_oracle/Cargo.lock @@ -4226,6 +4226,8 @@ checksum = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f" [[package]] name = "switchboard-common" version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83bfe6e728a1f2500bdbdddd3c17de1faf031f3d6c5f186a889ce66c80377e4" dependencies = [ "envy", "getrandom 0.2.10", @@ -4239,6 +4241,8 @@ dependencies = [ [[package]] name = "switchboard-solana" version = "0.28.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dab64de18aaea4bde26fbaf931c7a02d7ede957c880626b8cdf029f98c086a80" dependencies = [ "anchor-client", "anchor-lang", diff --git a/examples/functions/01_basic_oracle/Cargo.toml b/examples/functions/01_basic_oracle/Cargo.toml index 7955f2395..6f6e2fb93 100644 --- a/examples/functions/01_basic_oracle/Cargo.toml +++ b/examples/functions/01_basic_oracle/Cargo.toml @@ -19,6 +19,6 @@ cpi = ["no-entrypoint"] default = [] [dependencies] -# switchboard-solana = "0.28.4" -switchboard-solana = { version = "0.28.4", path = "../../../rust/switchboard-solana" } -bytemuck = "^1" +switchboard-solana = "0.28.4" +# switchboard-solana = { version = "0.28.4", path = "../../../rust/switchboard-solana" } +bytemuck = "^1" \ No newline at end of file diff --git a/examples/functions/01_basic_oracle/README.md b/examples/functions/01_basic_oracle/README.md index 7792f49e5..e56123caf 100644 --- a/examples/functions/01_basic_oracle/README.md +++ b/examples/functions/01_basic_oracle/README.md @@ -2,36 +2,12 @@ ![Switchboard Logo](https://github.com/switchboard-xyz/sbv2-core/raw/main/website/static/img/icons/switchboard/avatar.png) -# anchor-vrf-lite-parser - -> An example program written in Anchor demonstrating how to integrate Switchboard Functions and verify attestation on-chain. - -[![Anchor Test Status](https://github.com/switchboard-xyz/sbv2-solana/actions/workflows/anchor-test.yml/badge.svg)](https://github.com/switchboard-xyz/sbv2-solana/actions/workflows/anchor-test.yml) - - - - - - - ## Usage -Build the example program +Deploy function: ```bash -anchor build -``` +sb solana function create "CkvizjVnm2zA5Wuwan34NhVT3zFc7vqUyGnA6tuEF5aE" --container ${CONTAINER_NAME} --cluster devnet --schedule "15 * * * * *" --containerRegistry dockerhub --keypair /Users/mgild/switchboard_environments_v2/devnet/upgrade_authority/upgrade_authority.json --mrEnclave 0x63ba8df478b4a74795a79a73b8f0a6f792f88e95f9ed6202289091e6e1b65fa1 --fundAmount 0.25 -Get your program ID and update `Anchor.toml` and `src/lib.rs` with your pubkey - -```bash -export ANCHOR_VRF_LITE_PARSER_PUBKEY=$(solana-keygen pubkey target/deploy/anchor_vrf_lite_parser-keypair.json) -sed -i '' s/5Hhm5xKDiThfidbpqjJpKmMJEcKmjj5tEUNFpi2DzSvb/"$ANCHOR_VRF_LITE_PARSER_PUBKEY"/g Anchor.toml -sed -i '' s/5Hhm5xKDiThfidbpqjJpKmMJEcKmjj5tEUNFpi2DzSvb/"$ANCHOR_VRF_LITE_PARSER_PUBKEY"/g src/lib.rs -``` - -Then run Anchor test - -```bash -anchor test -``` +sb solana function create "2ie3JZfKcvsRLsJaP5fSo43gUo1vsurnUAtAgUdUAiDG" --container ${CONTAINER_NAME} --schedule "30 * * * * *" --containerRegistry dockerhub --keypair /Users/mgild/switchboard_environments_v2/mainnet/upgrade_authority/upgrade_authority.json --mainnetBeta --mrEnclave 0x63ba8df478b4a74795a79a73b8f0a6f792f88e95f9ed6202289091e6e1b65fa1 --fundAmount 0.25 +``` \ No newline at end of file diff --git a/examples/functions/01_basic_oracle/package.json b/examples/functions/01_basic_oracle/package.json index 7894f5ce1..48d135400 100644 --- a/examples/functions/01_basic_oracle/package.json +++ b/examples/functions/01_basic_oracle/package.json @@ -15,8 +15,7 @@ "@coral-xyz/anchor": "^0.28.0", "@solana/spl-token": "^0.3.6", "@solana/web3.js": "^1.78.0", - "@switchboard-xyz/common": "^2.3.0", - "@switchboard-xyz/solana.js": "^2.5.0" + "@switchboard-xyz/solana.js": "^" }, "devDependencies": { "@types/bn.js": "^5.1.0", @@ -27,4 +26,4 @@ "mocha": "^9.0.3", "ts-mocha": "^10.0.0" } -} +} \ No newline at end of file diff --git a/examples/functions/01_basic_oracle/scripts/fnCreate.ts b/examples/functions/01_basic_oracle/scripts/fnCreate.ts new file mode 100644 index 000000000..77df7c130 --- /dev/null +++ b/examples/functions/01_basic_oracle/scripts/fnCreate.ts @@ -0,0 +1,62 @@ +import type { BasicOracle } from "../target/types/basic_oracle"; + +import * as anchor from "@coral-xyz/anchor"; +import { Connection, PublicKey } from "@solana/web3.js"; +import * as sb from "@switchboard-xyz/solana.js"; + +const rpcUrl = + "https://api.devnet.solana.com"; +const kp = sb.loadKeypair( + "~/switchboard_environments_v2/devnet/upgrade_authority/upgrade_authority.json" +); +const DEFAULT_DEVNET_QUEUE = "CkvizjVnm2zA5Wuwan34NhVT3zFc7vqUyGnA6tuEF5aE"; +const DEFAULT_MAINNET_QUEUE = "2ie3JZfKcvsRLsJaP5fSo43gUo1vsurnUAtAgUdUAiDG"; + +async function main() { + const con = new Connection(rpcUrl); + const switchboardProgram = await sb.SwitchboardProgram.load( + "mainnet-beta", + con, + kp + ); + const attestationProgram = await sb.SwitchboardProgram.loadAnchorProgram( + "mainnet-beta", + con, + kp, + switchboardProgram.attestationProgramId + ); + + console.log(`ProgramID: ${switchboardProgram}`); + + const recentSlot = ( + await con.getLatestBlockhashAndContext({ + commitment: "finalized", + }) + ).context.slot; + console.log(recentSlot); + const [fn, tx] = await sb.FunctionAccount.create(switchboardProgram, { + container: "t1", + recentSlot: recentSlot, + attestationQueue: new sb.AttestationQueueAccount( + switchboardProgram, + new PublicKey(DEFAULT_DEVNET_QUEUE) + ), + mrEnclave: Buffer.from( + "63ba8df478b4a74795a79a73b8f0a6f792f88e95f9ed6202289091e6e1b65fa1", + "hex" + ), + requestsDisabled: false, + requestsRequireAuthorization: false, + requestsDefaultSlotsUntilExpiration: new anchor.BN("0"), + requestsFee: 0, + }); + + // console.log("Your transaction signature", tx); + + console.log("Your transaction signature", tx); +} + +main().catch((err) => { + console.error(err); + process.exit(1); +}); diff --git a/examples/functions/01_basic_oracle/sgx-function/Cargo.toml b/examples/functions/01_basic_oracle/sgx-function/Cargo.toml index 94a5fd639..87b650bdf 100644 --- a/examples/functions/01_basic_oracle/sgx-function/Cargo.toml +++ b/examples/functions/01_basic_oracle/sgx-function/Cargo.toml @@ -15,7 +15,7 @@ tokio = "^1" futures = "0.3" serde = "^1" serde_json = "^1" -# switchboard-solana = "0.28.4" switchboard-utils = "0.8.0" -switchboard-solana = { version = "0.28.4", path = "../../../../rust/switchboard-solana" } -# switchboard-utils = { version = "0.8.0", path = "../../../../../../rust/switchboard-utils" } +switchboard-solana = "0.28.4" +# switchboard-solana = { version = "0.28.4", path = "../../../../rust/switchboard-solana" } +# switchboard-utils = { version = "0.8.0", path = "../../../../../../rust/switchboard-utils" } \ No newline at end of file diff --git a/examples/functions/01_basic_oracle/sgx-function/src/main.rs b/examples/functions/01_basic_oracle/sgx-function/src/main.rs index 3983807f6..9669597b2 100644 --- a/examples/functions/01_basic_oracle/sgx-function/src/main.rs +++ b/examples/functions/01_basic_oracle/sgx-function/src/main.rs @@ -25,4 +25,4 @@ async fn main() { // Finally, emit the signed quote and partially signed transaction to the functionRunner oracle // The functionRunner oracle will use the last outputted word to stdout as the serialized result. This is what gets executed on-chain. runner.emit(ixs).await.unwrap(); -} +} \ No newline at end of file diff --git a/examples/functions/01_basic_oracle/src/actions/set_function.rs b/examples/functions/01_basic_oracle/src/actions/set_function.rs index 60c5c1a1b..e59de4f9a 100644 --- a/examples/functions/01_basic_oracle/src/actions/set_function.rs +++ b/examples/functions/01_basic_oracle/src/actions/set_function.rs @@ -33,4 +33,4 @@ impl SetFunction<'_> { program.function = ctx.accounts.function.key(); Ok(()) } -} \ No newline at end of file +} diff --git a/examples/functions/01_basic_oracle/src/lib.rs b/examples/functions/01_basic_oracle/src/lib.rs index fa791bde5..a07db0fe3 100644 --- a/examples/functions/01_basic_oracle/src/lib.rs +++ b/examples/functions/01_basic_oracle/src/lib.rs @@ -12,7 +12,7 @@ pub use model::*; pub mod utils; pub use utils::*; -declare_id!("APWppEwwfddbooTUijn3oAVnQH6jkLDxW4JrTMbBoQXJ"); +declare_id!("EF68PJkRqQu2VthTSy19kg6TWynMtRmLpxcMDKEdLC8t"); pub const PROGRAM_SEED: &[u8] = b"BASICORACLE"; @@ -53,4 +53,4 @@ pub mod basic_oracle { ) -> anchor_lang::Result<()> { TriggerFunction::actuate(&ctx, ¶ms) } -} \ No newline at end of file +} diff --git a/examples/functions/01_basic_oracle/tsconfig.json b/examples/functions/01_basic_oracle/tsconfig.json index 01747a206..260a06b6b 100644 --- a/examples/functions/01_basic_oracle/tsconfig.json +++ b/examples/functions/01_basic_oracle/tsconfig.json @@ -14,16 +14,12 @@ "./node_modules/@types" ], "module": "commonjs", + "moduleResolution": "node", "noEmit": true, "esModuleInterop": true, "strict": false, "strictNullChecks": false, - "target": "es6", - "paths": { - "@switchboard-xyz/solana.js": [ - "../../../../../javascript/solana.js" - ] - } + "target": "es6" }, "include": [ "tests/**/*", @@ -32,10 +28,5 @@ "exclude": [ "target", "lib" - ], - "references": [ - { - "path": "../../../../../javascript/solana.js" - } ] } \ No newline at end of file diff --git a/examples/functions/03_candles_oracle/package.json b/examples/functions/03_candles_oracle/package.json index dadefe0b8..e4dbee1e6 100644 --- a/examples/functions/03_candles_oracle/package.json +++ b/examples/functions/03_candles_oracle/package.json @@ -7,8 +7,9 @@ "directory": "examples/functions/01_basic_oracle" }, "scripts": { - "build:anchor": "anchor build", - "clean": "pnpm exec rimraf node_modules .anchor lib .turbo" + "build:cargo": "anchor build", + "fix": "cargo fmt && pnpm exec prettier ./tests/*.ts -w", + "clean": "pnpm exec rimraf node_modules .anchor .turbo" }, "dependencies": { "@coral-xyz/anchor": "^0.28.0", diff --git a/examples/functions/05_raffle_program/package.json b/examples/functions/05_raffle_program/package.json index 694c65e47..9539c60c8 100644 --- a/examples/functions/05_raffle_program/package.json +++ b/examples/functions/05_raffle_program/package.json @@ -1,8 +1,9 @@ { "name": "solana-raffle-program", "scripts": { - "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", - "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + "build:cargo": "anchor build", + "fix": "cargo fmt && pnpm exec prettier ./tests/*.ts -w", + "clean": "pnpm exec rimraf node_modules .anchor .turbo" }, "dependencies": { "@coral-xyz/anchor": "^0.28.0", diff --git a/javascript/solana.js/esbuild.js b/javascript/solana.js/esbuild.js index e3b78b361..e9fbc21bd 100644 --- a/javascript/solana.js/esbuild.js +++ b/javascript/solana.js/esbuild.js @@ -1,6 +1,7 @@ /* eslint node/no-unpublished-require: 0 */ /* eslint no-unused-vars: 0 */ +import * as utils from "@switchboard-xyz/common/esm-utils"; import { execSync } from "child_process"; import { build } from "esbuild"; import fs from "fs"; @@ -146,9 +147,7 @@ async function main() { execSync(`${tscPath} --outDir lib-cjs -p tsconfig.cjs.json`, { encoding: "utf-8", }); - execSync(`tsx scripts/move-cjs-to-lib`, { - encoding: "utf-8", - }); + utils.moveCjsFiles("lib-cjs", "lib"); fs.rmSync("lib-cjs", { recursive: true }); console.log(`Generating entrypoints ...`); diff --git a/javascript/solana.js/idl/attestation-devnet.json b/javascript/solana.js/idl/attestation-devnet.json index be164cb71..c6f01736d 100644 --- a/javascript/solana.js/idl/attestation-devnet.json +++ b/javascript/solana.js/idl/attestation-devnet.json @@ -1810,12 +1810,16 @@ "type": "bool" }, { - "name": "requestsDefaultSlotsUntilExpiration", + "name": "reserved1", "docs": [ - "The number of slots after a request has been verified before allowing a non-authority account to close the account.", - "Useful if you want to submit multiple txns in your custom function and need the account to be kept alive for multiple slots." + "DEPRECATED." ], - "type": "u64" + "type": { + "array": [ + "u8", + 8 + ] + } }, { "name": "requestsFee", @@ -2340,10 +2344,6 @@ "name": "requestsRequireAuthorization", "type": "bool" }, - { - "name": "requestsDefaultSlotsUntilExpiration", - "type": "u64" - }, { "name": "requestsFee", "type": "u64" @@ -2442,12 +2442,6 @@ "option": "bool" } }, - { - "name": "requestsDefaultSlotsUntilExpiration", - "type": { - "option": "u64" - } - }, { "name": "requestsFee", "type": { @@ -2654,6 +2648,12 @@ "type": { "option": "u64" } + }, + { + "name": "validAfterSlot", + "type": { + "option": "u64" + } } ] } @@ -2690,6 +2690,12 @@ "type": { "option": "u64" } + }, + { + "name": "validAfterSlot", + "type": { + "option": "u64" + } } ] } @@ -2909,6 +2915,13 @@ ], "type": "publicKey" }, + { + "name": "validAfterSlot", + "docs": [ + "The slot when the request can first be executed." + ], + "type": "u64" + }, { "name": "ebuf", "docs": [ @@ -2917,7 +2930,7 @@ "type": { "array": [ "u8", - 64 + 56 ] } } @@ -3724,6 +3737,11 @@ { "code": 6040, "name": "AccountCloseNotReady" + }, + { + "code": 6041, + "name": "FunctionRequestNotReady", + "msg": "The FunctionRequestAccount is not ready to be verified" } ] } \ No newline at end of file diff --git a/javascript/solana.js/package.json b/javascript/solana.js/package.json index d9f2f1762..8e0cc54fa 100644 --- a/javascript/solana.js/package.json +++ b/javascript/solana.js/package.json @@ -1,6 +1,6 @@ { "name": "@switchboard-xyz/solana.js", - "version": "2.5.0", + "version": "2.5.4", "author": "", "license": "MIT", "description": "A Typescript client to interact with Switchboard on Solana.", diff --git a/javascript/solana.js/src/SwitchboardProgram.ts b/javascript/solana.js/src/SwitchboardProgram.ts index 354b78748..04f18dc28 100644 --- a/javascript/solana.js/src/SwitchboardProgram.ts +++ b/javascript/solana.js/src/SwitchboardProgram.ts @@ -573,6 +573,25 @@ export class SwitchboardProgram { } } + /** + * Verifies that a new keypair has been provided and the corresponding account does not already exist. + * + * **NOTE:** Creating new accounts without this check may prevent the ability to withdraw any existing funds. + * + * @param keypair - The Keypair to be verified. + * @throws Will throw an error if the account for the keypair already exists. + */ + public async verifyNewKeypairs(...keypairs: Keypair[]): Promise { + const accounts = await this.connection.getMultipleAccountsInfo( + keypairs.map((k) => k.publicKey) + ); + for (const [n, account] of accounts.entries()) { + if (account) { + throw new errors.ExistingKeypair(); + } + } + } + /** * Retrieves the account namespace for the Switchboard V2 Program. * @return The AccountNamespace instance for the Switchboard V2 Program. diff --git a/javascript/solana.js/src/accounts/aggregatorAccount.ts b/javascript/solana.js/src/accounts/aggregatorAccount.ts index 797206c69..39d811616 100644 --- a/javascript/solana.js/src/accounts/aggregatorAccount.ts +++ b/javascript/solana.js/src/accounts/aggregatorAccount.ts @@ -256,7 +256,7 @@ export class AggregatorAccount extends Account { } const keypair = params.keypair ?? Keypair.generate(); - program.verifyNewKeypair(keypair); + await program.verifyNewKeypair(keypair); const ixns: TransactionInstruction[] = []; const signers: Keypair[] = [keypair]; @@ -1237,7 +1237,6 @@ export class AggregatorAccount extends Account { }); } - const varianceThreshold = params.varianceThreshold ?? 0; const setConfigIxn = ix.aggregatorSetConfig( this.program, { @@ -1258,9 +1257,10 @@ export class AggregatorAccount extends Account { minJobResults: params.minJobResults ?? null, forceReportPeriod: params.forceReportPeriod ?? null, varianceThreshold: - varianceThreshold >= 0 + params.varianceThreshold !== undefined && + params.varianceThreshold !== null ? new BorshDecimal( - SwitchboardDecimal.fromBig(new Big(varianceThreshold)) + SwitchboardDecimal.fromBig(new Big(params.varianceThreshold)) ) : null, basePriorityFee: params.basePriorityFee ?? null, diff --git a/javascript/solana.js/src/accounts/aggregatorHistoryBuffer.ts b/javascript/solana.js/src/accounts/aggregatorHistoryBuffer.ts index 3d5d37eec..96dec630e 100644 --- a/javascript/solana.js/src/accounts/aggregatorHistoryBuffer.ts +++ b/javascript/solana.js/src/accounts/aggregatorHistoryBuffer.ts @@ -244,7 +244,7 @@ export class AggregatorHistoryBuffer extends Account< options?: TransactionObjectOptions ): Promise<[AggregatorHistoryBuffer, TransactionObject]> { const buffer = params.keypair ?? Keypair.generate(); - program.verifyNewKeypair(buffer); + await program.verifyNewKeypair(buffer); const ixns: TransactionInstruction[] = []; const signers: Keypair[] = params.aggregatorAuthority diff --git a/javascript/solana.js/src/accounts/attestationQueueAccount.ts b/javascript/solana.js/src/accounts/attestationQueueAccount.ts index 23f96e774..bf1bd5aec 100644 --- a/javascript/solana.js/src/accounts/attestationQueueAccount.ts +++ b/javascript/solana.js/src/accounts/attestationQueueAccount.ts @@ -7,6 +7,7 @@ import type { TransactionObjectOptions, } from "../TransactionObject.js"; import { TransactionObject } from "../TransactionObject.js"; +import type { WithRequired } from "../types.js"; import { parseRawBuffer } from "../utils.js"; import { Account } from "./account.js"; @@ -154,12 +155,9 @@ export class AttestationQueueAccount extends Account, options?: TransactionObjectOptions ): [AttestationQueueAccount, TransactionObject] { - const queueKeypair = params.keypair ?? Keypair.generate(); - program.verifyNewKeypair(queueKeypair); - const instruction = types.attestationQueueInit( program, { @@ -174,15 +172,15 @@ export class AttestationQueueAccount extends Account { + const queueKeypair = params.keypair ?? Keypair.generate(); + await program.verifyNewKeypair(queueKeypair); + const [account, txnObject] = this.createInstruction( program, program.walletPubkey, - params, + { ...params, keypair: queueKeypair }, options ); return [account, await program.signAndSend(txnObject, options)]; diff --git a/javascript/solana.js/src/accounts/bufferRelayAccount.ts b/javascript/solana.js/src/accounts/bufferRelayAccount.ts index 46bb7c0dd..f5b5909be 100644 --- a/javascript/solana.js/src/accounts/bufferRelayAccount.ts +++ b/javascript/solana.js/src/accounts/bufferRelayAccount.ts @@ -116,8 +116,7 @@ export class BufferRelayerAccount extends Account { const keypair = params.keypair ?? Keypair.generate(); - program.verifyNewKeypair(keypair); - + await program.verifyNewKeypair(keypair); const size = 2048; const ixns: TransactionInstruction[] = []; diff --git a/javascript/solana.js/src/accounts/crankAccount.ts b/javascript/solana.js/src/accounts/crankAccount.ts index 7654eed4b..ffccba477 100644 --- a/javascript/solana.js/src/accounts/crankAccount.ts +++ b/javascript/solana.js/src/accounts/crankAccount.ts @@ -6,6 +6,7 @@ import type { TransactionObjectOptions, } from "../TransactionObject.js"; import { TransactionObject } from "../TransactionObject.js"; +import type { WithRequired } from "../types.js"; import type { OnAccountChangeCallback } from "./account.js"; import { Account } from "./account.js"; @@ -104,14 +105,13 @@ export class CrankAccount extends Account { params: CrankInitParams, options?: TransactionObjectOptions ): Promise<[CrankAccount, TransactionObject]> { - const keypair = params.keypair ?? Keypair.generate(); - program.verifyNewKeypair(keypair); + const maxRows = params.maxRows ?? 500; + const crankSize = CrankDataBuffer.getAccountSize(maxRows); + const keypair = params.keypair ?? Keypair.generate(); const buffer = params.dataBufferKeypair ?? anchor.web3.Keypair.generate(); - program.verifyNewKeypair(buffer); - const maxRows = params.maxRows ?? 500; - const crankSize = CrankDataBuffer.getAccountSize(maxRows); + await program.verifyNewKeypairs(keypair, buffer); const crankInit = new TransactionObject( payer, diff --git a/javascript/solana.js/src/accounts/functionAccount.ts b/javascript/solana.js/src/accounts/functionAccount.ts index 94e4c31b9..dbdab3684 100644 --- a/javascript/solana.js/src/accounts/functionAccount.ts +++ b/javascript/solana.js/src/accounts/functionAccount.ts @@ -328,7 +328,7 @@ export class FunctionAccount extends Account { await program.connection.getLatestBlockhashAndContext({ commitment: "finalized", }) - ).context.slot + ).context.slot - 1 ); const creatorSeed = params.creatorSeed diff --git a/javascript/solana.js/src/accounts/functionRequestAccount.ts b/javascript/solana.js/src/accounts/functionRequestAccount.ts index af79a497d..74816b898 100644 --- a/javascript/solana.js/src/accounts/functionRequestAccount.ts +++ b/javascript/solana.js/src/accounts/functionRequestAccount.ts @@ -123,7 +123,7 @@ export class FunctionRequestAccount extends Account { } const jobKeypair = params.keypair ?? Keypair.generate(); - program.verifyNewKeypair(jobKeypair); const authority = params.authority ? params.authority.publicKey : payer; @@ -255,10 +255,12 @@ export class JobAccount extends Account { params: JobInitParams, options?: SendTransactionObjectOptions ): Promise<[JobAccount, Array]> { + const keypair = params.keypair ?? Keypair.generate(); + await program.verifyNewKeypair(keypair); const [account, transactions] = JobAccount.createInstructions( program, program.walletPubkey, - params, + { ...params, keypair }, options ); const txSignature = await program.signAndSendAll(transactions, options); diff --git a/javascript/solana.js/src/accounts/queueAccount.ts b/javascript/solana.js/src/accounts/queueAccount.ts index 3c9dae9e4..760241002 100644 --- a/javascript/solana.js/src/accounts/queueAccount.ts +++ b/javascript/solana.js/src/accounts/queueAccount.ts @@ -166,10 +166,8 @@ export class QueueAccount extends Account { options?: TransactionObjectOptions ): Promise<[QueueAccount, TransactionObject]> { const keypair = params.keypair ?? Keypair.generate(); - program.verifyNewKeypair(keypair); - const dataBuffer = params.dataBufferKeypair ?? Keypair.generate(); - program.verifyNewKeypair(dataBuffer); + await program.verifyNewKeypairs(keypair, dataBuffer); const queueAccount = new QueueAccount(program, keypair.publicKey); queueAccount.dataBuffer = new QueueDataBuffer( @@ -509,7 +507,7 @@ export class QueueAccount extends Account { authority: job.authority, expiration: job.expiration, variables: job.variables, - keypair: job.keypair, + keypair: job.keypair ?? Keypair.generate(), }, options ); @@ -534,7 +532,7 @@ export class QueueAccount extends Account { queueAccount: this, queueAuthority: queueAuthorityPubkey, keypair: params.keypair, - authority: params.authority, + authority: payer, // payer is authority until end of the instruction }, options ); @@ -548,7 +546,7 @@ export class QueueAccount extends Account { fundAmount: params.fundAmount, funderTokenWallet: params.funderTokenWallet ?? userTokenAddress, funderAuthority: params.funderAuthority, - withdrawAuthority: params.withdrawAuthority ?? params.authority, + withdrawAuthority: params.withdrawAuthority ?? params.authority, // make sure we set this correctly aggregatorAccount: aggregatorAccount, queueAccount: this, jobAuthorities: [], // create lease before adding jobs to skip this step @@ -606,10 +604,12 @@ export class QueueAccount extends Account { // set priority fees if ( - params.basePriorityFee !== undefined || - params.priorityFeeBump !== undefined || - params.priorityFeeBumpPeriod !== undefined || - params.maxPriorityFeeMultiplier !== undefined + (params.basePriorityFee !== undefined && params.basePriorityFee > 0) || + (params.priorityFeeBump !== undefined && params.priorityFeeBump > 0) || + (params.priorityFeeBumpPeriod !== undefined && + params.priorityFeeBumpPeriod > 0) || + (params.maxPriorityFeeMultiplier !== undefined && + params.maxPriorityFeeMultiplier > 0) ) { const setAggregatorConfig = await aggregatorAccount.setConfigInstruction( payer, @@ -1028,7 +1028,7 @@ export class QueueAccount extends Account { authority: params.job.authority, expiration: params.job.expiration, variables: params.job.variables, - keypair: params.job.keypair, + keypair: params.job.keypair ?? Keypair.generate(), } ); txns.push(...jobInit); diff --git a/javascript/solana.js/src/accounts/verifierAccount.ts b/javascript/solana.js/src/accounts/verifierAccount.ts index 69ce2a272..689003c44 100644 --- a/javascript/solana.js/src/accounts/verifierAccount.ts +++ b/javascript/solana.js/src/accounts/verifierAccount.ts @@ -149,7 +149,7 @@ export class VerifierAccount extends Account { options?: TransactionObjectOptions ): Promise<[VerifierAccount, TransactionObject]> { const verifierKeypair = params.keypair ?? Keypair.generate(); - program.verifyNewKeypair(verifierKeypair); + await program.verifyNewKeypair(verifierKeypair); const queueData = await params.queueAccount.loadData(); diff --git a/javascript/solana.js/src/accounts/vrfAccount.ts b/javascript/solana.js/src/accounts/vrfAccount.ts index 60c276116..63edcdbf0 100644 --- a/javascript/solana.js/src/accounts/vrfAccount.ts +++ b/javascript/solana.js/src/accounts/vrfAccount.ts @@ -106,7 +106,7 @@ export class VrfAccount extends Account { params: VrfInitParams, options?: TransactionObjectOptions ): Promise<[VrfAccount, TransactionObject]> { - program.verifyNewKeypair(params.vrfKeypair); + await program.verifyNewKeypair(params.vrfKeypair); const vrfAccount = new VrfAccount(program, params.vrfKeypair.publicKey); const size = program.account.vrfAccountData.size; diff --git a/javascript/solana.js/src/types.ts b/javascript/solana.js/src/types.ts index f54d8f535..112c07489 100644 --- a/javascript/solana.js/src/types.ts +++ b/javascript/solana.js/src/types.ts @@ -27,6 +27,8 @@ import type { import type { OracleJob } from "@switchboard-xyz/common"; +export type WithRequired = T & { [P in K]-?: T[P] }; + export interface AccountDefinition { account: T; } diff --git a/javascript/solana.js/src/utils.ts b/javascript/solana.js/src/utils.ts index bb6ed624c..2969d6e18 100644 --- a/javascript/solana.js/src/utils.ts +++ b/javascript/solana.js/src/utils.ts @@ -151,6 +151,7 @@ export async function updateStaticFeed( aggregatorAccount.program, aggregatorAccount.program.walletPubkey, { + keypair: Keypair.generate(), data: OracleJob.encodeDelimited( OracleJob.create({ tasks: [ diff --git a/javascript/solana.js/test/aggregator.spec.ts b/javascript/solana.js/test/aggregator.spec.ts index 967ce4ab2..c28a453de 100644 --- a/javascript/solana.js/test/aggregator.spec.ts +++ b/javascript/solana.js/test/aggregator.spec.ts @@ -465,6 +465,8 @@ describe("Aggregator Tests", () => { enable: true, fundAmount: 0.25, historyLimit: 25, + forceReportPeriod: 3600, + varianceThreshold: 0.25, jobs: [ { pubkey: jobAccount.publicKey }, { @@ -492,5 +494,17 @@ describe("Aggregator Tests", () => { agg1.authority.equals(myAuth.publicKey), `AggregatorAuthorityMismatch, expected ${myAuth.publicKey}, received ${agg1.authority}` ); + const forceReportPeriod = agg1.forceReportPeriod.toNumber(); + console.log(`forceReportPeriod: ${forceReportPeriod}`); + assert( + forceReportPeriod === 3600, + `AggregatorForceReportPeriodMismatch, expected 3600, received ${forceReportPeriod}` + ); + const varianceThreshold = agg1.varianceThreshold.toBig().toNumber(); + console.log(`varianceThreshold: ${varianceThreshold}`); + assert( + varianceThreshold === 0.25, + `AggregatorVarianceThresholdMismatch, expected 0.25 %, received ${varianceThreshold}` + ); }); }); diff --git a/javascript/solana.js/tsconfig.base.json b/javascript/solana.js/tsconfig.base.json index 83160ced0..99a5cdda3 100644 --- a/javascript/solana.js/tsconfig.base.json +++ b/javascript/solana.js/tsconfig.base.json @@ -28,6 +28,16 @@ "strictNullChecks": false, "strictFunctionTypes": true, "noImplicitReturns": true, - "esModuleInterop": true - } -} + "esModuleInterop": true, + "paths": { + "@switchboard-xyz/common": [ + "../common" + ] + } + }, + "references": [ + { + "path": "../common" + } + ] +} \ No newline at end of file diff --git a/javascript/solana.js/tsconfig.json b/javascript/solana.js/tsconfig.json index c35fbf1a8..bf6cf30eb 100644 --- a/javascript/solana.js/tsconfig.json +++ b/javascript/solana.js/tsconfig.json @@ -28,7 +28,15 @@ "strictPropertyInitialization": false, "strict": true, "strictNullChecks": true, - "allowJs": true + "allowJs": true, + "paths": { + "@switchboard-xyz/common": [ + "../common" + ], + "@switchboard-xyz/oracle": [ + "../oracle" + ] + } }, "typedocOptions": { "entryPoints": [ diff --git a/rust/switchboard-solana/Cargo.anchor27.toml b/rust/switchboard-solana/Cargo.anchor27.toml index f5761ac7c..d9698339b 100644 --- a/rust/switchboard-solana/Cargo.anchor27.toml +++ b/rust/switchboard-solana/Cargo.anchor27.toml @@ -1,6 +1,6 @@ [package] name = "switchboard-solana" -version = "0.27.4" +version = "0.27.5" edition = "2021" description = "A Rust library to interact with Switchboard accounts." readme = "README.md" diff --git a/rust/switchboard-solana/Cargo.lock b/rust/switchboard-solana/Cargo.lock index 14123b11f..ab6cc4252 100644 --- a/rust/switchboard-solana/Cargo.lock +++ b/rust/switchboard-solana/Cargo.lock @@ -4249,7 +4249,7 @@ dependencies = [ [[package]] name = "switchboard-solana" -version = "0.28.4" +version = "0.28.5" dependencies = [ "anchor-client", "anchor-lang", diff --git a/rust/switchboard-solana/Cargo.toml b/rust/switchboard-solana/Cargo.toml index dd1a03ea6..3350846d4 100644 --- a/rust/switchboard-solana/Cargo.toml +++ b/rust/switchboard-solana/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "switchboard-solana" -version = "0.28.4" +version = "0.28.5" edition = "2021" description = "A Rust library to interact with Switchboard accounts." readme = "README.md" @@ -47,4 +47,4 @@ tokio = "1" url = "2.4" [package.metadata.docs.rs] -rustdoc-args = ["--cfg", "doc_cfg"] +rustdoc-args = ["--cfg", "doc_cfg"] \ No newline at end of file diff --git a/rust/switchboard-solana/src/attestation_program/accounts/attestation_queue.rs b/rust/switchboard-solana/src/attestation_program/accounts/attestation_queue.rs index 15fcca582..913681687 100644 --- a/rust/switchboard-solana/src/attestation_program/accounts/attestation_queue.rs +++ b/rust/switchboard-solana/src/attestation_program/accounts/attestation_queue.rs @@ -177,4 +177,4 @@ impl AttestationQueueAccountData { crate::client::load_account(client, pubkey).await } } -} +} \ No newline at end of file diff --git a/rust/switchboard-solana/src/client/function_runner.rs b/rust/switchboard-solana/src/client/function_runner.rs index 6e6fbab0b..18ba7de1a 100644 --- a/rust/switchboard-solana/src/client/function_runner.rs +++ b/rust/switchboard-solana/src/client/function_runner.rs @@ -2,6 +2,7 @@ use crate::prelude::*; use anchor_lang::solana_program::instruction::Instruction; use anchor_lang::solana_program::message::Message; use anchor_lang::solana_program::pubkey::Pubkey; +use anchor_lang::AnchorDeserialize; use hex; use sgx_quote::Quote; use solana_client::rpc_client::RpcClient; @@ -290,12 +291,12 @@ impl FunctionRunner { )); } - let function_data = self.load_function_data().await?; + let function_data: FunctionAccountData = *bytemuck::try_from_bytes( + &hex::decode(std::env::var("FUNCTION_DATA").unwrap()).unwrap() + ).unwrap(); - let queue_authority = self - .load_queue_authority(function_data.attestation_queue) - .await?; - let verifier_enclave_signer = self.load_verifier_signer(self.verifier).await?; + let queue_authority = Pubkey::from_str(&std::env::var("QUEUE_AUTHORITY").unwrap()).unwrap(); + let verifier_enclave_signer = Pubkey::from_str(&std::env::var("VERIFIER_ENCLAVE_SIGNER").unwrap()).unwrap(); let verifier_permission = AttestationPermissionAccountData::get_pda( &queue_authority, @@ -346,6 +347,7 @@ impl FunctionRunner { ))); } + // TODO: replace with variables let function_data = self.load_function_data().await?; let queue_authority = self @@ -419,6 +421,7 @@ impl FunctionRunner { fn_key: self.function.to_bytes().into(), signer: self.signer.to_bytes().into(), fn_request_key, + // TODO: hash should be checked against fn_request_hash: Vec::new(), chain_result_info: Solana(SOLFunctionResult { serialized_tx: bincode::serialize(&tx).unwrap(), @@ -547,4 +550,4 @@ impl ToAccountMetas for FunctionRequestVerifyAccounts { AccountMeta::new_readonly(anchor_spl::token::ID, false), ] } -} +} \ No newline at end of file