diff --git a/package.json b/package.json index 18eaf70..c67d5a1 100644 --- a/package.json +++ b/package.json @@ -8,8 +8,8 @@ "dist" ], "dependencies": { - "@dappio-wonderland/gateway-idls": "^0.2.6", - "@dappio-wonderland/navigator": "^0.2.11", + "@dappio-wonderland/gateway-idls": "^0.2.7-test.3", + "@dappio-wonderland/navigator": "^0.2.14-test.13", "@jup-ag/core": "1.0.0-beta.26", "@project-serum/anchor": "^0.24.2", "@project-serum/borsh": "^0.2.5", @@ -45,6 +45,7 @@ "testAdapterNftFinance": "ANCHOR_WALLET=~/.config/solana/gateway.json ts-mocha -p ./tsconfig.json -t 1000000 tests/testAdapterNftFinance.ts", "testAdapterFrancium": "ANCHOR_WALLET=~/.config/solana/gateway.json ts-mocha -p ./tsconfig.json -t 1000000 tests/testAdapterFrancium.ts", "testAdapterKatana": "ANCHOR_WALLET=~/.config/solana/gateway.json ts-mocha -p ./tsconfig.json -t 1000000 tests/testAdapterKatana.ts", - "testAdapterFriktion": "ANCHOR_WALLET=~/.config/solana/gateway.json ts-mocha -p ./tsconfig.json -t 1000000 tests/testAdapterFriktion.ts" + "testAdapterFriktion": "ANCHOR_WALLET=~/.config/solana/gateway.json ts-mocha -p ./tsconfig.json -t 1000000 tests/testAdapterFriktion.ts", + "testAdapterGenopets": "ANCHOR_WALLET=~/.config/solana/gateway.json ts-mocha -p ./tsconfig.json -t 1000000 tests/testAdapterGenopets.ts" } } diff --git a/src/builder.ts b/src/builder.ts index 366f968..d1c2818 100644 --- a/src/builder.ts +++ b/src/builder.ts @@ -14,6 +14,7 @@ import { nftFinance, katana, friktion, + genopets, } from "@dappio-wonderland/navigator"; import { ActionType, @@ -63,6 +64,7 @@ import { ProtocolFrancium } from "./protocols/francium"; import { ProtocolKatana } from "./protocols/katana"; import { ProtocolTulip } from "./protocols/tulip"; import { ProtocolFriktion } from "./protocols/friktion"; +import { ProtocolGenopets } from "./protocols/genopets"; export class GatewayBuilder { public params: GatewayParams; @@ -109,6 +111,8 @@ export class GatewayBuilder { // Extra Metadata poolDirection: PoolDirection.Obverse, swapMinOutAmount: new anchor.BN(0), + lockDuration: 0, + harvestType: 0, }; this._metadata = { @@ -437,6 +441,20 @@ export class GatewayBuilder { this.params ); + break; + case SupportedProtocols.Genopets: + this._metadata.farm = await genopets.infos.getFarm( + this._provider.connection, + stakeParams.farmId + ); + + protocol = new ProtocolGenopets( + this._provider.connection, + this._program, + await this.getGatewayStateKey(), + this.params + ); + break; default: throw new Error("Unsupported Protocol"); @@ -539,6 +557,20 @@ export class GatewayBuilder { this.params ); + break; + case SupportedProtocols.Genopets: + this._metadata.farm = await genopets.infos.getFarm( + this._provider.connection, + unstakeParams.farmId + ); + + protocol = new ProtocolGenopets( + this._provider.connection, + this._program, + await this.getGatewayStateKey(), + this.params + ); + break; default: throw new Error("Unsupported Protocol"); @@ -627,6 +659,20 @@ export class GatewayBuilder { await this.getGatewayStateKey(), this.params ); + break; + case SupportedProtocols.Genopets: + this._metadata.farm = await genopets.infos.getFarm( + this._provider.connection, + harvestParams.farmId + ); + + protocol = new ProtocolGenopets( + this._provider.connection, + this._program, + await this.getGatewayStateKey(), + this.params + ); + break; default: throw new Error("Unsupported Protocol"); diff --git a/src/ids.ts b/src/ids.ts index 65343a9..0ea949e 100644 --- a/src/ids.ts +++ b/src/ids.ts @@ -3,7 +3,7 @@ import { PublicKey } from "@solana/web3.js"; // Program IDs export const GATEWAY_PROGRAM_ID = new PublicKey( - "GATEp6AEtXtwHABNWHKH9qeh3uJDZtZJ7YBNYzHsX3FS" + "9dwUanLrLHoaUEw7YYZG4VkqWWvMpxjmNYmTB71Gzwnu" ); export const RAYDIUM_ADAPTER_PROGRAM_ID = new PublicKey( @@ -26,6 +26,10 @@ export const NFT_FINANCE_ADAPTER_PROGRAM_ID = new PublicKey( "ADPTyBr92sBCE1hdYBRvXbMpF4hKs17xyDjFPxopcsrh" ); +export const GENOPETS_ADAPTER_PROGRAM_ID = new PublicKey( + "ADPTR3wPKDCZ8HNBBpY3GGXB8hu6DZDqyPJMimyHjKNk" +); + export const SERUM_PROGRAM_ID = new PublicKey( "9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin" ); diff --git a/src/protocols/genopets.ts b/src/protocols/genopets.ts new file mode 100644 index 0000000..d055077 --- /dev/null +++ b/src/protocols/genopets.ts @@ -0,0 +1,599 @@ +import * as anchor from "@project-serum/anchor"; +import { + TOKEN_PROGRAM_ID, + getAssociatedTokenAddress, + ASSOCIATED_TOKEN_PROGRAM_ID, +} from "@solana/spl-token-v2"; +import { struct, u64, u8 } from "@project-serum/borsh"; +import { + createATAWithoutCheckIx, + getActivityIndex, + getGatewayAuthority, +} from "../utils"; +import { IFarmInfo, genopets } from "@dappio-wonderland/navigator"; +import { + GatewayParams, + HarvestParams, + HarvestType, + IProtocolFarm, + PAYLOAD_SIZE, + StakeParams, + UnstakeParams, +} from "../types"; +import { GENOPETS_ADAPTER_PROGRAM_ID } from "../ids"; +import { Gateway } from "@dappio-wonderland/gateway-idls"; + +export class ProtocolGenopets implements IProtocolFarm { + constructor( + private _connection: anchor.web3.Connection, + private _gatewayProgram: anchor.Program, + private _gatewayStateKey: anchor.web3.PublicKey, + private _gatewayParams: GatewayParams + ) {} + + async stake( + params: StakeParams, + farmInfo: IFarmInfo, + userKey: anchor.web3.PublicKey + ): Promise<{ txs: anchor.web3.Transaction[]; input: Buffer }> { + // Handle payload input here + const inputLayout = struct([u64("stakeAmount"), u8("lockDuration")]); + let payload = Buffer.alloc(PAYLOAD_SIZE); + inputLayout.encode( + { + stakeAmount: new anchor.BN(params.lpAmount), + lockDuration: params.lockDuration ? params.lockDuration : 0, + }, + payload + ); + + this._gatewayParams.lockDuration = params.lockDuration + ? params.lockDuration + : 0; + + // Handle transaction here + const farm = farmInfo as genopets.FarmInfo; + const farmWrapper = new genopets.FarmInfoWrapper(farm); + const farmerId = await genopets.infos.getFarmerId(farm, userKey); + const farmerAccount = await this._connection.getAccountInfo(farmerId); + let userDeposit = genopets.getFarmerInstanceKey(userKey, 0); + let userReDeposit = genopets.getFarmerInstanceKey(userKey, 1); + if (farmerAccount) { + const farmer = (await genopets.infos.getFarmer( + this._connection, + farmerId + )) as genopets.FarmerInfo; + const farmerWrapper = new genopets.FarmerInfoWrapper(farmer); + userDeposit = farmerWrapper.getFarmerInstance(); + userReDeposit = farmerWrapper.getLatestFarmerInstance(); + } + + let preInstructions: anchor.web3.TransactionInstruction[] = []; + + const userPoolTokenAccount = await getAssociatedTokenAddress( + farm.poolToken, + userKey + ); + preInstructions.push( + await createATAWithoutCheckIx(userKey, farm.poolToken) + ); + + const userSgeneTokenAccount = await getAssociatedTokenAddress( + farm.master.mintSgene, + userKey + ); + preInstructions.push( + await createATAWithoutCheckIx(userKey, farm.master.mintSgene) + ); + + const vaultATA = await getAssociatedTokenAddress( + farm.poolToken, + farmerId, + true + ); + preInstructions.push( + await createATAWithoutCheckIx(farmerId, farm.poolToken, userKey) + ); + + const remainingAccounts = [ + { pubkey: userKey, isSigner: true, isWritable: true }, // 0 + { pubkey: farm.master.id, isSigner: false, isWritable: true }, // 1 + { + pubkey: farm.farmId, + isSigner: false, + isWritable: true, + }, // 2 + { pubkey: farm.poolToken, isSigner: false, isWritable: true }, // 3 + { pubkey: farmerId, isSigner: false, isWritable: true }, // 4 + { + pubkey: userPoolTokenAccount, + isSigner: false, + isWritable: true, + }, // 5 + { + pubkey: userSgeneTokenAccount, + isSigner: false, + isWritable: true, + }, // 6 + { + pubkey: vaultATA, + isSigner: false, + isWritable: true, + }, // 7 + { + pubkey: farm.master.sgeneMinter, + isSigner: false, + isWritable: false, + }, // 8 + { + pubkey: farm.master.mintSgene, + isSigner: false, + isWritable: true, + }, // 9 + { + pubkey: userDeposit, + isSigner: false, + isWritable: true, + }, // 10 + { + pubkey: userReDeposit, + isSigner: false, + isWritable: true, + }, // 11 + { + pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, + isSigner: false, + isWritable: false, + }, // 12 + { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, // 13 + { + pubkey: anchor.web3.SystemProgram.programId, + isSigner: false, + isWritable: false, + }, // 14 + { + pubkey: anchor.web3.SYSVAR_RENT_PUBKEY, + isSigner: false, + isWritable: false, + }, // 15 + ]; + + const txStake = await this._gatewayProgram.methods + .stake() + .accounts({ + gatewayState: this._gatewayStateKey, + adapterProgramId: GENOPETS_ADAPTER_PROGRAM_ID, + baseProgramId: genopets.GENOPETS_FARM_PROGRAM_ID, + activityIndex: await getActivityIndex(userKey), + gatewayAuthority: getGatewayAuthority(), + }) + .preInstructions(preInstructions) + .remainingAccounts(remainingAccounts) + .transaction(); + + return { txs: [txStake], input: payload }; + } + + async unstake( + params: UnstakeParams, + farmInfo: IFarmInfo, + userKey: anchor.web3.PublicKey + ): Promise<{ txs: anchor.web3.Transaction[]; input: Buffer }> { + // Handle payload input here + const inputLayout = struct([u64("dummy1")]); + let payload = Buffer.alloc(PAYLOAD_SIZE); + inputLayout.encode( + { + dummy1: new anchor.BN(69), + }, + payload + ); + + // Handle transaction here + const farm = farmInfo as genopets.FarmInfo; + const farmWrapper = new genopets.FarmInfoWrapper(farm); + const farmerId = await genopets.infos.getFarmerId(farm, userKey); + const farmerAccount = await this._connection.getAccountInfo(farmerId); + let userDeposit = genopets.getFarmerInstanceKey(userKey, 0); + let userReDeposit = genopets.getFarmerInstanceKey(userKey, 1); + if (farmerAccount) { + const farmer = (await genopets.infos.getFarmer( + this._connection, + farmerId + )) as genopets.FarmerInfo; + const farmerWrapper = new genopets.FarmerInfoWrapper(farmer); + userDeposit = params.farmerKey || farmerWrapper.getFarmerInstance(); + userReDeposit = farmerWrapper.getFarmerInstance(); + } + + let preInstructions: anchor.web3.TransactionInstruction[] = []; + + const userPoolTokenAccount = await getAssociatedTokenAddress( + farm.poolToken, + userKey + ); + preInstructions.push( + await createATAWithoutCheckIx(userKey, farm.poolToken) + ); + + const userSgeneTokenAccount = await getAssociatedTokenAddress( + farm.master.mintSgene, + userKey + ); + preInstructions.push( + await createATAWithoutCheckIx(userKey, farm.master.mintSgene) + ); + + const vaultATA = await getAssociatedTokenAddress( + farm.poolToken, + farmerId, + true + ); + + const remainingAccounts = [ + { pubkey: userKey, isSigner: true, isWritable: true }, // 0 + { pubkey: farm.master.id, isSigner: false, isWritable: true }, // 1 + { + pubkey: farm.farmId, + isSigner: false, + isWritable: true, + }, // 2 + { pubkey: farm.poolToken, isSigner: false, isWritable: false }, // 3 + { pubkey: farmerId, isSigner: false, isWritable: true }, // 4 + { + pubkey: userPoolTokenAccount, + isSigner: false, + isWritable: true, + }, // 5 + { + pubkey: vaultATA, + isSigner: false, + isWritable: true, + }, // 6 + { + pubkey: farm.master.sgeneMinter, + isSigner: false, + isWritable: false, + }, // 7 + { + pubkey: userSgeneTokenAccount, + isSigner: false, + isWritable: true, + }, // 8 + { + pubkey: farm.master.mintSgene, + isSigner: false, + isWritable: true, + }, // 9 + { + pubkey: farm.master.geneRewarder, + isSigner: false, + isWritable: false, + }, // 10 + { + pubkey: farm.master.ataGeneRewarder, + isSigner: false, + isWritable: true, + }, // 11 + { + pubkey: userReDeposit, + isSigner: false, + isWritable: true, + }, // 12 + { + pubkey: userDeposit, + isSigner: false, + isWritable: true, + }, // 13 + { + pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, + isSigner: false, + isWritable: false, + }, // 14 + { + pubkey: TOKEN_PROGRAM_ID, + isSigner: false, + isWritable: false, + }, // 15 + { + pubkey: anchor.web3.SystemProgram.programId, + isSigner: false, + isWritable: false, + }, // 16 + { + pubkey: anchor.web3.SYSVAR_RENT_PUBKEY, + isSigner: false, + isWritable: false, + }, // 17 + ]; + + const txUnstake = await this._gatewayProgram.methods + .unstake() + .accounts({ + gatewayState: this._gatewayStateKey, + adapterProgramId: GENOPETS_ADAPTER_PROGRAM_ID, + baseProgramId: genopets.GENOPETS_FARM_PROGRAM_ID, + activityIndex: await getActivityIndex(userKey), + gatewayAuthority: getGatewayAuthority(), + }) + .preInstructions(preInstructions) + .remainingAccounts(remainingAccounts) + .transaction(); + + return { txs: [txUnstake], input: payload }; + } + + async harvest( + params: HarvestParams, + farmInfo: IFarmInfo, + userKey: anchor.web3.PublicKey + ): Promise<{ txs: anchor.web3.Transaction[]; input: Buffer }> { + // Handle payload input here + const inputLayout = struct([u8("harvestType")]); + let payload = Buffer.alloc(PAYLOAD_SIZE); + inputLayout.encode( + { + harvestType: params.type, + }, + payload + ); + + this._gatewayParams.harvestType = params.type; + + // Handle transaction here + const farm = farmInfo as genopets.FarmInfo; + const farmWrapper = new genopets.FarmInfoWrapper(farm); + const farmerId = await genopets.infos.getFarmerId(farm, userKey); + const farmerAccount = await this._connection.getAccountInfo(farmerId); + let userDeposit = genopets.getFarmerInstanceKey(userKey, 0); + let userReDeposit = genopets.getFarmerInstanceKey(userKey, 1); + + let preInstructions: anchor.web3.TransactionInstruction[] = []; + + const userSgeneTokenAccount = await getAssociatedTokenAddress( + farm.master.mintSgene, + userKey + ); + preInstructions.push( + await createATAWithoutCheckIx(userKey, farm.master.mintSgene) + ); + + let remainingAccounts: anchor.web3.AccountMeta[] = []; + switch (params.type) { + case HarvestType.initialize: + if (farmerAccount) { + const farmer = (await genopets.infos.getFarmer( + this._connection, + farmerId + )) as genopets.FarmerInfo; + const farmerWrapper = new genopets.FarmerInfoWrapper(farmer); + userDeposit = farmerWrapper.getFarmerInstance(); + userReDeposit = farmerWrapper.getLatestFarmerInstance(); + } + + remainingAccounts = [ + { pubkey: userKey, isSigner: true, isWritable: true }, // 0 + { pubkey: farm.master.id, isSigner: false, isWritable: true }, // 1 + { pubkey: farmerId, isSigner: false, isWritable: true }, // 2 + { + pubkey: farm.master.sgeneMinter, + isSigner: false, + isWritable: false, + }, // 3 + { + pubkey: farm.master.mintSgene, + isSigner: false, + isWritable: true, + }, // 4 + { + pubkey: userSgeneTokenAccount, + isSigner: false, + isWritable: true, + }, // 5 + { + pubkey: userDeposit, + isSigner: false, + isWritable: true, + }, // 6 + { + pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, + isSigner: false, + isWritable: false, + }, // 7 + { + pubkey: TOKEN_PROGRAM_ID, + isSigner: false, + isWritable: false, + }, // 8 + { + pubkey: anchor.web3.SystemProgram.programId, + isSigner: false, + isWritable: false, + }, // 9 + { + pubkey: anchor.web3.SYSVAR_RENT_PUBKEY, + isSigner: false, + isWritable: false, + }, // 10 + ]; + break; + case HarvestType.completeAsGene: + if (farmerAccount) { + const farmer = (await genopets.infos.getFarmer( + this._connection, + farmerId + )) as genopets.FarmerInfo; + const farmerWrapper = new genopets.FarmerInfoWrapper(farmer); + userDeposit = params.farmerKey || farmerWrapper.getFarmerInstance(); + userReDeposit = farmerWrapper.getFarmerInstance(); + } + + const userPoolTokenAccount = await getAssociatedTokenAddress( + farm.poolToken, + userKey + ); + preInstructions.push( + await createATAWithoutCheckIx(userKey, farm.poolToken) + ); + + const vaultATA = await getAssociatedTokenAddress( + farm.poolToken, + farmerId, + true + ); + remainingAccounts = [ + { pubkey: userKey, isSigner: true, isWritable: true }, // 0 + { pubkey: farm.master.id, isSigner: false, isWritable: true }, // 1 + { + pubkey: farm.farmId, + isSigner: false, + isWritable: true, + }, // 2 + { pubkey: farm.poolToken, isSigner: false, isWritable: false }, // 3 + { pubkey: farmerId, isSigner: false, isWritable: true }, // 4 + { + pubkey: userPoolTokenAccount, + isSigner: false, + isWritable: true, + }, // 5 + { + pubkey: vaultATA, + isSigner: false, + isWritable: true, + }, // 6 + { + pubkey: farm.master.sgeneMinter, + isSigner: false, + isWritable: false, + }, // 7 + { + pubkey: userSgeneTokenAccount, + isSigner: false, + isWritable: true, + }, // 8 + { + pubkey: farm.master.mintSgene, + isSigner: false, + isWritable: true, + }, // 9 + { + pubkey: farm.master.geneRewarder, + isSigner: false, + isWritable: false, + }, // 10 + { + pubkey: farm.master.ataGeneRewarder, + isSigner: false, + isWritable: true, + }, // 11 + { + pubkey: userReDeposit, + isSigner: false, + isWritable: true, + }, // 12 + { + pubkey: userDeposit, + isSigner: false, + isWritable: true, + }, // 13 + { + pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, + isSigner: false, + isWritable: false, + }, // 14 + { + pubkey: TOKEN_PROGRAM_ID, + isSigner: false, + isWritable: false, + }, // 15 + { + pubkey: anchor.web3.SystemProgram.programId, + isSigner: false, + isWritable: false, + }, // 16 + { + pubkey: anchor.web3.SYSVAR_RENT_PUBKEY, + isSigner: false, + isWritable: false, + }, // 17 + ]; + break; + case HarvestType.completeAsSGene: + if (farmerAccount) { + const farmer = (await genopets.infos.getFarmer( + this._connection, + farmerId + )) as genopets.FarmerInfo; + const farmerWrapper = new genopets.FarmerInfoWrapper(farmer); + userDeposit = params.farmerKey || farmerWrapper.getFarmerInstance(); + userReDeposit = farmerWrapper.getLatestFarmerInstance(); + } + + remainingAccounts = [ + { pubkey: userKey, isSigner: true, isWritable: true }, // 0 + { pubkey: farm.master.id, isSigner: false, isWritable: true }, // 1 + { pubkey: farmerId, isSigner: false, isWritable: true }, // 2 + { + pubkey: farm.master.sgeneMinter, + isSigner: false, + isWritable: false, + }, // 3 + { + pubkey: userSgeneTokenAccount, + isSigner: false, + isWritable: true, + }, // 4 + { + pubkey: farm.master.mintSgene, + isSigner: false, + isWritable: true, + }, // 5 + { + pubkey: userDeposit, + isSigner: false, + isWritable: true, + }, // 6 + { + pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, + isSigner: false, + isWritable: false, + }, // 7 + { + pubkey: TOKEN_PROGRAM_ID, + isSigner: false, + isWritable: false, + }, // 8 + { + pubkey: anchor.web3.SystemProgram.programId, + isSigner: false, + isWritable: false, + }, // 9 + { + pubkey: anchor.web3.SYSVAR_RENT_PUBKEY, + isSigner: false, + isWritable: false, + }, // 10 + ]; + break; + + default: + console.error("Error: Unsupported harvest type"); + break; + } + + const txHarvest = await this._gatewayProgram.methods + .harvest() + .accounts({ + gatewayState: this._gatewayStateKey, + adapterProgramId: GENOPETS_ADAPTER_PROGRAM_ID, + baseProgramId: genopets.GENOPETS_FARM_PROGRAM_ID, + activityIndex: await getActivityIndex(userKey), + gatewayAuthority: getGatewayAuthority(), + }) + .preInstructions(preInstructions) + .remainingAccounts(remainingAccounts) + .transaction(); + + return { txs: [txHarvest], input: payload }; + } +} diff --git a/src/types.ts b/src/types.ts index 06c25ed..26ddc89 100644 --- a/src/types.ts +++ b/src/types.ts @@ -219,6 +219,7 @@ export enum SupportedProtocols { Francium = 9, Friktion = 10, Katana = 11, + Genopets = 12, } export interface RouteInfoExtend extends RouteInfo { @@ -272,6 +273,8 @@ export interface StakeParams { farmerKey?: anchor.web3.PublicKey; lpAmount?: number; version?: number; + lockDuration?: number; + mint?: anchor.web3.PublicKey; } export interface UnstakeParams { @@ -280,6 +283,7 @@ export interface UnstakeParams { shareAmount: number; farmerKey?: anchor.web3.PublicKey; version?: number; + mint?: anchor.web3.PublicKey; } export interface HarvestParams { @@ -287,6 +291,8 @@ export interface HarvestParams { farmId: anchor.web3.PublicKey; farmerKey?: anchor.web3.PublicKey; version?: number; + type?: HarvestType; + mint?: anchor.web3.PublicKey; } export interface SupplyParams { @@ -398,6 +404,12 @@ export enum PoolDirection { Reverse, } +export enum HarvestType { + initialize, + completeAsGene, + completeAsSGene, +} + export type GatewayParams = TypeDef< { name: "GatewayParams"; @@ -458,6 +470,14 @@ export type GatewayParams = TypeDef< { name: "poolDirection"; type: "u8"; + }, + { + name: "lockDuration"; + type: "u8"; + }, + { + name: "harvestType"; + type: "u8"; } ]; }; diff --git a/tests/testAdapterGenopets.ts b/tests/testAdapterGenopets.ts new file mode 100644 index 0000000..f83fc89 --- /dev/null +++ b/tests/testAdapterGenopets.ts @@ -0,0 +1,354 @@ +import * as anchor from "@project-serum/anchor"; +import { PublicKey, Connection } from "@solana/web3.js"; +import NodeWallet from "@project-serum/anchor/dist/cjs/nodewallet"; +import { getAccount, getAssociatedTokenAddress } from "@solana/spl-token-v2"; +import { + AddLiquidityParams, + StakeParams, + GatewayBuilder, + SupportedProtocols, + SwapParams, + UnstakeParams, + RemoveLiquidityParams, + HarvestParams, + WSOL, + HarvestType, +} from "../src"; +import { genopets } from "@dappio-wonderland/navigator"; + +describe("Gateway", () => { + const connection = new Connection( + "https://rpc-mainnet-fork.epochs.studio/notcache", + { + commitment: "confirmed", + wsEndpoint: "wss://rpc-mainnet-fork.epochs.studio/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 options = anchor.AnchorProvider.defaultOptions(); + const wallet = NodeWallet.local(); + const provider = new anchor.AnchorProvider(connection, wallet, options); + + anchor.setProvider(provider); + + const GENE_USDC_LP = new PublicKey( + "7GKvfHEXenNiWYbJBKae89mdaMPr5gGMYwZmyC8gBNVG" + ); + const GENE_MINT = new PublicKey( + "GENEtH5amGSi8kHAtQoezp1XEXwZJ8vcuePYnXdKrMYz" + ); + const USDC_MINT = new PublicKey( + "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" + ); + + const mint = GENE_USDC_LP; + // const mint = GENE_MINT; + let outAmount = 0; + it("Stake in Genopets", async () => { + const poolId = new anchor.web3.PublicKey( + "Enq8vJucRbkzKA1i1PahJNhMyUTzoVL5Cs8n5rC3NLGn" // GENE-USDC + ); + const farmId = genopets.getFarmId(mint); + const swapParams: SwapParams = { + protocol: SupportedProtocols.Jupiter, + fromTokenMint: USDC_MINT, + toTokenMint: GENE_MINT, + amount: 100, // Swap half of the fromToken to proceed zapIn + slippage: 1, + }; + const addLiquidityParams: AddLiquidityParams = { + protocol: SupportedProtocols.Raydium, + poolId, + tokenInAmount: 100, + }; + const farm = (await genopets.infos.getFarm( + connection, + farmId + )) as genopets.FarmInfo; + const stakeParams: StakeParams = { + protocol: SupportedProtocols.Genopets, + farmId, + version: 1, + lpAmount: 10000, + lockDuration: 0, + mint, + }; + + const gateway = new GatewayBuilder(provider); + + await gateway.swap(swapParams); + outAmount = gateway.params.swapMinOutAmount.toNumber(); + await gateway.addLiquidity(addLiquidityParams); + await gateway.stake(stakeParams); + + await gateway.finalize(); + + + // console.log(`swapInAmount: ${gateway.params.swapInAmount}`); + // console.log(`swapMinOutAmount: ${gateway.params.swapMinOutAmount}`); + + const txs = gateway.transactions(); + + console.log("======"); + console.log("Txs are sent..."); + for (let tx of txs) { + const sig = await provider.sendAndConfirm(tx, [], { + skipPreflight: true, + commitment: "confirmed", + } as unknown as anchor.web3.ConfirmOptions); + console.log(sig); + } + console.log("Txs are executed"); + console.log("======"); + }); + + it("Unstake + Harvest in Genopets", async () => { + const farmId = genopets.getFarmId(mint); + const poolId = new anchor.web3.PublicKey( + "Enq8vJucRbkzKA1i1PahJNhMyUTzoVL5Cs8n5rC3NLGn" // GENE-USDC + ); + + const farm = (await genopets.infos.getFarm( + connection, + farmId + )) as genopets.FarmInfo; + + const farmerId = await genopets.infos.getFarmerId( + farm, + provider.wallet.publicKey + ); + const farmer = (await genopets.infos.getFarmer( + connection, + farmerId + )) as genopets.FarmerInfo; + const swapParams: SwapParams = { + protocol: SupportedProtocols.Jupiter, + fromTokenMint: GENE_MINT, + toTokenMint: USDC_MINT, + amount: outAmount, // Swap half of the fromToken to proceed zapIn + slippage: 2, + }; + + const harvestParams1: HarvestParams = { + protocol: SupportedProtocols.Genopets, + farmId, + type: HarvestType.initialize, + mint, + }; + + let farmerInstanceId: anchor.web3.PublicKey; + for (let farmerInstance of farmer.instance) { + if (farmerInstance?.isYield == true) { + farmerInstanceId = farmerInstance.id; + } + } + const harvestParams2: HarvestParams = { + protocol: SupportedProtocols.Genopets, + farmId, + type: HarvestType.completeAsSGene, + farmerKey: farmerInstanceId!, + mint, + }; + + for (let farmerInstance of farmer.instance) { + const timestamp = Number(farmerInstance?.lockUntil); + const currentTimestamp = Number(new Date()) / 1000; + if ( + farmerInstance?.isYield == false && + farmerInstance.poolToken.equals(mint) && + timestamp < currentTimestamp + ) { + farmerInstanceId = farmerInstance.id; + } + } + const harvestParams3: HarvestParams = { + protocol: SupportedProtocols.Genopets, + farmId, + type: HarvestType.completeAsGene, + farmerKey: farmerInstanceId!, + mint, + }; + const unstakeParams: UnstakeParams = { + protocol: SupportedProtocols.Genopets, + farmId, + shareAmount: 1000, // dummy + farmerKey: farmerInstanceId!, + mint, + }; + const removeLiquidityParams: RemoveLiquidityParams = { + protocol: SupportedProtocols.Raydium, + poolId, + }; + + const gateway = new GatewayBuilder(provider); + + // await gateway.harvest(harvestParams1); + // await gateway.harvest(harvestParams2); + // await gateway.harvest(harvestParams3); + await gateway.unstake(unstakeParams); + await gateway.removeLiquidity(removeLiquidityParams); + await gateway.swap(swapParams); + + await gateway.finalize(); + + + // console.log(`swapInAmount: ${gateway.gatewayParams.swapInAmount}`); + // console.log(`swapMinOutAmount: ${gateway.gatewayParams.swapMinOutAmount}`); + + const txs = gateway.transactions(); + + console.log("======"); + console.log("Txs are sent..."); + for (let tx of txs) { + const sig = await provider.sendAndConfirm(tx, [], { + skipPreflight: true, + commitment: "confirmed", + } as unknown as anchor.web3.ConfirmOptions); + console.log(sig); + } + console.log("Txs are executed"); + console.log("======"); + }); + + // it("Unstake all in Genopets", async () => { + // const farmId = genopets.getFarmId(mint); + + // const farm = (await genopets.infos.getFarm( + // connection, + // farmId + // )) as genopets.FarmInfo; + + // const farmerId = await genopets.infos.getFarmerId( + // farm, + // provider.wallet.publicKey + // ); + // const farmer = (await genopets.infos.getFarmer( + // connection, + // farmerId + // )) as genopets.FarmerInfo; + + // const gateway = new GatewayBuilder(provider); + + // const harvestParams1: HarvestParams = { + // protocol: SupportedProtocols.Genopets, + // farmId, + // type: HarvestType.initialize, + // mint, + // }; + // await gateway.harvest(harvestParams1); + + // let farmerInstanceId: anchor.web3.PublicKey; + // let counter = 0; + // for (let farmerInstance of farmer.instance) { + // const timestamp = Number(farmerInstance?.lockUntil); + // const currentTimestamp = Number(new Date()) / 1000; + // if ( + // farmerInstance?.isYield == false && + // farmerInstance.poolToken.equals(mint) && + // timestamp < currentTimestamp + // ) { + // farmerInstanceId = farmerInstance.id; + + // const unstakeParams: UnstakeParams = { + // protocol: SupportedProtocols.Genopets, + // farmId, + // shareAmount: 1000, // dummy + // farmerKey: farmerInstanceId!, + // mint, + // }; + + // await gateway.unstake(unstakeParams); + // counter++; + // if (counter == 1) break; + // } + // } + + // await gateway.finalize(); + + // + + // const txs = gateway.transactions(); + + // console.log("======"); + // console.log("Txs are sent..."); + // for (let tx of txs) { + // const sig = await provider.sendAndConfirm(tx, [], { + // skipPreflight: true, + // commitment: "confirmed", + // } as unknown as anchor.web3.ConfirmOptions); + // console.log(sig); + // } + // console.log("Txs are executed"); + // console.log("======"); + // }); + + // it("Harvest all in Genopets", async () => { + // const farmId = genopets.getFarmId(mint); + + // const farm = (await genopets.infos.getFarm( + // connection, + // farmId + // )) as genopets.FarmInfo; + + // const farmerId = await genopets.infos.getFarmerId( + // farm, + // provider.wallet.publicKey + // ); + // const farmer = (await genopets.infos.getFarmer( + // connection, + // farmerId + // )) as genopets.FarmerInfo; + + // const gateway = new GatewayBuilder(provider); + + // let farmerInstanceId: anchor.web3.PublicKey; + // let counter = 0; + // for (let farmerInstance of farmer.instance) { + // if (farmerInstance?.isYield == true) { + // farmerInstanceId = farmerInstance.id; + + // const harvestParams2: HarvestParams = { + // protocol: SupportedProtocols.Genopets, + // farmId, + // type: HarvestType.completeAsSGene, + // farmerKey: farmerInstanceId!, + // mint, + // }; + + // await gateway.harvest(harvestParams2); + // counter++; + // if (counter == 6) break; + // } + // } + + // await gateway.finalize(); + + // + + // const txs = gateway.transactions(); + + // console.log("======"); + // console.log("Txs are sent..."); + // for (let tx of txs) { + // const sig = await provider.sendAndConfirm(tx, [], { + // skipPreflight: true, + // commitment: "confirmed", + // } as unknown as anchor.web3.ConfirmOptions); + // console.log(sig); + // } + // console.log("Txs are executed"); + // console.log("======"); + // }); +}); diff --git a/yarn.lock b/yarn.lock index cee6642..d1951ed 100644 --- a/yarn.lock +++ b/yarn.lock @@ -21,15 +21,15 @@ tiny-invariant "^1.1.0" toformat "^2.0.0" -"@dappio-wonderland/gateway-idls@^0.2.6": - version "0.2.6" - resolved "https://registry.yarnpkg.com/@dappio-wonderland/gateway-idls/-/gateway-idls-0.2.6.tgz#dcd823b6527036aef7dbec5e9eb28cf5cdea2e60" - integrity sha512-jOvrS74Vnw5MlH6DTgHJQWoXlO81f71/2+LdefrKbybjorDUZ3xeQOCUofBA83PFNGXGP4VyWY4qGenVRuH+SQ== - -"@dappio-wonderland/navigator@^0.2.11": - version "0.2.11" - resolved "https://registry.yarnpkg.com/@dappio-wonderland/navigator/-/navigator-0.2.11.tgz#825599fd563eaee5ffc70aff7344006d190fb6c3" - integrity sha512-3o0+/4edUvI0smFnt8xxS0tKkcT4GPpw3us2uX1I8bAj/kIlgU5Ndqq+AOeAUc4vHnD9NH/pC6G3FhM72184rg== +"@dappio-wonderland/gateway-idls@^0.2.7-test.3": + version "0.2.7-test.3" + resolved "https://registry.yarnpkg.com/@dappio-wonderland/gateway-idls/-/gateway-idls-0.2.7-test.3.tgz#26958b259071b0c18a67d62f270464af1da9fc79" + integrity sha512-Aa9z49BhoB0DQW0z+SvEp7oI4mFKN8qZJSoItuQnnb26GFENKqkw3mK87HBK2dL+vwPtlUZNvuqLwFCb2zU9lg== + +"@dappio-wonderland/navigator@^0.2.14-test.13": + version "0.2.14-test.13" + resolved "https://registry.yarnpkg.com/@dappio-wonderland/navigator/-/navigator-0.2.14-test.13.tgz#abfbf04ff8ff96133355075fa2ee99bb82968ca0" + integrity sha512-ao0O3LA9Q+al6BC7KlsnMUnWQcB0ZQTzjHp8Mgs1eP8jhnsYiMhCUlMBxd+YX8/iADRJS8TjbpbGCoJdHye1kg== dependencies: "@project-serum/borsh" "^0.2.2" "@project-serum/serum" "^0.13.61"