From 02e922331091676e0df7411751f956a535a2a6b0 Mon Sep 17 00:00:00 2001 From: emerson Date: Thu, 3 Nov 2022 00:44:58 +0000 Subject: [PATCH 01/27] v0.2.14-test.2 --- package.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 3080edca..16a99430 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@dappio-wonderland/navigator", - "version": "0.2.14", + "version": "0.2.14-test.2", "description": "Dappio Navigator: The Universal Typescript Client for Instantiating DeFi Protocols", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -21,7 +21,8 @@ "testFriktion": "mocha --require ts-node/register --timeout 10000000 ./test/friktion.ts", "testNftFinance": "mocha --require ts-node/register --timeout 10000000 ./test/nftFinance.ts", "testLido": "mocha --require ts-node/register --timeout 10000000 ./test/lido.ts", - "testMarinade": "mocha --require ts-node/register --timeout 10000000 ./test/marinade.ts" + "testMarinade": "mocha --require ts-node/register --timeout 10000000 ./test/marinade.ts", + "testGenopets": "mocha --require ts-node/register --timeout 10000000 ./test/genopets.ts" }, "keywords": [], "author": "", From 0fb68088a613bfebbc89269c383011381baaee80 Mon Sep 17 00:00:00 2001 From: emerson Date: Thu, 3 Nov 2022 01:00:10 +0000 Subject: [PATCH 02/27] v0.2.14-test.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 16a99430..d09359b1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@dappio-wonderland/navigator", - "version": "0.2.14-test.2", + "version": "0.2.14-test.3", "description": "Dappio Navigator: The Universal Typescript Client for Instantiating DeFi Protocols", "main": "dist/index.js", "types": "dist/index.d.ts", From 384fd2d83e8c0a0732711426cbea86edc33f2013 Mon Sep 17 00:00:00 2001 From: emerson Date: Thu, 3 Nov 2022 01:02:27 +0000 Subject: [PATCH 03/27] v0.2.14-test.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d09359b1..8261bfa8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@dappio-wonderland/navigator", - "version": "0.2.14-test.3", + "version": "0.2.14-test.4", "description": "Dappio Navigator: The Universal Typescript Client for Instantiating DeFi Protocols", "main": "dist/index.js", "types": "dist/index.d.ts", From ae19d1a1e3b295b9ec72e021313a5996d68bd1b5 Mon Sep 17 00:00:00 2001 From: emerson Date: Thu, 3 Nov 2022 01:27:55 +0000 Subject: [PATCH 04/27] v0.2.14-test.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8261bfa8..e595fee6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@dappio-wonderland/navigator", - "version": "0.2.14-test.4", + "version": "0.2.14-test.5", "description": "Dappio Navigator: The Universal Typescript Client for Instantiating DeFi Protocols", "main": "dist/index.js", "types": "dist/index.d.ts", From ea8ea6474110efaab7efffdd6d026cf77d5d3f03 Mon Sep 17 00:00:00 2001 From: emerson Date: Thu, 3 Nov 2022 01:41:11 +0000 Subject: [PATCH 05/27] v0.2.14-test.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e595fee6..0d8dee03 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@dappio-wonderland/navigator", - "version": "0.2.14-test.5", + "version": "0.2.14-test.6", "description": "Dappio Navigator: The Universal Typescript Client for Instantiating DeFi Protocols", "main": "dist/index.js", "types": "dist/index.d.ts", From d4a34fc4664cc1c6fe0027ad9398828ca3b5087c Mon Sep 17 00:00:00 2001 From: emerson Date: Thu, 3 Nov 2022 01:44:47 +0000 Subject: [PATCH 06/27] wip --- src/genopets/ids.ts | 3 + src/genopets/index.ts | 39 ++++++++ src/genopets/infos.ts | 192 ++++++++++++++++++++++++++++++++++++++++ src/genopets/layouts.ts | 53 +++++++++++ src/index.ts | 1 + test/genopets.ts | 47 ++++++++++ 6 files changed, 335 insertions(+) create mode 100644 src/genopets/ids.ts create mode 100644 src/genopets/index.ts create mode 100644 src/genopets/infos.ts create mode 100644 src/genopets/layouts.ts create mode 100644 test/genopets.ts diff --git a/src/genopets/ids.ts b/src/genopets/ids.ts new file mode 100644 index 00000000..d76f6c6f --- /dev/null +++ b/src/genopets/ids.ts @@ -0,0 +1,3 @@ +import { PublicKey } from "@solana/web3.js"; + +export const GENOPETS_FARM_PROGRAM_ID = new PublicKey("StaKe9nb7aUjXpjpZ45o6uJBsZxj2BWCDBtjk8LCg2v"); diff --git a/src/genopets/index.ts b/src/genopets/index.ts new file mode 100644 index 00000000..b03f8562 --- /dev/null +++ b/src/genopets/index.ts @@ -0,0 +1,39 @@ +import { PublicKey } from "@solana/web3.js"; +import BN from "bn.js"; +import { IFarmInfo, IFarmerInfo } from "../types"; + +export * from "./ids"; +export * from "./infos"; +export * from "./layouts"; + +export interface FarmInfo extends IFarmInfo { + authority: PublicKey; + sgeneMinter: PublicKey; + mintSgene: PublicKey; + geneMint: PublicKey; + geneRewarder: PublicKey; + totalGeneRewarded: BN; + ataGeneRewarder: PublicKey; + totalGeneAllocated: BN; + totalWeight: BN; + startTime: BN; + endTime: BN; + epochTime: BN; + decayFactorPerEpoch: BN; + initialGenesPerEpoch: BN; + stakeParams: BN; + pausedState: BN; + totalRewardWeight: BN; + accumulatedYieldRewardsPerWeight: BN; + lastYieldDistribution: BN; + totalGeneStaked: BN; + timeFactor: BN; +} + +export interface FarmerInfo extends IFarmerInfo { + totalRewardWeight: BN; + subYieldRewards: BN; + activeDeposits: BN; + totalRewards: BN; + currentDepositIndex: BN; +} diff --git a/src/genopets/infos.ts b/src/genopets/infos.ts new file mode 100644 index 00000000..ef8fed85 --- /dev/null +++ b/src/genopets/infos.ts @@ -0,0 +1,192 @@ +import { Connection, PublicKey, AccountInfo } from "@solana/web3.js"; +import { IFarmInfoWrapper, IInstanceFarm } from "../types"; +import { GENOPETS_FARM_PROGRAM_ID } from "./ids"; +import { FARMER_LAYOUT, FARM_LAYOUT } from "./layouts"; +import * as types from "."; +import { BN } from "bn.js"; + +let infos: IInstanceFarm; +infos = class InstanceGenopets { + static async getAllFarms(connection: Connection): Promise { + const farmId = PublicKey.findProgramAddressSync([Buffer.from("stake-master-seed")], GENOPETS_FARM_PROGRAM_ID)[0]; + const farmAccountInfo = await connection.getAccountInfo(farmId); + const farm = this.parseFarm(farmAccountInfo?.data!, farmId); + + return [farm]; + } + + static async getAllFarmWrappers(connection: Connection): Promise { + return (await this.getAllFarms(connection)).map((farmInfo) => new FarmInfoWrapper(farmInfo)); + } + + static async getFarm(connection: Connection, farmId: PublicKey): Promise { + const expectedFarmId = PublicKey.findProgramAddressSync( + [Buffer.from("stake-master-seed")], + GENOPETS_FARM_PROGRAM_ID + )[0]; + if (!farmId.equals(expectedFarmId)) throw "Error: Wrong farmId."; + let account = (await connection.getAccountInfo(farmId)) as AccountInfo; + return this.parseFarm(account.data, farmId); + } + + static async getFarmWrapper(connection: Connection, farmId: PublicKey): Promise { + const farm = await this.getFarm(connection, farmId); + + return new FarmInfoWrapper(farm); + } + + static parseFarm(data: Buffer, farmId: PublicKey): types.FarmInfo { + const decodedData = FARM_LAYOUT.decode(data); + + let { + authority, + sgeneMinter, + mintSgene, + geneMint, + geneRewarder, + totalGeneRewarded, + ataGeneRewarder, + totalGeneAllocated, + totalWeight, + startTime, + endTime, + epochTime, + decayFactorPerEpoch, + initialGenesPerEpoch, + stakeParams, + pausedState, + totalRewardWeight, + accumulatedYieldRewardsPerWeight, + lastYieldDistribution, + totalGeneStaked, + timeFactor, + } = decodedData; + + return { + farmId, + authority, + sgeneMinter, + mintSgene, + geneMint, + geneRewarder, + totalGeneRewarded, + ataGeneRewarder, + totalGeneAllocated, + totalWeight, + startTime, + endTime, + epochTime, + decayFactorPerEpoch, + initialGenesPerEpoch, + stakeParams, + pausedState, + totalRewardWeight, + accumulatedYieldRewardsPerWeight, + lastYieldDistribution, + totalGeneStaked, + timeFactor, + }; + } + + static async getAllFarmers(connection: Connection, userKey: PublicKey): Promise { + const farmerId = PublicKey.findProgramAddressSync( + [Buffer.from("staker-seed"), userKey.toBuffer()], + GENOPETS_FARM_PROGRAM_ID + )[0]; + const farmerAccountInfo = await connection.getAccountInfo(farmerId); + let farmer = this.parseFarmer(farmerAccountInfo?.data!, farmerId); + return [farmer]; + } + + static async getFarmerId(farmInfo: types.FarmInfo, userKey: PublicKey): Promise { + const [farmerId, _] = PublicKey.findProgramAddressSync( + [Buffer.from("staker-seed"), userKey.toBuffer()], + GENOPETS_FARM_PROGRAM_ID + ); + + return farmerId; + } + + static async getFarmer(connection: Connection, farmerId: PublicKey, version?: number): Promise { + let data = (await connection.getAccountInfo(farmerId)) as AccountInfo; + return this.parseFarmer(data.data, farmerId); + } + + static parseFarmer(data: Buffer, farmerId: PublicKey): types.FarmerInfo { + let decodedData = FARMER_LAYOUT.decode(data); + let { owner, totalRewardWeight, subYieldRewards, activeDeposits, totalRewards, currentDepositIndex } = decodedData; + + return { + farmerId, + userKey: new PublicKey(owner), + totalRewardWeight, + subYieldRewards, + activeDeposits, + totalRewards, + currentDepositIndex, + }; + } +}; + +export { infos }; + +export class FarmInfoWrapper implements IFarmInfoWrapper { + constructor(public farmInfo: types.FarmInfo) {} + + getStakedAmount(): number { + // TODO + return 0; + } + + getAprs(_x: number, _y: number, _z: number): number[] { + // TODO + return []; + } + + getStakingPool(mint: PublicKey) { + return PublicKey.findProgramAddressSync( + [Buffer.from("stake-pool-seed"), mint.toBuffer()], + GENOPETS_FARM_PROGRAM_ID + )[0]; + } + + calcUserDeposit(userKey: PublicKey) { + return PublicKey.findProgramAddressSync( + [Buffer.from("staking-deposit"), userKey.toBuffer(), new BN(0).toArrayLike(Buffer, `le`, 4)], + GENOPETS_FARM_PROGRAM_ID + )[0]; + } + + calcUserReDeposit(userKey: PublicKey) { + return PublicKey.findProgramAddressSync( + [Buffer.from("staking-deposit"), userKey.toBuffer(), new BN(1).toArrayLike(Buffer, `le`, 4)], + GENOPETS_FARM_PROGRAM_ID + )[0]; + } +} + +export class FarmerInfoWrapper { + constructor(public farmerInfo: types.FarmerInfo) {} + + getUserDeposit() { + return PublicKey.findProgramAddressSync( + [ + Buffer.from("staking-deposit"), + this.farmerInfo.userKey.toBuffer(), + new BN(this.farmerInfo.currentDepositIndex).toArrayLike(Buffer, `le`, 4), + ], + GENOPETS_FARM_PROGRAM_ID + )[0]; + } + + getUserReDeposit() { + return PublicKey.findProgramAddressSync( + [ + Buffer.from("staking-deposit"), + this.farmerInfo.userKey.toBuffer(), + new BN(this.farmerInfo.currentDepositIndex).add(new BN(1)).toArrayLike(Buffer, `le`, 4), + ], + GENOPETS_FARM_PROGRAM_ID + )[0]; + } +} diff --git a/src/genopets/layouts.ts b/src/genopets/layouts.ts new file mode 100644 index 00000000..05a2e803 --- /dev/null +++ b/src/genopets/layouts.ts @@ -0,0 +1,53 @@ +import { publicKey, struct, u64, u128, u8, bool, u16, i64, u32, f64 } from "@project-serum/borsh"; +// @ts-ignore +import { blob } from "buffer-layout"; + +// StakingPool +export const POOL_LAYOUT = struct([ + u64("discriminator"), + publicKey("poolToken"), + u8("tokenDecimals"), + u32("weight"), + u64("earliestUnlockDate"), + u64("usersLockingWeight"), + u64("poolTokenReserve"), + u32("weightPerToken"), + bool("governanceEligible"), +]); + +// StakeMaster +export const FARM_LAYOUT = struct([ + u64("discriminator"), + publicKey("authority"), + publicKey("sgeneMinter"), + publicKey("mintSgene"), + publicKey("geneMint"), + publicKey("geneRewarder"), + u64("totalGeneRewarded"), + publicKey("ataGeneRewarder"), + u64("totalGeneAllocated"), + u32("totalWeight"), + u64("startTime"), + u32("endTime"), + u64("epochTime"), + f64("decayFactorPerEpoch"), + u64("initialGenesPerEpoch"), + u32("stakeParams"), + bool("pausedState"), + u64("totalRewardWeight"), + u64("accumulatedYieldRewardsPerWeight"), + u64("lastYieldDistribution"), + u64("totalGeneStaked"), + u64("timeFactor"), +]); + +// Staker +export const FARMER_LAYOUT = struct([ + u64("discriminator"), + publicKey("owner"), + u64("totalRewardWeight"), + u64("subYieldRewards"), + u32("activeDeposits"), + u64("totalRewards"), + u32("currentDepositIndex"), +]); diff --git a/src/index.ts b/src/index.ts index c602e105..c03e1366 100644 --- a/src/index.ts +++ b/src/index.ts @@ -12,3 +12,4 @@ export * as tulip from "./tulip"; export * as nftFinance from "./nftFinance"; export * as friktion from "./friktion"; export * as lido from "./lido"; +export * as genopets from "./genopets"; diff --git a/test/genopets.ts b/test/genopets.ts new file mode 100644 index 00000000..2242f18f --- /dev/null +++ b/test/genopets.ts @@ -0,0 +1,47 @@ +import { Connection, PublicKey } from "@solana/web3.js"; +import { genopets } from "../src"; + +describe("Genopets", () => { + // const connection = new Connection("https://rpc-mainnet-fork.dappio.xyz", { + // commitment, + // wsEndpoint: "wss://rpc-mainnet-fork.dappio.xyz/ws", + // }); + // const connection = new Connection("https://solana-api.tt-prod.net", { + // commitment: "confirmed", + // confirmTransactionInitialTimeout: 180 * 1000, + // }); + // const connection = new Connection("https://ssc-dao.genesysgo.net", { + // commitment: "confirmed", + // confirmTransactionInitialTimeout: 180 * 1000, + // }); + const connection = new Connection("https:////api.mainnet-beta.solana.com", { + commitment: "confirmed", + confirmTransactionInitialTimeout: 180 * 1000, + }); + // const connection = new Connection("https://rpc-mainnet-fork.epochs.studio", { + // commitment: "confirmed", + // confirmTransactionInitialTimeout: 180 * 1000, + // wsEndpoint: "wss://rpc-mainnet-fork.epochs.studio/ws", + // }); + + const userKey = new PublicKey("D6fo1sf7natK7fdtdGMHZPV4b7HXrNBVdndV5qtHzNsw"); + + it("Fetch all farms", async () => { + const farms = await genopets.infos.getAllFarms(connection); + const farm0 = farms[0]; + const farm = (await genopets.infos.getFarm(connection, farm0.farmId)) as genopets.FarmInfo; + console.log("farm:", farm); + console.log("farm authority:", farm.authority.toBase58()); + console.log("farm geneMint:", farm.geneMint.toBase58()); + console.log("farm mintSgene:", farm.mintSgene.toBase58()); + + const farmerWrapper = new genopets.FarmInfoWrapper(farm); + const userDeposit = farmerWrapper.calcUserDeposit(userKey); + console.log("userDeposit:", userDeposit.toBase58()); + }); + + it("Fetch all farmers", async () => { + const farmer = await genopets.infos.getAllFarmers(connection, userKey); + console.log("farmer:", farmer); + }); +}); From 6651fb3808ff51479087ca96bcd1099d0fa0f90a Mon Sep 17 00:00:00 2001 From: emerson Date: Thu, 3 Nov 2022 12:07:19 +0000 Subject: [PATCH 07/27] v0.2.14-test.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0d8dee03..ea62d385 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@dappio-wonderland/navigator", - "version": "0.2.14-test.6", + "version": "0.2.14-test.7", "description": "Dappio Navigator: The Universal Typescript Client for Instantiating DeFi Protocols", "main": "dist/index.js", "types": "dist/index.d.ts", From 519edcac4c2f52599372df9bc09f5e2a493349ef Mon Sep 17 00:00:00 2001 From: emerson Date: Thu, 3 Nov 2022 12:39:59 +0000 Subject: [PATCH 08/27] Add deposit in farmer --- src/genopets/index.ts | 16 +++++++++ src/genopets/infos.ts | 76 +++++++++++++++++++++++++++++++++++++++-- src/genopets/layouts.ts | 17 +++++++++ 3 files changed, 106 insertions(+), 3 deletions(-) diff --git a/src/genopets/index.ts b/src/genopets/index.ts index b03f8562..3aa27d5a 100644 --- a/src/genopets/index.ts +++ b/src/genopets/index.ts @@ -36,4 +36,20 @@ export interface FarmerInfo extends IFarmerInfo { activeDeposits: BN; totalRewards: BN; currentDepositIndex: BN; + userDeposit: Deposit[]; +} + +export interface Deposit { + user: PublicKey; + amount: BN; + poolToken: PublicKey; + rewardWeight: BN; + depositTimestamp: BN; + depositMultiplier: BN; + lockFrom: BN; + lockUntil: BN; + isYield: boolean; + tokenDecimals: BN; + active: boolean; + governanceEligible: boolean; } diff --git a/src/genopets/infos.ts b/src/genopets/infos.ts index ef8fed85..a1808a76 100644 --- a/src/genopets/infos.ts +++ b/src/genopets/infos.ts @@ -1,7 +1,14 @@ -import { Connection, PublicKey, AccountInfo } from "@solana/web3.js"; +import { + Connection, + PublicKey, + AccountInfo, + DataSizeFilter, + MemcmpFilter, + GetProgramAccountsConfig, +} from "@solana/web3.js"; import { IFarmInfoWrapper, IInstanceFarm } from "../types"; import { GENOPETS_FARM_PROGRAM_ID } from "./ids"; -import { FARMER_LAYOUT, FARM_LAYOUT } from "./layouts"; +import { DEPOSIT_LAYOUT, FARMER_LAYOUT, FARM_LAYOUT } from "./layouts"; import * as types from "."; import { BN } from "bn.js"; @@ -95,6 +102,20 @@ infos = class InstanceGenopets { )[0]; const farmerAccountInfo = await connection.getAccountInfo(farmerId); let farmer = this.parseFarmer(farmerAccountInfo?.data!, farmerId); + const sizeFilter: DataSizeFilter = { + dataSize: 244, + }; + const ownerIdFilter: MemcmpFilter = { + memcmp: { + offset: 8, + bytes: farmer.userKey.toString(), + }, + }; + const filters = [sizeFilter, ownerIdFilter]; + const config: GetProgramAccountsConfig = { filters: filters }; + const depositAccounts = await connection.getProgramAccounts(GENOPETS_FARM_PROGRAM_ID, config); + farmer.userDeposit = depositAccounts.map((deposit) => this._parseDeposit(deposit.account.data)); + return [farmer]; } @@ -109,7 +130,22 @@ infos = class InstanceGenopets { static async getFarmer(connection: Connection, farmerId: PublicKey, version?: number): Promise { let data = (await connection.getAccountInfo(farmerId)) as AccountInfo; - return this.parseFarmer(data.data, farmerId); + let farmer = this.parseFarmer(data.data, farmerId); + const sizeFilter: DataSizeFilter = { + dataSize: 244, + }; + const ownerIdFilter: MemcmpFilter = { + memcmp: { + offset: 8, + bytes: farmer.userKey.toString(), + }, + }; + const filters = [sizeFilter, ownerIdFilter]; + const config: GetProgramAccountsConfig = { filters: filters }; + const depositAccounts = await connection.getProgramAccounts(GENOPETS_FARM_PROGRAM_ID, config); + farmer.userDeposit = depositAccounts.map((deposit) => this._parseDeposit(deposit.account.data)); + + return farmer; } static parseFarmer(data: Buffer, farmerId: PublicKey): types.FarmerInfo { @@ -124,6 +160,40 @@ infos = class InstanceGenopets { activeDeposits, totalRewards, currentDepositIndex, + userDeposit: [], + }; + } + + private static _parseDeposit(data: Buffer): types.Deposit { + let decodedData = DEPOSIT_LAYOUT.decode(data); + let { + user, + amount, + poolToken, + rewardWeight, + depositTimestamp, + depositMultiplier, + lockFrom, + lockUntil, + isYield, + tokenDecimals, + active, + governanceEligible, + } = decodedData; + + return { + user, + amount, + poolToken, + rewardWeight, + depositTimestamp, + depositMultiplier, + lockFrom, + lockUntil, + isYield, + tokenDecimals, + active, + governanceEligible, }; } }; diff --git a/src/genopets/layouts.ts b/src/genopets/layouts.ts index 05a2e803..bc06112c 100644 --- a/src/genopets/layouts.ts +++ b/src/genopets/layouts.ts @@ -51,3 +51,20 @@ export const FARMER_LAYOUT = struct([ u64("totalRewards"), u32("currentDepositIndex"), ]); + +// Deposit +export const DEPOSIT_LAYOUT = struct([ + u64("discriminator"), + publicKey("user"), + u64("amount"), + publicKey("poolToken"), + u64("rewardWeight"), + u64("depositTimestamp"), + f64("depositMultiplier"), + u64("lockFrom"), + u64("lockUntil"), + bool("isYield"), + u8("tokenDecimals"), + bool("active"), + bool("governanceEligible"), +]); From 26325cd166408306abbbc5e93f694d217a307d4c Mon Sep 17 00:00:00 2001 From: emerson Date: Thu, 3 Nov 2022 12:40:11 +0000 Subject: [PATCH 09/27] Update farmer test --- test/genopets.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/test/genopets.ts b/test/genopets.ts index 2242f18f..961c857a 100644 --- a/test/genopets.ts +++ b/test/genopets.ts @@ -3,7 +3,7 @@ import { genopets } from "../src"; describe("Genopets", () => { // const connection = new Connection("https://rpc-mainnet-fork.dappio.xyz", { - // commitment, + // commitment: "confirmed", // wsEndpoint: "wss://rpc-mainnet-fork.dappio.xyz/ws", // }); // const connection = new Connection("https://solana-api.tt-prod.net", { @@ -14,17 +14,17 @@ describe("Genopets", () => { // commitment: "confirmed", // confirmTransactionInitialTimeout: 180 * 1000, // }); - const connection = new Connection("https:////api.mainnet-beta.solana.com", { - commitment: "confirmed", - confirmTransactionInitialTimeout: 180 * 1000, - }); - // const connection = new Connection("https://rpc-mainnet-fork.epochs.studio", { + // const connection = new Connection("https:////api.mainnet-beta.solana.com", { // commitment: "confirmed", // confirmTransactionInitialTimeout: 180 * 1000, - // wsEndpoint: "wss://rpc-mainnet-fork.epochs.studio/ws", // }); + const connection = new Connection("https://rpc-mainnet-fork.epochs.studio", { + commitment: "confirmed", + confirmTransactionInitialTimeout: 180 * 1000, + wsEndpoint: "wss://rpc-mainnet-fork.epochs.studio/ws", + }); - const userKey = new PublicKey("D6fo1sf7natK7fdtdGMHZPV4b7HXrNBVdndV5qtHzNsw"); + const userKey = new PublicKey("3bnAKgVhM1MihYpJQ6hK83BirWhVFbyhkvvCQqJ8tZ25"); it("Fetch all farms", async () => { const farms = await genopets.infos.getAllFarms(connection); @@ -41,7 +41,8 @@ describe("Genopets", () => { }); it("Fetch all farmers", async () => { - const farmer = await genopets.infos.getAllFarmers(connection, userKey); + const farmer = (await genopets.infos.getAllFarmers(connection, userKey)) as genopets.FarmerInfo[]; console.log("farmer:", farmer); + farmer[0].userDeposit.forEach((farmer, index) => console.log(`# ${index}:`, farmer)); }); }); From a8fe84e9bdea5fcaff10e2d6c0446ef254f6737a Mon Sep 17 00:00:00 2001 From: emerson Date: Thu, 3 Nov 2022 14:39:25 +0000 Subject: [PATCH 10/27] Add Id to Deposit interface --- src/genopets/index.ts | 1 + src/genopets/infos.ts | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/genopets/index.ts b/src/genopets/index.ts index 3aa27d5a..0fda5628 100644 --- a/src/genopets/index.ts +++ b/src/genopets/index.ts @@ -40,6 +40,7 @@ export interface FarmerInfo extends IFarmerInfo { } export interface Deposit { + depositId: PublicKey; user: PublicKey; amount: BN; poolToken: PublicKey; diff --git a/src/genopets/infos.ts b/src/genopets/infos.ts index a1808a76..629a3ad3 100644 --- a/src/genopets/infos.ts +++ b/src/genopets/infos.ts @@ -114,7 +114,7 @@ infos = class InstanceGenopets { const filters = [sizeFilter, ownerIdFilter]; const config: GetProgramAccountsConfig = { filters: filters }; const depositAccounts = await connection.getProgramAccounts(GENOPETS_FARM_PROGRAM_ID, config); - farmer.userDeposit = depositAccounts.map((deposit) => this._parseDeposit(deposit.account.data)); + farmer.userDeposit = depositAccounts.map((deposit) => this._parseDeposit(deposit.account.data, deposit.pubkey)); return [farmer]; } @@ -143,7 +143,7 @@ infos = class InstanceGenopets { const filters = [sizeFilter, ownerIdFilter]; const config: GetProgramAccountsConfig = { filters: filters }; const depositAccounts = await connection.getProgramAccounts(GENOPETS_FARM_PROGRAM_ID, config); - farmer.userDeposit = depositAccounts.map((deposit) => this._parseDeposit(deposit.account.data)); + farmer.userDeposit = depositAccounts.map((deposit) => this._parseDeposit(deposit.account.data, deposit.pubkey)); return farmer; } @@ -164,7 +164,7 @@ infos = class InstanceGenopets { }; } - private static _parseDeposit(data: Buffer): types.Deposit { + private static _parseDeposit(data: Buffer, depositId: PublicKey): types.Deposit { let decodedData = DEPOSIT_LAYOUT.decode(data); let { user, @@ -182,6 +182,7 @@ infos = class InstanceGenopets { } = decodedData; return { + depositId, user, amount, poolToken, From 13d1e1815fcfe1fa46ee97c307db697bbd502240 Mon Sep 17 00:00:00 2001 From: emerson Date: Thu, 3 Nov 2022 14:40:03 +0000 Subject: [PATCH 11/27] v0.2.14-test.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ea62d385..39247d8e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@dappio-wonderland/navigator", - "version": "0.2.14-test.7", + "version": "0.2.14-test.8", "description": "Dappio Navigator: The Universal Typescript Client for Instantiating DeFi Protocols", "main": "dist/index.js", "types": "dist/index.d.ts", From aad5adaf9c6b9ea01a46d7eb4f172a664654cf3b Mon Sep 17 00:00:00 2001 From: emerson Date: Thu, 3 Nov 2022 15:07:11 +0000 Subject: [PATCH 12/27] Update getFarmer --- src/genopets/index.ts | 2 +- src/genopets/infos.ts | 82 ++++++++++++++----------------------------- 2 files changed, 27 insertions(+), 57 deletions(-) diff --git a/src/genopets/index.ts b/src/genopets/index.ts index 0fda5628..c7e19ee8 100644 --- a/src/genopets/index.ts +++ b/src/genopets/index.ts @@ -36,7 +36,7 @@ export interface FarmerInfo extends IFarmerInfo { activeDeposits: BN; totalRewards: BN; currentDepositIndex: BN; - userDeposit: Deposit[]; + userDeposit: (Deposit | null)[]; } export interface Deposit { diff --git a/src/genopets/infos.ts b/src/genopets/infos.ts index 629a3ad3..311a9099 100644 --- a/src/genopets/infos.ts +++ b/src/genopets/infos.ts @@ -11,6 +11,7 @@ import { GENOPETS_FARM_PROGRAM_ID } from "./ids"; import { DEPOSIT_LAYOUT, FARMER_LAYOUT, FARM_LAYOUT } from "./layouts"; import * as types from "."; import { BN } from "bn.js"; +import { getMultipleAccounts } from "../utils"; let infos: IInstanceFarm; infos = class InstanceGenopets { @@ -102,19 +103,14 @@ infos = class InstanceGenopets { )[0]; const farmerAccountInfo = await connection.getAccountInfo(farmerId); let farmer = this.parseFarmer(farmerAccountInfo?.data!, farmerId); - const sizeFilter: DataSizeFilter = { - dataSize: 244, - }; - const ownerIdFilter: MemcmpFilter = { - memcmp: { - offset: 8, - bytes: farmer.userKey.toString(), - }, - }; - const filters = [sizeFilter, ownerIdFilter]; - const config: GetProgramAccountsConfig = { filters: filters }; - const depositAccounts = await connection.getProgramAccounts(GENOPETS_FARM_PROGRAM_ID, config); - farmer.userDeposit = depositAccounts.map((deposit) => this._parseDeposit(deposit.account.data, deposit.pubkey)); + const depositKeys: PublicKey[] = []; + for (let i = 0; i < Number(farmer.currentDepositIndex); i++) { + depositKeys.push(calcDeposit(farmer.userKey, i)); + } + const depositAccounts = await getMultipleAccounts(connection, depositKeys); + farmer.userDeposit = depositAccounts.map((deposit) => { + return deposit.account?.data ? this._parseDeposit(deposit.account?.data, deposit.pubkey) : null; + }); return [farmer]; } @@ -131,19 +127,14 @@ infos = class InstanceGenopets { static async getFarmer(connection: Connection, farmerId: PublicKey, version?: number): Promise { let data = (await connection.getAccountInfo(farmerId)) as AccountInfo; let farmer = this.parseFarmer(data.data, farmerId); - const sizeFilter: DataSizeFilter = { - dataSize: 244, - }; - const ownerIdFilter: MemcmpFilter = { - memcmp: { - offset: 8, - bytes: farmer.userKey.toString(), - }, - }; - const filters = [sizeFilter, ownerIdFilter]; - const config: GetProgramAccountsConfig = { filters: filters }; - const depositAccounts = await connection.getProgramAccounts(GENOPETS_FARM_PROGRAM_ID, config); - farmer.userDeposit = depositAccounts.map((deposit) => this._parseDeposit(deposit.account.data, deposit.pubkey)); + const depositKeys: PublicKey[] = []; + for (let i = 0; i < Number(farmer.currentDepositIndex); i++) { + depositKeys.push(calcDeposit(farmer.userKey, i)); + } + const depositAccounts = await getMultipleAccounts(connection, depositKeys); + farmer.userDeposit = depositAccounts.map((deposit) => { + return deposit.account?.data ? this._parseDeposit(deposit.account?.data, deposit.pubkey) : null; + }); return farmer; } @@ -220,44 +211,23 @@ export class FarmInfoWrapper implements IFarmInfoWrapper { GENOPETS_FARM_PROGRAM_ID )[0]; } - - calcUserDeposit(userKey: PublicKey) { - return PublicKey.findProgramAddressSync( - [Buffer.from("staking-deposit"), userKey.toBuffer(), new BN(0).toArrayLike(Buffer, `le`, 4)], - GENOPETS_FARM_PROGRAM_ID - )[0]; - } - - calcUserReDeposit(userKey: PublicKey) { - return PublicKey.findProgramAddressSync( - [Buffer.from("staking-deposit"), userKey.toBuffer(), new BN(1).toArrayLike(Buffer, `le`, 4)], - GENOPETS_FARM_PROGRAM_ID - )[0]; - } } export class FarmerInfoWrapper { constructor(public farmerInfo: types.FarmerInfo) {} getUserDeposit() { - return PublicKey.findProgramAddressSync( - [ - Buffer.from("staking-deposit"), - this.farmerInfo.userKey.toBuffer(), - new BN(this.farmerInfo.currentDepositIndex).toArrayLike(Buffer, `le`, 4), - ], - GENOPETS_FARM_PROGRAM_ID - )[0]; + return calcDeposit(this.farmerInfo.userKey, Number(this.farmerInfo.currentDepositIndex)); } getUserReDeposit() { - return PublicKey.findProgramAddressSync( - [ - Buffer.from("staking-deposit"), - this.farmerInfo.userKey.toBuffer(), - new BN(this.farmerInfo.currentDepositIndex).add(new BN(1)).toArrayLike(Buffer, `le`, 4), - ], - GENOPETS_FARM_PROGRAM_ID - )[0]; + return calcDeposit(this.farmerInfo.userKey, Number(this.farmerInfo.currentDepositIndex) + 1); } } + +export function calcDeposit(userKey: PublicKey, nonce: number) { + return PublicKey.findProgramAddressSync( + [Buffer.from("staking-deposit"), userKey.toBuffer(), new BN(nonce).toArrayLike(Buffer, `le`, 4)], + GENOPETS_FARM_PROGRAM_ID + )[0]; +} From a1036320871f97fc63dd399e3d97543535db6230 Mon Sep 17 00:00:00 2001 From: emerson Date: Thu, 3 Nov 2022 15:07:18 +0000 Subject: [PATCH 13/27] Update test --- test/genopets.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/genopets.ts b/test/genopets.ts index 961c857a..e3fbb5d1 100644 --- a/test/genopets.ts +++ b/test/genopets.ts @@ -36,13 +36,13 @@ describe("Genopets", () => { console.log("farm mintSgene:", farm.mintSgene.toBase58()); const farmerWrapper = new genopets.FarmInfoWrapper(farm); - const userDeposit = farmerWrapper.calcUserDeposit(userKey); + const userDeposit = genopets.calcDeposit(userKey, 0); console.log("userDeposit:", userDeposit.toBase58()); }); it("Fetch all farmers", async () => { const farmer = (await genopets.infos.getAllFarmers(connection, userKey)) as genopets.FarmerInfo[]; console.log("farmer:", farmer); - farmer[0].userDeposit.forEach((farmer, index) => console.log(`# ${index}:`, farmer)); + farmer[0].userDeposit.forEach((farmer, index) => console.log(`# ${index}:`, farmer?.depositId.toBase58())); }); }); From 287ac3c06e31f23d25c1ef0a0176ba6d6aeaca92 Mon Sep 17 00:00:00 2001 From: emerson Date: Thu, 3 Nov 2022 15:07:48 +0000 Subject: [PATCH 14/27] v0.2.14-test.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 39247d8e..197ed5b9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@dappio-wonderland/navigator", - "version": "0.2.14-test.8", + "version": "0.2.14-test.9", "description": "Dappio Navigator: The Universal Typescript Client for Instantiating DeFi Protocols", "main": "dist/index.js", "types": "dist/index.d.ts", From 618bc687fa272cdb61fa329e0c73bc4e50407614 Mon Sep 17 00:00:00 2001 From: emerson Date: Thu, 3 Nov 2022 15:49:25 +0000 Subject: [PATCH 15/27] Fix layout issue --- src/genopets/index.ts | 5 ++++- src/genopets/layouts.ts | 4 ++-- test/genopets.ts | 5 ++++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/genopets/index.ts b/src/genopets/index.ts index c7e19ee8..b19985fe 100644 --- a/src/genopets/index.ts +++ b/src/genopets/index.ts @@ -21,7 +21,10 @@ export interface FarmInfo extends IFarmInfo { epochTime: BN; decayFactorPerEpoch: BN; initialGenesPerEpoch: BN; - stakeParams: BN; + stakeParams: { + minStakeDuration: BN; + maxStakeDuration: BN; + }; pausedState: BN; totalRewardWeight: BN; accumulatedYieldRewardsPerWeight: BN; diff --git a/src/genopets/layouts.ts b/src/genopets/layouts.ts index bc06112c..072f6d6a 100644 --- a/src/genopets/layouts.ts +++ b/src/genopets/layouts.ts @@ -1,4 +1,4 @@ -import { publicKey, struct, u64, u128, u8, bool, u16, i64, u32, f64 } from "@project-serum/borsh"; +import { publicKey, struct, u64, u128, u8, bool, u16, i64, u32, f64, str } from "@project-serum/borsh"; // @ts-ignore import { blob } from "buffer-layout"; @@ -32,7 +32,7 @@ export const FARM_LAYOUT = struct([ u64("epochTime"), f64("decayFactorPerEpoch"), u64("initialGenesPerEpoch"), - u32("stakeParams"), + struct([u8("minStakeDuration"), u8("maxStakeDuration")], "stakeParams"), bool("pausedState"), u64("totalRewardWeight"), u64("accumulatedYieldRewardsPerWeight"), diff --git a/test/genopets.ts b/test/genopets.ts index e3fbb5d1..e12400cc 100644 --- a/test/genopets.ts +++ b/test/genopets.ts @@ -43,6 +43,9 @@ describe("Genopets", () => { it("Fetch all farmers", async () => { const farmer = (await genopets.infos.getAllFarmers(connection, userKey)) as genopets.FarmerInfo[]; console.log("farmer:", farmer); - farmer[0].userDeposit.forEach((farmer, index) => console.log(`# ${index}:`, farmer?.depositId.toBase58())); + farmer[0].userDeposit.forEach((farmer, index) => { + if (farmer?.user.equals(userKey)) + console.log(`# ${index}:`, farmer?.depositId.toBase58(), ", is_yield:", farmer.isYield); + }); }); }); From 7d913bfd49f6dd6dc92baa80037439a7b91762b3 Mon Sep 17 00:00:00 2001 From: emerson Date: Thu, 3 Nov 2022 15:49:55 +0000 Subject: [PATCH 16/27] v0.2.14-test.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 197ed5b9..a6687d52 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@dappio-wonderland/navigator", - "version": "0.2.14-test.9", + "version": "0.2.14-test.10", "description": "Dappio Navigator: The Universal Typescript Client for Instantiating DeFi Protocols", "main": "dist/index.js", "types": "dist/index.d.ts", From 04c60f5f2e7c25f9385056388232d30e83fcbb54 Mon Sep 17 00:00:00 2001 From: emerson Date: Thu, 3 Nov 2022 20:44:34 +0000 Subject: [PATCH 17/27] Rename --- src/genopets/infos.ts | 13 +++---------- src/genopets/layouts.ts | 4 ++-- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/src/genopets/infos.ts b/src/genopets/infos.ts index 311a9099..595512dd 100644 --- a/src/genopets/infos.ts +++ b/src/genopets/infos.ts @@ -1,14 +1,7 @@ -import { - Connection, - PublicKey, - AccountInfo, - DataSizeFilter, - MemcmpFilter, - GetProgramAccountsConfig, -} from "@solana/web3.js"; +import { Connection, PublicKey, AccountInfo } from "@solana/web3.js"; import { IFarmInfoWrapper, IInstanceFarm } from "../types"; import { GENOPETS_FARM_PROGRAM_ID } from "./ids"; -import { DEPOSIT_LAYOUT, FARMER_LAYOUT, FARM_LAYOUT } from "./layouts"; +import { FARMER_DEPOSIT_LAYOUT, FARMER_LAYOUT, FARM_LAYOUT } from "./layouts"; import * as types from "."; import { BN } from "bn.js"; import { getMultipleAccounts } from "../utils"; @@ -156,7 +149,7 @@ infos = class InstanceGenopets { } private static _parseDeposit(data: Buffer, depositId: PublicKey): types.Deposit { - let decodedData = DEPOSIT_LAYOUT.decode(data); + let decodedData = FARMER_DEPOSIT_LAYOUT.decode(data); let { user, amount, diff --git a/src/genopets/layouts.ts b/src/genopets/layouts.ts index 072f6d6a..36a44286 100644 --- a/src/genopets/layouts.ts +++ b/src/genopets/layouts.ts @@ -3,7 +3,7 @@ import { publicKey, struct, u64, u128, u8, bool, u16, i64, u32, f64, str } from import { blob } from "buffer-layout"; // StakingPool -export const POOL_LAYOUT = struct([ +export const FARM_INSTANCE_LAYOUT = struct([ u64("discriminator"), publicKey("poolToken"), u8("tokenDecimals"), @@ -53,7 +53,7 @@ export const FARMER_LAYOUT = struct([ ]); // Deposit -export const DEPOSIT_LAYOUT = struct([ +export const FARMER_DEPOSIT_LAYOUT = struct([ u64("discriminator"), publicKey("user"), u64("amount"), From 81d2582cf589526a81a28e44a00e4512a88fe911 Mon Sep 17 00:00:00 2001 From: emerson Date: Thu, 3 Nov 2022 21:18:53 +0000 Subject: [PATCH 18/27] Remove check and add error handling --- src/genopets/infos.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/genopets/infos.ts b/src/genopets/infos.ts index 595512dd..21144e9f 100644 --- a/src/genopets/infos.ts +++ b/src/genopets/infos.ts @@ -21,12 +21,8 @@ infos = class InstanceGenopets { } static async getFarm(connection: Connection, farmId: PublicKey): Promise { - const expectedFarmId = PublicKey.findProgramAddressSync( - [Buffer.from("stake-master-seed")], - GENOPETS_FARM_PROGRAM_ID - )[0]; - if (!farmId.equals(expectedFarmId)) throw "Error: Wrong farmId."; let account = (await connection.getAccountInfo(farmId)) as AccountInfo; + if (!account) throw "Error: Failed to get farm"; return this.parseFarm(account.data, farmId); } From 90fafd4f0a6f218197e1b24c3dca6c9f0f4abf57 Mon Sep 17 00:00:00 2001 From: emerson Date: Thu, 3 Nov 2022 21:19:44 +0000 Subject: [PATCH 19/27] Rename function --- src/genopets/infos.ts | 10 +++++----- test/genopets.ts | 11 +++++++++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/genopets/infos.ts b/src/genopets/infos.ts index 21144e9f..f54f6cb8 100644 --- a/src/genopets/infos.ts +++ b/src/genopets/infos.ts @@ -94,7 +94,7 @@ infos = class InstanceGenopets { let farmer = this.parseFarmer(farmerAccountInfo?.data!, farmerId); const depositKeys: PublicKey[] = []; for (let i = 0; i < Number(farmer.currentDepositIndex); i++) { - depositKeys.push(calcDeposit(farmer.userKey, i)); + depositKeys.push(getFarmerDepositKey(farmer.userKey, i)); } const depositAccounts = await getMultipleAccounts(connection, depositKeys); farmer.userDeposit = depositAccounts.map((deposit) => { @@ -118,7 +118,7 @@ infos = class InstanceGenopets { let farmer = this.parseFarmer(data.data, farmerId); const depositKeys: PublicKey[] = []; for (let i = 0; i < Number(farmer.currentDepositIndex); i++) { - depositKeys.push(calcDeposit(farmer.userKey, i)); + depositKeys.push(getFarmerDepositKey(farmer.userKey, i)); } const depositAccounts = await getMultipleAccounts(connection, depositKeys); farmer.userDeposit = depositAccounts.map((deposit) => { @@ -206,15 +206,15 @@ export class FarmerInfoWrapper { constructor(public farmerInfo: types.FarmerInfo) {} getUserDeposit() { - return calcDeposit(this.farmerInfo.userKey, Number(this.farmerInfo.currentDepositIndex)); + return getFarmerDepositKey(this.farmerInfo.userKey, Number(this.farmerInfo.currentDepositIndex)); } getUserReDeposit() { - return calcDeposit(this.farmerInfo.userKey, Number(this.farmerInfo.currentDepositIndex) + 1); + return getFarmerDepositKey(this.farmerInfo.userKey, Number(this.farmerInfo.currentDepositIndex) + 1); } } -export function calcDeposit(userKey: PublicKey, nonce: number) { +export function getFarmerDepositKey(userKey: PublicKey, nonce: number) { return PublicKey.findProgramAddressSync( [Buffer.from("staking-deposit"), userKey.toBuffer(), new BN(nonce).toArrayLike(Buffer, `le`, 4)], GENOPETS_FARM_PROGRAM_ID diff --git a/test/genopets.ts b/test/genopets.ts index e12400cc..a4019695 100644 --- a/test/genopets.ts +++ b/test/genopets.ts @@ -36,7 +36,7 @@ describe("Genopets", () => { console.log("farm mintSgene:", farm.mintSgene.toBase58()); const farmerWrapper = new genopets.FarmInfoWrapper(farm); - const userDeposit = genopets.calcDeposit(userKey, 0); + const userDeposit = genopets.getFarmerDepositKey(userKey, 0); console.log("userDeposit:", userDeposit.toBase58()); }); @@ -45,7 +45,14 @@ describe("Genopets", () => { console.log("farmer:", farmer); farmer[0].userDeposit.forEach((farmer, index) => { if (farmer?.user.equals(userKey)) - console.log(`# ${index}:`, farmer?.depositId.toBase58(), ", is_yield:", farmer.isYield); + console.log( + `# ${index}:`, + farmer?.depositId.toBase58(), + ", is_yield:", + farmer.isYield, + ", timestamp:", + Number(farmer.lockUntil) + ); }); }); }); From 4db1ad4f3a9e2570382a7ebe7a7489a34dd3c064 Mon Sep 17 00:00:00 2001 From: emerson Date: Thu, 3 Nov 2022 21:30:23 +0000 Subject: [PATCH 20/27] Remove redundant --- src/genopets/infos.ts | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/genopets/infos.ts b/src/genopets/infos.ts index f54f6cb8..fd1bd7a4 100644 --- a/src/genopets/infos.ts +++ b/src/genopets/infos.ts @@ -90,16 +90,7 @@ infos = class InstanceGenopets { [Buffer.from("staker-seed"), userKey.toBuffer()], GENOPETS_FARM_PROGRAM_ID )[0]; - const farmerAccountInfo = await connection.getAccountInfo(farmerId); - let farmer = this.parseFarmer(farmerAccountInfo?.data!, farmerId); - const depositKeys: PublicKey[] = []; - for (let i = 0; i < Number(farmer.currentDepositIndex); i++) { - depositKeys.push(getFarmerDepositKey(farmer.userKey, i)); - } - const depositAccounts = await getMultipleAccounts(connection, depositKeys); - farmer.userDeposit = depositAccounts.map((deposit) => { - return deposit.account?.data ? this._parseDeposit(deposit.account?.data, deposit.pubkey) : null; - }); + const farmer = await this.getFarmer(connection, farmerId); return [farmer]; } @@ -121,9 +112,11 @@ infos = class InstanceGenopets { depositKeys.push(getFarmerDepositKey(farmer.userKey, i)); } const depositAccounts = await getMultipleAccounts(connection, depositKeys); - farmer.userDeposit = depositAccounts.map((deposit) => { - return deposit.account?.data ? this._parseDeposit(deposit.account?.data, deposit.pubkey) : null; - }); + farmer.userDeposit = depositAccounts + .map((deposit) => { + return deposit.account?.data ? this._parseDeposit(deposit.account?.data, deposit.pubkey) : null; + }) + .filter((deposit) => Boolean(deposit)) as types.Deposit[]; return farmer; } From a354cc835939fe3dcd5555879b0eee4e7ec32ae8 Mon Sep 17 00:00:00 2001 From: emerson Date: Thu, 3 Nov 2022 21:30:31 +0000 Subject: [PATCH 21/27] Update type --- src/genopets/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/genopets/index.ts b/src/genopets/index.ts index b19985fe..d1e4f5e9 100644 --- a/src/genopets/index.ts +++ b/src/genopets/index.ts @@ -39,7 +39,7 @@ export interface FarmerInfo extends IFarmerInfo { activeDeposits: BN; totalRewards: BN; currentDepositIndex: BN; - userDeposit: (Deposit | null)[]; + userDeposit: Deposit[]; } export interface Deposit { From 0b2401b809e3e0fd9f63f19983754c65fcfa8359 Mon Sep 17 00:00:00 2001 From: emerson Date: Thu, 3 Nov 2022 21:31:38 +0000 Subject: [PATCH 22/27] v0.2.14-test.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a6687d52..6ae315d2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@dappio-wonderland/navigator", - "version": "0.2.14-test.10", + "version": "0.2.14-test.11", "description": "Dappio Navigator: The Universal Typescript Client for Instantiating DeFi Protocols", "main": "dist/index.js", "types": "dist/index.d.ts", From 9e87238a354f38efb1816c0b0a0844bf0a9c9554 Mon Sep 17 00:00:00 2001 From: emerson Date: Thu, 3 Nov 2022 22:26:33 +0000 Subject: [PATCH 23/27] Rename function --- src/genopets/infos.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/genopets/infos.ts b/src/genopets/infos.ts index fd1bd7a4..1ebe3ee3 100644 --- a/src/genopets/infos.ts +++ b/src/genopets/infos.ts @@ -187,7 +187,7 @@ export class FarmInfoWrapper implements IFarmInfoWrapper { return []; } - getStakingPool(mint: PublicKey) { + getFarmInstance(mint: PublicKey) { return PublicKey.findProgramAddressSync( [Buffer.from("stake-pool-seed"), mint.toBuffer()], GENOPETS_FARM_PROGRAM_ID From 33f5fcacbc8ebfa6e424064bc80843dd8b40a1a0 Mon Sep 17 00:00:00 2001 From: emerson Date: Fri, 4 Nov 2022 00:03:05 +0000 Subject: [PATCH 24/27] Refactor --- src/genopets/ids.ts | 3 ++ src/genopets/index.ts | 46 ++++++++++++++++- src/genopets/infos.ts | 111 +++++++++++++++++++++++++--------------- src/genopets/layouts.ts | 6 +-- src/genopets/utils.ts | 17 ++++++ test/genopets.ts | 12 +++-- 6 files changed, 145 insertions(+), 50 deletions(-) create mode 100644 src/genopets/utils.ts diff --git a/src/genopets/ids.ts b/src/genopets/ids.ts index d76f6c6f..3bbdc315 100644 --- a/src/genopets/ids.ts +++ b/src/genopets/ids.ts @@ -1,3 +1,6 @@ import { PublicKey } from "@solana/web3.js"; export const GENOPETS_FARM_PROGRAM_ID = new PublicKey("StaKe9nb7aUjXpjpZ45o6uJBsZxj2BWCDBtjk8LCg2v"); + +// calculate by findProgramAddressSync([Buffer.from("stake-master-seed")], GENOPETS_FARM_PROGRAM_ID) +export const FARM_MASTER_ID = new PublicKey("tEAbLeDznDdQ5jvdk1cdm2qUzoYmyc6nX5FChAyAB2U"); diff --git a/src/genopets/index.ts b/src/genopets/index.ts index d1e4f5e9..584812fb 100644 --- a/src/genopets/index.ts +++ b/src/genopets/index.ts @@ -5,8 +5,22 @@ import { IFarmInfo, IFarmerInfo } from "../types"; export * from "./ids"; export * from "./infos"; export * from "./layouts"; +export * from "./utils"; export interface FarmInfo extends IFarmInfo { + master: FarmMaster; + poolToken: PublicKey; + tokenDecimals: BN; + weight: BN; + earliestUnlockDate: BN; + usersLockingWeight: BN; + poolTokenReserve: BN; + weightPerToken: BN; + governanceEligible: boolean; +} + +export interface FarmMaster { + id: PublicKey; authority: PublicKey; sgeneMinter: PublicKey; mintSgene: PublicKey; @@ -39,10 +53,10 @@ export interface FarmerInfo extends IFarmerInfo { activeDeposits: BN; totalRewards: BN; currentDepositIndex: BN; - userDeposit: Deposit[]; + instance: FarmerInstance[]; } -export interface Deposit { +export interface FarmerInstance { depositId: PublicKey; user: PublicKey; amount: BN; @@ -57,3 +71,31 @@ export interface Deposit { active: boolean; governanceEligible: boolean; } + +export const defaultFarmerMaster = { + id: PublicKey.default, + authority: PublicKey.default, + sgeneMinter: PublicKey.default, + mintSgene: PublicKey.default, + geneMint: PublicKey.default, + geneRewarder: PublicKey.default, + totalGeneRewarded: new BN(0), + ataGeneRewarder: PublicKey.default, + totalGeneAllocated: new BN(0), + totalWeight: new BN(0), + startTime: new BN(0), + endTime: new BN(0), + epochTime: new BN(0), + decayFactorPerEpoch: new BN(0), + initialGenesPerEpoch: new BN(0), + stakeParams: { + minStakeDuration: new BN(0), + maxStakeDuration: new BN(0), + }, + pausedState: new BN(0), + totalRewardWeight: new BN(0), + accumulatedYieldRewardsPerWeight: new BN(0), + lastYieldDistribution: new BN(0), + totalGeneStaked: new BN(0), + timeFactor: new BN(0), +}; diff --git a/src/genopets/infos.ts b/src/genopets/infos.ts index 1ebe3ee3..33323a86 100644 --- a/src/genopets/infos.ts +++ b/src/genopets/infos.ts @@ -1,19 +1,30 @@ -import { Connection, PublicKey, AccountInfo } from "@solana/web3.js"; +import { Connection, PublicKey, AccountInfo, DataSizeFilter, GetProgramAccountsConfig } from "@solana/web3.js"; import { IFarmInfoWrapper, IInstanceFarm } from "../types"; -import { GENOPETS_FARM_PROGRAM_ID } from "./ids"; -import { FARMER_DEPOSIT_LAYOUT, FARMER_LAYOUT, FARM_LAYOUT } from "./layouts"; +import { FARM_MASTER_ID, GENOPETS_FARM_PROGRAM_ID } from "./ids"; +import { FARMER_INSTANCE_LAYOUT, FARMER_LAYOUT, FARM_MASTER_LAYOUT, FARM_LAYOUT } from "./layouts"; import * as types from "."; -import { BN } from "bn.js"; import { getMultipleAccounts } from "../utils"; +import { getFarmerInstanceKey } from "./utils"; let infos: IInstanceFarm; infos = class InstanceGenopets { static async getAllFarms(connection: Connection): Promise { - const farmId = PublicKey.findProgramAddressSync([Buffer.from("stake-master-seed")], GENOPETS_FARM_PROGRAM_ID)[0]; - const farmAccountInfo = await connection.getAccountInfo(farmId); - const farm = this.parseFarm(farmAccountInfo?.data!, farmId); + const farmMasterAccount = await connection.getAccountInfo(FARM_MASTER_ID); + const farmMaster = this._parseFarmMaster(farmMasterAccount?.data!, FARM_MASTER_ID); - return [farm]; + const sizeFilter: DataSizeFilter = { + dataSize: 250, + }; + const filters = [sizeFilter]; + const config: GetProgramAccountsConfig = { filters: filters }; + const allFarms = await connection.getProgramAccounts(GENOPETS_FARM_PROGRAM_ID, config); + const farms = allFarms.map((account) => { + let farm = this.parseFarm(account.account.data, account.pubkey); + farm.master = farmMaster; + return farm; + }); + + return farms; } static async getAllFarmWrappers(connection: Connection): Promise { @@ -21,9 +32,13 @@ infos = class InstanceGenopets { } static async getFarm(connection: Connection, farmId: PublicKey): Promise { - let account = (await connection.getAccountInfo(farmId)) as AccountInfo; - if (!account) throw "Error: Failed to get farm"; - return this.parseFarm(account.data, farmId); + const [farmMasterAccount, farmAccount] = await getMultipleAccounts(connection, [FARM_MASTER_ID, farmId]); + if (!farmMasterAccount || !farmAccount) throw "Error: Failed to get farm"; + const farmMaster = this._parseFarmMaster(farmMasterAccount.account?.data!, FARM_MASTER_ID); + let farm = this.parseFarm(farmAccount.account?.data!, farmId); + farm.master = farmMaster; + + return farm; } static async getFarmWrapper(connection: Connection, farmId: PublicKey): Promise { @@ -35,6 +50,34 @@ infos = class InstanceGenopets { static parseFarm(data: Buffer, farmId: PublicKey): types.FarmInfo { const decodedData = FARM_LAYOUT.decode(data); + let { + poolToken, + tokenDecimals, + weight, + earliestUnlockDate, + usersLockingWeight, + poolTokenReserve, + weightPerToken, + governanceEligible, + } = decodedData; + + return { + farmId, + master: types.defaultFarmerMaster, + poolToken, + tokenDecimals, + weight, + earliestUnlockDate, + usersLockingWeight, + poolTokenReserve, + weightPerToken, + governanceEligible, + }; + } + + private static _parseFarmMaster(data: Buffer, id: PublicKey): types.FarmMaster { + const decodedData = FARM_MASTER_LAYOUT.decode(data); + let { authority, sgeneMinter, @@ -60,7 +103,7 @@ infos = class InstanceGenopets { } = decodedData; return { - farmId, + id, authority, sgeneMinter, mintSgene, @@ -107,16 +150,18 @@ infos = class InstanceGenopets { static async getFarmer(connection: Connection, farmerId: PublicKey, version?: number): Promise { let data = (await connection.getAccountInfo(farmerId)) as AccountInfo; let farmer = this.parseFarmer(data.data, farmerId); - const depositKeys: PublicKey[] = []; + const farmerInstanceKeys: PublicKey[] = []; for (let i = 0; i < Number(farmer.currentDepositIndex); i++) { - depositKeys.push(getFarmerDepositKey(farmer.userKey, i)); + farmerInstanceKeys.push(getFarmerInstanceKey(farmer.userKey, i)); } - const depositAccounts = await getMultipleAccounts(connection, depositKeys); - farmer.userDeposit = depositAccounts - .map((deposit) => { - return deposit.account?.data ? this._parseDeposit(deposit.account?.data, deposit.pubkey) : null; + const farmerInstanceAccounts = await getMultipleAccounts(connection, farmerInstanceKeys); + farmer.instance = farmerInstanceAccounts + .map((farmerInstance) => { + return farmerInstance.account?.data + ? this._parseFarmerInstance(farmerInstance.account?.data, farmerInstance.pubkey) + : null; }) - .filter((deposit) => Boolean(deposit)) as types.Deposit[]; + .filter((farmerInstance) => Boolean(farmerInstance)) as types.FarmerInstance[]; return farmer; } @@ -133,12 +178,12 @@ infos = class InstanceGenopets { activeDeposits, totalRewards, currentDepositIndex, - userDeposit: [], + instance: [], }; } - private static _parseDeposit(data: Buffer, depositId: PublicKey): types.Deposit { - let decodedData = FARMER_DEPOSIT_LAYOUT.decode(data); + private static _parseFarmerInstance(data: Buffer, depositId: PublicKey): types.FarmerInstance { + let decodedData = FARMER_INSTANCE_LAYOUT.decode(data); let { user, amount, @@ -186,30 +231,16 @@ export class FarmInfoWrapper implements IFarmInfoWrapper { // TODO return []; } - - getFarmInstance(mint: PublicKey) { - return PublicKey.findProgramAddressSync( - [Buffer.from("stake-pool-seed"), mint.toBuffer()], - GENOPETS_FARM_PROGRAM_ID - )[0]; - } } export class FarmerInfoWrapper { constructor(public farmerInfo: types.FarmerInfo) {} - getUserDeposit() { - return getFarmerDepositKey(this.farmerInfo.userKey, Number(this.farmerInfo.currentDepositIndex)); + getFarmerInstance() { + return getFarmerInstanceKey(this.farmerInfo.userKey, Number(this.farmerInfo.currentDepositIndex)); } - getUserReDeposit() { - return getFarmerDepositKey(this.farmerInfo.userKey, Number(this.farmerInfo.currentDepositIndex) + 1); + getLatestFarmerInstance() { + return getFarmerInstanceKey(this.farmerInfo.userKey, Number(this.farmerInfo.currentDepositIndex) + 1); } } - -export function getFarmerDepositKey(userKey: PublicKey, nonce: number) { - return PublicKey.findProgramAddressSync( - [Buffer.from("staking-deposit"), userKey.toBuffer(), new BN(nonce).toArrayLike(Buffer, `le`, 4)], - GENOPETS_FARM_PROGRAM_ID - )[0]; -} diff --git a/src/genopets/layouts.ts b/src/genopets/layouts.ts index 36a44286..a2c8b954 100644 --- a/src/genopets/layouts.ts +++ b/src/genopets/layouts.ts @@ -3,7 +3,7 @@ import { publicKey, struct, u64, u128, u8, bool, u16, i64, u32, f64, str } from import { blob } from "buffer-layout"; // StakingPool -export const FARM_INSTANCE_LAYOUT = struct([ +export const FARM_LAYOUT = struct([ u64("discriminator"), publicKey("poolToken"), u8("tokenDecimals"), @@ -16,7 +16,7 @@ export const FARM_INSTANCE_LAYOUT = struct([ ]); // StakeMaster -export const FARM_LAYOUT = struct([ +export const FARM_MASTER_LAYOUT = struct([ u64("discriminator"), publicKey("authority"), publicKey("sgeneMinter"), @@ -53,7 +53,7 @@ export const FARMER_LAYOUT = struct([ ]); // Deposit -export const FARMER_DEPOSIT_LAYOUT = struct([ +export const FARMER_INSTANCE_LAYOUT = struct([ u64("discriminator"), publicKey("user"), u64("amount"), diff --git a/src/genopets/utils.ts b/src/genopets/utils.ts new file mode 100644 index 00000000..fc8c961b --- /dev/null +++ b/src/genopets/utils.ts @@ -0,0 +1,17 @@ +import { PublicKey } from "@solana/web3.js"; +import { BN } from "bn.js"; +import { GENOPETS_FARM_PROGRAM_ID } from "./ids"; + +export function getFarmerInstanceKey(userKey: PublicKey, nonce: number): PublicKey { + return PublicKey.findProgramAddressSync( + [Buffer.from("staking-deposit"), userKey.toBuffer(), new BN(nonce).toArrayLike(Buffer, `le`, 4)], + GENOPETS_FARM_PROGRAM_ID + )[0]; +} + +export function getFarmId(mint: PublicKey): PublicKey { + return PublicKey.findProgramAddressSync( + [Buffer.from("stake-pool-seed"), mint.toBuffer()], + GENOPETS_FARM_PROGRAM_ID + )[0]; +} diff --git a/test/genopets.ts b/test/genopets.ts index a4019695..13595040 100644 --- a/test/genopets.ts +++ b/test/genopets.ts @@ -31,19 +31,21 @@ describe("Genopets", () => { const farm0 = farms[0]; const farm = (await genopets.infos.getFarm(connection, farm0.farmId)) as genopets.FarmInfo; console.log("farm:", farm); - console.log("farm authority:", farm.authority.toBase58()); - console.log("farm geneMint:", farm.geneMint.toBase58()); - console.log("farm mintSgene:", farm.mintSgene.toBase58()); + console.log("farm pool token:", farm.poolToken.toBase58()); + console.log("farm master authority:", farm.master.authority.toBase58()); + console.log("farm master geneMint:", farm.master.geneMint.toBase58()); + console.log("farm master mintSgene:", farm.master.mintSgene.toBase58()); const farmerWrapper = new genopets.FarmInfoWrapper(farm); - const userDeposit = genopets.getFarmerDepositKey(userKey, 0); + const userDeposit = genopets.getFarmerInstanceKey(userKey, 0); console.log("userDeposit:", userDeposit.toBase58()); }); it("Fetch all farmers", async () => { const farmer = (await genopets.infos.getAllFarmers(connection, userKey)) as genopets.FarmerInfo[]; console.log("farmer:", farmer); - farmer[0].userDeposit.forEach((farmer, index) => { + console.log("farmer:", farmer[0].farmerId.toBase58()); + farmer[0].instance.forEach((farmer, index) => { if (farmer?.user.equals(userKey)) console.log( `# ${index}:`, From b9b1967e0301b2790510c0ed65955d8f59770ad3 Mon Sep 17 00:00:00 2001 From: emerson Date: Fri, 4 Nov 2022 00:03:49 +0000 Subject: [PATCH 25/27] v0.2.14-test.12 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6ae315d2..2efb310e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@dappio-wonderland/navigator", - "version": "0.2.14-test.11", + "version": "0.2.14-test.12", "description": "Dappio Navigator: The Universal Typescript Client for Instantiating DeFi Protocols", "main": "dist/index.js", "types": "dist/index.d.ts", From 27d36f65176fe0538d0fac07ee56b53e772e5def Mon Sep 17 00:00:00 2001 From: emerson Date: Fri, 4 Nov 2022 00:20:51 +0000 Subject: [PATCH 26/27] Rename --- src/genopets/index.ts | 2 +- src/genopets/infos.ts | 2 +- test/genopets.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/genopets/index.ts b/src/genopets/index.ts index 584812fb..84a08faf 100644 --- a/src/genopets/index.ts +++ b/src/genopets/index.ts @@ -57,7 +57,7 @@ export interface FarmerInfo extends IFarmerInfo { } export interface FarmerInstance { - depositId: PublicKey; + id: PublicKey; user: PublicKey; amount: BN; poolToken: PublicKey; diff --git a/src/genopets/infos.ts b/src/genopets/infos.ts index 33323a86..25b80ba6 100644 --- a/src/genopets/infos.ts +++ b/src/genopets/infos.ts @@ -200,7 +200,7 @@ infos = class InstanceGenopets { } = decodedData; return { - depositId, + id: depositId, user, amount, poolToken, diff --git a/test/genopets.ts b/test/genopets.ts index 13595040..8fc9717f 100644 --- a/test/genopets.ts +++ b/test/genopets.ts @@ -49,7 +49,7 @@ describe("Genopets", () => { if (farmer?.user.equals(userKey)) console.log( `# ${index}:`, - farmer?.depositId.toBase58(), + farmer?.id.toBase58(), ", is_yield:", farmer.isYield, ", timestamp:", From 897e95867618daf84487a1c55dec808f2e86ef44 Mon Sep 17 00:00:00 2001 From: emerson Date: Fri, 4 Nov 2022 00:21:25 +0000 Subject: [PATCH 27/27] v0.2.14-test.13 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2efb310e..2c72e547 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@dappio-wonderland/navigator", - "version": "0.2.14-test.12", + "version": "0.2.14-test.13", "description": "Dappio Navigator: The Universal Typescript Client for Instantiating DeFi Protocols", "main": "dist/index.js", "types": "dist/index.d.ts",