solana.js: oracle stake ixns
This commit is contained in:
parent
37af41d11e
commit
5a49b6269c
|
@ -698,7 +698,7 @@ export class AggregatorAccount extends Account<types.AggregatorAccountData> {
|
|||
|
||||
public async openRoundInstruction(
|
||||
payer: PublicKey,
|
||||
params: Partial<{ payoutWallet: PublicKey }>
|
||||
params?: { payoutWallet?: PublicKey }
|
||||
): Promise<TransactionObject> {
|
||||
const aggregatorData = await this.loadData();
|
||||
const queueAccount = new QueueAccount(
|
||||
|
@ -760,9 +760,9 @@ export class AggregatorAccount extends Account<types.AggregatorAccountData> {
|
|||
return new TransactionObject(payer, ixns, []);
|
||||
}
|
||||
|
||||
public async openRound(
|
||||
params: Partial<{ payoutWallet: PublicKey }>
|
||||
): Promise<TransactionSignature> {
|
||||
public async openRound(params?: {
|
||||
payoutWallet?: PublicKey;
|
||||
}): Promise<TransactionSignature> {
|
||||
const openRoundTxn = await this.openRoundInstruction(
|
||||
this.program.walletPubkey,
|
||||
params
|
||||
|
|
|
@ -192,7 +192,7 @@ export class BufferRelayerAccount extends Account<types.BufferRelayerAccountData
|
|||
);
|
||||
const tokenAmountBN = new BN(tokenAccount.amount.toString());
|
||||
if (tokenAmountBN.lt(queue.reward)) {
|
||||
const wrapTxn = await this.program.mint.wrapInstruction(payer, {
|
||||
const wrapTxn = await this.program.mint.wrapInstructions(payer, {
|
||||
fundUpTo: new Big(this.program.mint.fromTokenAmountBN(queue.reward)),
|
||||
});
|
||||
ixns.push(...wrapTxn.ixns);
|
||||
|
|
|
@ -120,7 +120,7 @@ export class LeaseAccount extends Account<types.LeaseAccountData> {
|
|||
(await program.mint.getBalance(funderAuthority)) ?? 0;
|
||||
|
||||
if (loadAmount && funderTokenBalance < loadAmount) {
|
||||
const wrapIxns = await program.mint.wrapInstruction(
|
||||
const wrapIxns = await program.mint.wrapInstructions(
|
||||
payer,
|
||||
{ amount: loadAmount },
|
||||
params.funderAuthority
|
||||
|
@ -354,7 +354,7 @@ export class LeaseAccount extends Account<types.LeaseAccountData> {
|
|||
const funderBalance =
|
||||
(await this.program.mint.getBalance(funderAuthority)) ?? 0;
|
||||
if (funderBalance < params.loadAmount) {
|
||||
const wrapIxns = await this.program.mint.unwrapInstruction(
|
||||
const wrapIxns = await this.program.mint.unwrapInstructions(
|
||||
payer,
|
||||
params.loadAmount,
|
||||
params.funderAuthority
|
||||
|
@ -395,20 +395,6 @@ export class LeaseAccount extends Account<types.LeaseAccountData> {
|
|||
return new TransactionObject(payer, ixns, signers);
|
||||
}
|
||||
|
||||
public async withdraw(params: {
|
||||
amount: number;
|
||||
unwrap?: boolean;
|
||||
withdrawWallet?: PublicKey;
|
||||
withdrawAuthority?: Keypair;
|
||||
}): Promise<TransactionSignature> {
|
||||
const withdrawTxn = await this.withdrawInstruction(
|
||||
this.program.walletPubkey,
|
||||
params
|
||||
);
|
||||
const txnSignature = await this.program.signAndSend(withdrawTxn);
|
||||
return txnSignature;
|
||||
}
|
||||
|
||||
public async withdrawInstruction(
|
||||
payer: PublicKey,
|
||||
params: {
|
||||
|
@ -499,7 +485,7 @@ export class LeaseAccount extends Account<types.LeaseAccountData> {
|
|||
|
||||
if (params.unwrap) {
|
||||
txns.push(
|
||||
await this.program.mint.unwrapInstruction(
|
||||
await this.program.mint.unwrapInstructions(
|
||||
payer,
|
||||
params.amount,
|
||||
params.withdrawAuthority
|
||||
|
@ -515,6 +501,20 @@ export class LeaseAccount extends Account<types.LeaseAccountData> {
|
|||
return packed[0];
|
||||
}
|
||||
|
||||
public async withdraw(params: {
|
||||
amount: number;
|
||||
unwrap?: boolean;
|
||||
withdrawWallet?: PublicKey;
|
||||
withdrawAuthority?: Keypair;
|
||||
}): Promise<TransactionSignature> {
|
||||
const withdrawTxn = await this.withdrawInstruction(
|
||||
this.program.walletPubkey,
|
||||
params
|
||||
);
|
||||
const txnSignature = await this.program.signAndSend(withdrawTxn);
|
||||
return txnSignature;
|
||||
}
|
||||
|
||||
public async setAuthority(params: {
|
||||
newAuthority: PublicKey;
|
||||
withdrawAuthority: Keypair;
|
||||
|
|
|
@ -4,6 +4,7 @@ import { Account, OnAccountChangeCallback } from './account';
|
|||
import * as anchor from '@project-serum/anchor';
|
||||
import { SwitchboardProgram } from '../program';
|
||||
import {
|
||||
Commitment,
|
||||
Keypair,
|
||||
PublicKey,
|
||||
SystemProgram,
|
||||
|
@ -30,6 +31,35 @@ export class OracleAccount extends Account<types.OracleAccountData> {
|
|||
*/
|
||||
public size = this.program.account.oracleAccountData.size;
|
||||
|
||||
decode(data: Buffer): types.OracleAccountData {
|
||||
try {
|
||||
return types.OracleAccountData.decode(data);
|
||||
} catch {
|
||||
return this.program.coder.decode<types.OracleAccountData>(
|
||||
OracleAccount.accountName,
|
||||
data
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke a callback each time an OracleAccount's data has changed on-chain.
|
||||
* @param callback - the callback invoked when the oracle state changes
|
||||
* @param commitment - optional, the desired transaction finality. defaults to 'confirmed'
|
||||
* @returns the websocket subscription id
|
||||
*/
|
||||
onChange(
|
||||
callback: OnAccountChangeCallback<types.OracleAccountData>,
|
||||
commitment: Commitment = 'confirmed'
|
||||
): number {
|
||||
return this.program.connection.onAccountChange(
|
||||
this.publicKey,
|
||||
accountInfo => {
|
||||
callback(this.decode(accountInfo.data));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve and decode the {@linkcode types.OracleAccountData} stored in this account.
|
||||
*/
|
||||
|
@ -42,98 +72,6 @@ export class OracleAccount extends Account<types.OracleAccountData> {
|
|||
return data;
|
||||
}
|
||||
|
||||
public static async createInstructions(
|
||||
program: SwitchboardProgram,
|
||||
payer: PublicKey,
|
||||
params: {
|
||||
queueAccount: QueueAccount;
|
||||
} & OracleInitParams
|
||||
): Promise<[OracleAccount, TransactionObject]> {
|
||||
const tokenWallet = Keypair.generate();
|
||||
// console.log(`tokenWallet`, tokenWallet.publicKey.toBase58());
|
||||
|
||||
const authority = params.authority?.publicKey ?? payer;
|
||||
|
||||
const [oracleAccount, oracleBump] = OracleAccount.fromSeed(
|
||||
program,
|
||||
params.queueAccount.publicKey,
|
||||
tokenWallet.publicKey
|
||||
);
|
||||
|
||||
const ixns = [
|
||||
SystemProgram.createAccount({
|
||||
fromPubkey: payer,
|
||||
newAccountPubkey: tokenWallet.publicKey,
|
||||
space: spl.ACCOUNT_SIZE,
|
||||
lamports: await program.connection.getMinimumBalanceForRentExemption(
|
||||
spl.ACCOUNT_SIZE
|
||||
),
|
||||
programId: spl.TOKEN_PROGRAM_ID,
|
||||
}),
|
||||
spl.createInitializeAccountInstruction(
|
||||
tokenWallet.publicKey,
|
||||
program.mint.address,
|
||||
authority
|
||||
),
|
||||
spl.createSetAuthorityInstruction(
|
||||
tokenWallet.publicKey,
|
||||
authority,
|
||||
spl.AuthorityType.AccountOwner,
|
||||
program.programState.publicKey
|
||||
),
|
||||
types.oracleInit(
|
||||
program,
|
||||
{
|
||||
params: {
|
||||
name: new Uint8Array(
|
||||
Buffer.from(params.name ?? '', 'utf8').slice(0, 32)
|
||||
),
|
||||
metadata: new Uint8Array(
|
||||
Buffer.from(params.metadata ?? '', 'utf8').slice(0, 128)
|
||||
),
|
||||
oracleBump,
|
||||
stateBump: program.programState.bump,
|
||||
},
|
||||
},
|
||||
{
|
||||
oracle: oracleAccount.publicKey,
|
||||
oracleAuthority: authority,
|
||||
wallet: tokenWallet.publicKey,
|
||||
programState: program.programState.publicKey,
|
||||
queue: params.queueAccount.publicKey,
|
||||
payer,
|
||||
systemProgram: SystemProgram.programId,
|
||||
}
|
||||
),
|
||||
];
|
||||
|
||||
return [
|
||||
new OracleAccount(program, oracleAccount.publicKey),
|
||||
new TransactionObject(
|
||||
payer,
|
||||
ixns,
|
||||
params.authority ? [tokenWallet, params.authority] : [tokenWallet]
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
public static async create(
|
||||
program: SwitchboardProgram,
|
||||
params: {
|
||||
queueAccount: QueueAccount;
|
||||
} & OracleInitParams
|
||||
): Promise<[OracleAccount, TransactionSignature]> {
|
||||
const [oracleAccount, txnObject] = await OracleAccount.createInstructions(
|
||||
program,
|
||||
program.walletPubkey,
|
||||
params
|
||||
);
|
||||
|
||||
const txnSignature = await program.signAndSend(txnObject);
|
||||
|
||||
return [oracleAccount, txnSignature];
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads an OracleAccount from the expected PDA seed format.
|
||||
* @param program The Switchboard program for the current connection.
|
||||
|
@ -153,24 +91,172 @@ export class OracleAccount extends Account<types.OracleAccountData> {
|
|||
return [new OracleAccount(program, publicKey), bump];
|
||||
}
|
||||
|
||||
decode(data: Buffer): types.OracleAccountData {
|
||||
try {
|
||||
return types.OracleAccountData.decode(data);
|
||||
} catch {
|
||||
return this.program.coder.decode<types.OracleAccountData>(
|
||||
OracleAccount.accountName,
|
||||
data
|
||||
);
|
||||
public static async createInstructions(
|
||||
program: SwitchboardProgram,
|
||||
payer: PublicKey,
|
||||
params: {
|
||||
queueAccount: QueueAccount;
|
||||
} & OracleInitParams &
|
||||
OracleStakeParams
|
||||
): Promise<[OracleAccount, TransactionObject]> {
|
||||
const tokenWallet = Keypair.generate();
|
||||
|
||||
const authority = params.authority?.publicKey ?? payer;
|
||||
|
||||
const txns: TransactionObject[] = [];
|
||||
|
||||
const [oracleAccount, oracleBump] = OracleAccount.fromSeed(
|
||||
program,
|
||||
params.queueAccount.publicKey,
|
||||
tokenWallet.publicKey
|
||||
);
|
||||
|
||||
const oracleInit = new TransactionObject(
|
||||
payer,
|
||||
[
|
||||
SystemProgram.createAccount({
|
||||
fromPubkey: payer,
|
||||
newAccountPubkey: tokenWallet.publicKey,
|
||||
space: spl.ACCOUNT_SIZE,
|
||||
lamports: await program.connection.getMinimumBalanceForRentExemption(
|
||||
spl.ACCOUNT_SIZE
|
||||
),
|
||||
programId: spl.TOKEN_PROGRAM_ID,
|
||||
}),
|
||||
spl.createInitializeAccountInstruction(
|
||||
tokenWallet.publicKey,
|
||||
program.mint.address,
|
||||
authority
|
||||
),
|
||||
spl.createSetAuthorityInstruction(
|
||||
tokenWallet.publicKey,
|
||||
authority,
|
||||
spl.AuthorityType.AccountOwner,
|
||||
program.programState.publicKey
|
||||
),
|
||||
types.oracleInit(
|
||||
program,
|
||||
{
|
||||
params: {
|
||||
name: new Uint8Array(
|
||||
Buffer.from(params.name ?? '', 'utf8').slice(0, 32)
|
||||
),
|
||||
metadata: new Uint8Array(
|
||||
Buffer.from(params.metadata ?? '', 'utf8').slice(0, 128)
|
||||
),
|
||||
oracleBump,
|
||||
stateBump: program.programState.bump,
|
||||
},
|
||||
},
|
||||
{
|
||||
oracle: oracleAccount.publicKey,
|
||||
oracleAuthority: authority,
|
||||
wallet: tokenWallet.publicKey,
|
||||
programState: program.programState.publicKey,
|
||||
queue: params.queueAccount.publicKey,
|
||||
payer,
|
||||
systemProgram: SystemProgram.programId,
|
||||
}
|
||||
),
|
||||
],
|
||||
params.authority ? [params.authority, tokenWallet] : [tokenWallet]
|
||||
);
|
||||
|
||||
txns.push(oracleInit);
|
||||
|
||||
if (params.stakeAmount && params.stakeAmount > 0) {
|
||||
const depositTxn = await oracleAccount.stakeInstructions(payer, {
|
||||
stakeAmount: params.stakeAmount,
|
||||
funderAuthority: params.funderAuthority,
|
||||
funderTokenAccount: params.funderTokenAccount,
|
||||
tokenAccount: tokenWallet.publicKey,
|
||||
});
|
||||
txns.push(depositTxn);
|
||||
}
|
||||
|
||||
const packed = TransactionObject.pack(txns);
|
||||
if (packed.length > 1) {
|
||||
throw new Error(`Expected a single TransactionObject`);
|
||||
}
|
||||
|
||||
return [oracleAccount, packed[0]];
|
||||
}
|
||||
|
||||
onChange(callback: OnAccountChangeCallback<types.OracleAccountData>): number {
|
||||
return this.program.connection.onAccountChange(
|
||||
this.publicKey,
|
||||
accountInfo => {
|
||||
callback(this.decode(accountInfo.data));
|
||||
}
|
||||
public static async create(
|
||||
program: SwitchboardProgram,
|
||||
params: {
|
||||
queueAccount: QueueAccount;
|
||||
} & OracleInitParams &
|
||||
OracleStakeParams
|
||||
): Promise<[OracleAccount, TransactionSignature]> {
|
||||
const [oracleAccount, txnObject] = await OracleAccount.createInstructions(
|
||||
program,
|
||||
program.walletPubkey,
|
||||
params
|
||||
);
|
||||
|
||||
const txnSignature = await program.signAndSend(txnObject);
|
||||
|
||||
return [oracleAccount, txnSignature];
|
||||
}
|
||||
|
||||
async stakeInstructions(
|
||||
payer: PublicKey,
|
||||
params: OracleStakeParams & { tokenAccount?: PublicKey }
|
||||
): Promise<TransactionObject> {
|
||||
if (!params.stakeAmount || params.stakeAmount <= 0) {
|
||||
throw new Error(`stake amount should be greater than 0`);
|
||||
}
|
||||
|
||||
const tokenWallet =
|
||||
params.tokenAccount ?? (await this.loadData()).tokenAccount;
|
||||
|
||||
const funderAuthority = params.funderAuthority?.publicKey ?? payer;
|
||||
const funderTokenAccount =
|
||||
this.program.mint.getAssociatedAddress(funderAuthority);
|
||||
const funderTokenAccountInfo = await this.program.connection.getAccountInfo(
|
||||
funderTokenAccount
|
||||
);
|
||||
|
||||
let wrapFundsTxn: TransactionObject;
|
||||
|
||||
if (!funderTokenAccountInfo) {
|
||||
let userTokenAccount: PublicKey;
|
||||
[userTokenAccount, wrapFundsTxn] =
|
||||
await this.program.mint.createWrappedUserInstructions(
|
||||
payer,
|
||||
params.stakeAmount,
|
||||
params.funderAuthority
|
||||
);
|
||||
} else {
|
||||
wrapFundsTxn = await this.program.mint.wrapInstructions(
|
||||
payer,
|
||||
{ amount: params.stakeAmount },
|
||||
params.funderAuthority
|
||||
);
|
||||
}
|
||||
|
||||
wrapFundsTxn.add(
|
||||
spl.createTransferInstruction(
|
||||
funderTokenAccount,
|
||||
tokenWallet,
|
||||
funderAuthority,
|
||||
this.program.mint.toTokenAmount(params.stakeAmount)
|
||||
)
|
||||
);
|
||||
|
||||
return wrapFundsTxn;
|
||||
}
|
||||
|
||||
async stake(
|
||||
params: OracleStakeParams & { tokenAccount?: PublicKey }
|
||||
): Promise<TransactionSignature> {
|
||||
const stakeTxn = await this.stakeInstructions(
|
||||
this.program.walletPubkey,
|
||||
params
|
||||
);
|
||||
const txnSignature = await this.program.signAndSend(stakeTxn);
|
||||
return txnSignature;
|
||||
}
|
||||
|
||||
heartbeatInstruction(
|
||||
|
@ -201,7 +287,7 @@ export class OracleAccount extends Account<types.OracleAccountData> {
|
|||
);
|
||||
}
|
||||
|
||||
async heartbeat(params: {
|
||||
async heartbeat(params?: {
|
||||
queueAccount: QueueAccount;
|
||||
tokenWallet?: PublicKey;
|
||||
queueAuthority?: PublicKey;
|
||||
|
@ -209,23 +295,27 @@ export class OracleAccount extends Account<types.OracleAccountData> {
|
|||
permission?: [PermissionAccount, number];
|
||||
authority?: Keypair;
|
||||
}): Promise<TransactionSignature> {
|
||||
const tokenWallet =
|
||||
params.tokenWallet ?? (await this.loadData()).tokenAccount;
|
||||
const oracle = await this.loadData();
|
||||
const tokenWallet = params?.tokenWallet ?? oracle.tokenAccount;
|
||||
|
||||
const queue = params.queue ?? (await params.queueAccount.loadData());
|
||||
const oracles = await params.queueAccount.loadOracles();
|
||||
const queueAccount =
|
||||
params?.queueAccount ??
|
||||
new QueueAccount(this.program, oracle.queuePubkey);
|
||||
|
||||
const queue = params?.queue ?? (await queueAccount.loadData());
|
||||
const oracles = await queueAccount.loadOracles();
|
||||
|
||||
let lastPubkey = this.publicKey;
|
||||
if (queue.size !== 0) {
|
||||
if (oracles.length !== 0) {
|
||||
lastPubkey = oracles[queue.gcIdx];
|
||||
}
|
||||
|
||||
const [permissionAccount, permissionBump] =
|
||||
params.permission ??
|
||||
params?.permission ??
|
||||
PermissionAccount.fromSeed(
|
||||
this.program,
|
||||
params.queueAuthority ?? queue.authority,
|
||||
params.queueAccount.publicKey,
|
||||
queue.authority,
|
||||
queueAccount.publicKey,
|
||||
this.publicKey
|
||||
);
|
||||
try {
|
||||
|
@ -236,19 +326,29 @@ export class OracleAccount extends Account<types.OracleAccountData> {
|
|||
);
|
||||
}
|
||||
|
||||
if (
|
||||
params?.authority &&
|
||||
!oracle.oracleAuthority.equals(params.authority.publicKey)
|
||||
) {
|
||||
throw new errors.IncorrectAuthority(
|
||||
oracle.oracleAuthority,
|
||||
params.authority.publicKey
|
||||
);
|
||||
}
|
||||
|
||||
const heartbeatTxn = new TransactionObject(
|
||||
this.program.walletPubkey,
|
||||
[
|
||||
this.heartbeatInstruction(this.program.walletPubkey, {
|
||||
tokenWallet: tokenWallet,
|
||||
gcOracle: lastPubkey,
|
||||
oracleQueue: params.queueAccount.publicKey,
|
||||
oracleQueue: queueAccount.publicKey,
|
||||
dataBuffer: queue.dataBuffer,
|
||||
permission: [permissionAccount, permissionBump],
|
||||
authority: params.authority ? params.authority.publicKey : undefined,
|
||||
authority: oracle.oracleAuthority,
|
||||
}),
|
||||
],
|
||||
params.authority ? [params.authority] : []
|
||||
params?.authority ? [params.authority] : []
|
||||
);
|
||||
|
||||
const txnSignature = await this.program.signAndSend(heartbeatTxn);
|
||||
|
@ -357,3 +457,12 @@ export interface OracleInitParams {
|
|||
/** Alternative keypair that will be the authority for the oracle. If not set the payer will be used. */
|
||||
authority?: Keypair;
|
||||
}
|
||||
|
||||
export interface OracleStakeParams {
|
||||
/** The amount of funds to deposit into the oracle's staking wallet. The oracle must have the {@linkcode QueueAccount} minStake before being permitted to heartbeat and join the queue. */
|
||||
stakeAmount?: number;
|
||||
/** The tokenAccount for the account funding the staking wallet. Will default to the payer's associatedTokenAccount if not provided. */
|
||||
funderTokenAccount?: PublicKey;
|
||||
/** The funderTokenAccount authority for approving the transfer of funds from the funderTokenAccount into the oracle staking wallet. Will default to the payer if not provided. */
|
||||
funderAuthority?: Keypair;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,11 @@ import {
|
|||
} from '@solana/web3.js';
|
||||
import * as errors from '../errors';
|
||||
import * as types from '../generated';
|
||||
import {
|
||||
PermitOracleHeartbeat,
|
||||
PermitOracleQueueUsage,
|
||||
PermitVrfRequests,
|
||||
} from '../generated/types/SwitchboardPermission';
|
||||
import { SwitchboardProgram } from '../program';
|
||||
import { TransactionObject } from '../transaction';
|
||||
import { Account } from './account';
|
||||
|
@ -20,6 +25,29 @@ export interface PermissionAccountInitParams {
|
|||
authority: PublicKey;
|
||||
}
|
||||
|
||||
export interface PermitNoneJSON {
|
||||
kind: 'PermitNone';
|
||||
}
|
||||
|
||||
export class PermitNone {
|
||||
static readonly discriminator = 0;
|
||||
static readonly kind = 'NONE';
|
||||
readonly discriminator = 0;
|
||||
readonly kind = 'PermitNone';
|
||||
|
||||
toJSON(): PermitNoneJSON {
|
||||
return {
|
||||
kind: 'PermitNone',
|
||||
};
|
||||
}
|
||||
|
||||
toEncodable() {
|
||||
return {
|
||||
PermitOracleHeartbeat: {},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export interface PermissionSetParams {
|
||||
/** The {@linkcode types.SwitchboardPermission} to set for the grantee. */
|
||||
permission: types.SwitchboardPermissionKind;
|
||||
|
@ -39,6 +67,25 @@ export interface PermissionSetParams {
|
|||
export class PermissionAccount extends Account<types.PermissionAccountData> {
|
||||
static accountName = 'PermissionAccountData';
|
||||
|
||||
static getPermissions(
|
||||
permission: types.PermissionAccountData
|
||||
): types.SwitchboardPermissionKind | PermitNone {
|
||||
switch (permission.permissions) {
|
||||
case 0:
|
||||
return new PermitNone();
|
||||
case 1:
|
||||
return new PermitOracleHeartbeat();
|
||||
case 2:
|
||||
return new PermitOracleQueueUsage();
|
||||
case 3:
|
||||
return new PermitVrfRequests();
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Failed to find the assigned permissions, expected a value from 0 - 3, received ${permission.permissions}`
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a PermissionAccount from the expected PDA seed format.
|
||||
* @param program The Switchboard program for the current connection.
|
||||
|
|
|
@ -24,7 +24,11 @@ import { BufferRelayerAccount, BufferRelayerInit } from './bufferRelayAccount';
|
|||
import { CrankAccount, CrankInitParams } from './crankAccount';
|
||||
import { JobAccount, JobInitParams } from './jobAccount';
|
||||
import { LeaseAccount } from './leaseAccount';
|
||||
import { OracleAccount, OracleInitParams } from './oracleAccount';
|
||||
import {
|
||||
OracleAccount,
|
||||
OracleInitParams,
|
||||
OracleStakeParams,
|
||||
} from './oracleAccount';
|
||||
import { PermissionAccount, PermissionSetParams } from './permissionAccount';
|
||||
import { QueueDataBuffer } from './queueDataBuffer';
|
||||
import { VrfAccount, VrfInitParams } from './vrfAccount';
|
||||
|
@ -274,8 +278,10 @@ export class QueueAccount extends Account<types.OracleQueueAccountData> {
|
|||
public async createOracleInstructions(
|
||||
/** The publicKey of the account that will pay for the new accounts. Will also be used as the account authority if no other authority is provided. */
|
||||
payer: PublicKey,
|
||||
params: OracleInitParams & Partial<Omit<PermissionSetParams, 'permission'>>
|
||||
): Promise<[OracleAccount, TransactionObject]> {
|
||||
params: OracleInitParams &
|
||||
OracleStakeParams &
|
||||
Partial<Omit<PermissionSetParams, 'permission'>>
|
||||
): Promise<[OracleAccount, Array<TransactionObject>]> {
|
||||
const queue = await this.loadData();
|
||||
|
||||
const [oracleAccount, createOracleTxnObject] =
|
||||
|
@ -302,7 +308,10 @@ export class QueueAccount extends Account<types.OracleQueueAccountData> {
|
|||
|
||||
return [
|
||||
oracleAccount,
|
||||
createOracleTxnObject.combine(createPermissionTxnObject),
|
||||
TransactionObject.pack([
|
||||
createOracleTxnObject,
|
||||
createPermissionTxnObject,
|
||||
]),
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -326,8 +335,10 @@ export class QueueAccount extends Account<types.OracleQueueAccountData> {
|
|||
* ```
|
||||
*/
|
||||
public async createOracle(
|
||||
params: OracleInitParams & Partial<Omit<PermissionSetParams, 'permission'>>
|
||||
): Promise<[OracleAccount, TransactionSignature]> {
|
||||
params: OracleInitParams &
|
||||
OracleStakeParams &
|
||||
Partial<Omit<PermissionSetParams, 'permission'>>
|
||||
): Promise<[OracleAccount, Array<TransactionSignature>]> {
|
||||
const signers: Keypair[] = [];
|
||||
|
||||
const queue = await this.loadData();
|
||||
|
@ -344,9 +355,9 @@ export class QueueAccount extends Account<types.OracleQueueAccountData> {
|
|||
params
|
||||
);
|
||||
|
||||
const signature = await this.program.signAndSend(txn);
|
||||
const signatures = await this.program.signAndSendAll(txn);
|
||||
|
||||
return [oracleAccount, signature];
|
||||
return [oracleAccount, signatures];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import * as anchor from '@project-serum/anchor';
|
||||
import { PublicKey } from '@solana/web3.js';
|
||||
|
||||
export class SwitchboardProgramIsBrowserError extends Error {
|
||||
constructor() {
|
||||
|
@ -69,3 +70,11 @@ export class TransactionMissingSignerError extends Error {
|
|||
Object.setPrototypeOf(this, TransactionMissingSignerError.prototype);
|
||||
}
|
||||
}
|
||||
export class IncorrectAuthority extends Error {
|
||||
constructor(expectedAuthority: PublicKey, receivedAuthority: PublicKey) {
|
||||
super(
|
||||
`incorrect authority, expected ${expectedAuthority}, received ${receivedAuthority}`
|
||||
);
|
||||
Object.setPrototypeOf(this, IncorrectAuthority.prototype);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,8 +31,11 @@ export class Mint {
|
|||
return this.provider.connection;
|
||||
}
|
||||
|
||||
public static async load(provider: anchor.AnchorProvider): Promise<Mint> {
|
||||
const splMint = await spl.getMint(provider.connection, Mint.native);
|
||||
public static async load(
|
||||
provider: anchor.AnchorProvider,
|
||||
mint = Mint.native
|
||||
): Promise<Mint> {
|
||||
const splMint = await spl.getMint(provider.connection, mint);
|
||||
return new Mint(provider, splMint);
|
||||
}
|
||||
|
||||
|
@ -84,15 +87,11 @@ export class Mint {
|
|||
return this.fromTokenAmount(userAccount.amount);
|
||||
}
|
||||
|
||||
public getAssociatedAddress(
|
||||
user: anchor.web3.PublicKey
|
||||
): anchor.web3.PublicKey {
|
||||
public getAssociatedAddress(user: PublicKey): PublicKey {
|
||||
return Mint.getAssociatedAddress(user);
|
||||
}
|
||||
|
||||
public static getAssociatedAddress(
|
||||
user: anchor.web3.PublicKey
|
||||
): anchor.web3.PublicKey {
|
||||
public static getAssociatedAddress(user: PublicKey): PublicKey {
|
||||
const [associatedToken] = anchor.utils.publicKey.findProgramAddressSync(
|
||||
[
|
||||
user.toBuffer(),
|
||||
|
@ -107,7 +106,7 @@ export class Mint {
|
|||
public async getOrCreateAssociatedUser(
|
||||
payer: PublicKey,
|
||||
user?: Keypair
|
||||
): Promise<anchor.web3.PublicKey> {
|
||||
): Promise<PublicKey> {
|
||||
const owner = user ? user.publicKey : payer;
|
||||
const associatedToken = Mint.getAssociatedAddress(owner);
|
||||
const accountInfo = await this.connection.getAccountInfo(associatedToken);
|
||||
|
@ -120,9 +119,9 @@ export class Mint {
|
|||
}
|
||||
|
||||
public async createAssocatedUser(
|
||||
payer: anchor.web3.PublicKey,
|
||||
payer: PublicKey,
|
||||
user?: Keypair
|
||||
): Promise<[anchor.web3.PublicKey, string]> {
|
||||
): Promise<[PublicKey, string]> {
|
||||
const [txn, associatedToken] = this.createAssocatedUserInstruction(
|
||||
payer,
|
||||
user
|
||||
|
@ -133,7 +132,7 @@ export class Mint {
|
|||
}
|
||||
|
||||
public static createAssocatedUserInstruction(
|
||||
payer: anchor.web3.PublicKey,
|
||||
payer: PublicKey,
|
||||
user?: Keypair
|
||||
): [TransactionObject, PublicKey] {
|
||||
const owner = user ? user.publicKey : payer;
|
||||
|
@ -184,8 +183,107 @@ export class Mint {
|
|||
return [account, sig];
|
||||
}
|
||||
|
||||
public async wrapInstruction(
|
||||
payer: anchor.web3.PublicKey,
|
||||
public async signAndSend(
|
||||
txn: TransactionObject,
|
||||
opts: anchor.web3.ConfirmOptions = {
|
||||
skipPreflight: false,
|
||||
maxRetries: 10,
|
||||
}
|
||||
): Promise<TransactionSignature> {
|
||||
const blockhash = await this.connection.getLatestBlockhash();
|
||||
const txnSignature = await this.provider.sendAndConfirm(
|
||||
await this.provider.wallet.signTransaction(txn.toTxn(blockhash)),
|
||||
txn.signers,
|
||||
opts
|
||||
);
|
||||
return txnSignature;
|
||||
}
|
||||
}
|
||||
|
||||
export class NativeMint extends Mint {
|
||||
public static async load(
|
||||
provider: anchor.AnchorProvider
|
||||
): Promise<NativeMint> {
|
||||
const splMint = await spl.getMint(provider.connection, Mint.native);
|
||||
return new NativeMint(provider, splMint);
|
||||
}
|
||||
|
||||
public async createWrappedUserInstructions(
|
||||
payer: PublicKey,
|
||||
amount: number,
|
||||
user?: Keypair
|
||||
): Promise<[PublicKey, TransactionObject]> {
|
||||
const owner = user ? user.publicKey : payer;
|
||||
const associatedAddress = this.getAssociatedAddress(owner);
|
||||
const associatedAccountInfo =
|
||||
this.connection.getAccountInfo(associatedAddress);
|
||||
if (!associatedAccountInfo) {
|
||||
throw new Error(
|
||||
`Associated token address already exists for this user ${owner}`
|
||||
);
|
||||
}
|
||||
|
||||
const ephemeralAccount = Keypair.generate();
|
||||
const ephemeralWallet = this.getAssociatedAddress(
|
||||
ephemeralAccount.publicKey
|
||||
);
|
||||
|
||||
const wrapAmountLamports = this.toTokenAmount(amount);
|
||||
|
||||
return [
|
||||
associatedAddress,
|
||||
new TransactionObject(
|
||||
payer,
|
||||
[
|
||||
spl.createAssociatedTokenAccountInstruction(
|
||||
payer,
|
||||
associatedAddress,
|
||||
owner,
|
||||
Mint.native
|
||||
),
|
||||
spl.createAssociatedTokenAccountInstruction(
|
||||
payer,
|
||||
ephemeralWallet,
|
||||
ephemeralAccount.publicKey,
|
||||
spl.NATIVE_MINT
|
||||
),
|
||||
SystemProgram.transfer({
|
||||
fromPubkey: owner,
|
||||
toPubkey: ephemeralWallet,
|
||||
lamports: wrapAmountLamports,
|
||||
}),
|
||||
spl.createSyncNativeInstruction(ephemeralWallet),
|
||||
spl.createTransferInstruction(
|
||||
ephemeralWallet,
|
||||
associatedAddress,
|
||||
ephemeralAccount.publicKey,
|
||||
wrapAmountLamports
|
||||
),
|
||||
spl.createCloseAccountInstruction(
|
||||
ephemeralWallet,
|
||||
owner,
|
||||
ephemeralAccount.publicKey
|
||||
),
|
||||
],
|
||||
user ? [user, ephemeralAccount] : [ephemeralAccount]
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
public async createWrappedUser(
|
||||
payer: PublicKey,
|
||||
amount: number,
|
||||
user?: Keypair
|
||||
): Promise<[PublicKey, TransactionSignature]> {
|
||||
const [tokenAccount, createWrappedUserTxn] =
|
||||
await this.createWrappedUserInstructions(payer, amount, user);
|
||||
const txSignature = await this.signAndSend(createWrappedUserTxn);
|
||||
|
||||
return [tokenAccount, txSignature];
|
||||
}
|
||||
|
||||
public async wrapInstructions(
|
||||
payer: PublicKey,
|
||||
params:
|
||||
| {
|
||||
amount: number;
|
||||
|
@ -193,10 +291,6 @@ export class Mint {
|
|||
| { fundUpTo: Big },
|
||||
user?: Keypair
|
||||
): Promise<TransactionObject> {
|
||||
if (!this.address.equals(Mint.native)) {
|
||||
throw new NativeMintOnlyError();
|
||||
}
|
||||
|
||||
const ixns: TransactionInstruction[] = [];
|
||||
|
||||
const owner = user ? user.publicKey : payer;
|
||||
|
@ -209,16 +303,6 @@ export class Mint {
|
|||
userAccountInfo === null
|
||||
? null
|
||||
: spl.unpackAccount(userAddress, userAccountInfo);
|
||||
// if (userAccount === null) {
|
||||
// ixns.push(
|
||||
// spl.createAssociatedTokenAccountInstruction(
|
||||
// payer,
|
||||
// userAddress,
|
||||
// owner,
|
||||
// Mint.native
|
||||
// )
|
||||
// );
|
||||
// }
|
||||
|
||||
const tokenBalance = userAccount
|
||||
? new Big(this.fromTokenAmount(userAccount.amount))
|
||||
|
@ -283,7 +367,7 @@ export class Mint {
|
|||
}
|
||||
|
||||
public async wrap(
|
||||
payer: anchor.web3.PublicKey,
|
||||
payer: PublicKey,
|
||||
params:
|
||||
| {
|
||||
amount: number;
|
||||
|
@ -291,25 +375,17 @@ export class Mint {
|
|||
| { fundUpTo: Big },
|
||||
user?: Keypair
|
||||
) {
|
||||
if (!this.address.equals(Mint.native)) {
|
||||
throw new NativeMintOnlyError();
|
||||
}
|
||||
|
||||
const wrapIxns = await this.wrapInstruction(payer, params, user);
|
||||
const wrapIxns = await this.wrapInstructions(payer, params, user);
|
||||
const txSignature = await this.signAndSend(wrapIxns);
|
||||
|
||||
return txSignature;
|
||||
}
|
||||
|
||||
public async unwrapInstruction(
|
||||
payer: anchor.web3.PublicKey,
|
||||
public async unwrapInstructions(
|
||||
payer: PublicKey,
|
||||
amount?: number,
|
||||
user?: Keypair
|
||||
): Promise<TransactionObject> {
|
||||
if (!this.address.equals(Mint.native)) {
|
||||
throw new NativeMintOnlyError();
|
||||
}
|
||||
|
||||
const owner = user ? user.publicKey : payer;
|
||||
|
||||
const ixns: TransactionInstruction[] = [];
|
||||
|
@ -359,7 +435,7 @@ export class Mint {
|
|||
}
|
||||
|
||||
public async unwrap(
|
||||
payer: anchor.web3.PublicKey,
|
||||
payer: PublicKey,
|
||||
amount?: number,
|
||||
user?: Keypair
|
||||
): Promise<TransactionSignature> {
|
||||
|
@ -367,24 +443,8 @@ export class Mint {
|
|||
throw new NativeMintOnlyError();
|
||||
}
|
||||
|
||||
const unwrapTxn = await this.unwrapInstruction(payer, amount, user);
|
||||
const unwrapTxn = await this.unwrapInstructions(payer, amount, user);
|
||||
const txSignature = await this.signAndSend(unwrapTxn);
|
||||
return txSignature;
|
||||
}
|
||||
|
||||
private async signAndSend(
|
||||
txn: TransactionObject,
|
||||
opts: anchor.web3.ConfirmOptions = {
|
||||
skipPreflight: false,
|
||||
maxRetries: 10,
|
||||
}
|
||||
): Promise<TransactionSignature> {
|
||||
const blockhash = await this.connection.getLatestBlockhash();
|
||||
const txnSignature = await this.provider.sendAndConfirm(
|
||||
await this.provider.wallet.signTransaction(txn.toTxn(blockhash)),
|
||||
txn.signers,
|
||||
opts
|
||||
);
|
||||
return txnSignature;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,9 +9,12 @@ import {
|
|||
Transaction,
|
||||
TransactionSignature,
|
||||
} from '@solana/web3.js';
|
||||
import { Mint } from './mint';
|
||||
import { types } from './';
|
||||
import { Mint, NativeMint } from './mint';
|
||||
import { TransactionObject } from './transaction';
|
||||
import { SwitchboardEvents } from './switchboardEvents';
|
||||
import { fromCode as fromSwitchboardCode } from './generated/errors/custom';
|
||||
import { fromCode as fromAnchorCode } from './generated/errors/anchor';
|
||||
|
||||
/**
|
||||
* Switchboard Devnet Program ID
|
||||
|
@ -86,7 +89,7 @@ export class SwitchboardProgram {
|
|||
bump: number;
|
||||
};
|
||||
|
||||
readonly mint: Mint;
|
||||
readonly mint: NativeMint;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
|
@ -94,7 +97,7 @@ export class SwitchboardProgram {
|
|||
constructor(
|
||||
program: anchor.Program,
|
||||
cluster: Cluster | 'localnet',
|
||||
mint: Mint
|
||||
mint: NativeMint
|
||||
) {
|
||||
this._program = program;
|
||||
this.cluster = cluster;
|
||||
|
@ -169,7 +172,9 @@ export class SwitchboardProgram {
|
|||
payerKeypair,
|
||||
programId
|
||||
);
|
||||
const mint = await Mint.load(program.provider as anchor.AnchorProvider);
|
||||
const mint = await NativeMint.load(
|
||||
program.provider as anchor.AnchorProvider
|
||||
);
|
||||
return new SwitchboardProgram(program, cluster, mint);
|
||||
};
|
||||
|
||||
|
@ -308,17 +313,37 @@ export class SwitchboardProgram {
|
|||
s.publicKey.equals(txn.payer) || reqSigners.has(s.publicKey.toBase58())
|
||||
);
|
||||
|
||||
const txnSignature = await this.provider.sendAndConfirm(
|
||||
txn.toTxn(blockhash ?? (await this.connection.getLatestBlockhash())),
|
||||
filteredSigners,
|
||||
{
|
||||
skipPreflight: false,
|
||||
maxRetries: 10,
|
||||
...opts,
|
||||
}
|
||||
const transaction = txn.toTxn(
|
||||
blockhash ?? (await this.connection.getLatestBlockhash())
|
||||
);
|
||||
|
||||
return txnSignature;
|
||||
try {
|
||||
const txnSignature = await this.provider.sendAndConfirm(
|
||||
transaction,
|
||||
filteredSigners,
|
||||
{
|
||||
skipPreflight: false,
|
||||
maxRetries: 10,
|
||||
...opts,
|
||||
}
|
||||
);
|
||||
|
||||
return txnSignature;
|
||||
} catch (error) {
|
||||
if ('code' in (error as any) && typeof (error as any).code === 'number') {
|
||||
const switchboardError = fromSwitchboardCode((error as any).code);
|
||||
if (switchboardError) {
|
||||
throw switchboardError;
|
||||
}
|
||||
|
||||
const anchorError = fromAnchorCode((error as any).code);
|
||||
if (anchorError) {
|
||||
throw anchorError;
|
||||
}
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
/* eslint-disable no-unused-vars */
|
||||
import 'mocha';
|
||||
import chai, { expect } from 'chai';
|
||||
import assert from 'assert';
|
||||
|
||||
import * as sbv2 from '../src';
|
||||
import { setupTest, TestContext } from './utilts';
|
||||
|
@ -189,9 +187,8 @@ describe('Aggregator Tests', () => {
|
|||
}
|
||||
const aggregatorAccount = fundedAggregator;
|
||||
|
||||
const initialUserTokenBalance = await ctx.program.mint.getBalance(
|
||||
ctx.payer.publicKey
|
||||
);
|
||||
const initialUserTokenBalance =
|
||||
(await ctx.program.mint.getBalance(ctx.payer.publicKey)) ?? 0;
|
||||
|
||||
const [leaseAccount] = LeaseAccount.fromSeed(
|
||||
ctx.program,
|
||||
|
@ -214,6 +211,13 @@ describe('Aggregator Tests', () => {
|
|||
);
|
||||
}
|
||||
|
||||
const finalUserBalance = await ctx.program.mint.getBalance(
|
||||
ctx.payer.publicKey
|
||||
);
|
||||
if (!finalUserBalance) {
|
||||
throw new Error(`Users wrapped account was closed`);
|
||||
}
|
||||
|
||||
const finalUserTokenBalance =
|
||||
(await ctx.program.mint.getBalance(ctx.payer.publicKey)) ?? 0;
|
||||
if (initialUserTokenBalance !== finalUserTokenBalance) {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import 'mocha';
|
||||
import chai, { expect } from 'chai';
|
||||
import assert from 'assert';
|
||||
|
||||
import { setupTest, TestContext } from './utilts';
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
import 'mocha';
|
||||
import chai, { expect } from 'chai';
|
||||
import assert from 'assert';
|
||||
|
||||
import * as anchor from '@project-serum/anchor';
|
||||
import { setupTest, TestContext } from './utilts';
|
||||
|
|
|
@ -1,10 +1,18 @@
|
|||
import 'mocha';
|
||||
import assert from 'assert';
|
||||
|
||||
import * as sbv2 from '../src';
|
||||
import { setupTest, TestContext } from './utilts';
|
||||
import { Keypair } from '@solana/web3.js';
|
||||
import { AggregatorAccount, OracleAccount, QueueAccount, types } from '../src';
|
||||
import {
|
||||
AggregatorAccount,
|
||||
OracleAccount,
|
||||
PermissionAccount,
|
||||
QueueAccount,
|
||||
types,
|
||||
} from '../src';
|
||||
import { OracleJob } from '@switchboard-xyz/common';
|
||||
import { PermitOracleQueueUsage } from '../src/generated/types/SwitchboardPermission';
|
||||
|
||||
describe('Open Round Tests', () => {
|
||||
let ctx: TestContext;
|
||||
|
@ -15,17 +23,18 @@ describe('Open Round Tests', () => {
|
|||
let queueAccount: QueueAccount;
|
||||
let queue: types.OracleQueueAccountData;
|
||||
|
||||
let createOracleSignature1: string;
|
||||
let createOracleSignature1: string[];
|
||||
let oracleAccount1: OracleAccount;
|
||||
let oracle1: types.OracleAccountData;
|
||||
|
||||
let createOracleSignature2: string;
|
||||
let createOracleSignature2: string[];
|
||||
let oracleAccount2: OracleAccount;
|
||||
let oracle2: types.OracleAccountData;
|
||||
|
||||
let createAggregatorSignatures: string[];
|
||||
let aggregatorAccount: AggregatorAccount;
|
||||
let aggregator: types.AggregatorAccountData;
|
||||
let aggregatorPermissionAccount: PermissionAccount;
|
||||
|
||||
before(async () => {
|
||||
ctx = await setupTest();
|
||||
|
@ -52,6 +61,7 @@ describe('Open Round Tests', () => {
|
|||
name: 'oracle-1',
|
||||
metadata: 'oracle-1',
|
||||
queueAuthority,
|
||||
enable: true,
|
||||
});
|
||||
oracle1 = await oracleAccount1.loadData();
|
||||
|
||||
|
@ -59,18 +69,18 @@ describe('Open Round Tests', () => {
|
|||
name: 'oracle-2',
|
||||
metadata: 'oracle-2',
|
||||
queueAuthority,
|
||||
enable: true,
|
||||
});
|
||||
oracle2 = await oracleAccount2.loadData();
|
||||
|
||||
[aggregatorAccount, createAggregatorSignatures] =
|
||||
await queueAccount.createFeed({
|
||||
queueAuthority: queueAuthority,
|
||||
batchSize: 1,
|
||||
minRequiredOracleResults: 1,
|
||||
batchSize: 2,
|
||||
minRequiredOracleResults: 2,
|
||||
minRequiredJobResults: 1,
|
||||
minUpdateDelaySeconds: 60,
|
||||
minUpdateDelaySeconds: 5,
|
||||
fundAmount: 1,
|
||||
enable: true,
|
||||
enable: false,
|
||||
jobs: [
|
||||
{
|
||||
weight: 2,
|
||||
|
@ -88,5 +98,64 @@ describe('Open Round Tests', () => {
|
|||
},
|
||||
],
|
||||
});
|
||||
|
||||
[aggregatorPermissionAccount] = PermissionAccount.fromSeed(
|
||||
ctx.program,
|
||||
queueAuthority.publicKey,
|
||||
queueAccount.publicKey,
|
||||
aggregatorAccount.publicKey
|
||||
);
|
||||
});
|
||||
|
||||
it('fails to call open round when aggregator lacks permissions', async () => {
|
||||
assert.rejects(
|
||||
async () => {
|
||||
await aggregatorAccount.openRound();
|
||||
},
|
||||
new RegExp(/custom program error: 0x1793/g)
|
||||
// { code: 6035 } // PermissionDenied
|
||||
);
|
||||
});
|
||||
|
||||
it('sets aggregator permissions', async () => {
|
||||
await aggregatorPermissionAccount.set({
|
||||
permission: new PermitOracleQueueUsage(),
|
||||
enable: true,
|
||||
queueAuthority,
|
||||
});
|
||||
const permissions = await aggregatorPermissionAccount.loadData();
|
||||
|
||||
assert(
|
||||
permissions.permissions === PermitOracleQueueUsage.discriminator + 1,
|
||||
`Aggregator has incorrect permissions, expected ${
|
||||
PermitOracleQueueUsage.kind
|
||||
}, received ${PermissionAccount.getPermissions(permissions).kind}`
|
||||
);
|
||||
});
|
||||
|
||||
it('fails to call open round when not enough oracles are heartbeating', async () => {
|
||||
assert.rejects(
|
||||
async () => {
|
||||
await aggregatorAccount.openRound();
|
||||
},
|
||||
new RegExp(/custom program error: 0x17a4/g)
|
||||
// { code: 6052 } // InsufficientOracleQueueError
|
||||
);
|
||||
|
||||
// still fails when queueSize < batchSize
|
||||
await oracleAccount1.heartbeat();
|
||||
assert.rejects(
|
||||
async () => {
|
||||
await aggregatorAccount.openRound();
|
||||
},
|
||||
new RegExp(/custom program error: 0x17a4/g)
|
||||
// { code: 6052 } // InsufficientOracleQueueError
|
||||
);
|
||||
});
|
||||
|
||||
it('successfully calls open round', async () => {
|
||||
await oracleAccount2.heartbeat();
|
||||
// start heartbeating
|
||||
await aggregatorAccount.openRound();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import 'mocha';
|
||||
import chai, { expect } from 'chai';
|
||||
import assert from 'assert';
|
||||
|
||||
import * as sbv2 from '../src';
|
||||
|
@ -46,6 +45,7 @@ describe('Queue Tests', () => {
|
|||
queueAuthority,
|
||||
enable: true,
|
||||
authority: oracleAuthority,
|
||||
stakeAmount: 2,
|
||||
});
|
||||
|
||||
const oracle = await oracleAccount.loadData();
|
||||
|
|
|
@ -58,8 +58,8 @@ export async function setupTest(): Promise<TestContext> {
|
|||
payer.publicKey,
|
||||
1 * LAMPORTS_PER_SOL
|
||||
);
|
||||
await program.connection.confirmTransaction(airdropTxn);
|
||||
console.log(`Airdrop requested: ${airdropTxn}`);
|
||||
await program.connection.confirmTransaction(airdropTxn);
|
||||
}
|
||||
|
||||
// Check if programStateAccount exists
|
||||
|
|
Loading…
Reference in New Issue