doc comments

This commit is contained in:
Conner Gallagher 2022-11-30 17:18:09 -07:00
parent e0eed72270
commit 46e68b8f20
10 changed files with 198 additions and 15 deletions

View File

@ -7,6 +7,7 @@ import { SwitchboardProgram } from '../program';
import {
AccountInfo,
AccountMeta,
Commitment,
Keypair,
PublicKey,
SystemProgram,
@ -24,6 +25,16 @@ import * as spl from '@solana/spl-token';
import { TransactionObject } from '../transaction';
import { TOKEN_PROGRAM_ID } from '@solana/spl-token';
/**
* @class AggregatorAccount
* Account type holding a data feed's update configuration, job accounts, and its current result.
*
* An aggregator account belongs to a single {@linkcode QueueAccount} but can later be transferred by the aggregator's authority. In order for an {@linkcode OracleAccount} to respond to an aggregator's update request, the aggregator must initialize a {@linkcode PermissionAccount} and {@linkcode LeaseAccount}. These will need to be recreated when transferring queues.
*
* Optionally, An aggregator can be pushed onto a {@linkcode CrankAccount} in order to be updated
*
* Optionally, an aggregator can add a history buffer to store the last N historical samples along with their update timestamp.
*/
export class AggregatorAccount extends Account<types.AggregatorAccountData> {
static accountName = 'AggregatorAccountData';
@ -55,14 +66,22 @@ export class AggregatorAccount extends Account<types.AggregatorAccountData> {
}
}
/**
* Invoke a callback each time an AggregatorAccount's data has changed on-chain.
* @param callback - the callback invoked when the aggregator state changes
* @param commitment - optional, the desired transaction finality. defaults to 'confirmed'
* @returns the websocket subscription id
*/
public onChange(
callback: OnAccountChangeCallback<types.AggregatorAccountData>
callback: OnAccountChangeCallback<types.AggregatorAccountData>,
commitment: Commitment = 'confirmed'
): number {
return this.program.connection.onAccountChange(
this.publicKey,
accountInfo => {
callback(this.decode(accountInfo.data));
}
},
commitment
);
}

View File

@ -5,6 +5,7 @@ import {
TOKEN_PROGRAM_ID,
} from '@solana/spl-token';
import {
Commitment,
Keypair,
PublicKey,
SystemProgram,
@ -23,6 +24,10 @@ import { JobAccount } from './jobAccount';
import { PermissionAccount } from './permissionAccount';
import { QueueAccount } from './queueAccount';
/**
* @class BufferRelayerAccount
* Account type holding a buffer of data sourced from the buffers sole {@linkcode JobAccount}. A buffer relayer has no consensus mechanism and relies on trusting an {@linkcode OracleAccount} to respond honestly. A buffer relayer has a max capacity of 500 bytes.
*/
export class BufferRelayerAccount extends Account<types.BufferRelayerAccountData> {
static accountName = 'BufferRelayerAccountData';
@ -44,14 +49,22 @@ export class BufferRelayerAccount extends Account<types.BufferRelayerAccountData
}
}
/**
* Invoke a callback each time a BufferRelayerAccount's data has changed on-chain.
* @param callback - the callback invoked when the buffer relayer state changes
* @param commitment - optional, the desired transaction finality. defaults to 'confirmed'
* @returns the websocket subscription id
*/
public onChange(
callback: OnAccountChangeCallback<types.BufferRelayerAccountData>
callback: OnAccountChangeCallback<types.BufferRelayerAccountData>,
commitment: Commitment = 'confirmed'
): number {
return this.program.connection.onAccountChange(
this.publicKey,
accountInfo => {
callback(this.decode(accountInfo.data));
}
},
commitment
);
}

View File

@ -18,7 +18,8 @@ import { AggregatorAccount } from './aggregatorAccount';
import { QueueAccount } from './queueAccount';
/**
* A Switchboard account representing a crank of aggregators ordered by next update time.
* @class CrankAccount
* Account holding a priority queue of aggregators and their next available update time. This is a scheduling mechanism to ensure {@linkcode AggregatorAccount}'s are updated as close as possible to their specified update interval.
*/
export class CrankAccount extends Account<types.CrankAccountData> {
static accountName = 'CrankAccountData';
@ -31,6 +32,12 @@ export class CrankAccount extends Account<types.CrankAccountData> {
*/
public size = this.program.account.crankAccountData.size;
/**
* Invoke a callback each time a CrankAccount's data has changed on-chain.
* @param callback - the callback invoked when the cranks state changes
* @param commitment - optional, the desired transaction finality. defaults to 'confirmed'
* @returns the websocket subscription id
*/
onChange(
callback: OnAccountChangeCallback<types.CrankAccountData>,
commitment: Commitment = 'confirmed'
@ -42,6 +49,12 @@ export class CrankAccount extends Account<types.CrankAccountData> {
);
}
/**
* Invoke a callback each time a crank's buffer has changed on-chain. The buffer stores a list of {@linkcode AggregatorAccount} public keys along with their next available update time.
* @param callback - the callback invoked when the crank's buffer changes
* @param commitment - optional, the desired transaction finality. defaults to 'confirmed'
* @returns the websocket subscription id
*/
onBufferChange(
callback: OnAccountChangeCallback<Array<types.CrankRow>>,
_dataBuffer?: PublicKey,

View File

@ -13,6 +13,10 @@ import { SwitchboardProgram } from '../program';
import { Account } from './account';
import { TransactionObject } from '../transaction';
/**
* @class JobAccount
* Account type storing a list of SwitchboardTasks {@linkcode OracleJob.ITask} dictating how to source data off-chain.
*/
export class JobAccount extends Account<types.JobAccountData> {
static accountName = 'JobAccountData';

View File

@ -16,6 +16,10 @@ import { QueueAccount } from './queueAccount';
import { TransactionObject } from '../transaction';
import { BN } from 'bn.js';
/**
* @class LeaseAccount
* Account type representing an {@linkcode AggregatorAccount}'s pre-funded escrow used to reward {@linkcode OracleAccount}'s for responding to open round requests.
*/
export class LeaseAccount extends Account<types.LeaseAccountData> {
static accountName = 'LeaseAccountData';

View File

@ -15,6 +15,12 @@ import { QueueAccount } from './queueAccount';
import * as spl from '@solana/spl-token';
import { TransactionObject } from '../transaction';
/**
* @class OracleAccount
* Account type holding an oracle's configuration including the authority and the reward/slashing wallet along with a set of metrics tracking its reliability.
*
* An oracle is a server that sits between the internet and a blockchain and facilitates the flow of information and is rewarded for responding with the honest majority.
*/
export class OracleAccount extends Account<types.OracleAccountData> {
static accountName = 'OracleAccountData';

View File

@ -14,6 +14,13 @@ export interface PermissionAccountInitParams {
grantee: PublicKey;
authority: PublicKey;
}
/**
* @class PermissionAccount
* Account type dictating the level of permissions between a granter and a grantee.
*
* A {@linkcode QueueAccount} acts as the granter where the queue authority assigns or revokes a grantee's {@linkcode types.SwitchboardPermission}. A grantee can be one of the following: {@linkcode AggregatorAccount}, {@linkcode BufferRelayerAccount}, or {@linkcode VrfAccount}.
*/
export class PermissionAccount extends Account<types.PermissionAccountData> {
static accountName = 'PermissionAccountData';

View File

@ -13,6 +13,7 @@ import {
import { TransactionObject } from '../transaction';
/**
* @class ProgramStateAccount
* Account type representing Switchboard global program state.
*/
export class ProgramStateAccount extends Account<types.SbState> {

View File

@ -28,6 +28,12 @@ import { OracleAccount } from './oracleAccount';
import { PermissionAccount } from './permissionAccount';
import { VrfAccount, VrfInitParams } from './vrfAccount';
/**
* @class QueueAccount
* Account type representing an oracle queue's configuration along with a buffer account holding a list of oracles that are actively heartbeating.
*
* A QueueAccount is responsible for allocating update requests to it's round robin queue of {@linkcode OracleAccount}'s.
*/
export class QueueAccount extends Account<types.OracleQueueAccountData> {
static accountName = 'OracleQueueAccountData';
@ -51,6 +57,12 @@ export class QueueAccount extends Account<types.OracleQueueAccountData> {
public static getMetadata = (queue: types.OracleQueueAccountData) =>
Buffer.from(queue.metadata).toString('utf8').replace(/u0000/g, '');
/**
* Invoke a callback each time a QueueAccount's data has changed on-chain.
* @param callback - the callback invoked when the queues state changes
* @param commitment - optional, the desired transaction finality. defaults to 'confirmed'
* @returns the websocket subscription id
*/
onChange(
callback: OnAccountChangeCallback<types.OracleQueueAccountData>,
commitment: Commitment = 'confirmed'
@ -63,6 +75,12 @@ export class QueueAccount extends Account<types.OracleQueueAccountData> {
);
}
/**
* Invoke a callback each time a QueueAccount's oracle queue buffer has changed on-chain. The buffer stores a list of oracle's and their last heartbeat timestamp.
* @param callback - the callback invoked when the queues buffer changes
* @param commitment - optional, the desired transaction finality. defaults to 'confirmed'
* @returns the websocket subscription id
*/
onBufferChange(
callback: OnAccountChangeCallback<Array<PublicKey>>,
_dataBuffer?: PublicKey,
@ -101,6 +119,9 @@ export class QueueAccount extends Account<types.OracleQueueAccountData> {
return this.program.mint.mint;
}
/**
* Create a new QueueAccount.
*/
public static async create(
program: SwitchboardProgram,
params: QueueInitParams
@ -114,6 +135,9 @@ export class QueueAccount extends Account<types.OracleQueueAccountData> {
return [txnSignature, account];
}
/**
* Create a {@linkcode TransactionObject} that contains the Solana TransactionInstructions and signers required to create a new QueueAccount on-chain.
*/
public static async createInstructions(
program: SwitchboardProgram,
payer: PublicKey,
@ -191,6 +215,9 @@ export class QueueAccount extends Account<types.OracleQueueAccountData> {
];
}
/**
* Create a new {@linkcode OracleAccount} for the queue.
*/
public async createOracle(params: {
name?: string;
metadata?: string;
@ -219,6 +246,9 @@ export class QueueAccount extends Account<types.OracleQueueAccountData> {
return [signature, oracleAccount];
}
/**
* Create a {@linkcode TransactionObject} that can then be used to create a new {@linkcode OracleAccount} for the queue.
*/
public async createOracleInstructions(
payer: PublicKey,
params: {
@ -259,6 +289,45 @@ export class QueueAccount extends Account<types.OracleQueueAccountData> {
];
}
/**
* Create a new {@linkcode AggregatorAccount} for the queue, along with its {@linkcode PermissionAccount} and {@linkcode LeaseAccount}.
*
* Optionally, specify a crankPubkey in order to push it onto an existing {@linkcode CrankAccount}.
*
* Optionally, enable the permissions by setting a queueAuthority keypair along with the enable boolean set to true.
*
* ```ts
* import {QueueAccount} from '@switchboard-xyz/solana.js';
* const queueAccount = new QueueAccount(program, queuePubkey);
* const [aggregatorInitSignatures, aggregatorAccount] =
await queueAccount.createFeed({
enable: true, // not needed if queue has unpermissionedFeedsEnabled
queueAuthority: queueAuthority, // not needed if queue has unpermissionedFeedsEnabled
batchSize: 1,
minRequiredOracleResults: 1,
minRequiredJobResults: 1,
minUpdateDelaySeconds: 60,
fundAmount: 2.5, // deposit 2.5 wSOL into the leaseAccount escrow
jobs: [
{ pubkey: jobAccount.publicKey },
{
weight: 2,
data: OracleJob.encodeDelimited(
OracleJob.fromObject({
tasks: [
{
valueTask: {
value: 1,
},
},
],
})
).finish(),
},
],
});
* ```
*/
public async createFeed(
params: Omit<
Omit<Omit<AggregatorInitParams, 'queueAccount'>, 'queueAuthority'>,
@ -302,6 +371,46 @@ export class QueueAccount extends Account<types.OracleQueueAccountData> {
return [signatures, aggregatorAccount];
}
/**
* Create a new {@linkcode TransactionObject} containing the instructions and signers needed to create a new {@linkcode AggregatorAccount} for the queue along with its {@linkcode PermissionAccount} and {@linkcode LeaseAccount}.
*
* Optionally, specify a crankPubkey in order to push it onto an existing {@linkcode CrankAccount}.
*
* Optionally, enable the permissions by setting a queueAuthority keypair along with the enable boolean set to true.
*
* ```ts
* import {QueueAccount} from '@switchboard-xyz/solana.js';
* const queueAccount = new QueueAccount(program, queuePubkey);
* const [aggregatorInitTxnObject, aggregatorAccount] =
await queueAccount.createFeedInstructions({
enable: true, // not needed if queue has unpermissionedFeedsEnabled
queueAuthority: queueAuthority, // not needed if queue has unpermissionedFeedsEnabled
batchSize: 1,
minRequiredOracleResults: 1,
minRequiredJobResults: 1,
minUpdateDelaySeconds: 60,
fundAmount: 2.5, // deposit 2.5 wSOL into the leaseAccount escrow
jobs: [
{ pubkey: jobAccount.publicKey },
{
weight: 2,
data: OracleJob.encodeDelimited(
OracleJob.fromObject({
tasks: [
{
valueTask: {
value: 1,
},
},
],
})
).finish(),
},
],
});
const aggregatorInitSignatures = await this.program.signAndSendAll(txns);
* ```
*/
public async createFeedInstructions(
payer: PublicKey,
params: Omit<
@ -455,16 +564,6 @@ export class QueueAccount extends Account<types.OracleQueueAccountData> {
return [packed, aggregatorAccount];
}
public async createCrankInstructions(
payer: PublicKey,
params: Omit<CrankInitParams, 'queueAccount'>
): Promise<[TransactionObject, CrankAccount]> {
return await CrankAccount.createInstructions(this.program, payer, {
...params,
queueAccount: this,
});
}
public async createCrank(
params: Omit<CrankInitParams, 'queueAccount'>
): Promise<[TransactionSignature, CrankAccount]> {
@ -476,6 +575,16 @@ export class QueueAccount extends Account<types.OracleQueueAccountData> {
return [txnSignature, crankAccount];
}
public async createCrankInstructions(
payer: PublicKey,
params: Omit<CrankInitParams, 'queueAccount'>
): Promise<[TransactionObject, CrankAccount]> {
return await CrankAccount.createInstructions(this.program, payer, {
...params,
queueAccount: this,
});
}
public async createBufferRelayerInstructions(
payer: PublicKey,
params: Omit<Omit<BufferRelayerInit, 'jobAccount'>, 'queueAccount'> & {

View File

@ -22,6 +22,7 @@ import { QueueAccount } from './queueAccount';
/**
* @class VrfAccount
* Account holding a Verifiable Random Function result with a callback instruction for consuming on-chain pseudo-randomness.
*/
export class VrfAccount extends Account<types.VrfAccountData> {
static accountName = 'VrfAccountData';
@ -31,6 +32,12 @@ export class VrfAccount extends Account<types.VrfAccountData> {
*/
public readonly size = this.program.account.vrfAccountData.size;
/**
* Invoke a callback each time a VrfAccount's data has changed on-chain.
* @param callback - the callback invoked when the vrf state changes
* @param commitment - optional, the desired transaction finality. defaults to 'confirmed'
* @returns the websocket subscription id
*/
onChange(
callback: OnAccountChangeCallback<types.VrfAccountData>,
commitment: Commitment = 'confirmed'