Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Anchor.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,4 @@ test-feed = "yarn vitest run test/data-feed.test.ts"
test-minter = "yarn vitest run test/minter-vault.test.ts"
test-redeemer = "yarn vitest run test/redeemer-vault.test.ts"
test-tokens = "yarn vitest run test/mtokens.test.ts"
test-squads= "yarn vitest run test/squads.test.ts"
Binary file added external/squads.so
Binary file not shown.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"@solana/spl-token": "0.4.9",
"@solana/spl-token-metadata": "0.1.6",
"@solana/web3.js": "1.95.4",
"@sqds/multisig": "2.1.4",
"@switchboard-xyz/on-demand": "1.2.54",
"@types/bn.js": "5.1.6",
"anchor-bankrun": "0.5.0",
Expand Down
3 changes: 3 additions & 0 deletions test/constants/squads.constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { PublicKey } from "@solana/web3.js";

export const SQUADS_PROGRAM_ID = new PublicKey('SQDS4ep65T869zMMBKyuUq6aD6EgTu8psMjkvj52pCf');
8 changes: 4 additions & 4 deletions test/data-feed.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ describe('data-feed', () => {
const feedUpdatedAtSlot = 348058928n;

it('when underlying Switchboard feed is valid', async () => {
const fixture = await vaultsFixture(feedUpdatedAtSlot);
const fixture = await vaultsFixture(undefined, feedUpdatedAtSlot);

const feed = await createNewFeed(fixture, {
mode: 'switchboard',
Expand Down Expand Up @@ -512,7 +512,7 @@ describe('data-feed', () => {
});

it('should fail: when underlying Switchboard feed is stale', async () => {
const fixture = await vaultsFixture(feedUpdatedAtSlot + 150n);
const fixture = await vaultsFixture(undefined, feedUpdatedAtSlot + 150n);

const feed = await createNewFeed(fixture, {
mode: 'switchboard',
Expand Down Expand Up @@ -547,7 +547,7 @@ describe('data-feed', () => {
});

it('should fail: when price is > max price', async () => {
const fixture = await vaultsFixture(feedUpdatedAtSlot);
const fixture = await vaultsFixture(undefined, feedUpdatedAtSlot);

const feed = await createNewFeed(fixture, {
mode: 'switchboard',
Expand Down Expand Up @@ -582,7 +582,7 @@ describe('data-feed', () => {
});

it('should fail: when price is < min price', async () => {
const fixture = await vaultsFixture(feedUpdatedAtSlot);
const fixture = await vaultsFixture(undefined, feedUpdatedAtSlot);

const feed = await createNewFeed(fixture, {
mode: 'switchboard',
Expand Down
6 changes: 3 additions & 3 deletions test/fixture/ac.fixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import { AccessControl } from 'target/types/access_control';
import ACCESS_CONTROL_IDL from '../../target/idl/access_control.json' with { type: 'json' };
import { AC_ROLES } from '../constants/ac.constants';
import { acRoleToBuffer, generateAcRoleAccount } from '../helpers/ac.helpers';
import { initBankrun, processTransaction } from '../helpers/common.helpers';
import { initBankrun, InitBankrunReturnType, processTransaction } from '../helpers/common.helpers';
import { generateAcAccount } from '../helpers/vaults.helpers';

export const acFixture = async (initSlot?: bigint) => {
const { provider, context, accounts } = await initBankrun(10, initSlot);
export const acFixture = async (fixture?: InitBankrunReturnType, initSlot?: bigint) => {
const { provider, context, accounts } = fixture ?? await initBankrun(10, initSlot);
const [authority, ...regularAccounts] = accounts;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand Down
6 changes: 3 additions & 3 deletions test/fixture/dafa-feed.fixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import DATA_FEED_IDL from '../../target/idl/data_feed.json' with { type: 'json'
import { AC_ROLES } from '../constants/ac.constants';
import { DATA_FEED_AC_ROLES } from '../constants/data-feed.constants';
import { acRoleToBuffer, getAccountAcRoleStatePda } from '../helpers/ac.helpers';
import { formatUnits, parseUnits, processTransaction, toBN } from '../helpers/common.helpers';
import { formatUnits, InitBankrunReturnType, parseUnits, processTransaction, toBN } from '../helpers/common.helpers';
import {
DataFeedMode,
generateFeedAcccount,
Expand Down Expand Up @@ -65,8 +65,8 @@ const initMockedFeeds = async (context: ProgramTestContext) => {
};
};

export const dataFeedFixture = async (initSlot?: bigint) => {
const acF = await acFixture(initSlot);
export const dataFeedFixture = async (fixture?: InitBankrunReturnType, initSlot?: bigint) => {
const acF = await acFixture(fixture, initSlot);

const {
provider,
Expand Down
138 changes: 138 additions & 0 deletions test/fixture/squads.fixture.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import { Program } from '@coral-xyz/anchor';
import { Keypair, PublicKey, Transaction } from '@solana/web3.js';

import { AccessControl } from 'target/types/access_control';

import ACCESS_CONTROL_IDL from '../../target/idl/access_control.json' with { type: 'json' };
import { AC_ROLES } from '../constants/ac.constants';
import { acRoleToBuffer, generateAcRoleAccount } from '../helpers/ac.helpers';
import { initBankrun, processTransaction } from '../helpers/common.helpers';
import { generateAcAccount } from '../helpers/vaults.helpers';
import { ProgramTestContext } from 'solana-bankrun';
import { DAY } from '../constants/common.constants';
import * as multisig from "@sqds/multisig";
import { SQUADS_PROGRAM_ID } from '../constants/squads.constant';

const createMultisig = async (context: ProgramTestContext, {
authority,
timelock = 2n * DAY,
connection,
member
}: {
authority: Keypair,
member?: PublicKey
timelock?: bigint;
connection: any;
}) => {
const createKey = Keypair.generate();
const [multisigPda] = multisig.getMultisigPda({
createKey: createKey.publicKey,
});

const programConfigPda = multisig.getProgramConfigPda({})[0];

const programConfig =
await multisig.accounts.ProgramConfig.fromAccountAddress(
connection,
programConfigPda
);

const configTreasury = programConfig.treasury;

await processTransaction(context, new Transaction().add(multisig.instructions.multisigCreateV2({
// Must sign the transaction, unless the .rpc method is used.
createKey: createKey.publicKey,
// The creator & fee payer
creator: authority.publicKey,
// The PDA of the multisig you are creating, derived by a random PublicKey
multisigPda,
// Here the config authority will be the system program
configAuthority: null,
// Create without any time-lock
timeLock: Number(timelock),
// List of the members to add to the multisig
members: [{
// Members Public Key
key: member ?? authority.publicKey,
// Granted Proposer, Voter, and Executor permissions
permissions: multisig.types.Permissions.all(),
},

],
// This means that there needs to be 2 votes for a transaction proposal to be approved
threshold: 1,
// This is for the program config treasury account
treasury: configTreasury,
// Rent reclaim account
rentCollector: null
})), [authority, createKey]);

return multisigPda as PublicKey;

}

export const squadsFixture = async (initSlot?: bigint) => {
const { provider, context, accounts } = await initBankrun(10, initSlot, [{
name: 'external/squads',
programId: SQUADS_PROGRAM_ID,
}]);

const [authority, ...regularAccounts] = accounts;


const mockAccounts = [{
data: Buffer.from('xNJa55CVjD92Raz2HiWPdZHPcd7iP2i7V0ot8H6/wFdsT5Tc2zbKegAAAAAAAAAAPpPXMsRIJCeQ0tu1MaQKvRnxbFXjEyz/UnetydaTq1oAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
'base64'),
publicKey: new PublicKey('BSTq9w3kZwNwpBXJEvTZz2G9ZTNyKBvoSeXMvwb4cNZr'),
owner: SQUADS_PROGRAM_ID,
}]

for (const account of mockAccounts) {
context.setAccount(account.publicKey, {
data: account.data,
owner: account.owner,
lamports: 10000,
executable: false
});
}


const multisigPda = await createMultisig(context, {
authority,
connection: provider.connection,
});

const multisigSignerPda = await createMultisig(context, {
authority,
connection: provider.connection,
timelock: 0n
});

const multisigWithSquadsSignerPda = await createMultisig(context, {
authority,
connection: provider.connection,
member: multisigSignerPda
});

const squadsConnection = provider.connection as any;

return {
provider,
context,
authority,
multisigPda,
regularAccounts,
squadsConnection,
accounts,
multisigSignerPda,
multisigWithSquadsSignerPda,
getMutlisigData: async (pda?: PublicKey) => {
return await multisig.accounts.Multisig.fromAccountAddress(
squadsConnection,
pda ?? multisigPda
);
}
};
};

export type SquadsFixtureReturnType = Awaited<ReturnType<typeof squadsFixture>>;
5 changes: 3 additions & 2 deletions test/fixture/vaults.fixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { acRoleToBuffer, getAccountAcRoleStatePda } from '../helpers/ac.helpers'
import {
createMint,
getOrCreateAta,
InitBankrunReturnType,
parseUnits,
processTransaction,
toBN,
Expand All @@ -34,8 +35,8 @@ import {
import { dataFeedFixture } from './dafa-feed.fixture';
import { tokenAuthorityFixture } from './token-authority.fixture';

export const vaultsFixture = async (initSlot?: bigint) => {
const dfFixture = await dataFeedFixture(initSlot);
export const vaultsFixture = async (fixture?: InitBankrunReturnType, initSlot?: bigint) => {
const dfFixture = await dataFeedFixture(fixture, initSlot);
const taFixture = await tokenAuthorityFixture(dfFixture);

const {
Expand Down
38 changes: 30 additions & 8 deletions test/helpers/common.helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@ import {
Signer,
SystemProgram,
Transaction,
VersionedTransaction,
} from '@solana/web3.js';
import { BankrunProvider } from 'anchor-bankrun';
import BN from 'bn.js';
import {
AddedAccount,
AddedProgram,
BanksTransactionMeta,
Clock,
ProgramTestContext,
Expand All @@ -39,6 +41,7 @@ import { MidasVaults } from '@/target/types/midas_vaults';
import { TokenAuthority } from '@/target/types/token_authority';

import { DEFAULT_PUBKEY } from '../constants/common.constants';
import { SQUADS_PROGRAM_ID } from '../constants/squads.constant';
// import { ZERO_ADDRESS } from "test/constants/common.constants";

export interface OptionalCommonParams {
Expand All @@ -57,7 +60,19 @@ export function numToHex(decimalCode: number): string {
return hexCode;
}

export const initBankrun = async (numAccounts = 10, initSlot?: bigint) => {
export type InitBankrunReturnType = {
context: ProgramTestContext;
provider: BankrunProvider;
accounts: Keypair[];
};

let bunrunReturnCache: InitBankrunReturnType | null = null;

export const initBankrun = async (numAccounts = 10, initSlot?: bigint, extraPrograms: AddedProgram[] = []) => {
if (bunrunReturnCache) {
return bunrunReturnCache;
}

const accounts: Keypair[] = [];

const accountsToInject: AddedAccount[] = [];
Expand All @@ -77,19 +92,22 @@ export const initBankrun = async (numAccounts = 10, initSlot?: bigint) => {
});
}

const context = await startAnchor('.', [], [...accountsToInject]);
const context = await startAnchor('.', extraPrograms, [...accountsToInject]);

if (initSlot) {
await warpToSlot(context, initSlot);
}
const provider = new BankrunProvider(context);

anchor.setProvider(provider);

return {
bunrunReturnCache = {
context,
provider,
accounts,
};

return bunrunReturnCache;
};

export const fromBN = (bn?: BN) => {
Expand Down Expand Up @@ -118,7 +136,7 @@ export const findPDA = <TProgram extends Idl | unknown>(

export const expectTxReverted = async (
ctx: ProgramTestContext,
transaction: web3.Transaction,
transaction: Transaction | VersionedTransaction,
signers: (Keypair | Signer)[],
opt?: OptionalCommonParams,
) => {
Expand Down Expand Up @@ -206,7 +224,7 @@ export const expectEvents = async <TProgram extends Idl>(

export const expectTxNotReverted = async (
ctx: ProgramTestContext,
transaction: Transaction,
transaction: Transaction | VersionedTransaction,
signers: (Keypair | Signer)[],
) => {
try {
Expand All @@ -228,7 +246,7 @@ export const warpToSlot = async (ctx: ProgramTestContext, slot: bigint) => {

export const processTransaction = async (
ctx: ProgramTestContext,
transaction: Transaction,
transaction: Transaction | VersionedTransaction,
signers: (Keypair | Signer)[],
) => {
// Need to generate new blockhash
Expand All @@ -238,8 +256,12 @@ export const processTransaction = async (
const blockHash = ctx.lastBlockhash;
const client = ctx.banksClient;

transaction.recentBlockhash = blockHash;
transaction.sign(...signers);
if(transaction instanceof Transaction) {
transaction.recentBlockhash = blockHash;
transaction.sign(...signers);
} else {
transaction.sign([...signers]);
}

return await client.processTransaction(transaction);
};
Expand Down
Loading