test-raydium-sdk-v2
Version:
An SDK for building applications on top of Raydium.
1,097 lines (965 loc) • 33.8 kB
text/typescript
import {
PublicKey,
SystemProgram,
SYSVAR_RENT_PUBKEY,
SYSVAR_CLOCK_PUBKEY,
TransactionInstruction,
Connection,
} from "@solana/web3.js";
import {
createAssociatedTokenAccountInstruction,
TOKEN_PROGRAM_ID,
ASSOCIATED_TOKEN_PROGRAM_ID,
} from "@solana/spl-token";
import BN from "bn.js";
import { struct, u8, u64, u32, bool } from "@/marshmallow";
import { FormatFarmKeyOut } from "@/api/type";
import { getATAAddress } from "@/common/pda";
import { createLogger } from "@/common/logger";
import { parseBigNumberish } from "@/common/bignumber";
import {
accountMeta,
commonSystemAccountMeta,
SOLMint,
RENT_PROGRAM_ID,
INSTRUCTION_PROGRAM_ID,
} from "@/common/pubKey";
import { InstructionType } from "@/common/txTool/txType";
import { InstructionReturn } from "../type";
import {
associatedLedgerAccountLayout,
farmRewardLayout,
withdrawRewardLayout,
farmLedgerLayoutV3_2,
farmAddRewardLayout,
} from "./layout";
import { FarmRewardInfoConfig, RewardInfoKey, RewardType } from "./type";
import {
getRegistrarAddress,
getVotingTokenMint,
getVotingMintAuthority,
getVoterAddress,
getVoterWeightRecordAddress,
getTokenOwnerRecordAddress,
} from "./pda";
import { dwLayout, farmRewardRestartLayout } from "./layout";
import { getAssociatedLedgerAccount, getDepositEntryIndex } from "./util";
import { poolTypeV6 } from "./config";
const logger = createLogger("Raydium_farm_instruction");
const anchorDataBuf = {
voterStakeRegistryCreateVoter: Buffer.from([6, 24, 245, 52, 243, 255, 148, 25]), // CreateVoter
voterStakeRegistryCreateDepositEntry: Buffer.from([185, 131, 167, 186, 159, 125, 19, 67]), // CreateDepositEntry
voterStakeRegistryDeposit: Buffer.from([242, 35, 198, 137, 82, 225, 242, 182]), // Deposit
voterStakeRegistryWithdraw: Buffer.from([183, 18, 70, 156, 148, 109, 161, 34]), // Withdraw
voterStakeRegistryUpdateVoterWeightRecord: Buffer.from([45, 185, 3, 36, 109, 190, 115, 169]), // UpdateVoterWeightRecord
};
export function createAssociatedLedgerAccountInstruction(params: {
version: number;
id: PublicKey;
programId: PublicKey;
ledger: PublicKey;
owner: PublicKey;
}): InstructionReturn {
const { version, id, ledger, programId, owner } = params;
const instruction = { 3: 9, 5: 10 }[version];
if (!instruction) logger.logWithError(`invalid farm pool version: ${version}`);
const data = Buffer.alloc(associatedLedgerAccountLayout.span);
associatedLedgerAccountLayout.encode(
{
instruction: instruction!,
},
data,
);
const keys = [
accountMeta({ pubkey: id }),
accountMeta({ pubkey: ledger }),
accountMeta({ pubkey: owner, isWritable: false }),
accountMeta({ pubkey: SystemProgram.programId, isWritable: false }),
accountMeta({ pubkey: SYSVAR_RENT_PUBKEY, isWritable: false }),
];
return {
instruction: new TransactionInstruction({
programId,
keys,
data,
}),
instructionType: InstructionType.FarmV3CreateLedger,
};
}
interface CreateFarmInstruction {
farmId: PublicKey;
farmAuthority: PublicKey;
lpVault: PublicKey;
lpMint: PublicKey;
lockVault: PublicKey;
lockMint: PublicKey;
lockUserAccount?: PublicKey;
programId: PublicKey;
owner: PublicKey;
rewardInfo: RewardInfoKey[];
rewardInfoConfig: FarmRewardInfoConfig[];
nonce: number;
}
export function makeCreateFarmInstruction(params: CreateFarmInstruction): InstructionReturn {
const data = Buffer.alloc(farmRewardLayout.span);
farmRewardLayout.encode(
{
instruction: 0,
nonce: new BN(params.nonce),
rewardTimeInfo: params.rewardInfoConfig,
},
data,
);
const keys = [
...commonSystemAccountMeta,
accountMeta({ pubkey: params.farmId }),
accountMeta({ pubkey: params.farmAuthority, isWritable: false }),
accountMeta({ pubkey: params.lpVault }),
accountMeta({ pubkey: params.lpMint, isWritable: false }),
accountMeta({ pubkey: params.lockVault }),
accountMeta({ pubkey: params.lockMint, isWritable: false }),
accountMeta({ pubkey: params.lockUserAccount ?? SOLMint }),
accountMeta({ pubkey: params.owner, isWritable: false, isSigner: true }),
];
for (const item of params.rewardInfo) {
keys.push(
...[
accountMeta({ pubkey: item.rewardMint, isWritable: false }),
accountMeta({ pubkey: item.rewardVault }),
accountMeta({ pubkey: item.userRewardToken }),
],
);
}
return {
instruction: new TransactionInstruction({ programId: params.programId, keys, data }),
instructionType: InstructionType.FarmV6Create,
};
}
interface CreatorWithdrawFarmRewardInstruction {
id: PublicKey;
programId: PublicKey;
authority: PublicKey;
lpVault: PublicKey;
rewardVault: PublicKey;
userRewardToken: PublicKey;
owner: PublicKey;
}
export function makeCreatorWithdrawFarmRewardInstruction(
params: CreatorWithdrawFarmRewardInstruction,
): InstructionReturn {
const data = Buffer.alloc(withdrawRewardLayout.span);
withdrawRewardLayout.encode({ instruction: 5 }, data);
const keys = [
accountMeta({ pubkey: TOKEN_PROGRAM_ID, isWritable: false }),
accountMeta({ pubkey: params.id }),
accountMeta({ pubkey: params.authority, isWritable: false }),
accountMeta({ pubkey: params.lpVault, isWritable: false }),
accountMeta({ pubkey: params.rewardVault }),
accountMeta({ pubkey: params.userRewardToken }),
accountMeta({ pubkey: params.owner, isWritable: false, isSigner: true }),
];
return {
instruction: new TransactionInstruction({ programId: params.programId, keys, data }),
instructionType: InstructionType.FarmV6CreatorWithdraw,
};
}
export function voterStakeRegistryDeposit(
programId: PublicKey,
registrar: PublicKey,
voter: PublicKey,
voterVault: PublicKey,
depositToken: PublicKey,
depositAuthority: PublicKey,
userStakerInfoV2: PublicKey,
pool: PublicKey,
votingMint: PublicKey,
votingMintAuthority: PublicKey,
stakeProgramId: PublicKey,
depositEntryIndex: number,
amount: BN,
): TransactionInstruction {
const dataLayout = struct([u8("depositEntryIndex"), u64("amount")]);
const keys = [
{ pubkey: registrar, isSigner: false, isWritable: false },
{ pubkey: voter, isSigner: false, isWritable: true },
{ pubkey: voterVault, isSigner: false, isWritable: true },
{ pubkey: depositToken, isSigner: false, isWritable: true },
{ pubkey: depositAuthority, isSigner: false, isWritable: false },
{ pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
{ pubkey: userStakerInfoV2, isSigner: false, isWritable: true },
{ pubkey: pool, isSigner: false, isWritable: false },
{ pubkey: votingMint, isSigner: false, isWritable: true },
{ pubkey: votingMintAuthority, isSigner: false, isWritable: false },
{ pubkey: stakeProgramId, isSigner: false, isWritable: false },
{ pubkey: INSTRUCTION_PROGRAM_ID, isSigner: false, isWritable: false },
];
const data = Buffer.alloc(dataLayout.span);
dataLayout.encode(
{
depositEntryIndex,
amount,
},
data,
);
const aData = Buffer.from([...anchorDataBuf.voterStakeRegistryDeposit, ...data]);
return new TransactionInstruction({
keys,
programId,
data: aData,
});
}
export function voterStakeRegistryUpdateVoterWeightRecord(
programId: PublicKey,
registrar: PublicKey,
voter: PublicKey,
voterWeightRecord: PublicKey,
): TransactionInstruction {
const dataLayout = struct([]);
const keys = [
{ pubkey: registrar, isSigner: false, isWritable: false },
{ pubkey: voter, isSigner: false, isWritable: false },
{ pubkey: voterWeightRecord, isSigner: false, isWritable: true },
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
];
const data = Buffer.alloc(dataLayout.span);
dataLayout.encode({}, data);
const aData = Buffer.from([...anchorDataBuf.voterStakeRegistryUpdateVoterWeightRecord, ...data]);
return new TransactionInstruction({
keys,
programId,
data: aData,
});
}
export function voterStakeRegistryWithdraw(
programId: PublicKey,
registrar: PublicKey,
voter: PublicKey,
voterAuthority: PublicKey,
tokenOwnerRecord: PublicKey,
voterWeightRecord: PublicKey,
vault: PublicKey,
destination: PublicKey,
userStakerInfoV2: PublicKey,
pool: PublicKey,
votingMint: PublicKey,
votingMintAuthority: PublicKey,
stakeProgramId: PublicKey,
depositEntryIndex: number,
amount: BN,
): TransactionInstruction {
const dataLayout = struct([u8("depositEntryIndex"), u64("amount")]);
const keys = [
{ pubkey: registrar, isSigner: false, isWritable: false },
{ pubkey: voter, isSigner: false, isWritable: true },
{ pubkey: voterAuthority, isSigner: true, isWritable: false },
{ pubkey: tokenOwnerRecord, isSigner: false, isWritable: false },
{ pubkey: voterWeightRecord, isSigner: false, isWritable: true },
{ pubkey: vault, isSigner: false, isWritable: true },
{ pubkey: destination, isSigner: false, isWritable: true },
{ pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
{ pubkey: userStakerInfoV2, isSigner: false, isWritable: true },
{ pubkey: pool, isSigner: false, isWritable: false },
{ pubkey: votingMint, isSigner: false, isWritable: true },
{ pubkey: votingMintAuthority, isSigner: false, isWritable: false },
{ pubkey: stakeProgramId, isSigner: false, isWritable: false },
{ pubkey: INSTRUCTION_PROGRAM_ID, isSigner: false, isWritable: false },
];
const data = Buffer.alloc(dataLayout.span);
dataLayout.encode(
{
depositEntryIndex,
amount,
},
data,
);
const aData = Buffer.from([...anchorDataBuf.voterStakeRegistryWithdraw, ...data]);
return new TransactionInstruction({
keys,
programId,
data: aData,
});
}
export function governanceCreateTokenOwnerRecord(
programId: PublicKey,
realm: PublicKey,
governingTokenOwner: PublicKey,
governingTokenMint: PublicKey,
payer: PublicKey,
tokenOwnerRecordAddress: PublicKey,
): TransactionInstruction {
const dataLayout = struct([u8("ins")]);
const keys = [
{ pubkey: realm, isSigner: false, isWritable: false },
{ pubkey: governingTokenOwner, isSigner: false, isWritable: false },
{ pubkey: tokenOwnerRecordAddress, isSigner: false, isWritable: true },
{ pubkey: governingTokenMint, isSigner: false, isWritable: false },
{ pubkey: payer, isSigner: true, isWritable: true },
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
];
const data = Buffer.alloc(dataLayout.span);
dataLayout.encode({ ins: 23 }, data);
return new TransactionInstruction({
keys,
programId,
data,
});
}
export function voterStakeRegistryCreateVoter(
programId: PublicKey,
registrar: PublicKey,
voter: PublicKey,
voterWeightRecord: PublicKey,
voterAuthority: PublicKey,
payer: PublicKey,
voterBump: number,
voterWeightRecordBump: number,
): TransactionInstruction {
const dataLayout = struct([u8("voterBump"), u8("voterWeightRecordBump")]);
const keys = [
{ pubkey: registrar, isSigner: false, isWritable: false },
{ pubkey: voter, isSigner: false, isWritable: true },
{ pubkey: voterAuthority, isSigner: true, isWritable: false },
{ pubkey: voterWeightRecord, isSigner: false, isWritable: true },
{ pubkey: payer, isSigner: true, isWritable: true },
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
{ pubkey: RENT_PROGRAM_ID, isSigner: false, isWritable: false },
{ pubkey: INSTRUCTION_PROGRAM_ID, isSigner: false, isWritable: false },
];
const data = Buffer.alloc(dataLayout.span);
dataLayout.encode({ voterBump, voterWeightRecordBump }, data);
const aData = Buffer.from([...anchorDataBuf.voterStakeRegistryCreateVoter, ...data]);
return new TransactionInstruction({
keys,
programId,
data: aData,
});
}
export function voterStakeRegistryCreateDepositEntry(
programId: PublicKey,
registrar: PublicKey,
voter: PublicKey,
voterVault: PublicKey,
voterAuthority: PublicKey,
payer: PublicKey,
depositMint: PublicKey,
depositEntryIndex: number,
kind: number,
startTs: BN | undefined,
periods: number,
allowClawback: boolean,
): TransactionInstruction {
const dataLayout = struct([
u8("depositEntryIndex"),
u8("kind"),
u8("option"),
u64("startTs"),
u32("periods"),
bool("allowClawback"),
]);
const keys = [
{ pubkey: registrar, isSigner: false, isWritable: false },
{ pubkey: voter, isSigner: false, isWritable: true },
{ pubkey: voterVault, isSigner: false, isWritable: true },
{ pubkey: voterAuthority, isSigner: true, isWritable: false },
{ pubkey: payer, isSigner: true, isWritable: true },
{ pubkey: depositMint, isSigner: false, isWritable: false },
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
{ pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
{ pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
{ pubkey: RENT_PROGRAM_ID, isSigner: false, isWritable: false },
];
const data = Buffer.alloc(dataLayout.span);
dataLayout.encode(
{
depositEntryIndex,
kind,
option: startTs === undefined ? 0 : 1,
startTs: startTs!,
periods,
allowClawback,
},
data,
);
const aData = Buffer.from([...anchorDataBuf.voterStakeRegistryCreateDepositEntry, ...data]);
return new TransactionInstruction({
keys,
programId,
data: aData,
});
}
export async function makeDepositTokenInstruction({
connection,
programId,
governanceProgramId,
voteWeightAddinProgramId,
realm,
communityTokenMint,
owner,
poolId,
tokenProgram,
}: {
connection: Connection;
programId: PublicKey;
governanceProgramId: PublicKey;
voteWeightAddinProgramId: PublicKey;
realm: PublicKey;
communityTokenMint: PublicKey;
owner: PublicKey;
poolId: PublicKey;
tokenProgram?: PublicKey;
}): Promise<TransactionInstruction[]> {
const registrar = getRegistrarAddress(voteWeightAddinProgramId, realm, communityTokenMint).publicKey;
const ownerPda = getAssociatedLedgerAccount({ programId, poolId, owner, version: 3 });
const ownerAccountInfo = await connection.getAccountInfo(ownerPda);
if (ownerAccountInfo === null) {
throw Error("user is not staker");
}
const ownerInfo = farmLedgerLayoutV3_2.decode(ownerAccountInfo.data);
const mintAmount = ownerInfo.deposited.sub(ownerInfo.voteLockedBalance);
console.log("amount", mintAmount.toString());
if (mintAmount.eq(new BN(0))) {
throw Error("user do not has new stake amount");
}
const votingMint = getVotingTokenMint(programId, poolId).publicKey;
const votingMintAuthority = getVotingMintAuthority(programId, poolId).publicKey;
const { publicKey: voter, nonce: voterBump } = getVoterAddress(voteWeightAddinProgramId, registrar, owner);
const voterVault = getATAAddress(voter, votingMint, tokenProgram).publicKey;
const { publicKey: voterWeightRecord, nonce: voterWeightRecordBump } = getVoterWeightRecordAddress(
voteWeightAddinProgramId,
registrar,
owner,
);
const tokenOwnerRecordAddress = getTokenOwnerRecordAddress(
governanceProgramId,
realm,
communityTokenMint,
owner,
).publicKey;
const instructions: TransactionInstruction[] = [];
const depositToken = getATAAddress(owner, votingMint, tokenProgram).publicKey;
const depositTokenAccountInfo = await connection.getAccountInfo(depositToken);
if (depositTokenAccountInfo === null) {
instructions.push(createAssociatedTokenAccountInstruction(owner, depositToken, owner, votingMint));
}
const voterAccountInfo = await connection.getAccountInfo(voter);
if (voterAccountInfo === null) {
const createTokenOwnerRecodeIns = governanceCreateTokenOwnerRecord(
governanceProgramId,
realm,
owner,
communityTokenMint,
owner,
tokenOwnerRecordAddress,
);
instructions.push(
createTokenOwnerRecodeIns,
voterStakeRegistryCreateVoter(
voteWeightAddinProgramId,
registrar,
voter,
voterWeightRecord,
owner,
owner,
voterBump,
voterWeightRecordBump,
),
);
}
const { index: depositEntryIndex, isInit: depositEntryInit } = await getDepositEntryIndex(
connection,
registrar,
voter,
votingMint,
);
if (!depositEntryInit) {
instructions.push(
voterStakeRegistryCreateDepositEntry(
voteWeightAddinProgramId,
registrar,
voter,
voterVault,
owner,
owner,
votingMint,
depositEntryIndex,
0,
undefined,
0,
false,
),
);
}
instructions.push(
voterStakeRegistryDeposit(
voteWeightAddinProgramId,
registrar,
voter,
voterVault,
depositToken,
owner,
ownerPda,
poolId,
votingMint,
votingMintAuthority,
programId,
depositEntryIndex,
mintAmount,
),
voterStakeRegistryUpdateVoterWeightRecord(voteWeightAddinProgramId, registrar, voter, voterWeightRecord),
);
return instructions;
}
export async function makeWithdrawTokenInstruction({
connection,
programId,
governanceProgramId,
voteWeightAddinProgramId,
realm,
communityTokenMint,
owner,
poolId,
tokenProgram,
}: {
connection: Connection;
programId: PublicKey;
governanceProgramId: PublicKey;
voteWeightAddinProgramId: PublicKey;
realm: PublicKey;
communityTokenMint: PublicKey;
owner: PublicKey;
poolId: PublicKey;
tokenProgram?: PublicKey;
}): Promise<TransactionInstruction[]> {
const registrar = getRegistrarAddress(voteWeightAddinProgramId, realm, communityTokenMint).publicKey;
const ownerPda = getAssociatedLedgerAccount({ programId, poolId, owner, version: 3 });
const ownerAccountInfo = await connection.getAccountInfo(ownerPda);
if (ownerAccountInfo === null) {
throw Error("user is not staker");
}
const ownerInfo = farmLedgerLayoutV3_2.decode(ownerAccountInfo.data);
if (ownerInfo.voteLockedBalance.eq(new BN(0))) {
throw Error("user has vote locked balance = 0");
}
const votingMint = getVotingTokenMint(programId, poolId).publicKey;
const votingMintAuthority = getVotingMintAuthority(programId, poolId).publicKey;
const { publicKey: voter } = getVoterAddress(voteWeightAddinProgramId, registrar, owner);
const voterVault = getATAAddress(voter, votingMint, tokenProgram).publicKey;
const { publicKey: voterWeightRecord } = getVoterWeightRecordAddress(voteWeightAddinProgramId, registrar, owner);
const tokenOwnerRecordAddress = getTokenOwnerRecordAddress(
governanceProgramId,
realm,
communityTokenMint,
owner,
).publicKey;
const instructions: TransactionInstruction[] = [];
const { index: depositEntryIndex, isInit: depositEntryInit } = await getDepositEntryIndex(
connection,
registrar,
voter,
votingMint,
);
if (!depositEntryInit) throw Error("deposit entry index check error");
instructions.push(
voterStakeRegistryWithdraw(
voteWeightAddinProgramId,
registrar,
voter,
owner,
tokenOwnerRecordAddress,
voterWeightRecord,
voterVault,
getATAAddress(owner, votingMint, tokenProgram).publicKey,
ownerPda,
poolId,
votingMint,
votingMintAuthority,
programId,
depositEntryIndex,
ownerInfo.voteLockedBalance,
),
);
return instructions;
}
export function makeRestartRewardInstruction({
payer,
rewardVault,
userRewardTokenPub,
farmKeys,
rewardInfo,
}: {
payer: PublicKey;
rewardVault: PublicKey;
userRewardTokenPub: PublicKey;
farmKeys: {
id: PublicKey;
programId: PublicKey;
lpVault: PublicKey;
};
rewardInfo: {
openTime: number;
endTime: number;
perSecond: string;
};
}): TransactionInstruction {
const data = Buffer.alloc(farmRewardRestartLayout.span);
farmRewardRestartLayout.encode(
{
instruction: 3,
rewardReopenTime: parseBigNumberish(rewardInfo.openTime),
rewardEndTime: parseBigNumberish(rewardInfo.endTime),
rewardPerSecond: parseBigNumberish(rewardInfo.perSecond),
},
data,
);
const keys = [
accountMeta({ pubkey: TOKEN_PROGRAM_ID, isWritable: false }),
accountMeta({ pubkey: farmKeys.id }),
accountMeta({ pubkey: farmKeys.lpVault, isWritable: false }),
accountMeta({ pubkey: rewardVault }),
accountMeta({ pubkey: userRewardTokenPub! }),
accountMeta({ pubkey: payer, isWritable: false, isSigner: true }),
];
return new TransactionInstruction({ programId: farmKeys.programId, keys, data });
}
export function makeAddNewRewardInstruction({
payer,
userRewardTokenPub,
farmKeys,
rewardVault,
rewardInfo,
}: {
payer: PublicKey;
userRewardTokenPub: PublicKey;
rewardVault: PublicKey;
farmKeys: {
id: PublicKey;
programId: PublicKey;
authority: PublicKey;
};
rewardInfo: {
mint: PublicKey;
openTime: number;
endTime: number;
perSecond: string;
rewardType: RewardType;
};
}): TransactionInstruction {
const data = Buffer.alloc(farmAddRewardLayout.span);
farmAddRewardLayout.encode(
{
instruction: 4,
isSet: new BN(1),
rewardPerSecond: parseBigNumberish(rewardInfo.perSecond),
rewardOpenTime: parseBigNumberish(rewardInfo.openTime),
rewardEndTime: parseBigNumberish(rewardInfo.endTime),
rewardType: parseBigNumberish(poolTypeV6[rewardInfo.rewardType]),
},
data,
);
const keys = [
...commonSystemAccountMeta,
accountMeta({ pubkey: farmKeys.id }),
accountMeta({ pubkey: farmKeys.authority, isWritable: false }),
accountMeta({ pubkey: rewardInfo.mint, isWritable: false }),
accountMeta({ pubkey: rewardVault }),
accountMeta({ pubkey: userRewardTokenPub! }),
accountMeta({ pubkey: payer, isWritable: false, isSigner: true }),
];
return new TransactionInstruction({ programId: farmKeys.programId, keys, data });
}
export function makeDepositWithdrawInstruction(params: {
instruction: number;
amount: BN;
farmInfo: { id: string; programId: string };
farmKeys: FormatFarmKeyOut;
lpAccount: PublicKey;
owner: PublicKey;
rewardAccounts: PublicKey[];
deposit?: boolean;
version: 3 | 5 | 6;
}): TransactionInstruction {
const { farmInfo, farmKeys, version, lpAccount, rewardAccounts, owner, instruction, amount, deposit } = params;
const [programId, id] = [new PublicKey(farmInfo.programId), new PublicKey(farmInfo.id)];
const ledgerAddress = getAssociatedLedgerAccount({
programId,
poolId: id,
owner,
version,
});
const data = Buffer.alloc(dwLayout.span);
dwLayout.encode(
{
instruction,
amount,
},
data,
);
const keys =
version === 6
? [
accountMeta({ pubkey: TOKEN_PROGRAM_ID, isWritable: false }),
...(deposit ? [accountMeta({ pubkey: SystemProgram.programId, isWritable: false })] : []),
accountMeta({ pubkey: id }),
accountMeta({ pubkey: new PublicKey(farmKeys.authority), isWritable: false }),
accountMeta({ pubkey: new PublicKey(farmKeys.lpVault) }),
accountMeta({ pubkey: ledgerAddress }),
accountMeta({ pubkey: owner, isWritable: false, isSigner: true }),
accountMeta({ pubkey: lpAccount }),
]
: [
accountMeta({ pubkey: id }),
accountMeta({ pubkey: new PublicKey(farmKeys.authority), isWritable: false }),
accountMeta({ pubkey: ledgerAddress }),
accountMeta({ pubkey: owner, isWritable: false, isSigner: true }),
accountMeta({ pubkey: lpAccount }),
accountMeta({ pubkey: new PublicKey(farmKeys.lpVault) }),
accountMeta({ pubkey: rewardAccounts[0] }),
accountMeta({ pubkey: new PublicKey(farmKeys.rewardInfos[0].vault) }),
// system
accountMeta({ pubkey: SYSVAR_CLOCK_PUBKEY, isWritable: false }),
accountMeta({ pubkey: TOKEN_PROGRAM_ID, isWritable: false }),
];
if (version === 5) {
for (let index = 1; index < farmKeys.rewardInfos.length; index++) {
keys.push(accountMeta({ pubkey: rewardAccounts[index] }));
keys.push(accountMeta({ pubkey: new PublicKey(farmKeys.rewardInfos[index].vault) }));
}
}
if (version === 6) {
for (let index = 0; index < farmKeys.rewardInfos.length; index++) {
keys.push(accountMeta({ pubkey: new PublicKey(farmKeys.rewardInfos[index].vault) }));
keys.push(accountMeta({ pubkey: rewardAccounts[index] }));
}
}
return new TransactionInstruction({ programId, keys, data });
}
interface DepositWithdrawParams {
amount: BN;
farmInfo: { id: string; programId: string };
farmKeys: FormatFarmKeyOut;
lpAccount: PublicKey;
owner: PublicKey;
rewardAccounts: PublicKey[];
userAuxiliaryLedgers?: PublicKey[];
}
export function makeWithdrawInstructionV6(params: DepositWithdrawParams): TransactionInstruction {
const { farmInfo, farmKeys, lpAccount, rewardAccounts, owner, amount } = params;
const [programId, id] = [new PublicKey(farmInfo.programId), new PublicKey(farmInfo.id)];
const ledgerAddress = getAssociatedLedgerAccount({
programId,
poolId: id,
owner,
version: 6,
});
const data = Buffer.alloc(dwLayout.span);
dwLayout.encode(
{
instruction: 2,
amount: parseBigNumberish(amount),
},
data,
);
const keys = [
accountMeta({ pubkey: TOKEN_PROGRAM_ID, isWritable: false }),
accountMeta({ pubkey: id }),
accountMeta({ pubkey: new PublicKey(farmKeys.authority), isWritable: false }),
accountMeta({ pubkey: new PublicKey(farmKeys.lpVault) }),
accountMeta({ pubkey: ledgerAddress }),
accountMeta({ pubkey: owner, isWritable: false, isSigner: true }),
accountMeta({ pubkey: lpAccount }),
];
for (let index = 0; index < farmKeys.rewardInfos.length; index++) {
keys.push(accountMeta({ pubkey: new PublicKey(farmKeys.rewardInfos[index].vault) }));
keys.push(accountMeta({ pubkey: rewardAccounts[index] }));
}
return new TransactionInstruction({ programId, keys, data });
}
export function makeWithdrawInstructionV5(params: DepositWithdrawParams): TransactionInstruction {
const { farmInfo, farmKeys, lpAccount, rewardAccounts, owner, amount, userAuxiliaryLedgers } = params;
const [programId, id] = [new PublicKey(farmInfo.programId), new PublicKey(farmInfo.id)];
const ledgerAddress = getAssociatedLedgerAccount({
programId,
poolId: id,
owner,
version: 5,
});
const data = Buffer.alloc(dwLayout.span);
dwLayout.encode(
{
instruction: 12,
amount: parseBigNumberish(amount),
},
data,
);
const keys = [
accountMeta({ pubkey: id }),
accountMeta({ pubkey: new PublicKey(farmKeys.authority), isWritable: false }),
accountMeta({ pubkey: ledgerAddress }),
accountMeta({ pubkey: owner, isWritable: false, isSigner: true }),
accountMeta({ pubkey: lpAccount }),
accountMeta({ pubkey: new PublicKey(farmKeys.lpVault) }),
accountMeta({ pubkey: rewardAccounts[0] }),
accountMeta({ pubkey: new PublicKey(farmKeys.rewardInfos[0].vault) }),
// system
accountMeta({ pubkey: SYSVAR_CLOCK_PUBKEY, isWritable: false }),
accountMeta({ pubkey: TOKEN_PROGRAM_ID, isWritable: false }),
];
for (let index = 1; index < farmKeys.rewardInfos.length; index++) {
keys.push(accountMeta({ pubkey: rewardAccounts[index] }));
keys.push(accountMeta({ pubkey: new PublicKey(farmKeys.rewardInfos[index].vault) }));
}
if (userAuxiliaryLedgers) {
for (const auxiliaryLedger of userAuxiliaryLedgers) {
keys.push(accountMeta({ pubkey: auxiliaryLedger }));
}
}
return new TransactionInstruction({ programId, keys, data });
}
export function makeWithdrawInstructionV3(params: DepositWithdrawParams): TransactionInstruction {
const { farmInfo, farmKeys, lpAccount, rewardAccounts, owner, amount, userAuxiliaryLedgers } = params;
const [programId, id] = [new PublicKey(farmInfo.programId), new PublicKey(farmInfo.id)];
const ledgerAddress = getAssociatedLedgerAccount({
programId,
poolId: id,
owner,
version: 3,
});
const data = Buffer.alloc(dwLayout.span);
dwLayout.encode(
{
instruction: 11,
amount: parseBigNumberish(amount),
},
data,
);
const keys = [
accountMeta({ pubkey: id }),
accountMeta({ pubkey: new PublicKey(farmKeys.authority), isWritable: false }),
accountMeta({ pubkey: ledgerAddress }),
accountMeta({ pubkey: owner, isWritable: false, isSigner: true }),
accountMeta({ pubkey: lpAccount }),
accountMeta({ pubkey: new PublicKey(farmKeys.lpVault) }),
accountMeta({ pubkey: rewardAccounts[0] }),
accountMeta({ pubkey: new PublicKey(farmKeys.rewardInfos[0].vault) }),
// system
accountMeta({ pubkey: SYSVAR_CLOCK_PUBKEY, isWritable: false }),
accountMeta({ pubkey: TOKEN_PROGRAM_ID, isWritable: false }),
];
if (userAuxiliaryLedgers) {
for (const auxiliaryLedger of userAuxiliaryLedgers) {
keys.push(accountMeta({ pubkey: auxiliaryLedger }));
}
}
return new TransactionInstruction({ programId, keys, data });
}
export function makeDepositInstructionV3(params: DepositWithdrawParams): TransactionInstruction {
const { farmInfo, farmKeys, lpAccount, rewardAccounts, owner, amount, userAuxiliaryLedgers } = params;
const [programId, id] = [new PublicKey(farmInfo.programId), new PublicKey(farmInfo.id)];
const ledgerAddress = getAssociatedLedgerAccount({
programId,
poolId: id,
owner,
version: 3,
});
const data = Buffer.alloc(dwLayout.span);
dwLayout.encode(
{
instruction: 10,
amount: parseBigNumberish(amount),
},
data,
);
const keys = [
accountMeta({ pubkey: id }),
accountMeta({ pubkey: new PublicKey(farmKeys.authority), isWritable: false }),
accountMeta({ pubkey: ledgerAddress }),
accountMeta({ pubkey: owner, isWritable: false, isSigner: true }),
accountMeta({ pubkey: lpAccount }),
accountMeta({ pubkey: new PublicKey(farmKeys.lpVault) }),
accountMeta({ pubkey: rewardAccounts[0] }),
accountMeta({ pubkey: new PublicKey(farmKeys.rewardInfos[0].vault) }),
// system
accountMeta({ pubkey: SYSVAR_CLOCK_PUBKEY, isWritable: false }),
accountMeta({ pubkey: TOKEN_PROGRAM_ID, isWritable: false }),
];
if (userAuxiliaryLedgers) {
for (const auxiliaryLedger of userAuxiliaryLedgers) {
keys.push(accountMeta({ pubkey: auxiliaryLedger }));
}
}
return new TransactionInstruction({ programId, keys, data });
}
export function makeDepositInstructionV5(params: DepositWithdrawParams): TransactionInstruction {
const { farmInfo, farmKeys, lpAccount, rewardAccounts, owner, amount, userAuxiliaryLedgers } = params;
const [programId, id] = [new PublicKey(farmInfo.programId), new PublicKey(farmInfo.id)];
const ledgerAddress = getAssociatedLedgerAccount({
programId,
poolId: id,
owner,
version: 5,
});
const data = Buffer.alloc(dwLayout.span);
dwLayout.encode(
{
instruction: 11,
amount: parseBigNumberish(amount),
},
data,
);
const keys = [
accountMeta({ pubkey: id }),
accountMeta({ pubkey: new PublicKey(farmKeys.authority), isWritable: false }),
accountMeta({ pubkey: ledgerAddress }),
accountMeta({ pubkey: owner, isWritable: false, isSigner: true }),
accountMeta({ pubkey: lpAccount }),
accountMeta({ pubkey: new PublicKey(farmKeys.lpVault) }),
accountMeta({ pubkey: rewardAccounts[0] }),
accountMeta({ pubkey: new PublicKey(farmKeys.rewardInfos[0].vault) }),
// system
accountMeta({ pubkey: SYSVAR_CLOCK_PUBKEY, isWritable: false }),
accountMeta({ pubkey: TOKEN_PROGRAM_ID, isWritable: false }),
];
for (let index = 1; index < farmKeys.rewardInfos.length; index++) {
keys.push(accountMeta({ pubkey: rewardAccounts[index] }));
keys.push(accountMeta({ pubkey: new PublicKey(farmKeys.rewardInfos[index].vault) }));
}
if (userAuxiliaryLedgers) {
for (const auxiliaryLedger of userAuxiliaryLedgers) {
keys.push(accountMeta({ pubkey: auxiliaryLedger }));
}
}
return new TransactionInstruction({ programId, keys, data });
}
export function makeDepositInstructionV6(params: DepositWithdrawParams): TransactionInstruction {
const { farmInfo, farmKeys, lpAccount, rewardAccounts, owner, amount } = params;
const [programId, id] = [new PublicKey(farmInfo.programId), new PublicKey(farmInfo.id)];
const ledgerAddress = getAssociatedLedgerAccount({
programId,
poolId: id,
owner,
version: 6,
});
const data = Buffer.alloc(dwLayout.span);
dwLayout.encode(
{
instruction: 1,
amount: parseBigNumberish(amount),
},
data,
);
const keys = [
accountMeta({ pubkey: TOKEN_PROGRAM_ID, isWritable: false }),
accountMeta({ pubkey: SystemProgram.programId, isWritable: false }),
accountMeta({ pubkey: id }),
accountMeta({ pubkey: new PublicKey(farmKeys.authority), isWritable: false }),
accountMeta({ pubkey: new PublicKey(farmKeys.lpVault) }),
accountMeta({ pubkey: ledgerAddress }),
accountMeta({ pubkey: owner, isWritable: false, isSigner: true }),
accountMeta({ pubkey: lpAccount }),
];
for (let index = 0; index < farmKeys.rewardInfos.length; index++) {
keys.push(accountMeta({ pubkey: new PublicKey(farmKeys.rewardInfos[index].vault) }));
keys.push(accountMeta({ pubkey: rewardAccounts[index] }));
}
return new TransactionInstruction({ programId, keys, data });
}