diff --git a/ts-client/src/farm.ts b/ts-client/src/farm.ts index 9b51766..46a789b 100644 --- a/ts-client/src/farm.ts +++ b/ts-client/src/farm.ts @@ -7,9 +7,11 @@ import { PublicKey, Transaction, TransactionInstruction, + SYSVAR_CLOCK_PUBKEY, + ParsedAccountData, } from "@solana/web3.js"; -import { FarmProgram, Opt, PoolState, UserState } from "./types"; +import { FarmProgram, Opt, PoolState, UserState, ParsedClockState } from "./types"; import { chunks, getFarmInfo, @@ -19,6 +21,7 @@ import { } from "./utils"; import { FARM_PROGRAM_ID, SIMULATION_USER } from "./constant"; + const chunkedFetchMultipleUserAccount = async ( program: FarmProgram, pks: PublicKey[], @@ -63,6 +66,18 @@ const getAllPoolState = async ( return poolStates; }; +const getAllUserState = async ( + farmMints: Array, + program: FarmProgram +) => { + const poolStates = (await chunkedFetchMultipleUserAccount( + program, + farmMints + )) as Array; + + return poolStates; +}; + const MAX_CLAIM_ALL_ALLOWED = 2; export class PoolFarmImpl { @@ -351,25 +366,25 @@ export class PoolFarmImpl { await Promise.all( isDual ? [ - getOrCreateATAInstruction( - this.poolState.rewardAMint, - owner, - this.program.provider.connection - ), - getOrCreateATAInstruction( - this.poolState.rewardBMint, - owner, - this.program.provider.connection - ), - ] + getOrCreateATAInstruction( + this.poolState.rewardAMint, + owner, + this.program.provider.connection + ), + getOrCreateATAInstruction( + this.poolState.rewardBMint, + owner, + this.program.provider.connection + ), + ] : [ - getOrCreateATAInstruction( - this.poolState.rewardAMint, - owner, - this.program.provider.connection - ), - [undefined, undefined], - ] + getOrCreateATAInstruction( + this.poolState.rewardAMint, + owner, + this.program.provider.connection + ), + [undefined, undefined], + ] ); userRewardAIx && preInstructions.push(userRewardAIx); userRewardBIx && preInstructions.push(userRewardBIx); @@ -431,3 +446,39 @@ export class PoolFarmImpl { return simulatedReward; } } + +export const getOnchainTime = async (connection: Connection) => { + const parsedClock = await connection.getParsedAccountInfo(SYSVAR_CLOCK_PUBKEY); + + const parsedClockAccount = (parsedClock.value!.data as ParsedAccountData).parsed as ParsedClockState; + + const currentTime = parsedClockAccount.info.unixTimestamp; + return currentTime; +}; + +function rewardPerToken(pool: PoolState, lastTimeRewardApplicable: number) { + let totalStake = pool.totalStaked; + if (totalStake.isZero()) { + return { + a: pool.rewardAPerTokenStored, + b: pool.rewardBPerTokenStored, + } + } + let timePeriod = new BN(lastTimeRewardApplicable - pool.lastUpdateTime.toNumber()); + return { + a: pool.rewardAPerTokenStored.add(timePeriod.mul(pool.rewardARateU128).div(totalStake)), + b: pool.rewardAPerTokenStored.add(timePeriod.mul(pool.rewardARateU128).div(totalStake)) + } +} + +export function getClaimableRewardSync(onchainTIme: number, userState: UserState, poolState: PoolState) { + // update reward + let rewardDurationEnd = poolState.rewardDurationEnd.toNumber(); + let lastTimeRewardApplicable = ((onchainTIme < rewardDurationEnd) ? onchainTIme : rewardDurationEnd); + let { a, b } = rewardPerToken(poolState, lastTimeRewardApplicable); + + return { + a: (userState.balanceStaked.mul(a.sub(userState.rewardAPerTokenComplete)).div(new BN(1_000_000_000))).add(userState.rewardAPerTokenPending), + b: (userState.balanceStaked.mul(b.sub(userState.rewardBPerTokenComplete)).div(new BN(1_000_000_000))).add(userState.rewardBPerTokenPending), + } +} diff --git a/ts-client/src/idl/farming-idl.ts b/ts-client/src/idl/farming-idl.ts index d5030e5..36ef054 100644 --- a/ts-client/src/idl/farming-idl.ts +++ b/ts-client/src/idl/farming-idl.ts @@ -1,1729 +1,2131 @@ export type Farming = { - version: "0.2.1"; - name: "farming"; - docs: ["Dual farming program"]; - instructions: [ + "version": "0.2.2", + "name": "farming", + "docs": [ + "Dual farming program" + ], + "instructions": [ { - name: "initializePool"; - docs: [ + "name": "initializePool", + "docs": [ "Initializes a new pool. Able to create pool with single reward by passing the same Mint account for reward_a_mint and reward_a_mint" - ]; - accounts: [ - { - name: "pool"; - isMut: true; - isSigner: false; - docs: ["Global accounts for the staking instance."]; - }, - { - name: "stakingMint"; - isMut: false; - isSigner: false; - docs: ["Staking mint"]; - }, - { - name: "stakingVault"; - isMut: true; - isSigner: false; - docs: ["Staking vault PDA"]; - }, - { - name: "rewardAMint"; - isMut: false; - isSigner: false; - docs: ["Reward A mint"]; - }, - { - name: "rewardAVault"; - isMut: true; - isSigner: false; - docs: ["Reward A vault PDA"]; - }, - { - name: "rewardBMint"; - isMut: false; - isSigner: false; - docs: ["Reward B mint"]; - }, - { - name: "rewardBVault"; - isMut: true; - isSigner: false; - docs: ["Reward B vault PDA"]; - }, - { - name: "authority"; - isMut: true; - isSigner: true; - docs: ["Authority of the pool"]; - }, - { - name: "base"; - isMut: false; - isSigner: true; - docs: ["Base"]; - }, - { - name: "systemProgram"; - isMut: false; - isSigner: false; - docs: ["System program"]; - }, - { - name: "tokenProgram"; - isMut: false; - isSigner: false; - docs: ["SPL Token program"]; - }, - { - name: "rent"; - isMut: false; - isSigner: false; - docs: ["Rent"]; + ], + "accounts": [ + { + "name": "pool", + "isMut": true, + "isSigner": false, + "docs": [ + "Global accounts for the staking instance." + ] + }, + { + "name": "stakingMint", + "isMut": false, + "isSigner": false, + "docs": [ + "Staking mint" + ] + }, + { + "name": "stakingVault", + "isMut": true, + "isSigner": false, + "docs": [ + "Staking vault PDA" + ] + }, + { + "name": "rewardAMint", + "isMut": false, + "isSigner": false, + "docs": [ + "Reward A mint" + ] + }, + { + "name": "rewardAVault", + "isMut": true, + "isSigner": false, + "docs": [ + "Reward A vault PDA" + ] + }, + { + "name": "rewardBMint", + "isMut": false, + "isSigner": false, + "docs": [ + "Reward B mint" + ] + }, + { + "name": "rewardBVault", + "isMut": true, + "isSigner": false, + "docs": [ + "Reward B vault PDA" + ] + }, + { + "name": "authority", + "isMut": true, + "isSigner": true, + "docs": [ + "Authority of the pool" + ] + }, + { + "name": "base", + "isMut": false, + "isSigner": true, + "docs": [ + "Base" + ] + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false, + "docs": [ + "System program" + ] + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false, + "docs": [ + "SPL Token program" + ] + }, + { + "name": "rent", + "isMut": false, + "isSigner": false, + "docs": [ + "Rent" + ] } - ]; - args: [ + ], + "args": [ { - name: "rewardDuration"; - type: "u64"; + "name": "rewardDuration", + "type": "u64" } - ]; + ] }, { - name: "createUser"; - docs: ["Initialize a user staking account"]; - accounts: [ - { - name: "pool"; - isMut: true; - isSigner: false; - docs: ["Global accounts for the staking instance."]; - }, - { - name: "user"; - isMut: true; - isSigner: false; - docs: ["User"]; - }, - { - name: "owner"; - isMut: true; - isSigner: true; - docs: ["Authority of user account"]; - }, - { - name: "systemProgram"; - isMut: false; - isSigner: false; - docs: ["Misc."]; + "name": "createUser", + "docs": [ + "Initialize a user staking account" + ], + "accounts": [ + { + "name": "pool", + "isMut": true, + "isSigner": false, + "docs": [ + "Global accounts for the staking instance." + ] + }, + { + "name": "user", + "isMut": true, + "isSigner": false, + "docs": [ + "User" + ] + }, + { + "name": "owner", + "isMut": true, + "isSigner": true, + "docs": [ + "Authority of user account" + ] + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false, + "docs": [ + "Misc." + ] } - ]; - args: []; + ], + "args": [] }, { - name: "pause"; - docs: ["Pause the pool"]; - accounts: [ - { - name: "pool"; - isMut: true; - isSigner: false; - docs: ["Global accounts for the staking instance."]; - }, - { - name: "authority"; - isMut: false; - isSigner: true; - docs: ["Authority of the pool"]; + "name": "pause", + "docs": [ + "Pause the pool" + ], + "accounts": [ + { + "name": "pool", + "isMut": true, + "isSigner": false, + "docs": [ + "Global accounts for the staking instance." + ] + }, + { + "name": "authority", + "isMut": false, + "isSigner": true, + "docs": [ + "Authority of the pool" + ] } - ]; - args: []; + ], + "args": [] }, { - name: "unpause"; - docs: ["Unpauses a previously paused pool. Allowing for funding."]; - accounts: [ - { - name: "pool"; - isMut: true; - isSigner: false; - docs: ["Global accounts for the staking instance."]; - }, - { - name: "authority"; - isMut: false; - isSigner: true; - docs: ["Authority of the pool"]; + "name": "unpause", + "docs": [ + "Unpauses a previously paused pool. Allowing for funding." + ], + "accounts": [ + { + "name": "pool", + "isMut": true, + "isSigner": false, + "docs": [ + "Global accounts for the staking instance." + ] + }, + { + "name": "authority", + "isMut": false, + "isSigner": true, + "docs": [ + "Authority of the pool" + ] } - ]; - args: []; + ], + "args": [] }, { - name: "deposit"; - docs: ["User deposit tokens in the pool."]; - accounts: [ - { - name: "pool"; - isMut: true; - isSigner: false; - docs: ["Global accounts for the deposit/withdraw instance."]; - }, - { - name: "stakingVault"; - isMut: true; - isSigner: false; - docs: ["Staking vault PDA."]; - }, - { - name: "user"; - isMut: true; - isSigner: false; - docs: ["User."]; - }, - { - name: "owner"; - isMut: false; - isSigner: true; - docs: ["Authority of user"]; - }, - { - name: "stakeFromAccount"; - isMut: true; - isSigner: false; - docs: ["User staking ATA"]; - }, - { - name: "tokenProgram"; - isMut: false; - isSigner: false; - docs: ["Misc."]; + "name": "deposit", + "docs": [ + "User deposit tokens in the pool." + ], + "accounts": [ + { + "name": "pool", + "isMut": true, + "isSigner": false, + "docs": [ + "Global accounts for the deposit/withdraw instance." + ] + }, + { + "name": "stakingVault", + "isMut": true, + "isSigner": false, + "docs": [ + "Staking vault PDA." + ] + }, + { + "name": "user", + "isMut": true, + "isSigner": false, + "docs": [ + "User." + ] + }, + { + "name": "owner", + "isMut": false, + "isSigner": true, + "docs": [ + "Authority of user" + ] + }, + { + "name": "stakeFromAccount", + "isMut": true, + "isSigner": false, + "docs": [ + "User staking ATA" + ] + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false, + "docs": [ + "Misc." + ] } - ]; - args: [ + ], + "args": [ { - name: "amount"; - type: "u64"; + "name": "amount", + "type": "u64" } - ]; + ] }, { - name: "withdraw"; - docs: ["User withdraw tokens in the pool."]; - accounts: [ - { - name: "pool"; - isMut: true; - isSigner: false; - docs: ["Global accounts for the deposit/withdraw instance."]; - }, - { - name: "stakingVault"; - isMut: true; - isSigner: false; - docs: ["Staking vault PDA."]; - }, - { - name: "user"; - isMut: true; - isSigner: false; - docs: ["User."]; - }, - { - name: "owner"; - isMut: false; - isSigner: true; - docs: ["Authority of user"]; - }, - { - name: "stakeFromAccount"; - isMut: true; - isSigner: false; - docs: ["User staking ATA"]; - }, - { - name: "tokenProgram"; - isMut: false; - isSigner: false; - docs: ["Misc."]; + "name": "withdraw", + "docs": [ + "User withdraw tokens in the pool." + ], + "accounts": [ + { + "name": "pool", + "isMut": true, + "isSigner": false, + "docs": [ + "Global accounts for the deposit/withdraw instance." + ] + }, + { + "name": "stakingVault", + "isMut": true, + "isSigner": false, + "docs": [ + "Staking vault PDA." + ] + }, + { + "name": "user", + "isMut": true, + "isSigner": false, + "docs": [ + "User." + ] + }, + { + "name": "owner", + "isMut": false, + "isSigner": true, + "docs": [ + "Authority of user" + ] + }, + { + "name": "stakeFromAccount", + "isMut": true, + "isSigner": false, + "docs": [ + "User staking ATA" + ] + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false, + "docs": [ + "Misc." + ] } - ]; - args: [ + ], + "args": [ { - name: "sptAmount"; - type: "u64"; + "name": "sptAmount", + "type": "u64" } - ]; + ] }, { - name: "authorizeFunder"; - docs: ["Authorize additional funders for the pool"]; - accounts: [ - { - name: "pool"; - isMut: true; - isSigner: false; - docs: ["Global accounts for the staking instance."]; - }, - { - name: "authority"; - isMut: false; - isSigner: true; - docs: ["Authority of the pool"]; + "name": "authorizeFunder", + "docs": [ + "Authorize additional funders for the pool" + ], + "accounts": [ + { + "name": "pool", + "isMut": true, + "isSigner": false, + "docs": [ + "Global accounts for the staking instance." + ] + }, + { + "name": "authority", + "isMut": false, + "isSigner": true, + "docs": [ + "Authority of the pool" + ] } - ]; - args: [ + ], + "args": [ { - name: "funderToAdd"; - type: "publicKey"; + "name": "funderToAdd", + "type": "publicKey" } - ]; + ] }, { - name: "deauthorizeFunder"; - docs: ["Deauthorize funders for the pool"]; - accounts: [ - { - name: "pool"; - isMut: true; - isSigner: false; - docs: ["Global accounts for the staking instance."]; - }, - { - name: "authority"; - isMut: false; - isSigner: true; - docs: ["Authority of the pool"]; + "name": "deauthorizeFunder", + "docs": [ + "Deauthorize funders for the pool" + ], + "accounts": [ + { + "name": "pool", + "isMut": true, + "isSigner": false, + "docs": [ + "Global accounts for the staking instance." + ] + }, + { + "name": "authority", + "isMut": false, + "isSigner": true, + "docs": [ + "Authority of the pool" + ] } - ]; - args: [ + ], + "args": [ { - name: "funderToRemove"; - type: "publicKey"; + "name": "funderToRemove", + "type": "publicKey" } - ]; + ] }, { - name: "fund"; - docs: [ + "name": "fund", + "docs": [ "Fund the pool with rewards. This resets the clock on the end date, pushing it out to the set duration. And, linearly redistributes remaining rewards." - ]; - accounts: [ - { - name: "pool"; - isMut: true; - isSigner: false; - docs: ["Global accounts for the staking instance."]; - }, - { - name: "stakingVault"; - isMut: true; - isSigner: false; - docs: ["Staking vault PDA"]; - }, - { - name: "rewardAVault"; - isMut: true; - isSigner: false; - docs: ["Reward A Vault PDA"]; - }, - { - name: "rewardBVault"; - isMut: true; - isSigner: false; - docs: ["Reward B Vault PDA"]; - }, - { - name: "funder"; - isMut: false; - isSigner: true; - docs: ["Funder"]; - }, - { - name: "fromA"; - isMut: true; - isSigner: false; - docs: ["Funder reward A ATA"]; - }, - { - name: "fromB"; - isMut: true; - isSigner: false; - docs: ["Funder reward B ATA"]; - }, - { - name: "tokenProgram"; - isMut: false; - isSigner: false; - docs: ["Misc."]; + ], + "accounts": [ + { + "name": "pool", + "isMut": true, + "isSigner": false, + "docs": [ + "Global accounts for the staking instance." + ] + }, + { + "name": "stakingVault", + "isMut": true, + "isSigner": false, + "docs": [ + "Staking vault PDA" + ] + }, + { + "name": "rewardAVault", + "isMut": true, + "isSigner": false, + "docs": [ + "Reward A Vault PDA" + ] + }, + { + "name": "rewardBVault", + "isMut": true, + "isSigner": false, + "docs": [ + "Reward B Vault PDA" + ] + }, + { + "name": "funder", + "isMut": false, + "isSigner": true, + "docs": [ + "Funder" + ] + }, + { + "name": "fromA", + "isMut": true, + "isSigner": false, + "docs": [ + "Funder reward A ATA" + ] + }, + { + "name": "fromB", + "isMut": true, + "isSigner": false, + "docs": [ + "Funder reward B ATA" + ] + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false, + "docs": [ + "Misc." + ] } - ]; - args: [ + ], + "args": [ { - name: "amountA"; - type: "u64"; + "name": "amountA", + "type": "u64" }, { - name: "amountB"; - type: "u64"; + "name": "amountB", + "type": "u64" } - ]; + ] }, { - name: "claim"; - docs: ["User claim rewards"]; - accounts: [ + "name": "claim", + "docs": [ + "User claim rewards" + ], + "accounts": [ { - name: "pool"; - isMut: true; - isSigner: false; - docs: ["Global accounts for the staking instance."]; + "name": "pool", + "isMut": true, + "isSigner": false, + "docs": [ + "Global accounts for the staking instance." + ] }, { - name: "stakingVault"; - isMut: true; - isSigner: false; - docs: ["Staking vault PDA."]; + "name": "stakingVault", + "isMut": true, + "isSigner": false, + "docs": [ + "Staking vault PDA." + ] }, { - name: "rewardAVault"; - isMut: true; - isSigner: false; - docs: ["Reward A Vault PDA"]; + "name": "rewardAVault", + "isMut": true, + "isSigner": false, + "docs": [ + "Reward A Vault PDA" + ] }, { - name: "rewardBVault"; - isMut: true; - isSigner: false; - docs: ["Reward B Vault PDA"]; + "name": "rewardBVault", + "isMut": true, + "isSigner": false, + "docs": [ + "Reward B Vault PDA" + ] }, { - name: "user"; - isMut: true; - isSigner: false; - docs: ["User."]; + "name": "user", + "isMut": true, + "isSigner": false, + "docs": [ + "User." + ] }, { - name: "owner"; - isMut: false; - isSigner: true; - docs: ["Authority of user"]; + "name": "owner", + "isMut": false, + "isSigner": true, + "docs": [ + "Authority of user" + ] }, { - name: "rewardAAccount"; - isMut: true; - isSigner: false; - docs: ["User's Reward A ATA"]; + "name": "rewardAAccount", + "isMut": true, + "isSigner": false, + "docs": [ + "User's Reward A ATA" + ] }, { - name: "rewardBAccount"; - isMut: true; - isSigner: false; - docs: ["User's Reward B ATA"]; + "name": "rewardBAccount", + "isMut": true, + "isSigner": false, + "docs": [ + "User's Reward B ATA" + ] }, { - name: "tokenProgram"; - isMut: false; - isSigner: false; + "name": "tokenProgram", + "isMut": false, + "isSigner": false } - ]; - args: []; + ], + "args": [] }, { - name: "withdrawExtraToken"; - docs: ["Withdraw token that mistakenly deposited to staking_vault"]; - accounts: [ - { - name: "pool"; - isMut: false; - isSigner: false; - docs: ["Global accounts for the staking instance."]; - }, - { - name: "stakingVault"; - isMut: true; - isSigner: false; - docs: ["Staking vault PDA"]; - }, - { - name: "withdrawToAccount"; - isMut: true; - isSigner: false; - docs: ["Token account to receive mistakenly deposited token"]; - }, - { - name: "authority"; - isMut: false; - isSigner: true; - docs: ["Authority of the staking instance"]; - }, - { - name: "tokenProgram"; - isMut: false; - isSigner: false; - docs: ["Misc."]; + "name": "withdrawExtraToken", + "docs": [ + "Withdraw token that mistakenly deposited to staking_vault" + ], + "accounts": [ + { + "name": "pool", + "isMut": false, + "isSigner": false, + "docs": [ + "Global accounts for the staking instance." + ] + }, + { + "name": "stakingVault", + "isMut": true, + "isSigner": false, + "docs": [ + "Staking vault PDA" + ] + }, + { + "name": "withdrawToAccount", + "isMut": true, + "isSigner": false, + "docs": [ + "Token account to receive mistakenly deposited token" + ] + }, + { + "name": "authority", + "isMut": false, + "isSigner": true, + "docs": [ + "Authority of the staking instance" + ] + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false, + "docs": [ + "Misc." + ] } - ]; - args: []; + ], + "args": [] }, { - name: "closeUser"; - docs: [ + "name": "closeUser", + "docs": [ "Closes a users stake account. Validation is done to ensure this is only allowed when the user has nothing staked and no rewards pending." - ]; - accounts: [ + ], + "accounts": [ { - name: "pool"; - isMut: true; - isSigner: false; + "name": "pool", + "isMut": true, + "isSigner": false }, { - name: "user"; - isMut: true; - isSigner: false; + "name": "user", + "isMut": true, + "isSigner": false }, { - name: "owner"; - isMut: true; - isSigner: true; + "name": "owner", + "isMut": true, + "isSigner": true } - ]; - args: []; + ], + "args": [] }, { - name: "migrateFarmingRate"; - docs: ["anyone can call this"]; - accounts: [ + "name": "migrateFarmingRate", + "docs": [ + "anyone can call this" + ], + "accounts": [ { - name: "pool"; - isMut: true; - isSigner: false; + "name": "pool", + "isMut": true, + "isSigner": false } - ]; - args: []; + ], + "args": [] }, { - name: "closePool"; - docs: [ + "name": "closePool", + "docs": [ "Closes a pool account. Only able to be done when there are no users staked." - ]; - accounts: [ + ], + "accounts": [ { - name: "refundee"; - isMut: true; - isSigner: false; + "name": "refundee", + "isMut": true, + "isSigner": false }, { - name: "stakingRefundee"; - isMut: true; - isSigner: false; + "name": "stakingRefundee", + "isMut": true, + "isSigner": false }, { - name: "rewardARefundee"; - isMut: true; - isSigner: false; + "name": "rewardARefundee", + "isMut": true, + "isSigner": false }, { - name: "rewardBRefundee"; - isMut: true; - isSigner: false; + "name": "rewardBRefundee", + "isMut": true, + "isSigner": false }, { - name: "pool"; - isMut: true; - isSigner: false; + "name": "pool", + "isMut": true, + "isSigner": false }, { - name: "authority"; - isMut: false; - isSigner: true; + "name": "authority", + "isMut": false, + "isSigner": true }, { - name: "stakingVault"; - isMut: true; - isSigner: false; + "name": "stakingVault", + "isMut": true, + "isSigner": false }, { - name: "rewardAVault"; - isMut: true; - isSigner: false; + "name": "rewardAVault", + "isMut": true, + "isSigner": false }, { - name: "rewardBVault"; - isMut: true; - isSigner: false; + "name": "rewardBVault", + "isMut": true, + "isSigner": false }, { - name: "tokenProgram"; - isMut: false; - isSigner: false; + "name": "tokenProgram", + "isMut": false, + "isSigner": false } - ]; - args: []; + ], + "args": [] } - ]; - accounts: [ - { - name: "pool"; - docs: ["Pool account wrapper"]; - type: { - kind: "struct"; - fields: [ + ], + "accounts": [ + { + "name": "pool", + "docs": [ + "Pool account wrapper" + ], + "type": { + "kind": "struct", + "fields": [ { - name: "authority"; - docs: ["Privileged account."]; - type: "publicKey"; + "name": "authority", + "docs": [ + "Privileged account." + ], + "type": "publicKey" }, { - name: "paused"; - docs: ["Paused state of the program"]; - type: "bool"; + "name": "paused", + "docs": [ + "Paused state of the program" + ], + "type": "bool" }, { - name: "stakingMint"; - docs: ["Mint of the token that can be staked."]; - type: "publicKey"; + "name": "stakingMint", + "docs": [ + "Mint of the token that can be staked." + ], + "type": "publicKey" }, { - name: "stakingVault"; - docs: ["Vault to store staked tokens."]; - type: "publicKey"; + "name": "stakingVault", + "docs": [ + "Vault to store staked tokens." + ], + "type": "publicKey" }, { - name: "rewardAMint"; - docs: ["Mint of the reward A token."]; - type: "publicKey"; + "name": "rewardAMint", + "docs": [ + "Mint of the reward A token." + ], + "type": "publicKey" }, { - name: "rewardAVault"; - docs: ["Vault to store reward A tokens."]; - type: "publicKey"; + "name": "rewardAVault", + "docs": [ + "Vault to store reward A tokens." + ], + "type": "publicKey" }, { - name: "rewardBMint"; - docs: ["Mint of the reward B token."]; - type: "publicKey"; + "name": "rewardBMint", + "docs": [ + "Mint of the reward B token." + ], + "type": "publicKey" }, { - name: "rewardBVault"; - docs: ["Vault to store reward B tokens."]; - type: "publicKey"; + "name": "rewardBVault", + "docs": [ + "Vault to store reward B tokens." + ], + "type": "publicKey" }, { - name: "baseKey"; - docs: ["Base key"]; - type: "publicKey"; + "name": "baseKey", + "docs": [ + "Base key" + ], + "type": "publicKey" }, { - name: "rewardDuration"; - docs: ["The period which rewards are linearly distributed."]; - type: "u64"; + "name": "rewardDuration", + "docs": [ + "The period which rewards are linearly distributed." + ], + "type": "u64" }, { - name: "rewardDurationEnd"; - docs: ["The timestamp at which the current reward period ends."]; - type: "u64"; + "name": "rewardDurationEnd", + "docs": [ + "The timestamp at which the current reward period ends." + ], + "type": "u64" }, { - name: "lastUpdateTime"; - docs: ["The last time reward states were updated."]; - type: "u64"; + "name": "lastUpdateTime", + "docs": [ + "The last time reward states were updated." + ], + "type": "u64" }, { - name: "rewardARate"; - docs: ["deprecated field"]; - type: "u64"; + "name": "rewardARate", + "docs": [ + "deprecated field" + ], + "type": "u64" }, { - name: "rewardBRate"; - docs: ["deprecated field"]; - type: "u64"; + "name": "rewardBRate", + "docs": [ + "deprecated field" + ], + "type": "u64" }, { - name: "rewardAPerTokenStored"; - docs: ["Last calculated reward A per pool token."]; - type: "u128"; + "name": "rewardAPerTokenStored", + "docs": [ + "Last calculated reward A per pool token." + ], + "type": "u128" }, { - name: "rewardBPerTokenStored"; - docs: ["Last calculated reward B per pool token."]; - type: "u128"; + "name": "rewardBPerTokenStored", + "docs": [ + "Last calculated reward B per pool token." + ], + "type": "u128" }, { - name: "userStakeCount"; - docs: ["Users staked"]; - type: "u32"; + "name": "userStakeCount", + "docs": [ + "Users staked" + ], + "type": "u32" }, { - name: "funders"; - docs: [ + "name": "funders", + "docs": [ "authorized funders", "[] because short size, fixed account size, and ease of use on", "client due to auto generated account size property" - ]; - type: { - array: ["publicKey", 3]; - }; + ], + "type": { + "array": [ + "publicKey", + 3 + ] + } }, { - name: "rewardARateU128"; - docs: ["reward_a_rate in u128 form"]; - type: "u128"; + "name": "rewardARateU128", + "docs": [ + "reward_a_rate in u128 form" + ], + "type": "u128" }, { - name: "rewardBRateU128"; - docs: ["reward_b_rate in u128 form"]; - type: "u128"; + "name": "rewardBRateU128", + "docs": [ + "reward_b_rate in u128 form" + ], + "type": "u128" }, { - name: "poolBump"; - docs: ["Pool bump"]; - type: "u8"; + "name": "poolBump", + "docs": [ + "Pool bump" + ], + "type": "u8" }, { - name: "totalStaked"; - docs: ["Total staked amount"]; - type: "u64"; + "name": "totalStaked", + "docs": [ + "Total staked amount" + ], + "type": "u64" } - ]; - }; + ] + } }, { - name: "user"; - docs: ["Farming user account"]; - type: { - kind: "struct"; - fields: [ + "name": "user", + "docs": [ + "Farming user account" + ], + "type": { + "kind": "struct", + "fields": [ { - name: "pool"; - docs: ["Pool the this user belongs to."]; - type: "publicKey"; + "name": "pool", + "docs": [ + "Pool the this user belongs to." + ], + "type": "publicKey" }, { - name: "owner"; - docs: ["The owner of this account."]; - type: "publicKey"; + "name": "owner", + "docs": [ + "The owner of this account." + ], + "type": "publicKey" }, { - name: "rewardAPerTokenComplete"; - docs: ["The amount of token A claimed."]; - type: "u128"; + "name": "rewardAPerTokenComplete", + "docs": [ + "The amount of token A claimed." + ], + "type": "u128" }, { - name: "rewardBPerTokenComplete"; - docs: ["The amount of token B claimed."]; - type: "u128"; + "name": "rewardBPerTokenComplete", + "docs": [ + "The amount of token B claimed." + ], + "type": "u128" }, { - name: "rewardAPerTokenPending"; - docs: ["The amount of token A pending claim."]; - type: "u64"; + "name": "rewardAPerTokenPending", + "docs": [ + "The amount of token A pending claim." + ], + "type": "u64" }, { - name: "rewardBPerTokenPending"; - docs: ["The amount of token B pending claim."]; - type: "u64"; + "name": "rewardBPerTokenPending", + "docs": [ + "The amount of token B pending claim." + ], + "type": "u64" }, { - name: "balanceStaked"; - docs: ["The amount staked."]; - type: "u64"; + "name": "balanceStaked", + "docs": [ + "The amount staked." + ], + "type": "u64" }, { - name: "nonce"; - docs: ["Signer nonce."]; - type: "u8"; + "name": "nonce", + "docs": [ + "Signer nonce." + ], + "type": "u8" } - ]; - }; + ] + } } - ]; - events: [ + ], + "events": [ { - name: "EventDeposit"; - fields: [ + "name": "EventDeposit", + "fields": [ { - name: "amount"; - type: "u64"; - index: false; + "name": "amount", + "type": "u64", + "index": false } - ]; + ] }, { - name: "EventWithdraw"; - fields: [ + "name": "EventWithdraw", + "fields": [ { - name: "amount"; - type: "u64"; - index: false; + "name": "amount", + "type": "u64", + "index": false } - ]; + ] }, { - name: "EventFund"; - fields: [ + "name": "EventFund", + "fields": [ { - name: "amountA"; - type: "u64"; - index: false; + "name": "amountA", + "type": "u64", + "index": false }, { - name: "amountB"; - type: "u64"; - index: false; + "name": "amountB", + "type": "u64", + "index": false } - ]; + ] }, { - name: "EventClaim"; - fields: [ + "name": "EventClaim", + "fields": [ { - name: "amountA"; - type: "u64"; - index: false; + "name": "amountA", + "type": "u64", + "index": false }, { - name: "amountB"; - type: "u64"; - index: false; + "name": "amountB", + "type": "u64", + "index": false } - ]; + ] }, { - name: "EventAuthorizeFunder"; - fields: [ + "name": "EventAuthorizeFunder", + "fields": [ { - name: "newFunder"; - type: "publicKey"; - index: false; + "name": "newFunder", + "type": "publicKey", + "index": false } - ]; + ] }, { - name: "EventUnauthorizeFunder"; - fields: [ + "name": "EventUnauthorizeFunder", + "fields": [ { - name: "funder"; - type: "publicKey"; - index: false; + "name": "funder", + "type": "publicKey", + "index": false } - ]; + ] } - ]; - errors: [ + ], + "errors": [ { - code: 6000; - name: "InsufficientFundWithdraw"; - msg: "Insufficient funds to withdraw."; + "code": 6000, + "name": "InsufficientFundWithdraw", + "msg": "Insufficient funds to withdraw." }, { - code: 6001; - name: "AmountMustBeGreaterThanZero"; - msg: "Amount must be greater than zero."; + "code": 6001, + "name": "AmountMustBeGreaterThanZero", + "msg": "Amount must be greater than zero." }, { - code: 6002; - name: "SingleDepositTokenBCannotBeFunded"; - msg: "Reward B cannot be funded - pool is single deposit."; + "code": 6002, + "name": "SingleDepositTokenBCannotBeFunded", + "msg": "Reward B cannot be funded - pool is single deposit." }, { - code: 6003; - name: "PoolPaused"; - msg: "Pool is paused."; + "code": 6003, + "name": "PoolPaused", + "msg": "Pool is paused." }, { - code: 6004; - name: "DurationTooShort"; - msg: "Duration cannot be shorter than one day."; + "code": 6004, + "name": "DurationTooShort", + "msg": "Duration cannot be shorter than one day." }, { - code: 6005; - name: "FunderAlreadyAuthorized"; - msg: "Provided funder is already authorized to fund."; + "code": 6005, + "name": "FunderAlreadyAuthorized", + "msg": "Provided funder is already authorized to fund." }, { - code: 6006; - name: "MaxFunders"; - msg: "Maximum funders already authorized."; + "code": 6006, + "name": "MaxFunders", + "msg": "Maximum funders already authorized." }, { - code: 6007; - name: "CannotDeauthorizePoolAuthority"; - msg: "Cannot deauthorize the primary pool authority."; + "code": 6007, + "name": "CannotDeauthorizePoolAuthority", + "msg": "Cannot deauthorize the primary pool authority." }, { - code: 6008; - name: "CannotDeauthorizeMissingAuthority"; - msg: "Authority not found for deauthorization."; + "code": 6008, + "name": "CannotDeauthorizeMissingAuthority", + "msg": "Authority not found for deauthorization." }, { - code: 6009; - name: "MathOverflow"; - msg: "Math operation overflow"; + "code": 6009, + "name": "MathOverflow", + "msg": "Math operation overflow" } - ]; + ] }; export const IDL: Farming = { - version: "0.2.1", - name: "farming", - docs: ["Dual farming program"], - instructions: [ - { - name: "initializePool", - docs: [ - "Initializes a new pool. Able to create pool with single reward by passing the same Mint account for reward_a_mint and reward_a_mint", + "version": "0.2.2", + "name": "farming", + "docs": [ + "Dual farming program" + ], + "instructions": [ + { + "name": "initializePool", + "docs": [ + "Initializes a new pool. Able to create pool with single reward by passing the same Mint account for reward_a_mint and reward_a_mint" ], - accounts: [ - { - name: "pool", - isMut: true, - isSigner: false, - docs: ["Global accounts for the staking instance."], - }, - { - name: "stakingMint", - isMut: false, - isSigner: false, - docs: ["Staking mint"], - }, - { - name: "stakingVault", - isMut: true, - isSigner: false, - docs: ["Staking vault PDA"], - }, - { - name: "rewardAMint", - isMut: false, - isSigner: false, - docs: ["Reward A mint"], - }, - { - name: "rewardAVault", - isMut: true, - isSigner: false, - docs: ["Reward A vault PDA"], - }, - { - name: "rewardBMint", - isMut: false, - isSigner: false, - docs: ["Reward B mint"], - }, - { - name: "rewardBVault", - isMut: true, - isSigner: false, - docs: ["Reward B vault PDA"], - }, - { - name: "authority", - isMut: true, - isSigner: true, - docs: ["Authority of the pool"], - }, - { - name: "base", - isMut: false, - isSigner: true, - docs: ["Base"], - }, - { - name: "systemProgram", - isMut: false, - isSigner: false, - docs: ["System program"], - }, - { - name: "tokenProgram", - isMut: false, - isSigner: false, - docs: ["SPL Token program"], - }, - { - name: "rent", - isMut: false, - isSigner: false, - docs: ["Rent"], - }, + "accounts": [ + { + "name": "pool", + "isMut": true, + "isSigner": false, + "docs": [ + "Global accounts for the staking instance." + ] + }, + { + "name": "stakingMint", + "isMut": false, + "isSigner": false, + "docs": [ + "Staking mint" + ] + }, + { + "name": "stakingVault", + "isMut": true, + "isSigner": false, + "docs": [ + "Staking vault PDA" + ] + }, + { + "name": "rewardAMint", + "isMut": false, + "isSigner": false, + "docs": [ + "Reward A mint" + ] + }, + { + "name": "rewardAVault", + "isMut": true, + "isSigner": false, + "docs": [ + "Reward A vault PDA" + ] + }, + { + "name": "rewardBMint", + "isMut": false, + "isSigner": false, + "docs": [ + "Reward B mint" + ] + }, + { + "name": "rewardBVault", + "isMut": true, + "isSigner": false, + "docs": [ + "Reward B vault PDA" + ] + }, + { + "name": "authority", + "isMut": true, + "isSigner": true, + "docs": [ + "Authority of the pool" + ] + }, + { + "name": "base", + "isMut": false, + "isSigner": true, + "docs": [ + "Base" + ] + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false, + "docs": [ + "System program" + ] + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false, + "docs": [ + "SPL Token program" + ] + }, + { + "name": "rent", + "isMut": false, + "isSigner": false, + "docs": [ + "Rent" + ] + } ], - args: [ + "args": [ { - name: "rewardDuration", - type: "u64", - }, - ], + "name": "rewardDuration", + "type": "u64" + } + ] }, { - name: "createUser", - docs: ["Initialize a user staking account"], - accounts: [ - { - name: "pool", - isMut: true, - isSigner: false, - docs: ["Global accounts for the staking instance."], - }, - { - name: "user", - isMut: true, - isSigner: false, - docs: ["User"], - }, - { - name: "owner", - isMut: true, - isSigner: true, - docs: ["Authority of user account"], - }, - { - name: "systemProgram", - isMut: false, - isSigner: false, - docs: ["Misc."], - }, + "name": "createUser", + "docs": [ + "Initialize a user staking account" ], - args: [], + "accounts": [ + { + "name": "pool", + "isMut": true, + "isSigner": false, + "docs": [ + "Global accounts for the staking instance." + ] + }, + { + "name": "user", + "isMut": true, + "isSigner": false, + "docs": [ + "User" + ] + }, + { + "name": "owner", + "isMut": true, + "isSigner": true, + "docs": [ + "Authority of user account" + ] + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false, + "docs": [ + "Misc." + ] + } + ], + "args": [] }, { - name: "pause", - docs: ["Pause the pool"], - accounts: [ - { - name: "pool", - isMut: true, - isSigner: false, - docs: ["Global accounts for the staking instance."], - }, - { - name: "authority", - isMut: false, - isSigner: true, - docs: ["Authority of the pool"], - }, + "name": "pause", + "docs": [ + "Pause the pool" ], - args: [], + "accounts": [ + { + "name": "pool", + "isMut": true, + "isSigner": false, + "docs": [ + "Global accounts for the staking instance." + ] + }, + { + "name": "authority", + "isMut": false, + "isSigner": true, + "docs": [ + "Authority of the pool" + ] + } + ], + "args": [] }, { - name: "unpause", - docs: ["Unpauses a previously paused pool. Allowing for funding."], - accounts: [ - { - name: "pool", - isMut: true, - isSigner: false, - docs: ["Global accounts for the staking instance."], - }, - { - name: "authority", - isMut: false, - isSigner: true, - docs: ["Authority of the pool"], - }, + "name": "unpause", + "docs": [ + "Unpauses a previously paused pool. Allowing for funding." + ], + "accounts": [ + { + "name": "pool", + "isMut": true, + "isSigner": false, + "docs": [ + "Global accounts for the staking instance." + ] + }, + { + "name": "authority", + "isMut": false, + "isSigner": true, + "docs": [ + "Authority of the pool" + ] + } ], - args: [], + "args": [] }, { - name: "deposit", - docs: ["User deposit tokens in the pool."], - accounts: [ - { - name: "pool", - isMut: true, - isSigner: false, - docs: ["Global accounts for the deposit/withdraw instance."], - }, - { - name: "stakingVault", - isMut: true, - isSigner: false, - docs: ["Staking vault PDA."], - }, - { - name: "user", - isMut: true, - isSigner: false, - docs: ["User."], - }, - { - name: "owner", - isMut: false, - isSigner: true, - docs: ["Authority of user"], - }, - { - name: "stakeFromAccount", - isMut: true, - isSigner: false, - docs: ["User staking ATA"], - }, - { - name: "tokenProgram", - isMut: false, - isSigner: false, - docs: ["Misc."], - }, + "name": "deposit", + "docs": [ + "User deposit tokens in the pool." ], - args: [ - { - name: "amount", - type: "u64", - }, + "accounts": [ + { + "name": "pool", + "isMut": true, + "isSigner": false, + "docs": [ + "Global accounts for the deposit/withdraw instance." + ] + }, + { + "name": "stakingVault", + "isMut": true, + "isSigner": false, + "docs": [ + "Staking vault PDA." + ] + }, + { + "name": "user", + "isMut": true, + "isSigner": false, + "docs": [ + "User." + ] + }, + { + "name": "owner", + "isMut": false, + "isSigner": true, + "docs": [ + "Authority of user" + ] + }, + { + "name": "stakeFromAccount", + "isMut": true, + "isSigner": false, + "docs": [ + "User staking ATA" + ] + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false, + "docs": [ + "Misc." + ] + } ], + "args": [ + { + "name": "amount", + "type": "u64" + } + ] }, { - name: "withdraw", - docs: ["User withdraw tokens in the pool."], - accounts: [ - { - name: "pool", - isMut: true, - isSigner: false, - docs: ["Global accounts for the deposit/withdraw instance."], - }, - { - name: "stakingVault", - isMut: true, - isSigner: false, - docs: ["Staking vault PDA."], - }, - { - name: "user", - isMut: true, - isSigner: false, - docs: ["User."], - }, - { - name: "owner", - isMut: false, - isSigner: true, - docs: ["Authority of user"], - }, - { - name: "stakeFromAccount", - isMut: true, - isSigner: false, - docs: ["User staking ATA"], - }, - { - name: "tokenProgram", - isMut: false, - isSigner: false, - docs: ["Misc."], - }, + "name": "withdraw", + "docs": [ + "User withdraw tokens in the pool." ], - args: [ - { - name: "sptAmount", - type: "u64", - }, + "accounts": [ + { + "name": "pool", + "isMut": true, + "isSigner": false, + "docs": [ + "Global accounts for the deposit/withdraw instance." + ] + }, + { + "name": "stakingVault", + "isMut": true, + "isSigner": false, + "docs": [ + "Staking vault PDA." + ] + }, + { + "name": "user", + "isMut": true, + "isSigner": false, + "docs": [ + "User." + ] + }, + { + "name": "owner", + "isMut": false, + "isSigner": true, + "docs": [ + "Authority of user" + ] + }, + { + "name": "stakeFromAccount", + "isMut": true, + "isSigner": false, + "docs": [ + "User staking ATA" + ] + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false, + "docs": [ + "Misc." + ] + } ], + "args": [ + { + "name": "sptAmount", + "type": "u64" + } + ] }, { - name: "authorizeFunder", - docs: ["Authorize additional funders for the pool"], - accounts: [ - { - name: "pool", - isMut: true, - isSigner: false, - docs: ["Global accounts for the staking instance."], - }, - { - name: "authority", - isMut: false, - isSigner: true, - docs: ["Authority of the pool"], - }, + "name": "authorizeFunder", + "docs": [ + "Authorize additional funders for the pool" ], - args: [ - { - name: "funderToAdd", - type: "publicKey", - }, + "accounts": [ + { + "name": "pool", + "isMut": true, + "isSigner": false, + "docs": [ + "Global accounts for the staking instance." + ] + }, + { + "name": "authority", + "isMut": false, + "isSigner": true, + "docs": [ + "Authority of the pool" + ] + } ], + "args": [ + { + "name": "funderToAdd", + "type": "publicKey" + } + ] }, { - name: "deauthorizeFunder", - docs: ["Deauthorize funders for the pool"], - accounts: [ - { - name: "pool", - isMut: true, - isSigner: false, - docs: ["Global accounts for the staking instance."], - }, - { - name: "authority", - isMut: false, - isSigner: true, - docs: ["Authority of the pool"], - }, + "name": "deauthorizeFunder", + "docs": [ + "Deauthorize funders for the pool" ], - args: [ - { - name: "funderToRemove", - type: "publicKey", - }, + "accounts": [ + { + "name": "pool", + "isMut": true, + "isSigner": false, + "docs": [ + "Global accounts for the staking instance." + ] + }, + { + "name": "authority", + "isMut": false, + "isSigner": true, + "docs": [ + "Authority of the pool" + ] + } ], + "args": [ + { + "name": "funderToRemove", + "type": "publicKey" + } + ] }, { - name: "fund", - docs: [ - "Fund the pool with rewards. This resets the clock on the end date, pushing it out to the set duration. And, linearly redistributes remaining rewards.", + "name": "fund", + "docs": [ + "Fund the pool with rewards. This resets the clock on the end date, pushing it out to the set duration. And, linearly redistributes remaining rewards." ], - accounts: [ - { - name: "pool", - isMut: true, - isSigner: false, - docs: ["Global accounts for the staking instance."], - }, - { - name: "stakingVault", - isMut: true, - isSigner: false, - docs: ["Staking vault PDA"], - }, - { - name: "rewardAVault", - isMut: true, - isSigner: false, - docs: ["Reward A Vault PDA"], - }, - { - name: "rewardBVault", - isMut: true, - isSigner: false, - docs: ["Reward B Vault PDA"], - }, - { - name: "funder", - isMut: false, - isSigner: true, - docs: ["Funder"], - }, - { - name: "fromA", - isMut: true, - isSigner: false, - docs: ["Funder reward A ATA"], - }, - { - name: "fromB", - isMut: true, - isSigner: false, - docs: ["Funder reward B ATA"], - }, - { - name: "tokenProgram", - isMut: false, - isSigner: false, - docs: ["Misc."], - }, + "accounts": [ + { + "name": "pool", + "isMut": true, + "isSigner": false, + "docs": [ + "Global accounts for the staking instance." + ] + }, + { + "name": "stakingVault", + "isMut": true, + "isSigner": false, + "docs": [ + "Staking vault PDA" + ] + }, + { + "name": "rewardAVault", + "isMut": true, + "isSigner": false, + "docs": [ + "Reward A Vault PDA" + ] + }, + { + "name": "rewardBVault", + "isMut": true, + "isSigner": false, + "docs": [ + "Reward B Vault PDA" + ] + }, + { + "name": "funder", + "isMut": false, + "isSigner": true, + "docs": [ + "Funder" + ] + }, + { + "name": "fromA", + "isMut": true, + "isSigner": false, + "docs": [ + "Funder reward A ATA" + ] + }, + { + "name": "fromB", + "isMut": true, + "isSigner": false, + "docs": [ + "Funder reward B ATA" + ] + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false, + "docs": [ + "Misc." + ] + } ], - args: [ + "args": [ { - name: "amountA", - type: "u64", + "name": "amountA", + "type": "u64" }, { - name: "amountB", - type: "u64", - }, - ], + "name": "amountB", + "type": "u64" + } + ] }, { - name: "claim", - docs: ["User claim rewards"], - accounts: [ + "name": "claim", + "docs": [ + "User claim rewards" + ], + "accounts": [ { - name: "pool", - isMut: true, - isSigner: false, - docs: ["Global accounts for the staking instance."], + "name": "pool", + "isMut": true, + "isSigner": false, + "docs": [ + "Global accounts for the staking instance." + ] }, { - name: "stakingVault", - isMut: true, - isSigner: false, - docs: ["Staking vault PDA."], + "name": "stakingVault", + "isMut": true, + "isSigner": false, + "docs": [ + "Staking vault PDA." + ] }, { - name: "rewardAVault", - isMut: true, - isSigner: false, - docs: ["Reward A Vault PDA"], + "name": "rewardAVault", + "isMut": true, + "isSigner": false, + "docs": [ + "Reward A Vault PDA" + ] }, { - name: "rewardBVault", - isMut: true, - isSigner: false, - docs: ["Reward B Vault PDA"], + "name": "rewardBVault", + "isMut": true, + "isSigner": false, + "docs": [ + "Reward B Vault PDA" + ] }, { - name: "user", - isMut: true, - isSigner: false, - docs: ["User."], + "name": "user", + "isMut": true, + "isSigner": false, + "docs": [ + "User." + ] }, { - name: "owner", - isMut: false, - isSigner: true, - docs: ["Authority of user"], + "name": "owner", + "isMut": false, + "isSigner": true, + "docs": [ + "Authority of user" + ] }, { - name: "rewardAAccount", - isMut: true, - isSigner: false, - docs: ["User's Reward A ATA"], + "name": "rewardAAccount", + "isMut": true, + "isSigner": false, + "docs": [ + "User's Reward A ATA" + ] }, { - name: "rewardBAccount", - isMut: true, - isSigner: false, - docs: ["User's Reward B ATA"], + "name": "rewardBAccount", + "isMut": true, + "isSigner": false, + "docs": [ + "User's Reward B ATA" + ] }, { - name: "tokenProgram", - isMut: false, - isSigner: false, - }, + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } ], - args: [], + "args": [] }, { - name: "withdrawExtraToken", - docs: ["Withdraw token that mistakenly deposited to staking_vault"], - accounts: [ - { - name: "pool", - isMut: false, - isSigner: false, - docs: ["Global accounts for the staking instance."], - }, - { - name: "stakingVault", - isMut: true, - isSigner: false, - docs: ["Staking vault PDA"], - }, - { - name: "withdrawToAccount", - isMut: true, - isSigner: false, - docs: ["Token account to receive mistakenly deposited token"], - }, - { - name: "authority", - isMut: false, - isSigner: true, - docs: ["Authority of the staking instance"], - }, - { - name: "tokenProgram", - isMut: false, - isSigner: false, - docs: ["Misc."], - }, + "name": "withdrawExtraToken", + "docs": [ + "Withdraw token that mistakenly deposited to staking_vault" ], - args: [], + "accounts": [ + { + "name": "pool", + "isMut": false, + "isSigner": false, + "docs": [ + "Global accounts for the staking instance." + ] + }, + { + "name": "stakingVault", + "isMut": true, + "isSigner": false, + "docs": [ + "Staking vault PDA" + ] + }, + { + "name": "withdrawToAccount", + "isMut": true, + "isSigner": false, + "docs": [ + "Token account to receive mistakenly deposited token" + ] + }, + { + "name": "authority", + "isMut": false, + "isSigner": true, + "docs": [ + "Authority of the staking instance" + ] + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false, + "docs": [ + "Misc." + ] + } + ], + "args": [] }, { - name: "closeUser", - docs: [ - "Closes a users stake account. Validation is done to ensure this is only allowed when the user has nothing staked and no rewards pending.", + "name": "closeUser", + "docs": [ + "Closes a users stake account. Validation is done to ensure this is only allowed when the user has nothing staked and no rewards pending." ], - accounts: [ + "accounts": [ { - name: "pool", - isMut: true, - isSigner: false, + "name": "pool", + "isMut": true, + "isSigner": false }, { - name: "user", - isMut: true, - isSigner: false, + "name": "user", + "isMut": true, + "isSigner": false }, { - name: "owner", - isMut: true, - isSigner: true, - }, + "name": "owner", + "isMut": true, + "isSigner": true + } ], - args: [], + "args": [] }, { - name: "migrateFarmingRate", - docs: ["anyone can call this"], - accounts: [ + "name": "migrateFarmingRate", + "docs": [ + "anyone can call this" + ], + "accounts": [ { - name: "pool", - isMut: true, - isSigner: false, - }, + "name": "pool", + "isMut": true, + "isSigner": false + } ], - args: [], + "args": [] }, { - name: "closePool", - docs: [ - "Closes a pool account. Only able to be done when there are no users staked.", + "name": "closePool", + "docs": [ + "Closes a pool account. Only able to be done when there are no users staked." ], - accounts: [ + "accounts": [ { - name: "refundee", - isMut: true, - isSigner: false, + "name": "refundee", + "isMut": true, + "isSigner": false }, { - name: "stakingRefundee", - isMut: true, - isSigner: false, + "name": "stakingRefundee", + "isMut": true, + "isSigner": false }, { - name: "rewardARefundee", - isMut: true, - isSigner: false, + "name": "rewardARefundee", + "isMut": true, + "isSigner": false }, { - name: "rewardBRefundee", - isMut: true, - isSigner: false, + "name": "rewardBRefundee", + "isMut": true, + "isSigner": false }, { - name: "pool", - isMut: true, - isSigner: false, + "name": "pool", + "isMut": true, + "isSigner": false }, { - name: "authority", - isMut: false, - isSigner: true, + "name": "authority", + "isMut": false, + "isSigner": true }, { - name: "stakingVault", - isMut: true, - isSigner: false, + "name": "stakingVault", + "isMut": true, + "isSigner": false }, { - name: "rewardAVault", - isMut: true, - isSigner: false, + "name": "rewardAVault", + "isMut": true, + "isSigner": false }, { - name: "rewardBVault", - isMut: true, - isSigner: false, + "name": "rewardBVault", + "isMut": true, + "isSigner": false }, { - name: "tokenProgram", - isMut: false, - isSigner: false, - }, + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } ], - args: [], - }, + "args": [] + } ], - accounts: [ + "accounts": [ { - name: "pool", - docs: ["Pool account wrapper"], - type: { - kind: "struct", - fields: [ + "name": "pool", + "docs": [ + "Pool account wrapper" + ], + "type": { + "kind": "struct", + "fields": [ { - name: "authority", - docs: ["Privileged account."], - type: "publicKey", + "name": "authority", + "docs": [ + "Privileged account." + ], + "type": "publicKey" }, { - name: "paused", - docs: ["Paused state of the program"], - type: "bool", + "name": "paused", + "docs": [ + "Paused state of the program" + ], + "type": "bool" }, { - name: "stakingMint", - docs: ["Mint of the token that can be staked."], - type: "publicKey", + "name": "stakingMint", + "docs": [ + "Mint of the token that can be staked." + ], + "type": "publicKey" }, { - name: "stakingVault", - docs: ["Vault to store staked tokens."], - type: "publicKey", + "name": "stakingVault", + "docs": [ + "Vault to store staked tokens." + ], + "type": "publicKey" }, { - name: "rewardAMint", - docs: ["Mint of the reward A token."], - type: "publicKey", + "name": "rewardAMint", + "docs": [ + "Mint of the reward A token." + ], + "type": "publicKey" }, { - name: "rewardAVault", - docs: ["Vault to store reward A tokens."], - type: "publicKey", + "name": "rewardAVault", + "docs": [ + "Vault to store reward A tokens." + ], + "type": "publicKey" }, { - name: "rewardBMint", - docs: ["Mint of the reward B token."], - type: "publicKey", + "name": "rewardBMint", + "docs": [ + "Mint of the reward B token." + ], + "type": "publicKey" }, { - name: "rewardBVault", - docs: ["Vault to store reward B tokens."], - type: "publicKey", + "name": "rewardBVault", + "docs": [ + "Vault to store reward B tokens." + ], + "type": "publicKey" }, { - name: "baseKey", - docs: ["Base key"], - type: "publicKey", + "name": "baseKey", + "docs": [ + "Base key" + ], + "type": "publicKey" }, { - name: "rewardDuration", - docs: ["The period which rewards are linearly distributed."], - type: "u64", + "name": "rewardDuration", + "docs": [ + "The period which rewards are linearly distributed." + ], + "type": "u64" }, { - name: "rewardDurationEnd", - docs: ["The timestamp at which the current reward period ends."], - type: "u64", + "name": "rewardDurationEnd", + "docs": [ + "The timestamp at which the current reward period ends." + ], + "type": "u64" }, { - name: "lastUpdateTime", - docs: ["The last time reward states were updated."], - type: "u64", + "name": "lastUpdateTime", + "docs": [ + "The last time reward states were updated." + ], + "type": "u64" }, { - name: "rewardARate", - docs: ["deprecated field"], - type: "u64", + "name": "rewardARate", + "docs": [ + "deprecated field" + ], + "type": "u64" }, { - name: "rewardBRate", - docs: ["deprecated field"], - type: "u64", + "name": "rewardBRate", + "docs": [ + "deprecated field" + ], + "type": "u64" }, { - name: "rewardAPerTokenStored", - docs: ["Last calculated reward A per pool token."], - type: "u128", + "name": "rewardAPerTokenStored", + "docs": [ + "Last calculated reward A per pool token." + ], + "type": "u128" }, { - name: "rewardBPerTokenStored", - docs: ["Last calculated reward B per pool token."], - type: "u128", + "name": "rewardBPerTokenStored", + "docs": [ + "Last calculated reward B per pool token." + ], + "type": "u128" }, { - name: "userStakeCount", - docs: ["Users staked"], - type: "u32", + "name": "userStakeCount", + "docs": [ + "Users staked" + ], + "type": "u32" }, { - name: "funders", - docs: [ + "name": "funders", + "docs": [ "authorized funders", "[] because short size, fixed account size, and ease of use on", - "client due to auto generated account size property", + "client due to auto generated account size property" ], - type: { - array: ["publicKey", 3], - }, + "type": { + "array": [ + "publicKey", + 3 + ] + } }, { - name: "rewardARateU128", - docs: ["reward_a_rate in u128 form"], - type: "u128", + "name": "rewardARateU128", + "docs": [ + "reward_a_rate in u128 form" + ], + "type": "u128" }, { - name: "rewardBRateU128", - docs: ["reward_b_rate in u128 form"], - type: "u128", + "name": "rewardBRateU128", + "docs": [ + "reward_b_rate in u128 form" + ], + "type": "u128" }, { - name: "poolBump", - docs: ["Pool bump"], - type: "u8", + "name": "poolBump", + "docs": [ + "Pool bump" + ], + "type": "u8" }, { - name: "totalStaked", - docs: ["Total staked amount"], - type: "u64", - }, - ], - }, + "name": "totalStaked", + "docs": [ + "Total staked amount" + ], + "type": "u64" + } + ] + } }, { - name: "user", - docs: ["Farming user account"], - type: { - kind: "struct", - fields: [ + "name": "user", + "docs": [ + "Farming user account" + ], + "type": { + "kind": "struct", + "fields": [ { - name: "pool", - docs: ["Pool the this user belongs to."], - type: "publicKey", + "name": "pool", + "docs": [ + "Pool the this user belongs to." + ], + "type": "publicKey" }, { - name: "owner", - docs: ["The owner of this account."], - type: "publicKey", + "name": "owner", + "docs": [ + "The owner of this account." + ], + "type": "publicKey" }, { - name: "rewardAPerTokenComplete", - docs: ["The amount of token A claimed."], - type: "u128", + "name": "rewardAPerTokenComplete", + "docs": [ + "The amount of token A claimed." + ], + "type": "u128" }, { - name: "rewardBPerTokenComplete", - docs: ["The amount of token B claimed."], - type: "u128", + "name": "rewardBPerTokenComplete", + "docs": [ + "The amount of token B claimed." + ], + "type": "u128" }, { - name: "rewardAPerTokenPending", - docs: ["The amount of token A pending claim."], - type: "u64", + "name": "rewardAPerTokenPending", + "docs": [ + "The amount of token A pending claim." + ], + "type": "u64" }, { - name: "rewardBPerTokenPending", - docs: ["The amount of token B pending claim."], - type: "u64", + "name": "rewardBPerTokenPending", + "docs": [ + "The amount of token B pending claim." + ], + "type": "u64" }, { - name: "balanceStaked", - docs: ["The amount staked."], - type: "u64", + "name": "balanceStaked", + "docs": [ + "The amount staked." + ], + "type": "u64" }, { - name: "nonce", - docs: ["Signer nonce."], - type: "u8", - }, - ], - }, - }, + "name": "nonce", + "docs": [ + "Signer nonce." + ], + "type": "u8" + } + ] + } + } ], - events: [ + "events": [ { - name: "EventDeposit", - fields: [ + "name": "EventDeposit", + "fields": [ { - name: "amount", - type: "u64", - index: false, - }, - ], + "name": "amount", + "type": "u64", + "index": false + } + ] }, { - name: "EventWithdraw", - fields: [ + "name": "EventWithdraw", + "fields": [ { - name: "amount", - type: "u64", - index: false, - }, - ], + "name": "amount", + "type": "u64", + "index": false + } + ] }, { - name: "EventFund", - fields: [ + "name": "EventFund", + "fields": [ { - name: "amountA", - type: "u64", - index: false, + "name": "amountA", + "type": "u64", + "index": false }, { - name: "amountB", - type: "u64", - index: false, - }, - ], + "name": "amountB", + "type": "u64", + "index": false + } + ] }, { - name: "EventClaim", - fields: [ + "name": "EventClaim", + "fields": [ { - name: "amountA", - type: "u64", - index: false, + "name": "amountA", + "type": "u64", + "index": false }, { - name: "amountB", - type: "u64", - index: false, - }, - ], + "name": "amountB", + "type": "u64", + "index": false + } + ] }, { - name: "EventAuthorizeFunder", - fields: [ + "name": "EventAuthorizeFunder", + "fields": [ { - name: "newFunder", - type: "publicKey", - index: false, - }, - ], + "name": "newFunder", + "type": "publicKey", + "index": false + } + ] }, { - name: "EventUnauthorizeFunder", - fields: [ + "name": "EventUnauthorizeFunder", + "fields": [ { - name: "funder", - type: "publicKey", - index: false, - }, - ], - }, + "name": "funder", + "type": "publicKey", + "index": false + } + ] + } ], - errors: [ + "errors": [ { - code: 6000, - name: "InsufficientFundWithdraw", - msg: "Insufficient funds to withdraw.", + "code": 6000, + "name": "InsufficientFundWithdraw", + "msg": "Insufficient funds to withdraw." }, { - code: 6001, - name: "AmountMustBeGreaterThanZero", - msg: "Amount must be greater than zero.", + "code": 6001, + "name": "AmountMustBeGreaterThanZero", + "msg": "Amount must be greater than zero." }, { - code: 6002, - name: "SingleDepositTokenBCannotBeFunded", - msg: "Reward B cannot be funded - pool is single deposit.", + "code": 6002, + "name": "SingleDepositTokenBCannotBeFunded", + "msg": "Reward B cannot be funded - pool is single deposit." }, { - code: 6003, - name: "PoolPaused", - msg: "Pool is paused.", + "code": 6003, + "name": "PoolPaused", + "msg": "Pool is paused." }, { - code: 6004, - name: "DurationTooShort", - msg: "Duration cannot be shorter than one day.", + "code": 6004, + "name": "DurationTooShort", + "msg": "Duration cannot be shorter than one day." }, { - code: 6005, - name: "FunderAlreadyAuthorized", - msg: "Provided funder is already authorized to fund.", + "code": 6005, + "name": "FunderAlreadyAuthorized", + "msg": "Provided funder is already authorized to fund." }, { - code: 6006, - name: "MaxFunders", - msg: "Maximum funders already authorized.", + "code": 6006, + "name": "MaxFunders", + "msg": "Maximum funders already authorized." }, { - code: 6007, - name: "CannotDeauthorizePoolAuthority", - msg: "Cannot deauthorize the primary pool authority.", + "code": 6007, + "name": "CannotDeauthorizePoolAuthority", + "msg": "Cannot deauthorize the primary pool authority." }, { - code: 6008, - name: "CannotDeauthorizeMissingAuthority", - msg: "Authority not found for deauthorization.", + "code": 6008, + "name": "CannotDeauthorizeMissingAuthority", + "msg": "Authority not found for deauthorization." }, { - code: 6009, - name: "MathOverflow", - msg: "Math operation overflow", - }, - ], + "code": 6009, + "name": "MathOverflow", + "msg": "Math operation overflow" + } + ] }; diff --git a/ts-client/src/tests/farm.test.ts b/ts-client/src/tests/farm.test.ts index 7a692bb..d75aaf7 100644 --- a/ts-client/src/tests/farm.test.ts +++ b/ts-client/src/tests/farm.test.ts @@ -1,9 +1,9 @@ import { Cluster, Connection, Keypair, PublicKey } from "@solana/web3.js"; import AmmImpl from "@mercurial-finance/dynamic-amm-sdk"; -import { PoolFarmImpl } from "../farm"; +import { PoolFarmImpl, getOnchainTime, getClaimableRewardSync } from "../farm"; import { AnchorProvider, BN, Wallet } from "@coral-xyz/anchor"; import { bs58 } from "@coral-xyz/anchor/dist/cjs/utils/bytes"; -import { airDropSol } from "../utils"; +import { airDropSol, getFarmProgram } from "../utils"; import { DEVNET_COIN } from "../constant"; import { TokenListProvider } from "@solana/spl-token-registry"; @@ -41,7 +41,7 @@ describe("Interact with devnet farm", () => { let lpBalance: BN; let stakedBalance: BN; beforeAll(async () => { - await airDropSol(DEVNET.connection, mockWallet.publicKey).catch(() => {}); + await airDropSol(DEVNET.connection, mockWallet.publicKey).catch(() => { }); const USDT = DEVNET_COIN.find( (token) => @@ -150,4 +150,29 @@ describe("Interact with mainnet farm", () => { "9dGX6N3FLAVfKmvtkwHA9MVGsvEqGKnLFDQQFbw5dprr" ); }); + + + test("Get claimable reward", async () => { + let onchainTIme = await getOnchainTime(provider.connection); + const { program } = getFarmProgram(provider.connection); + + const poolAdrr = new PublicKey( + "29DQB5C97HgJg5EKQ2EtnvSk28sS93WkgmnaXErB7HtT" + ); + const poolState = await program.account.pool.fetchNullable(poolAdrr); + const owner = new PublicKey( + "BULRqL3U2jPgwvz6HYCyBVq9BMtK94Y1Nz98KQop23aD" + ) + const [userPda] = PublicKey.findProgramAddressSync( + [owner.toBuffer(), poolAdrr.toBuffer()], + program.programId + ); + + const userState = await program.account.user.fetchNullable(userPda); + + const { a, b } = getClaimableRewardSync(onchainTIme, userState, poolState); + console.log(a.toNumber(), b.toNumber()) + }); + + }); diff --git a/ts-client/src/types.ts b/ts-client/src/types.ts index 1a7a874..b9ba677 100644 --- a/ts-client/src/types.ts +++ b/ts-client/src/types.ts @@ -44,3 +44,18 @@ export type FarmProgram = Program; export type PoolState = IdlAccounts["pool"]; export type UserState = IdlAccounts["user"]; + + +/** Utils */ +export interface ParsedClockState { + info: { + epoch: number; + epochStartTimestamp: number; + leaderScheduleEpoch: number; + slot: number; + unixTimestamp: number; + }; + type: string; + program: string; + space: number; +}