diff --git a/.vscode/settings.json b/.vscode/settings.json index 6a4a0ec..392ef22 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,7 +7,7 @@ "editor.wordWrap": "on", "[typescript]": { "editor.codeActionsOnSave": { - "source.organizeImports": true + "source.organizeImports": false } } } diff --git a/javascript/solana.js/package.json b/javascript/solana.js/package.json index 5c3d8ae..6c62cdb 100644 --- a/javascript/solana.js/package.json +++ b/javascript/solana.js/package.json @@ -1,6 +1,6 @@ { "name": "@switchboard-xyz/solana.js", - "version": "2.1.1", + "version": "2.1.2", "author": "", "license": "MIT", "description": "API wrapper for integrating with the Switchboard V2 program on Solana", @@ -46,7 +46,6 @@ "@solana/spl-token": "^0.3.6", "@solana/web3.js": "^1.73.0", "@switchboard-xyz/common": "^2.1.33", - "@switchboard-xyz/oracle": "^2.1.13", "dotenv": "^16.0.3", "lodash": "^4.17.21" }, diff --git a/javascript/solana.js/src/test/SwitchboardTestContextV2.ts b/javascript/solana.js/src/SwitchboardTestContext.ts similarity index 70% rename from javascript/solana.js/src/test/SwitchboardTestContextV2.ts rename to javascript/solana.js/src/SwitchboardTestContext.ts index a5423e4..d09d0a1 100644 --- a/javascript/solana.js/src/test/SwitchboardTestContextV2.ts +++ b/javascript/solana.js/src/SwitchboardTestContext.ts @@ -7,22 +7,22 @@ import { QueueAccount, SwitchboardNetwork, SwitchboardProgram, -} from '..'; +} from '.'; import { AnchorProvider } from '@coral-xyz/anchor'; import { Connection, Keypair, PublicKey } from '@solana/web3.js'; -import { - IOracleConfig, - NodeOracle, - ReleaseChannel, - ReleaseChannelVersion, -} from '@switchboard-xyz/oracle'; +// import { +// IOracleConfig, +// NodeOracle, +// ReleaseChannel, +// ReleaseChannelVersion, +// } from '@switchboard-xyz/oracle'; import fs from 'fs'; import _ from 'lodash'; import os from 'os'; import path from 'path'; -export type NodeConfig = IOracleConfig & Partial; +// export type NodeConfig = IOracleConfig & Partial; export function findAnchorTomlWallet(workingDir = process.cwd()): string { let numDirs = 3; @@ -58,7 +58,7 @@ export function findAnchorTomlWallet(workingDir = process.cwd()): string { throw new Error(`Failed to find wallet path in Anchor.toml`); } -export type SwitchboardTestContextV2Init = Omit< +export type SwitchboardTestContextInit = Omit< Omit, 'oracles' > & { @@ -69,7 +69,7 @@ export type SwitchboardTestContextV2Init = Omit< // oraclePubkey: Ei4HcqRQtf6TfwbuRXKRwCtt8PDXhmq9NhYLWpoh23xp // TIP: Do NOT define an authority and defaul to Anchor.toml wallet -export const DEFAULT_LOCALNET_NETWORK: SwitchboardTestContextV2Init = { +export const DEFAULT_LOCALNET_NETWORK: SwitchboardTestContextInit = { name: 'Localnet Queue', metadata: 'Localnet Metadata', keypair: Keypair.fromSecretKey( @@ -112,8 +112,8 @@ export const DEFAULT_LOCALNET_NETWORK: SwitchboardTestContextV2Init = { }, }; -export class SwitchboardTestContextV2 { - _oracle?: NodeOracle; +export class SwitchboardTestContext { + // _oracle?: NodeOracle; constructor( readonly network: LoadedSwitchboardNetwork, @@ -134,10 +134,10 @@ export class SwitchboardTestContextV2 { static async load( connection: Connection, - networkInitParams?: Partial, + networkInitParams?: Partial, walletPath?: string, programId?: PublicKey - ): Promise { + ): Promise { const walletFsPath = walletPath ?? findAnchorTomlWallet(); const wallet = Keypair.fromSecretKey( new Uint8Array(JSON.parse(fs.readFileSync(walletFsPath, 'utf-8'))) @@ -187,7 +187,7 @@ export class SwitchboardTestContextV2 { } const network = await SwitchboardNetwork.fromQueue(queueAccount); - return new SwitchboardTestContextV2(network, walletFsPath); + return new SwitchboardTestContext(network, walletFsPath); } // eslint-disable-next-line no-empty } catch {} @@ -204,15 +204,15 @@ export class SwitchboardTestContextV2 { throw new Error(`Anchor wallet pubkey mismatch`); } } - return new SwitchboardTestContextV2(loadedNetwork, walletFsPath); + return new SwitchboardTestContext(loadedNetwork, walletFsPath); } static async loadFromProvider( provider: AnchorProvider, - networkInitParams?: Partial, + networkInitParams?: Partial, programId?: PublicKey - ): Promise { - const switchboard = await SwitchboardTestContextV2.load( + ): Promise { + const switchboard = await SwitchboardTestContext.load( provider.connection, networkInitParams, undefined, @@ -223,92 +223,92 @@ export class SwitchboardTestContextV2 { static async initFromProvider( provider: AnchorProvider, - networkInitParams?: Partial, - oracleParams?: Partial, + networkInitParams?: Partial, + // oracleParams?: Partial, programId?: PublicKey - ): Promise { - const switchboard = await SwitchboardTestContextV2.loadFromProvider( + ): Promise { + const switchboard = await SwitchboardTestContext.loadFromProvider( provider, networkInitParams, programId ); - await switchboard.start(oracleParams); + // await switchboard.start(oracleParams); return switchboard; } static async init( connection: Connection, - networkInitParams?: Partial, - oracleParams?: Partial, + networkInitParams?: Partial, + // oracleParams?: Partial, walletPath?: string, programId?: PublicKey - ): Promise { - const switchboard = await SwitchboardTestContextV2.load( + ): Promise { + const switchboard = await SwitchboardTestContext.load( connection, networkInitParams, walletPath, programId ); - await switchboard.start(oracleParams); + // await switchboard.start(oracleParams); return switchboard; } - async start( - oracleParams?: Partial | ReleaseChannel, - timeout = 60 - ) { - const releaseChannel: ReleaseChannel = - typeof oracleParams === 'string' && - (oracleParams === 'testnet' || - oracleParams === 'mainnet' || - oracleParams === 'latest') - ? oracleParams - : 'testnet'; + // async start( + // oracleParams?: Partial | ReleaseChannel, + // timeout = 60 + // ) { + // const releaseChannel: ReleaseChannel = + // typeof oracleParams === 'string' && + // (oracleParams === 'testnet' || + // oracleParams === 'mainnet' || + // oracleParams === 'latest') + // ? oracleParams + // : 'testnet'; - const baseConfig: NodeConfig = { - chain: 'solana', - releaseChannel: releaseChannel, - network: - this.program.cluster === 'mainnet-beta' - ? 'mainnet' - : this.program.cluster, - rpcUrl: this.program.connection.rpcEndpoint, - oracleKey: this.oracle.publicKey.toBase58(), - secretPath: this.walletPath, - envVariables: { - VERBOSE: '1', - DEBUG: '1', - DISABLE_NONE_QUEUE: '1', - DISABLE_METRICS: '1', - }, - }; + // const baseConfig: NodeConfig = { + // chain: 'solana', + // releaseChannel: releaseChannel, + // network: + // this.program.cluster === 'mainnet-beta' + // ? 'mainnet' + // : this.program.cluster, + // rpcUrl: this.program.connection.rpcEndpoint, + // oracleKey: this.oracle.publicKey.toBase58(), + // secretPath: this.walletPath, + // envVariables: { + // VERBOSE: '1', + // DEBUG: '1', + // DISABLE_NONE_QUEUE: '1', + // DISABLE_METRICS: '1', + // }, + // }; - const config: NodeConfig = - typeof oracleParams === 'string' - ? baseConfig - : _.merge(baseConfig, oracleParams); + // const config: NodeConfig = + // typeof oracleParams === 'string' + // ? baseConfig + // : _.merge(baseConfig, oracleParams); - this._oracle = await NodeOracle.fromReleaseChannel({ - ...config, - releaseChannel: releaseChannel, - chain: 'solana', - }); + // this._oracle = await NodeOracle.fromReleaseChannel({ + // ...config, + // releaseChannel: releaseChannel, + // chain: 'solana', + // }); - console.log(`Starting Switchboard oracle ...`); + // console.log(`Starting Switchboard oracle ...`); - await this._oracle.startAndAwait(timeout); - } + // await this._oracle.startAndAwait(timeout); + // } - stop() { - if (this._oracle) { - const stopped = this._oracle.stop(); - if (!stopped) { - console.error(`Failed to stop docker oracle`); + // stop() { + // if (this._oracle) { + // const stopped = this._oracle.stop(); + // if (!stopped) { + // console.error(`Failed to stop docker oracle`); - this._oracle.kill(); - } - } - } + // this._oracle.kill(); + // } + // } + // } public static findAnchorTomlWallet(workingDir = process.cwd()): string { try { @@ -326,3 +326,5 @@ export class SwitchboardTestContextV2 { return loadKeypair(keypairPath); } } + +export { SwitchboardTestContext as SwitchboardTestContextV2 }; diff --git a/javascript/solana.js/src/index.ts b/javascript/solana.js/src/index.ts index 45c9fdf..87b6a0c 100644 --- a/javascript/solana.js/src/index.ts +++ b/javascript/solana.js/src/index.ts @@ -9,6 +9,6 @@ export * from './SwitchboardError'; export * from './SwitchboardEvents'; export * from './SwitchboardNetwork'; export * from './SwitchboardProgram'; -export * from './test'; +export * from './SwitchboardTestContext'; export * from './TransactionObject'; export * from './utils'; diff --git a/javascript/solana.js/src/test/SwitchboardTestContext.ts b/javascript/solana.js/src/test/SwitchboardTestContext.ts deleted file mode 100644 index 5e2ccb2..0000000 --- a/javascript/solana.js/src/test/SwitchboardTestContext.ts +++ /dev/null @@ -1,740 +0,0 @@ -import { AggregatorAccount, JobAccount, QueueAccount } from '../accounts'; -import { - DEVNET_GENESIS_HASH, - SWITCHBOARD_LABS_DEVNET_PERMISSIONLESS_QUEUE, -} from '../const'; -import { AggregatorAccountData } from '../generated'; -import { Mint } from '../mint'; -import { SwitchboardNetwork } from '../SwitchboardNetwork'; -import { AnchorWallet, SwitchboardProgram } from '../SwitchboardProgram'; -import { TransactionObject } from '../TransactionObject'; - -import * as anchor from '@coral-xyz/anchor'; -import { clusterApiUrl, Connection, Keypair, PublicKey } from '@solana/web3.js'; -import { BNtoDateTimeString, OracleJob } from '@switchboard-xyz/common'; -import * as dotenv from 'dotenv'; -import fs from 'fs'; -import path from 'path'; - -export const LATEST_DOCKER_VERSION = 'dev-v2-RC_01_05_23_03_24'; - -/** Get the program data address for a given programId - * @param programId the programId for a given on-chain program - * @return the publicKey of the address holding the upgradeable program buffer - */ -export const getProgramDataAddress = (programId: PublicKey): PublicKey => { - return PublicKey.findProgramAddressSync( - [programId.toBytes()], - new PublicKey('BPFLoaderUpgradeab1e11111111111111111111111') - )[0]; -}; - -/** Get the IDL address for a given programId - * @param programId the programId for a given on-chain program - * @return the publicKey of the IDL address - */ -export const getIdlAddress = async ( - programId: PublicKey -): Promise => { - const base = (await PublicKey.findProgramAddress([], programId))[0]; - return PublicKey.createWithSeed(base, 'anchor:idl', programId); -}; - -export class SwitchboardTestContext { - constructor( - readonly program: SwitchboardProgram, - readonly queue: QueueAccount, - readonly payerTokenWallet: PublicKey - ) {} - - public static async load( - provider: anchor.AnchorProvider, - params?: { - tokenAmount?: number; - queueKey?: PublicKey | string; - filePath?: string; - } - ): Promise { - // fetch genesis hash - - const genesisHash = await provider.connection.getGenesisHash(); - if (genesisHash === DEVNET_GENESIS_HASH) { - // if queueKey is defined should we bother loading the local env? - - // first try to load the local env - try { - const testContext = await SwitchboardTestContext.loadFromEnv( - provider, - params?.filePath ?? undefined, - params?.tokenAmount ?? undefined - ); - // verify the oracle is heartbeating - const oracles = await testContext.queue.loadActiveOracleAccounts(); - if (oracles.length > 0) { - return testContext; - } - // eslint-disable-next-line no-empty - } catch (error) {} - - // fallback to the devnet permissionless queue - try { - const testContext = await SwitchboardTestContext.loadDevnetQueue( - provider, - params?.queueKey ?? undefined, - params?.tokenAmount ?? undefined - ); - // verify the oracle is heartbeating - const oracles = await testContext.queue.loadActiveOracleAccounts(); - if (oracles.length > 0) { - return testContext; - } - // eslint-disable-next-line no-empty - } catch (error) {} - - throw new Error( - `Failed to load a Switchboard environment from a local file or the devnet permissionless queue` - ); - } else { - const testContext = await SwitchboardTestContext.loadFromEnv( - provider, - params?.filePath ?? undefined, - params?.tokenAmount ?? undefined - ); - return testContext; - } - } - - /** Load SwitchboardTestContext using a specified queue - * @param provider anchor Provider containing connection and payer Keypair - * @param queueKey the oracle queue to load - * @param tokenAmount number of tokens to populate in switchboard mint's associated token account - */ - static async loadDevnetQueue( - provider: anchor.AnchorProvider, - queueKey: PublicKey | string = SWITCHBOARD_LABS_DEVNET_PERMISSIONLESS_QUEUE, - tokenAmount = 0 - ) { - const payerKeypair = (provider.wallet as AnchorWallet).payer; - - const balance = await provider.connection.getBalance( - payerKeypair.publicKey - ); - if (!balance) { - try { - await provider.connection.requestAirdrop( - payerKeypair.publicKey, - 1_000_000_000 - ); - // eslint-disable-next-line no-empty - } catch {} - } - - const program = await SwitchboardProgram.load( - 'devnet', - provider.connection, - payerKeypair - ).catch(error => { - throw new Error( - `Failed to load the SBV2 program for the given cluster, ${error.message}` - ); - }); - - const queueAccount = new QueueAccount( - program, - typeof queueKey === 'string' ? new PublicKey(queueKey) : queueKey - ); - try { - await queueAccount.loadData(); - const oracles = await queueAccount.loadOracles(); - if (oracles.length < 1) { - throw new Error(`OracleQueue has no active oracles heartbeating`); - } - } catch (error) { - throw new Error( - `Failed to load the SBV2 queue for the given cluster, ${ - (error as any).message - }` - ); - } - - const [userTokenAmount] = await program.mint.getOrCreateWrappedUser( - program.walletPubkey, - { fundUpTo: tokenAmount } - ); - - return new SwitchboardTestContext(program, queueAccount, userTokenAmount); - } - - /** Recursively loop through directories and return the filepath of switchboard.env - * @param envFileName alternative filename to search for. defaults to switchboard.env - * @returns the filepath for a switchboard env file to load - */ - public static findSwitchboardEnv(envFileName = 'switchboard.env'): string { - const NotFoundError = new Error( - 'failed to find switchboard.env file in current directory recursively' - ); - let retryCount = 5; - - let currentDirectory = process.cwd(); - while (retryCount > 0) { - // look for switchboard.env - try { - const currentPath = path.join(currentDirectory, envFileName); - if (fs.existsSync(currentPath)) { - return currentPath; - } - // eslint-disable-next-line no-empty - } catch {} - - // look for .switchboard directory - try { - const localSbvPath = path.join(currentDirectory, '.switchboard'); - if (fs.existsSync(localSbvPath)) { - const localSbvEnvPath = path.join(localSbvPath, envFileName); - if (fs.existsSync(localSbvEnvPath)) { - return localSbvEnvPath; - } - } - // eslint-disable-next-line no-empty - } catch {} - - currentDirectory = path.join(currentDirectory, '../'); - - --retryCount; - } - - throw NotFoundError; - } - - /** Load SwitchboardTestContext from an env file containing $SWITCHBOARD_PROGRAM_ID, $ORACLE_QUEUE, $AGGREGATOR - * @param provider anchor Provider containing connection and payer Keypair - * @param filePath filesystem path to env file - * @param tokenAmount number of tokens to populate in switchboard mint's associated token account - */ - public static async loadFromEnv( - provider: anchor.AnchorProvider, - filePath = SwitchboardTestContext.findSwitchboardEnv(), - tokenAmount = 0 - ): Promise { - // eslint-disable-next-line node/no-unpublished-require - dotenv.config({ path: filePath }); - if (!process.env.SWITCHBOARD_PROGRAM_ID) { - throw new Error(`your env file must have $SWITCHBOARD_PROGRAM_ID set`); - } - if (!process.env.ORACLE_QUEUE) { - throw new Error(`your env file must have $ORACLE_QUEUE set`); - } - - const program = await SwitchboardProgram.load( - 'devnet', - provider.connection, - (provider.wallet as AnchorWallet).payer, - new PublicKey(process.env.SWITCHBOARD_PROGRAM_ID) - ); - - const balance = await provider.connection.getBalance(program.walletPubkey); - if (!balance) { - try { - const airdropSignature = await provider.connection.requestAirdrop( - program.walletPubkey, - 1_000_000_000 - ); - await provider.connection.confirmTransaction(airdropSignature); - // eslint-disable-next-line no-empty - } catch {} - } - - const queueAccount = new QueueAccount( - program, - new PublicKey(process.env.ORACLE_QUEUE) - ); - - const [userTokenAmount] = await program.mint.getOrCreateWrappedUser( - program.walletPubkey, - { fundUpTo: tokenAmount } - ); - - return new SwitchboardTestContext(program, queueAccount, userTokenAmount); - } - - /** - * Create a static data feed that resolves to an expected value - * @param value - the static value the feed will resolve to - * @param timeout - the number of milliseconds to wait before timing out - */ - public async createStaticFeed( - value: number, - timeout = 30000 - ): Promise<[AggregatorAccount, AggregatorAccountData]> { - const [aggregatorAccount] = await this.queue.createFeed({ - name: `Value ${value}`, - batchSize: 1, - minRequiredOracleResults: 1, - minRequiredJobResults: 1, - minUpdateDelaySeconds: 10, - enable: true, - queueAuthorityPubkey: this.program.walletPubkey, - jobs: [ - { - data: OracleJob.encodeDelimited( - OracleJob.create({ - tasks: [ - OracleJob.Task.create({ - valueTask: OracleJob.ValueTask.create({ - value, - }), - }), - ], - }) - ).finish(), - }, - ], - }); - - const [state] = await aggregatorAccount.openRoundAndAwaitResult( - undefined, - timeout - ); - - return [aggregatorAccount, state]; - } - - /** - * Update an existing aggregator that resolves to a new static value then await the new result - * @params aggregatorAccount - the aggregator account to modify - * @param value - the static value the feed will resolve to - * @param timeout - the number of milliseconds to wait before timing out - */ - public async updateStaticFeed( - aggregatorAccount: AggregatorAccount, - value: number, - timeout = 30000 - ): Promise<[AggregatorAccount, AggregatorAccountData]> { - const aggregator = await aggregatorAccount.loadData(); - - const [jobAccount, jobInit] = JobAccount.createInstructions( - this.program, - this.program.walletPubkey, - { - data: OracleJob.encodeDelimited( - OracleJob.create({ - tasks: [ - OracleJob.Task.create({ - valueTask: OracleJob.ValueTask.create({ - value, - }), - }), - ], - }) - ).finish(), - } - ); - - const oldJobKeys = aggregator.jobPubkeysData.filter( - pubkey => !pubkey.equals(PublicKey.default) - ); - - const oldJobs: Array<[JobAccount, number]> = oldJobKeys.map((pubkey, i) => [ - new JobAccount(this.program, pubkey), - i, - ]); - - const removeJobTxns = oldJobs.map(job => - aggregatorAccount.removeJobInstruction(this.program.walletPubkey, { - job: job[0], - jobIdx: job[1], - }) - ); - - const addJobTxn = aggregatorAccount.addJobInstruction( - this.program.walletPubkey, - { job: jobAccount } - ); - - const txns = TransactionObject.pack([ - ...jobInit, - ...removeJobTxns, - addJobTxn, - ]); - await this.program.signAndSendAll(txns); - - const [state] = await aggregatorAccount.openRoundAndAwaitResult( - undefined, - timeout - ); - - return [aggregatorAccount, state]; - } - - static async createEnvironment( - payerKeypairPath: string, - alternateProgramId?: PublicKey - ): Promise { - const fullKeypairPath = - payerKeypairPath.startsWith('/') || payerKeypairPath.startsWith('C:') - ? payerKeypairPath - : path.join(process.cwd(), payerKeypairPath); - if (!fs.existsSync(fullKeypairPath)) { - throw new Error('Failed to find payer keypair path'); - } - - const payerKeypair = Keypair.fromSecretKey( - new Uint8Array( - JSON.parse( - fs.readFileSync(fullKeypairPath, { - encoding: 'utf-8', - }) - ) - ) - ); - - const connection = new Connection(clusterApiUrl('devnet'), { - commitment: 'confirmed', - }); - - const program = await SwitchboardProgram.load( - 'devnet', - connection, - payerKeypair, - alternateProgramId - ); - - const [userTokenWallet] = await program.mint.getOrCreateWrappedUser( - program.walletPubkey, - { amount: 0 } - ); - - const programDataAddress = getProgramDataAddress(program.programId); - const idlAddress = await getIdlAddress(program.programId); - - // use pre-generated keypairs so we dont need to rely on account loading - const dataBufferKeypair = Keypair.generate(); - const crankBufferKeypair = Keypair.generate(); - const oracleStakingWalletKeypair = Keypair.generate(); - - const [accounts] = await SwitchboardNetwork.create(program, { - name: 'Test Queue', - metadata: `created ${BNtoDateTimeString( - new anchor.BN(Math.floor(Date.now() / 1000)) - )}`, - authority: payerKeypair, - reward: 0, - minStake: 0, - queueSize: 10, - dataBufferKeypair: dataBufferKeypair, - unpermissionedFeeds: true, - unpermissionedVrf: true, - enableBufferRelayers: true, - slashingEnabled: false, - cranks: [ - { - name: 'Test Crank', - maxRows: 100, - dataBufferKeypair: crankBufferKeypair, - }, - ], - oracles: [ - { - name: 'Test Oracle', - enable: true, - stakingWalletKeypair: oracleStakingWalletKeypair, - queueAuthorityPubkey: program.walletPubkey, - }, - ], - }); - - const crank = accounts.cranks.shift(); - if (!crank) { - throw new Error(`Failed to create the crank`); - } - - const oracle = accounts.oracles.shift(); - if (!oracle) { - throw new Error(`Failed to create the oracle`); - } - - // async load the accounts - const programState = await accounts.programState.account.loadData(); - - return new SwitchboardTestEnvironment({ - switchboardProgramId: program.programId, - switchboardProgramDataAddress: programDataAddress, - switchboardIdlAddress: idlAddress, - switchboardProgramState: accounts.programState.account.publicKey, - switchboardVault: programState.tokenVault, - switchboardMint: programState.tokenMint.equals(PublicKey.default) - ? Mint.native - : programState.tokenMint, - tokenWallet: userTokenWallet, - oracleQueue: accounts.queue.account.publicKey, - oracleQueueAuthority: program.walletPubkey, - oracleQueueBuffer: dataBufferKeypair.publicKey, - crank: crank.account.publicKey, - crankBuffer: crankBufferKeypair.publicKey, - oracle: oracle.account.publicKey, - oracleAuthority: program.walletPubkey, - oracleEscrow: oracleStakingWalletKeypair.publicKey, - oraclePermissions: oracle.permission.account.publicKey, - payerKeypairPath: fullKeypairPath, - }); - } -} - -export interface ISwitchboardTestEnvironment { - switchboardProgramId: PublicKey; - switchboardProgramDataAddress: PublicKey; - switchboardIdlAddress: PublicKey; - switchboardProgramState: PublicKey; - switchboardVault: PublicKey; - switchboardMint: PublicKey; - tokenWallet: PublicKey; - oracleQueue: PublicKey; - oracleQueueAuthority: PublicKey; - oracleQueueBuffer: PublicKey; - crank: PublicKey; - crankBuffer: PublicKey; - oracle: PublicKey; - oracleAuthority: PublicKey; - oracleEscrow: PublicKey; - oraclePermissions: PublicKey; - payerKeypairPath: string; -} - -export class SwitchboardTestEnvironment implements ISwitchboardTestEnvironment { - switchboardProgramId: PublicKey; - switchboardProgramDataAddress: PublicKey; - switchboardIdlAddress: PublicKey; - switchboardProgramState: PublicKey; - switchboardVault: PublicKey; - switchboardMint: PublicKey; - tokenWallet: PublicKey; - oracleQueue: PublicKey; - oracleQueueAuthority: PublicKey; - oracleQueueBuffer: PublicKey; - crank: PublicKey; - crankBuffer: PublicKey; - oracle: PublicKey; - oracleAuthority: PublicKey; - oracleEscrow: PublicKey; - oraclePermissions: PublicKey; - payerKeypairPath: string; - - constructor(ctx: ISwitchboardTestEnvironment) { - this.switchboardProgramId = ctx.switchboardProgramId; - this.switchboardProgramDataAddress = ctx.switchboardProgramDataAddress; - this.switchboardIdlAddress = ctx.switchboardIdlAddress; - this.switchboardProgramState = ctx.switchboardProgramState; - this.switchboardVault = ctx.switchboardVault; - this.switchboardMint = ctx.switchboardMint; - this.tokenWallet = ctx.tokenWallet; - this.oracleQueue = ctx.oracleQueue; - this.oracleQueueAuthority = ctx.oracleQueueAuthority; - this.oracleQueueBuffer = ctx.oracleQueueBuffer; - this.crank = ctx.crank; - this.crankBuffer = ctx.crankBuffer; - this.oracle = ctx.oracle; - this.oracleAuthority = ctx.oracleAuthority; - this.oracleEscrow = ctx.oracleEscrow; - this.oraclePermissions = ctx.oraclePermissions; - this.payerKeypairPath = ctx.payerKeypairPath; - } - - public get envFileString(): string { - // const fileString = Object.keys(this) - // .map(key => { - // if (this[key] instanceof PublicKey) { - // return `${camelToUpperCaseWithUnderscores(key)}="${this[ - // key - // ].toBase58()}"`; - // } - // return; - // }) - // .filter(Boolean) - // .join('\n'); - return `SWITCHBOARD_PROGRAM_ID="${this.switchboardProgramId.toBase58()}" -SWITCHBOARD_PROGRAM_DATA_ADDRESS="${this.switchboardProgramDataAddress.toBase58()}" -SWITCHBOARD_IDL_ADDRESS="${this.switchboardIdlAddress.toBase58()}" -SWITCHBOARD_PROGRAM_STATE="${this.switchboardProgramState.toBase58()}" -SWITCHBOARD_VAULT="${this.switchboardVault.toBase58()}" -SWITCHBOARD_MINT="${this.switchboardMint.toBase58()}" -TOKEN_WALLET="${this.tokenWallet.toBase58()}" -ORACLE_QUEUE="${this.oracleQueue.toBase58()}" -ORACLE_QUEUE_AUTHORITY="${this.oracleQueueAuthority.toBase58()}" -ORACLE_QUEUE_BUFFER="${this.oracleQueueBuffer.toBase58()}" -CRANK="${this.crank.toBase58()}" -CRANK_BUFFER="${this.crankBuffer.toBase58()}" -ORACLE="${this.oracle.toBase58()}" -ORACLE_AUTHORITY="${this.oracleAuthority.toBase58()}" -ORACLE_ESCROW="${this.oracleEscrow.toBase58()}" -ORACLE_PERMISSIONS="${this.oraclePermissions.toBase58()}"`; - } - - public get anchorToml(): string { - return [ - ` -[test] -startup_wait = 10000 - -[test.validator] -url = "https://api.devnet.solana.com" -`, - Object.keys(this) - .map(key => { - if (this[key] instanceof PublicKey) { - return `[[test.validator.clone]] # ${key}\naddress = "${this[key]}"`; - } - }) - .filter(Boolean) - .join('\n\n'), - ].join('\n\n'); - } - - public get accountCloneString(): string { - const accounts = Object.keys(this).map(key => { - if (typeof this[key] === 'string') { - return; - } - - return `--clone ${(this[key] as PublicKey).toBase58()} \`# ${key}\` `; - }); - - return accounts.filter(Boolean).join(`\\\n`); - } - - public get dockerCompose(): string { - return `version: "3.3" -services: - oracle: - image: "switchboardlabs/node:\${SBV2_ORACLE_VERSION:-${LATEST_DOCKER_VERSION}}" # https://hub.docker.com/r/switchboardlabs/node/tags - network_mode: host - restart: always - secrets: - - PAYER_SECRETS - environment: - - VERBOSE=1 - - CLUSTER=\${CLUSTER:-localnet} - - HEARTBEAT_INTERVAL=30 # Seconds - - ORACLE_KEY=${this.oracle.toBase58()} - - TASK_RUNNER_SOLANA_RPC=${clusterApiUrl('mainnet-beta')} - # - RPC_URL=\${RPC_URL} -secrets: - PAYER_SECRETS: - file: ${this.payerKeypairPath}`; - } - - public get localValidatorScript(): string { - return `#!/bin/bash - -mkdir -p .anchor/test-ledger - -solana-test-validator -r --ledger .anchor/test-ledger --mint ${this.oracleAuthority.toBase58()} --bind-address 0.0.0.0 --url ${clusterApiUrl( - 'devnet' - )} --rpc-port 8899 ${this.accountCloneString}`; - } - - public get startOracleScript(): string { - return `#!/usr/bin/env bash - -script_dir=$( cd -- "$( dirname -- "\${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) - -docker-compose -f "$script_dir"/docker-compose.switchboard.yml up`; - } - - public toJSON(): ISwitchboardTestEnvironment { - return { - switchboardProgramId: this.switchboardProgramId, - switchboardProgramDataAddress: this.switchboardProgramDataAddress, - switchboardIdlAddress: this.switchboardIdlAddress, - switchboardProgramState: this.switchboardProgramState, - switchboardVault: this.switchboardVault, - switchboardMint: this.switchboardMint, - tokenWallet: this.tokenWallet, - oracleQueue: this.oracleQueue, - oracleQueueAuthority: this.oracleQueueAuthority, - oracleQueueBuffer: this.oracleQueueBuffer, - crank: this.crank, - crankBuffer: this.crankBuffer, - oracle: this.oracle, - oracleAuthority: this.oracleAuthority, - oracleEscrow: this.oracleEscrow, - oraclePermissions: this.oraclePermissions, - payerKeypairPath: this.payerKeypairPath, - }; - } - - /** Write switchboard test environment to filesystem */ - public writeAll(outputDir: string): void { - fs.mkdirSync(outputDir, { recursive: true }); - this.writeEnv(outputDir); - this.writeJSON(outputDir); - this.writeScripts(outputDir); - this.writeDockerCompose(outputDir); - this.writeAnchorToml(outputDir); - } - - /** Write the env file to filesystem */ - public writeEnv(filePath: string): void { - const ENV_FILE_PATH = path.join(filePath, 'switchboard.env'); - fs.writeFileSync(ENV_FILE_PATH, this.envFileString); - } - - public writeJSON(outputDir: string): void { - const JSON_FILE_PATH = path.join(outputDir, 'switchboard.json'); - fs.writeFileSync( - JSON_FILE_PATH, - JSON.stringify( - this.toJSON(), - (key, value) => { - if (value instanceof PublicKey) { - return value.toBase58(); - } - return value; - }, - 2 - ) - ); - } - - public writeScripts(outputDir: string): void { - // create script to start local validator with accounts cloned - const LOCAL_VALIDATOR_SCRIPT = path.join( - outputDir, - 'start-local-validator.sh' - ); - fs.writeFileSync(LOCAL_VALIDATOR_SCRIPT, this.localValidatorScript); - fs.chmodSync(LOCAL_VALIDATOR_SCRIPT, '755'); - - // create bash script to start local oracle - const ORACLE_SCRIPT = path.join(outputDir, 'start-oracle.sh'); - fs.writeFileSync(ORACLE_SCRIPT, this.startOracleScript); - fs.chmodSync(ORACLE_SCRIPT, '755'); - } - - public writeDockerCompose(outputDir: string): void { - const DOCKER_COMPOSE_FILEPATH = path.join( - outputDir, - 'docker-compose.switchboard.yml' - ); - fs.writeFileSync(DOCKER_COMPOSE_FILEPATH, this.dockerCompose); - } - - public writeAnchorToml(outputDir: string) { - const ANCHOR_TOML_FILEPATH = path.join( - outputDir, - 'Anchor.switchboard.toml' - ); - fs.writeFileSync(ANCHOR_TOML_FILEPATH, this.anchorToml); - } -} - -export function camelToUpperCaseWithUnderscores(str: string): string { - // Use a regular expression to match any uppercase or lowercase letters followed by uppercase letters - // and replace them with a matched group (the uppercase or lowercase letters) followed by an underscore - // and the uppercase letter - return ( - str - .replace(/([a-z]+)([A-Z])/g, (_, p1, p2) => p1 + '_' + p2) - // Make the entire string uppercase - .toUpperCase() - ); -} diff --git a/javascript/solana.js/src/test/index.ts b/javascript/solana.js/src/test/index.ts deleted file mode 100644 index 887da01..0000000 --- a/javascript/solana.js/src/test/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './SwitchboardTestContext'; -export * from './SwitchboardTestContextV2'; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7c8d5d4..e76b375 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -59,7 +59,6 @@ importers: '@solana/web3.js': ^1.73.0 '@switchboard-xyz/common': ^2.1.33 '@switchboard-xyz/eslint-config': latest - '@switchboard-xyz/oracle': ^2.1.13 '@types/chai': ^4.3.4 '@types/lodash': ^4.14.191 '@types/mocha': ^10.0.0 @@ -85,7 +84,6 @@ importers: '@solana/spl-token': 0.3.6_@solana+web3.js@1.73.0 '@solana/web3.js': 1.73.0 '@switchboard-xyz/common': 2.1.33 - '@switchboard-xyz/oracle': 2.1.13 dotenv: 16.0.3 lodash: 4.17.21 devDependencies: @@ -113,6 +111,7 @@ importers: '@coral-xyz/anchor': ^0.27.0 '@solana/web3.js': ^1.73.3 '@switchboard-xyz/common': ^2.1.33 + '@switchboard-xyz/oracle': ^2.1.13 '@switchboard-xyz/solana.js': workspace:* '@types/chai': ^4.3.0 '@types/mocha': ^9.0.0 @@ -128,6 +127,7 @@ importers: '@coral-xyz/anchor': 0.27.0 '@solana/web3.js': 1.73.3 '@switchboard-xyz/common': 2.1.33 + '@switchboard-xyz/oracle': 2.1.13 '@switchboard-xyz/solana.js': link:../../javascript/solana.js node-fetch: 2.6.7 devDependencies: @@ -146,6 +146,7 @@ importers: '@coral-xyz/anchor': ^0.27.0 '@solana/web3.js': ^1.73.3 '@switchboard-xyz/common': ^2.1.33 + '@switchboard-xyz/oracle': ^2.1.13 '@switchboard-xyz/solana.js': workspace:* '@types/chai': ^4.3.0 '@types/mocha': ^9.0.0 @@ -159,6 +160,7 @@ importers: '@coral-xyz/anchor': 0.27.0 '@solana/web3.js': 1.73.3 '@switchboard-xyz/common': 2.1.33 + '@switchboard-xyz/oracle': 2.1.13 '@switchboard-xyz/solana.js': link:../../javascript/solana.js devDependencies: '@types/chai': 4.3.4 @@ -174,6 +176,7 @@ importers: specifiers: '@coral-xyz/anchor': ^0.27.0 '@switchboard-xyz/common': ^2.1.33 + '@switchboard-xyz/oracle': ^2.1.13 '@switchboard-xyz/solana.js': workspace:* '@types/bn.js': ^5.1.0 '@types/chai': ^4.3.0 @@ -186,6 +189,7 @@ importers: dependencies: '@coral-xyz/anchor': 0.27.0 '@switchboard-xyz/common': 2.1.33 + '@switchboard-xyz/oracle': 2.1.13 '@switchboard-xyz/solana.js': link:../../javascript/solana.js devDependencies: '@types/bn.js': 5.1.1 @@ -205,6 +209,7 @@ importers: '@solana/spl-token': ^0.3.6 '@solana/web3.js': ^1.73.3 '@switchboard-xyz/common': ^2.1.33 + '@switchboard-xyz/oracle': ^2.1.13 '@switchboard-xyz/solana.js': workspace:* '@types/chai': ^4.3.0 '@types/mocha': ^9.0.0 @@ -231,6 +236,7 @@ importers: '@solana/spl-token': 0.3.6_@solana+web3.js@1.73.3 '@solana/web3.js': 1.73.3 '@switchboard-xyz/common': 2.1.33 + '@switchboard-xyz/oracle': 2.1.13 '@switchboard-xyz/solana.js': link:../../javascript/solana.js chalk: 4.1.2 dotenv: 16.0.3 @@ -257,6 +263,7 @@ importers: '@coral-xyz/anchor': ^0.27.0 '@solana/web3.js': ^1.73.3 '@switchboard-xyz/common': ^2.1.33 + '@switchboard-xyz/oracle': ^2.1.13 '@switchboard-xyz/solana.js': workspace:* '@types/chai': ^4.3.0 '@types/mocha': ^9.0.0 @@ -270,6 +277,7 @@ importers: '@coral-xyz/anchor': 0.27.0 '@solana/web3.js': 1.73.3 '@switchboard-xyz/common': 2.1.33 + '@switchboard-xyz/oracle': 2.1.13 '@switchboard-xyz/solana.js': link:../../javascript/solana.js devDependencies: '@types/chai': 4.3.4 @@ -1022,7 +1030,7 @@ packages: dependencies: '@types/http-cache-semantics': 4.0.1 '@types/keyv': 3.1.4 - '@types/node': 18.11.18 + '@types/node': 17.0.45 '@types/responselike': 1.0.0 dev: false @@ -1050,7 +1058,7 @@ packages: /@types/keyv/3.1.4: resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} dependencies: - '@types/node': 18.11.18 + '@types/node': 17.0.45 dev: false /@types/lodash/4.14.191: @@ -1081,7 +1089,6 @@ packages: /@types/node/17.0.45: resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} - dev: true /@types/node/18.11.18: resolution: {integrity: sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==} @@ -1097,7 +1104,7 @@ packages: /@types/responselike/1.0.0: resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==} dependencies: - '@types/node': 18.11.18 + '@types/node': 17.0.45 dev: false /@types/semver/7.3.13: @@ -1113,7 +1120,7 @@ packages: resolution: {integrity: sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==} requiresBuild: true dependencies: - '@types/node': 18.11.18 + '@types/node': 17.0.45 dev: false optional: true diff --git a/programs/anchor-buffer-parser/package.json b/programs/anchor-buffer-parser/package.json index faf1bc2..4b36e05 100644 --- a/programs/anchor-buffer-parser/package.json +++ b/programs/anchor-buffer-parser/package.json @@ -15,6 +15,7 @@ "@coral-xyz/anchor": "^0.27.0", "@solana/web3.js": "^1.73.3", "@switchboard-xyz/common": "^2.1.33", + "@switchboard-xyz/oracle": "^2.1.13", "@switchboard-xyz/solana.js": "workspace:*", "node-fetch": "^2.6" }, diff --git a/programs/anchor-buffer-parser/tests/anchor-buffer-parser.test.ts b/programs/anchor-buffer-parser/tests/anchor-buffer-parser.test.ts index 2989c3d..2002a17 100644 --- a/programs/anchor-buffer-parser/tests/anchor-buffer-parser.test.ts +++ b/programs/anchor-buffer-parser/tests/anchor-buffer-parser.test.ts @@ -1,6 +1,7 @@ import * as anchor from "@coral-xyz/anchor"; import { OracleJob, sleep } from "@switchboard-xyz/common"; -import { SwitchboardTestContextV2 } from "@switchboard-xyz/solana.js"; +import { NodeOracle } from "@switchboard-xyz/oracle"; +import { SwitchboardTestContext } from "@switchboard-xyz/solana.js"; import fetch from "node-fetch"; import { AnchorBufferParser } from "../target/types/anchor_buffer_parser"; @@ -11,13 +12,14 @@ describe("anchor-buffer-parser test", () => { const bufferParserProgram: anchor.Program = anchor.workspace.AnchorBufferParser; - let switchboard: SwitchboardTestContextV2; + let switchboard: SwitchboardTestContext; + let oracle: NodeOracle; before(async () => { - switchboard = await SwitchboardTestContextV2.loadFromProvider(provider, { + switchboard = await SwitchboardTestContext.loadFromProvider(provider, { // You can provide a keypair to so the PDA schemes dont change between test runs name: "Test Queue", - keypair: SwitchboardTestContextV2.loadKeypair("~/.keypairs/queue.json"), + keypair: SwitchboardTestContext.loadKeypair("~/.keypairs/queue.json"), queueSize: 10, reward: 0, minStake: 0, @@ -28,18 +30,33 @@ describe("anchor-buffer-parser test", () => { oracle: { name: "Test Oracle", enable: true, - stakingWalletKeypair: SwitchboardTestContextV2.loadKeypair( + stakingWalletKeypair: SwitchboardTestContext.loadKeypair( "~/.keypairs/oracleWallet.json" ), }, }); - await switchboard.start(); + + oracle = await NodeOracle.fromReleaseChannel({ + chain: "solana", + releaseChannel: "testnet", + network: "localnet", // disables production capabilities like monitoring and alerts + rpcUrl: switchboard.program.connection.rpcEndpoint, + oracleKey: switchboard.oracle.publicKey.toBase58(), + secretPath: switchboard.walletPath, + silent: false, // set to true to suppress oracle logs in the console + envVariables: { + VERBOSE: "1", + DEBUG: "1", + DISABLE_NONCE_QUEUE: "1", + DISABLE_METRICS: "1", + }, + }); + + await oracle.startAndAwait(); }); - after(async () => { - if (switchboard) { - switchboard.stop(); - } + after(() => { + oracle?.stop(); }); it("Create and read buffer account", async () => { diff --git a/programs/anchor-feed-parser/package.json b/programs/anchor-feed-parser/package.json index 68d1cba..a0d3420 100644 --- a/programs/anchor-feed-parser/package.json +++ b/programs/anchor-feed-parser/package.json @@ -15,6 +15,7 @@ "@coral-xyz/anchor": "^0.27.0", "@solana/web3.js": "^1.73.3", "@switchboard-xyz/common": "^2.1.33", + "@switchboard-xyz/oracle": "^2.1.13", "@switchboard-xyz/solana.js": "workspace:*" }, "devDependencies": { diff --git a/programs/anchor-feed-parser/tests/anchor-feed-parser.test.ts b/programs/anchor-feed-parser/tests/anchor-feed-parser.test.ts index 40acf15..a078df5 100644 --- a/programs/anchor-feed-parser/tests/anchor-feed-parser.test.ts +++ b/programs/anchor-feed-parser/tests/anchor-feed-parser.test.ts @@ -2,12 +2,11 @@ import * as anchor from "@coral-xyz/anchor"; import { OracleJob, sleep } from "@switchboard-xyz/common"; import { AggregatorAccount, - SwitchboardTestContextV2, + SwitchboardTestContext, } from "@switchboard-xyz/solana.js"; import assert from "assert"; -import chai from "chai"; import { AnchorFeedParser } from "../target/types/anchor_feed_parser"; -const expect = chai.expect; +import { NodeOracle } from "@switchboard-xyz/oracle"; describe("anchor-feed-parser test", () => { const provider = anchor.AnchorProvider.env(); @@ -16,14 +15,16 @@ describe("anchor-feed-parser test", () => { const feedParserProgram: anchor.Program = anchor.workspace.AnchorFeedParser; - let switchboard: SwitchboardTestContextV2; + let switchboard: SwitchboardTestContext; + let oracle: NodeOracle; + let aggregatorAccount: AggregatorAccount; before(async () => { - switchboard = await SwitchboardTestContextV2.loadFromProvider(provider, { + switchboard = await SwitchboardTestContext.loadFromProvider(provider, { // You can provide a keypair to so the PDA schemes dont change between test runs name: "Test Queue", - keypair: SwitchboardTestContextV2.loadKeypair("~/.keypairs/queue.json"), + keypair: SwitchboardTestContext.loadKeypair("~/.keypairs/queue.json"), queueSize: 10, reward: 0, minStake: 0, @@ -34,18 +35,33 @@ describe("anchor-feed-parser test", () => { oracle: { name: "Test Oracle", enable: true, - stakingWalletKeypair: SwitchboardTestContextV2.loadKeypair( + stakingWalletKeypair: SwitchboardTestContext.loadKeypair( "~/.keypairs/oracleWallet.json" ), }, }); - await switchboard.start(); + + oracle = await NodeOracle.fromReleaseChannel({ + chain: "solana", + releaseChannel: "testnet", + network: "localnet", // disables production capabilities like monitoring and alerts + rpcUrl: switchboard.program.connection.rpcEndpoint, + oracleKey: switchboard.oracle.publicKey.toBase58(), + secretPath: switchboard.walletPath, + silent: false, // set to true to suppress oracle logs in the console + envVariables: { + VERBOSE: "1", + DEBUG: "1", + DISABLE_NONCE_QUEUE: "1", + DISABLE_METRICS: "1", + }, + }); + + await oracle.startAndAwait(); }); - after(async () => { - if (switchboard) { - switchboard.stop(); - } + after(() => { + oracle?.stop(); }); it("Creates a static feed that resolves to 100", async () => { diff --git a/programs/anchor-history-parser/Anchor.toml b/programs/anchor-history-parser/Anchor.toml index e0d0739..8c03780 100644 --- a/programs/anchor-history-parser/Anchor.toml +++ b/programs/anchor-history-parser/Anchor.toml @@ -44,4 +44,4 @@ address = "7hkp1xfPBcD2t1vZMoWWQPzipHVcXeLAAaiGXdPSfDie" address="GvDMxPzN1sCj7L26YDK2HnMRXEQmQ2aemov8YBtPS7vR" [[test.validator.clone]] # sbv2 SOL/USD History Buffer -address="7LLvRhMs73FqcLkA8jvEE1AM2mYZXTmqfUv8GAEurymx" \ No newline at end of file +address="9GPTMZmtNU61ULAZoGxDZmnZoWeF8zvBmKp4WZY6Ln6j" \ No newline at end of file diff --git a/programs/anchor-history-parser/package.json b/programs/anchor-history-parser/package.json index b1995be..7812e85 100644 --- a/programs/anchor-history-parser/package.json +++ b/programs/anchor-history-parser/package.json @@ -15,6 +15,7 @@ "dependencies": { "@coral-xyz/anchor": "^0.27.0", "@switchboard-xyz/common": "^2.1.33", + "@switchboard-xyz/oracle": "^2.1.13", "@switchboard-xyz/solana.js": "workspace:*" }, "devDependencies": { diff --git a/programs/anchor-history-parser/tests/anchor-history-parser.test.ts b/programs/anchor-history-parser/tests/anchor-history-parser.test.ts index f319717..ede7788 100644 --- a/programs/anchor-history-parser/tests/anchor-history-parser.test.ts +++ b/programs/anchor-history-parser/tests/anchor-history-parser.test.ts @@ -4,15 +4,16 @@ import { Program } from "@coral-xyz/anchor"; import { OracleJob } from "@switchboard-xyz/common"; import { AggregatorAccount, - SwitchboardTestContextV2, + SwitchboardTestContext, } from "@switchboard-xyz/solana.js"; import { AnchorHistoryParser } from "../target/types/anchor_history_parser"; +import { NodeOracle } from "@switchboard-xyz/oracle"; export const AGGREGATOR_PUBKEY: anchor.web3.PublicKey = new anchor.web3.PublicKey("GvDMxPzN1sCj7L26YDK2HnMRXEQmQ2aemov8YBtPS7vR"); export const HISTORY_BUFFER_PUBKEY: anchor.web3.PublicKey = - new anchor.web3.PublicKey("7LLvRhMs73FqcLkA8jvEE1AM2mYZXTmqfUv8GAEurymx"); + new anchor.web3.PublicKey("9GPTMZmtNU61ULAZoGxDZmnZoWeF8zvBmKp4WZY6Ln6j"); export const sleep = (ms: number): Promise => new Promise((s) => setTimeout(s, ms)); @@ -28,13 +29,14 @@ describe("anchor-history-parser", () => { let aggregatorAccount: AggregatorAccount; let historyBuffer: anchor.web3.PublicKey; - let switchboard: SwitchboardTestContextV2; + let switchboard: SwitchboardTestContext; + let oracle: NodeOracle; before(async () => { - switchboard = await SwitchboardTestContextV2.loadFromProvider(provider, { + switchboard = await SwitchboardTestContext.loadFromProvider(provider, { // You can provide a keypair to so the PDA schemes dont change between test runs name: "Test Queue", - keypair: SwitchboardTestContextV2.loadKeypair("~/.keypairs/queue.json"), + keypair: SwitchboardTestContext.loadKeypair("~/.keypairs/queue.json"), queueSize: 10, reward: 0, minStake: 0, @@ -45,18 +47,33 @@ describe("anchor-history-parser", () => { oracle: { name: "Test Oracle", enable: true, - stakingWalletKeypair: SwitchboardTestContextV2.loadKeypair( + stakingWalletKeypair: SwitchboardTestContext.loadKeypair( "~/.keypairs/oracleWallet.json" ), }, }); - await switchboard.start(); + + oracle = await NodeOracle.fromReleaseChannel({ + chain: "solana", + releaseChannel: "testnet", + network: "localnet", // disables production capabilities like monitoring and alerts + rpcUrl: switchboard.program.connection.rpcEndpoint, + oracleKey: switchboard.oracle.publicKey.toBase58(), + secretPath: switchboard.walletPath, + silent: false, // set to true to suppress oracle logs in the console + envVariables: { + VERBOSE: "1", + DEBUG: "1", + DISABLE_NONCE_QUEUE: "1", + DISABLE_METRICS: "1", + }, + }); + + await oracle.startAndAwait(); }); - after(async () => { - if (switchboard) { - switchboard.stop(); - } + after(() => { + oracle?.stop(); }); /** Example showing how to create a new data feed with a history buffer storing 200k samples. diff --git a/programs/anchor-vrf-parser/package.json b/programs/anchor-vrf-parser/package.json index 61656d7..b3a58f9 100644 --- a/programs/anchor-vrf-parser/package.json +++ b/programs/anchor-vrf-parser/package.json @@ -20,6 +20,7 @@ "@solana/spl-token": "^0.3.6", "@solana/web3.js": "^1.73.3", "@switchboard-xyz/common": "^2.1.33", + "@switchboard-xyz/oracle": "^2.1.13", "@switchboard-xyz/solana.js": "workspace:*", "chalk": "^4.1.2", "dotenv": "^16.0.1", diff --git a/programs/anchor-vrf-parser/tests/anchor-vrf-parser.test.ts b/programs/anchor-vrf-parser/tests/anchor-vrf-parser.test.ts index 8c4bc81..cab99cf 100644 --- a/programs/anchor-vrf-parser/tests/anchor-vrf-parser.test.ts +++ b/programs/anchor-vrf-parser/tests/anchor-vrf-parser.test.ts @@ -17,12 +17,13 @@ import { PermissionAccount, QueueAccount, SwitchboardProgram, - SwitchboardTestContextV2, + SwitchboardTestContext, SWITCHBOARD_LABS_DEVNET_PERMISSIONLESS_QUEUE, types, } from "@switchboard-xyz/solana.js"; import { AnchorVrfParser } from "../target/types/anchor_vrf_parser"; +import { NodeOracle } from "@switchboard-xyz/oracle"; describe("anchor-vrf-parser test", () => { const provider = AnchorProvider.env(); @@ -56,7 +57,9 @@ describe("anchor-vrf-parser test", () => { ixData: vrfIxCoder.encode("updateResult", ""), // pass any params for instruction here }; - let switchboard: SwitchboardTestContextV2; + let switchboard: SwitchboardTestContext; + let oracle: NodeOracle; + let queueAccount: QueueAccount; let queue: types.OracleQueueAccountData; @@ -70,10 +73,10 @@ describe("anchor-vrf-parser test", () => { SWITCHBOARD_LABS_DEVNET_PERMISSIONLESS_QUEUE ); } else { - switchboard = await SwitchboardTestContextV2.loadFromProvider(provider, { + switchboard = await SwitchboardTestContext.loadFromProvider(provider, { // You can provide a keypair to so the PDA schemes dont change between test runs name: "Test Queue", - keypair: SwitchboardTestContextV2.loadKeypair("~/.keypairs/queue.json"), + keypair: SwitchboardTestContext.loadKeypair("~/.keypairs/queue.json"), queueSize: 10, reward: 0, minStake: 0, @@ -84,19 +87,36 @@ describe("anchor-vrf-parser test", () => { oracle: { name: "Test Oracle", enable: true, - stakingWalletKeypair: SwitchboardTestContextV2.loadKeypair( + stakingWalletKeypair: SwitchboardTestContext.loadKeypair( "~/.keypairs/oracleWallet.json" ), }, }); queueAccount = switchboard.queue; queue = await queueAccount.loadData(); - await switchboard.start(); + + oracle = await NodeOracle.fromReleaseChannel({ + chain: "solana", + releaseChannel: "testnet", + network: "localnet", // disables production capabilities like monitoring and alerts + rpcUrl: switchboard.program.connection.rpcEndpoint, + oracleKey: switchboard.oracle.publicKey.toBase58(), + secretPath: switchboard.walletPath, + silent: false, // set to true to suppress oracle logs in the console + envVariables: { + VERBOSE: "1", + DEBUG: "1", + DISABLE_NONCE_QUEUE: "1", + DISABLE_METRICS: "1", + }, + }); + + await oracle.startAndAwait(); } }); after(() => { - switchboard?.stop(); + oracle?.stop(); }); it("Creates a vrfClient account", async () => { diff --git a/programs/native-feed-parser/package.json b/programs/native-feed-parser/package.json index 9294378..7e52d52 100644 --- a/programs/native-feed-parser/package.json +++ b/programs/native-feed-parser/package.json @@ -16,6 +16,7 @@ "@coral-xyz/anchor": "^0.27.0", "@solana/web3.js": "^1.73.3", "@switchboard-xyz/common": "^2.1.33", + "@switchboard-xyz/oracle": "^2.1.13", "@switchboard-xyz/solana.js": "workspace:*" }, "devDependencies": { diff --git a/programs/native-feed-parser/tests/spl-feed-parser.test.ts b/programs/native-feed-parser/tests/spl-feed-parser.test.ts index fe6e8fc..9db0ebb 100644 --- a/programs/native-feed-parser/tests/spl-feed-parser.test.ts +++ b/programs/native-feed-parser/tests/spl-feed-parser.test.ts @@ -6,9 +6,10 @@ import { TransactionInstruction, } from "@solana/web3.js"; import { OracleJob, sleep } from "@switchboard-xyz/common"; +import { NodeOracle } from "@switchboard-xyz/oracle"; import { AggregatorAccount, - SwitchboardTestContextV2, + SwitchboardTestContext, } from "@switchboard-xyz/solana.js"; import assert from "assert"; import fs from "fs"; @@ -37,13 +38,14 @@ describe("native-feed-parser test", () => { anchor.setProvider(provider); let aggregatorAccount: AggregatorAccount; - let switchboard: SwitchboardTestContextV2; + let switchboard: SwitchboardTestContext; + let oracle: NodeOracle; before(async () => { - switchboard = await SwitchboardTestContextV2.loadFromProvider(provider, { + switchboard = await SwitchboardTestContext.loadFromProvider(provider, { // You can provide a keypair to so the PDA schemes dont change between test runs name: "Test Queue", - keypair: SwitchboardTestContextV2.loadKeypair("~/.keypairs/queue.json"), + keypair: SwitchboardTestContext.loadKeypair("~/.keypairs/queue.json"), queueSize: 10, reward: 0, minStake: 0, @@ -54,18 +56,33 @@ describe("native-feed-parser test", () => { oracle: { name: "Test Oracle", enable: true, - stakingWalletKeypair: SwitchboardTestContextV2.loadKeypair( + stakingWalletKeypair: SwitchboardTestContext.loadKeypair( "~/.keypairs/oracleWallet.json" ), }, }); - await switchboard.start(); + + oracle = await NodeOracle.fromReleaseChannel({ + chain: "solana", + releaseChannel: "testnet", + network: "localnet", // disables production capabilities like monitoring and alerts + rpcUrl: switchboard.program.connection.rpcEndpoint, + oracleKey: switchboard.oracle.publicKey.toBase58(), + secretPath: switchboard.walletPath, + silent: false, // set to true to suppress oracle logs in the console + envVariables: { + VERBOSE: "1", + DEBUG: "1", + DISABLE_NONCE_QUEUE: "1", + DISABLE_METRICS: "1", + }, + }); + + await oracle.startAndAwait(); }); - after(async () => { - if (switchboard) { - switchboard.stop(); - } + after(() => { + oracle?.stop(); }); it("Read SOL/USD Feed", async () => {