From 96fb7897a10f40120551ea29a93a924186c51b04 Mon Sep 17 00:00:00 2001 From: luciotato Date: Thu, 22 Sep 2022 05:52:34 -0300 Subject: [PATCH 1/6] initial, uses referral v2, idl updated --- .eslintignore | 1 + CHANGELOG.md | 4 + package.json | 2 +- .../marinade-referral-state.types.ts | 14 +- src/marinade.ts | 105 +++++--- src/programs/idl/marinade-referral-idl.json | 235 +++++++++++++++--- src/programs/idl/marinade-referral-idl.ts | 23 +- src/programs/marinade-referral-program.ts | 11 +- src/util/state-helpers.ts | 5 +- 9 files changed, 323 insertions(+), 77 deletions(-) create mode 100644 CHANGELOG.md diff --git a/.eslintignore b/.eslintignore index f06235c..b6e5f2b 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,2 +1,3 @@ node_modules dist +scripts \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..dac74dc --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,4 @@ + +v4.0.0 + +Uses Referral-Program V2 diff --git a/package.json b/package.json index 00cfcf8..ad22932 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@marinade.finance/marinade-ts-sdk", - "version": "3.1.4", + "version": "4.0.0", "description": "Marinade SDK for Typescript", "main": "dist/src/index.js", "repository": { diff --git a/src/marinade-referral-state/marinade-referral-state.types.ts b/src/marinade-referral-state/marinade-referral-state.types.ts index 7d5f648..dc9b9f6 100644 --- a/src/marinade-referral-state/marinade-referral-state.types.ts +++ b/src/marinade-referral-state/marinade-referral-state.types.ts @@ -14,10 +14,10 @@ export namespace MarinadeReferralStateResponse { export interface ReferralState { partnerName: string + validatorVoteKey: string|null + keepSelfStakePct: number partnerAccount: web3.PublicKey - tokenPartnerAccount: web3.PublicKey - transferDuration: number - lastTransferTime: BN + msolTokenPartnerAccount: web3.PublicKey depositSolAmount: BN depositSolOperations: BN depositStakeAccountAmount: BN @@ -32,5 +32,13 @@ export namespace MarinadeReferralStateResponse { maxFee: number maxNetStake: BN pause: boolean + operationDepositSolFee: number + operationDepositStakeAccountFee: number + operationLiquidUnstakeFee: number + operationDelayedUnstakeFee: number + accumDepositSolFee: BN + accumDepositStakeAccountFee: BN + accumLiquidUnstakeFee: BN + accumDelayedUnstakeFee: BN } } diff --git a/src/marinade.ts b/src/marinade.ts index f95ac8d..425b72b 100644 --- a/src/marinade.ts +++ b/src/marinade.ts @@ -38,7 +38,7 @@ export class Marinade { ) private provideReferralOrMainProgram(): MarinadeFinanceProgram | MarinadeReferralProgram { - return this.config.referralCode ? this.marinadeReferralProgram: this.marinadeFinanceProgram + return this.config.referralCode ? this.marinadeReferralProgram : this.marinadeFinanceProgram } /** @@ -162,13 +162,27 @@ export class Marinade { transaction.add(createAssociateTokenInstruction) } - const program = this.provideReferralOrMainProgram() - const depositInstruction = await program.depositInstructionBuilder({ - amountLamports, - marinadeState, - transferFrom: feePayer, - associatedMSolTokenAccountAddress, - }) + let depositInstruction + if (this.config.referralCode) { + const program = this.marinadeReferralProgram + const referralState = await this.getReferralPartnerState() + depositInstruction = await program.depositInstructionBuilder({ + amountLamports, + marinadeState, + transferFrom: feePayer, + associatedMSolTokenAccountAddress, + msolTokenPartnerAccount: referralState.state.msolTokenPartnerAccount + }) + } + else { + const program = this.marinadeFinanceProgram + depositInstruction = await program.depositInstructionBuilder({ + amountLamports, + marinadeState, + transferFrom: feePayer, + associatedMSolTokenAccountAddress, + }) + } transaction.add(depositInstruction) @@ -193,19 +207,33 @@ export class Marinade { const associatedTokenAccountInfos = await getOrCreateAssociatedTokenAccount(this.provider, marinadeState.mSolMintAddress, ownerAddress) const createAssociateTokenInstruction = associatedTokenAccountInfos.createAssociateTokenInstruction associatedMSolTokenAccountAddress = associatedTokenAccountInfos.associatedTokenAccountAddress - + if (createAssociateTokenInstruction) { transaction.add(createAssociateTokenInstruction) } } - const program = this.provideReferralOrMainProgram() - const liquidUnstakeInstruction = await program.liquidUnstakeInstructionBuilder({ - amountLamports, - marinadeState, - ownerAddress, - associatedMSolTokenAccountAddress, - }) + let liquidUnstakeInstruction + if (this.config.referralCode) { + const program = this.marinadeReferralProgram + const referralState = await this.getReferralPartnerState() + liquidUnstakeInstruction = await program.liquidUnstakeInstructionBuilder({ + amountLamports, + marinadeState, + ownerAddress, + associatedMSolTokenAccountAddress, + msolTokenPartnerAccount: referralState.state.msolTokenPartnerAccount, + }) + } + else { + const program = this.marinadeFinanceProgram + liquidUnstakeInstruction = await program.liquidUnstakeInstructionBuilder({ + amountLamports, + marinadeState, + ownerAddress, + associatedMSolTokenAccountAddress, + }) + } transaction.add(liquidUnstakeInstruction) @@ -264,16 +292,33 @@ export class Marinade { transaction.add(createAssociateTokenInstruction) } - const program = this.provideReferralOrMainProgram() - const depositStakeAccountInstruction = await program.depositStakeAccountInstructionBuilder({ - validatorIndex, - marinadeState, - duplicationFlag, - authorizedWithdrawerAddress, - associatedMSolTokenAccountAddress, - ownerAddress, - stakeAccountAddress, - }) + let depositStakeAccountInstruction + if (this.config.referralCode) { + const program = this.marinadeReferralProgram + const referralState = await this.getReferralPartnerState() + depositStakeAccountInstruction = await program.depositStakeAccountInstructionBuilder({ + validatorIndex, + marinadeState, + duplicationFlag, + authorizedWithdrawerAddress, + associatedMSolTokenAccountAddress, + ownerAddress, + stakeAccountAddress, + msolTokenPartnerAccount: referralState.state.msolTokenPartnerAccount, + }) + } + else { + const program = this.marinadeFinanceProgram + depositStakeAccountInstruction = await program.depositStakeAccountInstructionBuilder({ + validatorIndex, + marinadeState, + duplicationFlag, + authorizedWithdrawerAddress, + associatedMSolTokenAccountAddress, + ownerAddress, + stakeAccountAddress, + }) + } transaction.add(depositStakeAccountInstruction) @@ -289,7 +334,7 @@ export class Marinade { * Returns a transaction with the instructions to * Liquidate a delegated stake account. * Note that the stake must be fully activated and the validator must be known to Marinade - * and that the transaction should be executed immidiately after creation. + * and that the transaction should be executed immediately after creation. * * @param {web3.PublicKey} stakeAccountAddress - The account to be deposited * @param {BN} mSolToKeep - Optional amount of mSOL lamports to keep @@ -300,11 +345,11 @@ export class Marinade { const stakeBalance = new BN(totalBalance - rent) const marinadeState = await this.getMarinadeState() - const {transaction: depositTx, associatedMSolTokenAccountAddress, voterAddress} = await this.depositStakeAccount(stakeAccountAddress) + const { transaction: depositTx, associatedMSolTokenAccountAddress, voterAddress } = await this.depositStakeAccount(stakeAccountAddress) const availableMsol = computeMsolAmount(stakeBalance, marinadeState) const unstakeAmount = availableMsol.sub(mSolToKeep ?? new BN(0)) - const {transaction: unstakeTx} = await this.liquidUnstake(unstakeAmount, associatedMSolTokenAccountAddress) + const { transaction: unstakeTx } = await this.liquidUnstake(unstakeAmount, associatedMSolTokenAccountAddress) return { transaction: depositTx.add(unstakeTx), @@ -317,7 +362,7 @@ export class Marinade { * @todo */ async getDelayedUnstakeTickets(beneficiary?: web3.PublicKey): Promise> { - + return this.marinadeFinanceProgram.getDelayedUnstakeTickets(beneficiary) } diff --git a/src/programs/idl/marinade-referral-idl.json b/src/programs/idl/marinade-referral-idl.json index 7de0f5d..6be6567 100644 --- a/src/programs/idl/marinade-referral-idl.json +++ b/src/programs/idl/marinade-referral-idl.json @@ -69,6 +69,11 @@ "name": "referralState", "isMut": true, "isSigner": false + }, + { + "name": "msolTokenPartnerAccount", + "isMut": true, + "isSigner": false } ], "args": [ @@ -165,6 +170,11 @@ "name": "referralState", "isMut": true, "isSigner": false + }, + { + "name": "msolTokenPartnerAccount", + "isMut": true, + "isSigner": false } ], "args": [ @@ -236,6 +246,11 @@ "name": "referralState", "isMut": true, "isSigner": false + }, + { + "name": "msolTokenPartnerAccount", + "isMut": true, + "isSigner": false } ], "args": [ @@ -259,14 +274,28 @@ "isSigner": false }, { - "name": "treasuryMsolAccount", + "name": "msolMintAccount", + "isMut": false, + "isSigner": false + }, + { + "name": "foreman1", + "isMut": false, + "isSigner": false + }, + { + "name": "foreman2", "isMut": false, "isSigner": false } ], "args": [ { - "name": "treasuryMsolAuthBump", + "name": "minKeepPct", + "type": "u8" + }, + { + "name": "maxKeepPct", "type": "u8" } ] @@ -280,15 +309,10 @@ "isSigner": false }, { - "name": "adminAccount", + "name": "signer", "isMut": false, "isSigner": true }, - { - "name": "treasuryMsolAccount", - "isMut": false, - "isSigner": false - }, { "name": "referralState", "isMut": true, @@ -300,7 +324,7 @@ "isSigner": false }, { - "name": "tokenPartnerAccount", + "name": "msolTokenPartnerAccount", "isMut": false, "isSigner": false } @@ -309,6 +333,16 @@ { "name": "partnerName", "type": "string" + }, + { + "name": "validatorVoteKey", + "type": { + "option": "publicKey" + } + }, + { + "name": "keepSelfStakePct", + "type": "u8" } ] }, @@ -329,19 +363,71 @@ "name": "referralState", "isMut": true, "isSigner": false + }, + { + "name": "newPartnerAccount", + "isMut": false, + "isSigner": false + }, + { + "name": "newMsolTokenPartnerAccount", + "isMut": false, + "isSigner": false } ], "args": [ - { - "name": "transferDuration", - "type": "u32" - }, { "name": "pause", "type": "bool" } ] }, + { + "name": "updateOperationFees", + "accounts": [ + { + "name": "globalState", + "isMut": false, + "isSigner": false + }, + { + "name": "signer", + "isMut": false, + "isSigner": true + }, + { + "name": "referralState", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "operationDepositSolFee", + "type": { + "option": "u8" + } + }, + { + "name": "operationDepositStakeAccountFee", + "type": { + "option": "u8" + } + }, + { + "name": "operationLiquidUnstakeFee", + "type": { + "option": "u8" + } + }, + { + "name": "operationDelayedUnstakeFee", + "type": { + "option": "u8" + } + } + ] + }, { "name": "changeAuthority", "accounts": [ @@ -359,6 +445,16 @@ "name": "newAdminAccount", "isMut": false, "isSigner": false + }, + { + "name": "newForeman1", + "isMut": false, + "isSigner": false + }, + { + "name": "newForeman2", + "isMut": false, + "isSigner": false } ], "args": [] @@ -375,11 +471,23 @@ "type": "publicKey" }, { - "name": "treasuryMsolAccount", + "name": "msolMintAccount", "type": "publicKey" }, { - "name": "treasuryMsolAuthBump", + "name": "foreman1", + "type": "publicKey" + }, + { + "name": "foreman2", + "type": "publicKey" + }, + { + "name": "minKeepPct", + "type": "u8" + }, + { + "name": "maxKeepPct", "type": "u8" } ] @@ -395,20 +503,22 @@ "type": "string" }, { - "name": "partnerAccount", - "type": "publicKey" + "name": "validatorVoteKey", + "type": { + "option": "publicKey" + } }, { - "name": "tokenPartnerAccount", - "type": "publicKey" + "name": "keepSelfStakePct", + "type": "u8" }, { - "name": "transferDuration", - "type": "u32" + "name": "partnerAccount", + "type": "publicKey" }, { - "name": "lastTransferTime", - "type": "i64" + "name": "msolTokenPartnerAccount", + "type": "publicKey" }, { "name": "depositSolAmount", @@ -465,6 +575,38 @@ { "name": "pause", "type": "bool" + }, + { + "name": "operationDepositSolFee", + "type": "u8" + }, + { + "name": "operationDepositStakeAccountFee", + "type": "u8" + }, + { + "name": "operationLiquidUnstakeFee", + "type": "u8" + }, + { + "name": "operationDelayedUnstakeFee", + "type": "u8" + }, + { + "name": "accumDepositSolFee", + "type": "u64" + }, + { + "name": "accumDepositStakeAccountFee", + "type": "u64" + }, + { + "name": "accumLiquidUnstakeFee", + "type": "u64" + }, + { + "name": "accumDelayedUnstakeFee", + "type": "u64" } ] } @@ -488,13 +630,13 @@ }, { "code": 303, - "name": "InvalidBeneficiaryAccountOwner", - "msg": "Invalid beneficiary account owner" + "name": "InvalidPartnerAccountOwner", + "msg": "Invalid partner account owner" }, { "code": 304, - "name": "InvalidBeneficiaryAccountMint", - "msg": "Invalid beneficiary account mint" + "name": "InvalidPartnerAccountMint", + "msg": "Invalid partner account mint" }, { "code": 305, @@ -503,18 +645,43 @@ }, { "code": 306, - "name": "TreasuryTokenAuthorityDoesNotMatch", - "msg": "Treasury token authority does not match" + "name": "NotInitializedMintAccount", + "msg": "Mint account is not initialized" }, { "code": 307, - "name": "TreasuryTokenAccountMustNotBeDelegated", - "msg": "Treasury token account must not be delegated" + "name": "ReferralOperationFeeOverMax", + "msg": "Referral operation fee was set over the maximum permitted amount" }, { "code": 308, - "name": "TreasuryTokenAccountMustNotBeCloseable", - "msg": "Treasury token account must not be closeable" + "name": "NotAllowedForStakeAsCollateralPartner", + "msg": "Not allowed for stake-as-collateral-partners" + }, + { + "code": 309, + "name": "KeepPctOutOfRange", + "msg": "Keep_pct out of valid range" + }, + { + "code": 310, + "name": "MaxKeepPctOutOfRange", + "msg": "Max Keep_pct out of valid range, cannot go over 100%" + }, + { + "code": 311, + "name": "MinMaxKeepPctOutOfRange", + "msg": "Min Keep-pct is bounded by value of Max Keep_pct" + }, + { + "code": 312, + "name": "StakeAccountMustBeDelegatedToPartnerValidator", + "msg": "Stake-account must be delegated to partner validator" + }, + { + "code": 313, + "name": "StakeAccountAuthMustBePartnerAccount", + "msg": "Stake-account authority must be partner account" } ] -} +} \ No newline at end of file diff --git a/src/programs/idl/marinade-referral-idl.ts b/src/programs/idl/marinade-referral-idl.ts index 2240fc2..42a7e4e 100644 --- a/src/programs/idl/marinade-referral-idl.ts +++ b/src/programs/idl/marinade-referral-idl.ts @@ -17,6 +17,7 @@ export namespace MarinadeReferralIdl { tokenProgram: web3.PublicKey marinadeFinanceProgram: web3.PublicKey referralState: web3.PublicKey + msolTokenPartnerAccount: web3.PublicKey } } export namespace DepositStakeAccount { @@ -38,6 +39,7 @@ export namespace MarinadeReferralIdl { stakeProgram: web3.PublicKey marinadeFinanceProgram: web3.PublicKey referralState: web3.PublicKey + msolTokenPartnerAccount: web3.PublicKey } } export namespace LiquidUnstake { @@ -54,23 +56,25 @@ export namespace MarinadeReferralIdl { tokenProgram: web3.PublicKey marinadeFinanceProgram: web3.PublicKey referralState: web3.PublicKey + msolTokenPartnerAccount: web3.PublicKey } } export namespace Initialize { export type Accounts = { adminAccount: web3.PublicKey globalState: web3.PublicKey - treasuryMsolAccount: web3.PublicKey + msolMintAccount: web3.PublicKey + foreman1: web3.PublicKey + foreman2: web3.PublicKey } } export namespace InitReferralAccount { export type Accounts = { globalState: web3.PublicKey - adminAccount: web3.PublicKey - treasuryMsolAccount: web3.PublicKey + signer: web3.PublicKey referralState: web3.PublicKey partnerAccount: web3.PublicKey - tokenPartnerAccount: web3.PublicKey + msolTokenPartnerAccount: web3.PublicKey } } export namespace UpdateReferral { @@ -78,6 +82,15 @@ export namespace MarinadeReferralIdl { globalState: web3.PublicKey adminAccount: web3.PublicKey referralState: web3.PublicKey + newPartnerAccount: web3.PublicKey + newMsolTokenPartnerAccount: web3.PublicKey + } + } + export namespace UpdateOperationFees { + export type Accounts = { + globalState: web3.PublicKey + signer: web3.PublicKey + referralState: web3.PublicKey } } export namespace ChangeAuthority { @@ -85,6 +98,8 @@ export namespace MarinadeReferralIdl { globalState: web3.PublicKey adminAccount: web3.PublicKey newAdminAccount: web3.PublicKey + newForeman1: web3.PublicKey + newForeman2: web3.PublicKey } } } diff --git a/src/programs/marinade-referral-program.ts b/src/programs/marinade-referral-program.ts index 555f14d..e93b66b 100644 --- a/src/programs/marinade-referral-program.ts +++ b/src/programs/marinade-referral-program.ts @@ -22,10 +22,11 @@ export class MarinadeReferralProgram { ) } - liquidUnstakeInstructionAccounts = async({ marinadeState, ownerAddress, associatedMSolTokenAccountAddress }: { + liquidUnstakeInstructionAccounts = async({ marinadeState, ownerAddress, associatedMSolTokenAccountAddress, msolTokenPartnerAccount }: { marinadeState: MarinadeState, ownerAddress: web3.PublicKey, associatedMSolTokenAccountAddress: web3.PublicKey, + msolTokenPartnerAccount: web3.PublicKey, }): Promise => ({ marinadeFinanceProgram: marinadeState.marinadeFinanceProgramId, state: marinadeState.marinadeStateAddress, @@ -39,6 +40,7 @@ export class MarinadeReferralProgram { treasuryMsolAccount: marinadeState.treasuryMsolAccount, systemProgram: SYSTEM_PROGRAM_ID, tokenProgram: TOKEN_PROGRAM_ID, + msolTokenPartnerAccount: msolTokenPartnerAccount, }) liquidUnstakeInstruction = ({ accounts, amountLamports }: { @@ -55,10 +57,11 @@ export class MarinadeReferralProgram { accounts: await this.liquidUnstakeInstructionAccounts(accountsArgs), }) - depositInstructionAccounts = async({ marinadeState, transferFrom, associatedMSolTokenAccountAddress }: { + depositInstructionAccounts = async({ marinadeState, transferFrom, associatedMSolTokenAccountAddress, msolTokenPartnerAccount }: { marinadeState: MarinadeState, transferFrom: web3.PublicKey, associatedMSolTokenAccountAddress: web3.PublicKey, + msolTokenPartnerAccount: web3.PublicKey }): Promise => ({ reservePda: await marinadeState.reserveAddress(), marinadeFinanceProgram: marinadeState.marinadeFinanceProgramId, @@ -73,6 +76,7 @@ export class MarinadeReferralProgram { transferFrom, systemProgram: SYSTEM_PROGRAM_ID, tokenProgram: TOKEN_PROGRAM_ID, + msolTokenPartnerAccount: msolTokenPartnerAccount, }) depositInstruction = ({ accounts, amountLamports }: { @@ -96,6 +100,7 @@ export class MarinadeReferralProgram { stakeAccountAddress, authorizedWithdrawerAddress, associatedMSolTokenAccountAddress, + msolTokenPartnerAccount, }: { marinadeState: MarinadeState, duplicationFlag: web3.PublicKey, @@ -103,6 +108,7 @@ export class MarinadeReferralProgram { stakeAccountAddress: web3.PublicKey, authorizedWithdrawerAddress: web3.PublicKey, associatedMSolTokenAccountAddress: web3.PublicKey, + msolTokenPartnerAccount: web3.PublicKey, }): Promise => ({ duplicationFlag, stakeAuthority: authorizedWithdrawerAddress, @@ -121,6 +127,7 @@ export class MarinadeReferralProgram { systemProgram: SYSTEM_PROGRAM_ID, tokenProgram: TOKEN_PROGRAM_ID, stakeProgram: STAKE_PROGRAM_ID, + msolTokenPartnerAccount, }) depositStakeAccountInstruction = ({ accounts, validatorIndex }: { diff --git a/src/util/state-helpers.ts b/src/util/state-helpers.ts index 22ef0d8..4484f84 100644 --- a/src/util/state-helpers.ts +++ b/src/util/state-helpers.ts @@ -1,5 +1,4 @@ import { BN } from '@project-serum/anchor' -import BigNumber from 'bignumber.js' import { MarinadeState } from '../marinade-state/marinade-state' /** @@ -44,8 +43,8 @@ export function proportionalBN(amount: BN, numerator: BN, denominator: BN): BN { if (denominator.isZero()) { return amount } - const result = new BigNumber(amount.toString()).multipliedBy(new BigNumber(numerator.toString())).dividedBy(new BigNumber(denominator.toString())) - return new BN(result.decimalPlaces(0, BigNumber.ROUND_FLOOR).toString()) + const result = BigInt(amount.toString()) * BigInt(numerator.toString()) / BigInt(denominator.toString()) + return new BN(result.toString()) } /** From fe1b16ba10641d3f3fe64a1162f7052882ef45f1 Mon Sep 17 00:00:00 2001 From: luciotato Date: Thu, 22 Sep 2022 05:58:44 -0300 Subject: [PATCH 2/6] update marinadeReferralProgramId to V2 --- src/config/marinade-config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/marinade-config.ts b/src/config/marinade-config.ts index d32e018..cfd1c87 100644 --- a/src/config/marinade-config.ts +++ b/src/config/marinade-config.ts @@ -4,7 +4,7 @@ const DEFAULT_PROVIDER_URL = 'https://api.devnet.solana.com' export class MarinadeConfig { marinadeFinanceProgramId = new web3.PublicKey('MarBmsSgKXdrN1egZf5sqe1TMai9K1rChYNDJgjq7aD') - marinadeReferralProgramId = new web3.PublicKey('mRefx8ypXNxE59NhoBqwqb3vTvjgf8MYECp4kgJWiDY') + marinadeReferralProgramId = new web3.PublicKey('MR2LqxoSbw831bNy68utpu5n4YqBH3AzDmddkgk9LQv') marinadeStateAddress = new web3.PublicKey('8szGkuLTAux9XMgZ2vtY39jVSowEcpBfFfD8hXSEqdGC') marinadeReferralGlobalStateAddress = new web3.PublicKey('mRg6bDsAd5uwERAdNTynoUeRbqQsLa7yzuK2kkCUPGW') From 9f78e812516cfb6368141a7e9328573a38031def Mon Sep 17 00:00:00 2001 From: luciotato Date: Thu, 22 Sep 2022 06:07:29 -0300 Subject: [PATCH 3/6] fix referralState validatorVoteKey type --- src/marinade-referral-state/marinade-referral-state.types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/marinade-referral-state/marinade-referral-state.types.ts b/src/marinade-referral-state/marinade-referral-state.types.ts index dc9b9f6..107c667 100644 --- a/src/marinade-referral-state/marinade-referral-state.types.ts +++ b/src/marinade-referral-state/marinade-referral-state.types.ts @@ -14,7 +14,7 @@ export namespace MarinadeReferralStateResponse { export interface ReferralState { partnerName: string - validatorVoteKey: string|null + validatorVoteKey: web3.PublicKey|null keepSelfStakePct: number partnerAccount: web3.PublicKey msolTokenPartnerAccount: web3.PublicKey From b511bb4983362f931bf76fd26f0b573b2fb82a4f Mon Sep 17 00:00:00 2001 From: Ondra Chaloupka Date: Thu, 22 Sep 2022 15:27:38 +0200 Subject: [PATCH 4/6] Fix eslint to get running tests --- src/marinade.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/marinade.ts b/src/marinade.ts index 425b72b..e341a5b 100644 --- a/src/marinade.ts +++ b/src/marinade.ts @@ -171,7 +171,7 @@ export class Marinade { marinadeState, transferFrom: feePayer, associatedMSolTokenAccountAddress, - msolTokenPartnerAccount: referralState.state.msolTokenPartnerAccount + msolTokenPartnerAccount: referralState.state.msolTokenPartnerAccount, }) } else { @@ -335,7 +335,7 @@ export class Marinade { * Liquidate a delegated stake account. * Note that the stake must be fully activated and the validator must be known to Marinade * and that the transaction should be executed immediately after creation. - * + * * @param {web3.PublicKey} stakeAccountAddress - The account to be deposited * @param {BN} mSolToKeep - Optional amount of mSOL lamports to keep */ @@ -368,7 +368,7 @@ export class Marinade { /** * Returns estimated Due date for an unstake ticket created now - * + * */ async getEstimatedUnstakeTicketDueDate() { const marinadeState = await this.getMarinadeState() From ec33256035b2397e8ae0fabe4070885326f3c6d7 Mon Sep 17 00:00:00 2001 From: Ondra Chaloupka Date: Thu, 22 Sep 2022 11:59:33 +0200 Subject: [PATCH 5/6] Call adjustments to cache the referrral state call --- src/marinade.ts | 94 ++++++----------------- src/programs/marinade-referral-program.ts | 26 ++++--- 2 files changed, 42 insertions(+), 78 deletions(-) diff --git a/src/marinade.ts b/src/marinade.ts index e341a5b..1f80ef3 100644 --- a/src/marinade.ts +++ b/src/marinade.ts @@ -35,6 +35,7 @@ export class Marinade { this.config.marinadeReferralProgramId, this.provider, this.config.referralCode, + this, ) private provideReferralOrMainProgram(): MarinadeFinanceProgram | MarinadeReferralProgram { @@ -162,27 +163,13 @@ export class Marinade { transaction.add(createAssociateTokenInstruction) } - let depositInstruction - if (this.config.referralCode) { - const program = this.marinadeReferralProgram - const referralState = await this.getReferralPartnerState() - depositInstruction = await program.depositInstructionBuilder({ - amountLamports, - marinadeState, - transferFrom: feePayer, - associatedMSolTokenAccountAddress, - msolTokenPartnerAccount: referralState.state.msolTokenPartnerAccount, - }) - } - else { - const program = this.marinadeFinanceProgram - depositInstruction = await program.depositInstructionBuilder({ - amountLamports, - marinadeState, - transferFrom: feePayer, - associatedMSolTokenAccountAddress, - }) - } + const program = this.provideReferralOrMainProgram() + const depositInstruction = await program.depositInstructionBuilder({ + amountLamports, + marinadeState, + transferFrom: feePayer, + associatedMSolTokenAccountAddress, + }) transaction.add(depositInstruction) @@ -213,27 +200,13 @@ export class Marinade { } } - let liquidUnstakeInstruction - if (this.config.referralCode) { - const program = this.marinadeReferralProgram - const referralState = await this.getReferralPartnerState() - liquidUnstakeInstruction = await program.liquidUnstakeInstructionBuilder({ - amountLamports, - marinadeState, - ownerAddress, - associatedMSolTokenAccountAddress, - msolTokenPartnerAccount: referralState.state.msolTokenPartnerAccount, - }) - } - else { - const program = this.marinadeFinanceProgram - liquidUnstakeInstruction = await program.liquidUnstakeInstructionBuilder({ - amountLamports, - marinadeState, - ownerAddress, - associatedMSolTokenAccountAddress, - }) - } + const program = this.provideReferralOrMainProgram() + const liquidUnstakeInstruction = await program.liquidUnstakeInstructionBuilder({ + amountLamports, + marinadeState, + ownerAddress, + associatedMSolTokenAccountAddress, + }) transaction.add(liquidUnstakeInstruction) @@ -292,33 +265,16 @@ export class Marinade { transaction.add(createAssociateTokenInstruction) } - let depositStakeAccountInstruction - if (this.config.referralCode) { - const program = this.marinadeReferralProgram - const referralState = await this.getReferralPartnerState() - depositStakeAccountInstruction = await program.depositStakeAccountInstructionBuilder({ - validatorIndex, - marinadeState, - duplicationFlag, - authorizedWithdrawerAddress, - associatedMSolTokenAccountAddress, - ownerAddress, - stakeAccountAddress, - msolTokenPartnerAccount: referralState.state.msolTokenPartnerAccount, - }) - } - else { - const program = this.marinadeFinanceProgram - depositStakeAccountInstruction = await program.depositStakeAccountInstructionBuilder({ - validatorIndex, - marinadeState, - duplicationFlag, - authorizedWithdrawerAddress, - associatedMSolTokenAccountAddress, - ownerAddress, - stakeAccountAddress, - }) - } + const program = this.provideReferralOrMainProgram() + const depositStakeAccountInstruction = await program.depositStakeAccountInstructionBuilder({ + validatorIndex, + marinadeState, + duplicationFlag, + authorizedWithdrawerAddress, + associatedMSolTokenAccountAddress, + ownerAddress, + stakeAccountAddress, + }) transaction.add(depositStakeAccountInstruction) diff --git a/src/programs/marinade-referral-program.ts b/src/programs/marinade-referral-program.ts index e93b66b..3807040 100644 --- a/src/programs/marinade-referral-program.ts +++ b/src/programs/marinade-referral-program.ts @@ -2,16 +2,21 @@ import { BN, Idl, Program, Provider, web3 } from '@project-serum/anchor' import { TOKEN_PROGRAM_ID } from '@solana/spl-token' import { SYSVAR_CLOCK_PUBKEY, SYSVAR_RENT_PUBKEY } from '@solana/web3.js' import { MarinadeState } from '../marinade-state/marinade-state' +import { MarinadeReferralStateResponse } from '../marinade-referral-state/marinade-referral-state.types' +import { Marinade } from '../marinade' import { STAKE_PROGRAM_ID, SYSTEM_PROGRAM_ID } from '../util' import { assertNotNullAndReturn } from '../util/assert' import { MarinadeReferralIdl } from './idl/marinade-referral-idl' import * as marinadeReferralIdlSchema from './idl/marinade-referral-idl.json' export class MarinadeReferralProgram { + referralStateData: MarinadeReferralStateResponse.ReferralState | null = null + constructor( public readonly programAddress: web3.PublicKey, public readonly anchorProvider: Provider, public readonly referralState: web3.PublicKey | null, + readonly marinade: Marinade, ) { } get program(): Program { @@ -22,11 +27,10 @@ export class MarinadeReferralProgram { ) } - liquidUnstakeInstructionAccounts = async({ marinadeState, ownerAddress, associatedMSolTokenAccountAddress, msolTokenPartnerAccount }: { + liquidUnstakeInstructionAccounts = async({ marinadeState, ownerAddress, associatedMSolTokenAccountAddress }: { marinadeState: MarinadeState, ownerAddress: web3.PublicKey, associatedMSolTokenAccountAddress: web3.PublicKey, - msolTokenPartnerAccount: web3.PublicKey, }): Promise => ({ marinadeFinanceProgram: marinadeState.marinadeFinanceProgramId, state: marinadeState.marinadeStateAddress, @@ -40,7 +44,7 @@ export class MarinadeReferralProgram { treasuryMsolAccount: marinadeState.treasuryMsolAccount, systemProgram: SYSTEM_PROGRAM_ID, tokenProgram: TOKEN_PROGRAM_ID, - msolTokenPartnerAccount: msolTokenPartnerAccount, + msolTokenPartnerAccount: (await this.getReferralStateData()).msolTokenPartnerAccount, }) liquidUnstakeInstruction = ({ accounts, amountLamports }: { @@ -57,11 +61,10 @@ export class MarinadeReferralProgram { accounts: await this.liquidUnstakeInstructionAccounts(accountsArgs), }) - depositInstructionAccounts = async({ marinadeState, transferFrom, associatedMSolTokenAccountAddress, msolTokenPartnerAccount }: { + depositInstructionAccounts = async({ marinadeState, transferFrom, associatedMSolTokenAccountAddress }: { marinadeState: MarinadeState, transferFrom: web3.PublicKey, associatedMSolTokenAccountAddress: web3.PublicKey, - msolTokenPartnerAccount: web3.PublicKey }): Promise => ({ reservePda: await marinadeState.reserveAddress(), marinadeFinanceProgram: marinadeState.marinadeFinanceProgramId, @@ -76,7 +79,7 @@ export class MarinadeReferralProgram { transferFrom, systemProgram: SYSTEM_PROGRAM_ID, tokenProgram: TOKEN_PROGRAM_ID, - msolTokenPartnerAccount: msolTokenPartnerAccount, + msolTokenPartnerAccount: (await this.getReferralStateData()).msolTokenPartnerAccount, }) depositInstruction = ({ accounts, amountLamports }: { @@ -100,7 +103,6 @@ export class MarinadeReferralProgram { stakeAccountAddress, authorizedWithdrawerAddress, associatedMSolTokenAccountAddress, - msolTokenPartnerAccount, }: { marinadeState: MarinadeState, duplicationFlag: web3.PublicKey, @@ -108,7 +110,6 @@ export class MarinadeReferralProgram { stakeAccountAddress: web3.PublicKey, authorizedWithdrawerAddress: web3.PublicKey, associatedMSolTokenAccountAddress: web3.PublicKey, - msolTokenPartnerAccount: web3.PublicKey, }): Promise => ({ duplicationFlag, stakeAuthority: authorizedWithdrawerAddress, @@ -127,7 +128,7 @@ export class MarinadeReferralProgram { systemProgram: SYSTEM_PROGRAM_ID, tokenProgram: TOKEN_PROGRAM_ID, stakeProgram: STAKE_PROGRAM_ID, - msolTokenPartnerAccount, + msolTokenPartnerAccount: (await this.getReferralStateData()).msolTokenPartnerAccount, }) depositStakeAccountInstruction = ({ accounts, validatorIndex }: { @@ -143,4 +144,11 @@ export class MarinadeReferralProgram { validatorIndex, accounts: await this.depositStakeAccountInstructionAccounts(accountsArgs), }) + + async getReferralStateData(): Promise { + if (!this.referralStateData) { + this.referralStateData = (await this.marinade.getReferralPartnerState()).state + } + return this.referralStateData + } } From b538c57fef479fa9a4fc742c9f5d67ae8dccd4cf Mon Sep 17 00:00:00 2001 From: Ondra Chaloupka Date: Thu, 22 Sep 2022 18:33:32 +0200 Subject: [PATCH 6/6] Integration tests + code fixes in progress --- src/config/marinade-config.ts | 2 +- .../marinade-referral-state.types.ts | 7 ++++-- test/marinade-referral-state.spec.ts | 25 +++++++++++++------ test/test-world.ts | 2 -- 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/config/marinade-config.ts b/src/config/marinade-config.ts index cfd1c87..fc79096 100644 --- a/src/config/marinade-config.ts +++ b/src/config/marinade-config.ts @@ -7,7 +7,7 @@ export class MarinadeConfig { marinadeReferralProgramId = new web3.PublicKey('MR2LqxoSbw831bNy68utpu5n4YqBH3AzDmddkgk9LQv') marinadeStateAddress = new web3.PublicKey('8szGkuLTAux9XMgZ2vtY39jVSowEcpBfFfD8hXSEqdGC') - marinadeReferralGlobalStateAddress = new web3.PublicKey('mRg6bDsAd5uwERAdNTynoUeRbqQsLa7yzuK2kkCUPGW') + marinadeReferralGlobalStateAddress = new web3.PublicKey('MRSh4rUNrpn7mjAq9ENHV4rvwwPKMij113ScZq3twp2') stakeWithdrawAuthPDA = new web3.PublicKey('9eG63CdHjsfhHmobHgLtESGC8GabbmRcaSpHAZrtmhco') diff --git a/src/marinade-referral-state/marinade-referral-state.types.ts b/src/marinade-referral-state/marinade-referral-state.types.ts index 107c667..10f1a95 100644 --- a/src/marinade-referral-state/marinade-referral-state.types.ts +++ b/src/marinade-referral-state/marinade-referral-state.types.ts @@ -8,8 +8,11 @@ export const enum ProgramDerivedAddressSeed { export namespace MarinadeReferralStateResponse { export interface GlobalState { adminAccount: web3.PublicKey - treasuryMsolAccount: web3.PublicKey - treasuryMsolAuthBump: number + msolMintAccount: web3.PublicKey + foreman1: web3.PublicKey + foreman2: web3.PublicKey + minKeepPct: number + maxKeepPct: number } export interface ReferralState { diff --git a/test/marinade-referral-state.spec.ts b/test/marinade-referral-state.spec.ts index 7594086..e37c9e4 100644 --- a/test/marinade-referral-state.spec.ts +++ b/test/marinade-referral-state.spec.ts @@ -2,8 +2,8 @@ import { Marinade, MarinadeConfig, web3, BN } from '../src' import { MarinadeReferralStateResponse } from '../src/marinade-referral-state/marinade-referral-state.types' import * as TestWorld from './test-world' -describe('Marinade Referral State', () => { - describe('getReferralPartnerState', () => { +describe('Marinade Referral Program', () => { + describe('getReferralGlobalState', () => { it('fetches the referral program\'s global state which matches the expected type', async() => { const config = new MarinadeConfig({ connection: TestWorld.CONNECTION, @@ -15,8 +15,11 @@ describe('Marinade Referral State', () => { expect(state).toStrictEqual({ adminAccount: expect.any(web3.PublicKey), - treasuryMsolAccount: expect.any(web3.PublicKey), - treasuryMsolAuthBump: expect.any(Number), + msolMintAccount: expect.any(web3.PublicKey), + foreman1: expect.any(web3.PublicKey), + foreman2: expect.any(web3.PublicKey), + minKeepPct: expect.any(Number), + maxKeepPct: expect.any(Number), }) }) }) @@ -33,13 +36,14 @@ describe('Marinade Referral State', () => { expect(state).toStrictEqual({ baseFee: expect.any(Number), + validatorVoteKey: null, + keepSelfStakePct: expect.any(Number), delayedUnstakeAmount: expect.any(BN), delayedUnstakeOperations: expect.any(BN), depositSolAmount: expect.any(BN), depositSolOperations: expect.any(BN), depositStakeAccountAmount: expect.any(BN), depositStakeAccountOperations: expect.any(BN), - lastTransferTime: expect.any(BN), liqUnstakeSolAmount: expect.any(BN), liqUnstakeMsolAmount: expect.any(BN), liqUnstakeMsolFees: expect.any(BN), @@ -49,8 +53,15 @@ describe('Marinade Referral State', () => { partnerAccount: expect.any(web3.PublicKey), partnerName: TestWorld.PARTNER_NAME, pause: expect.any(Boolean), - tokenPartnerAccount: expect.any(web3.PublicKey), - transferDuration: expect.any(Number), + msolTokenPartnerAccount: expect.any(web3.PublicKey), + operationDepositSolFee: expect.any(Number), + operationDepositStakeAccountFee: expect.any(Number), + operationLiquidUnstakeFee: expect.any(Number), + operationDelayedUnstakeFee: expect.any(Number), + accumDepositSolFee: expect.any(BN), + accumDepositStakeAccountFee: expect.any(BN), + accumLiquidUnstakeFee: expect.any(BN), + accumDelayedUnstakeFee: expect.any(BN), }) }) }) diff --git a/test/test-world.ts b/test/test-world.ts index 24f3163..5fc3990 100644 --- a/test/test-world.ts +++ b/test/test-world.ts @@ -3,8 +3,6 @@ import { MarinadeUtils } from '../src' export const LAMPORTS_AIRDROP_CAP = MarinadeUtils.solToLamports(2) -export const MARINADE_PROGRAM_REFERRAL_ID = new web3.PublicKey('FqYPYHc3man91xYDCugbGuDdWgkNLp5TvbXPascHW6MR') - export const SDK_USER = web3.Keypair.fromSecretKey(new Uint8Array([ 120, 45, 242, 38, 63, 135, 84, 226, 66, 56, 76, 216, 125, 144, 38, 182, 53, 47, 169, 251, 128, 65,