Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for using Marinade Native in the SDK #59

Merged
merged 6 commits into from
Sep 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## v5.0.5

### Feat:

- Add support to stake into Marinade Native with or without Referral Code
- Add support to unstake from Marinade Native

## v5.0.4

### Fix:
Expand Down
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,47 @@ const {
const signature = await provider.send(transaction)
```

### Marinade Native Staking

You can now stake assets in Marinade Native through the SDK, either with or without a referral code.

#### Stake without referral code
If you choose to stake without a referral code, the methods exposed in `marinade-native-stake.ts` serve as wrappers for those already detailed in the [Native Stake SDK](https://www.npmjs.com/package/@marinade.finance/native-staking-sdk).
Please note that staking without a referral code will yield only Transaction Instructions.

#### Stake with referral code
To acquire a referral code, you'll need to visit the [Marinade dApp](https://marinade.finance/app/earn/) to retrieve it.
Once you have the code, you can input it into the methods described below. Please note that the method returns a Versioned Transaction.

Stake SOL to Marinade Native
```ts
...
const versionedTransaction = await getRefNativeStakeSOLTx(userPublicKey, amountLamports, refCode)
// sign and send the `transaction`
const signature = await wallet.sendTransaction(unsignedTx, connection)
```

Deposit Stake Account to Marinade Native
```ts
...
const versionedTransaction = await getRefNativeStakeAccountTx(userPublicKey, stakeAccountAddress, refCode)
// sign and send the `transaction`
const signature = await wallet.sendTransaction(versionedTransaction, connection)
```

#### Prepare for Unstake from Marinade Native
To initiate the process of unstaking, you'll need to merge your stake accounts back into a single account and pay the associated fee (in SOL). To do this, execute the following command:

```ts
...
const transaction = new Transaction()
const prepareUnstakeIx = await getPrepareNativeUnstakeSOLIx(userPublicKey, amountLamports)
transaction.add(...prepareUnstakeIx.payFees)
// sign and send the `transaction`
const signature = await wallet.sendTransaction(transaction, connection)
await authIx.onPaid()
```

### Liquidity pool

Add liquidity to the liquidity pool and receive LP tokens:
Expand Down
13 changes: 7 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@marinade.finance/marinade-ts-sdk",
"version": "5.0.4",
"version": "5.0.5",
"description": "Marinade SDK for Typescript",
"main": "dist/src/index.js",
"repository": {
Expand Down Expand Up @@ -37,24 +37,28 @@
"dependencies": {
"@coral-xyz/anchor": "^0.28.0",
"@marinade.finance/directed-stake-sdk": "^0.0.4",
"@marinade.finance/native-staking-sdk": "^1.0.0",
"@solana/spl-stake-pool": "^0.6.5",
"@solana/spl-token-3.x": "npm:@solana/spl-token@^0.3.8",
"borsh": "^0.7.0",
"bs58": "^5.0.0"
},
"devDependencies": {
"@jest/globals": "^29.5.0",
"@solana/web3.js": "^1.74.0",
"@types/bn.js": "^5.1.1",
"@types/bs58": "^4.0.1",
"@types/jest": "^29.5.1",
"@jest/globals": "^29.5.0",
"@types/node": "^18.16.3",
"@typescript-eslint/eslint-plugin": "^5.59.1",
"@typescript-eslint/parser": "^5.59.1",
"bn.js": "^5.2.1",
"eslint": "^8.39.0",
"gts": "^3.1.1",
"husky": "^8.0.3",
"jest": "^29.5.0",
"jest-each": "^29.5.0",
"jsbi": "^4.3.0",
"lint-staged": "^13.2.2",
"node-polyfill-webpack-plugin": "^2.0.1",
"terser-webpack-plugin": "^5.3.7",
Expand All @@ -63,10 +67,7 @@
"ts-node": "^10.9.1",
"typescript": "^5.0.4",
"webpack": "^5.81.0",
"webpack-cli": "^5.0.2",
"@solana/web3.js": "^1.74.0",
"bn.js": "^5.2.1",
"jsbi": "^4.3.0"
"webpack-cli": "^5.0.2"
},
"engines": {
"node": ">=16.0.0",
Expand Down
31 changes: 28 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export { Marinade } from './marinade'
export * from './marinade-native-stake'
export { MarinadeConfig } from './config/marinade-config'
export * as MarinadeBorsh from './marinade-state/borsh/index'
export { MarinadeReferralPartnerState } from './marinade-referral-state/marinade-referral-partner-state'
Expand Down
116 changes: 116 additions & 0 deletions src/marinade-native-stake.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import {
PublicKey,
TransactionInstruction,
VersionedTransaction,
} from '@solana/web3.js'
import BN from 'bn.js'
import { NativeStakingSDK } from '@marinade.finance/native-staking-sdk'
import {
AuthStakeSOLIxResponse,
UnstakeSOLIxResponse,
} from './marinade-native-stake.types'

/**
* Retrieves the instruction for staking SOL with Marinade Native.
*
* @param {PublicKey} userPublicKey - The PublicKey associated with the user.
* @param {BN} amountToStake - The amount to be staked, in lamports.
* @returns {AuthStakeSOLIxResponse} - The instructions to include in the transaction for staking in Marinade Native, along with the new stake keypair.
*/
export function getAuthNativeStakeSOLIx(
userPublicKey: PublicKey,
amountToStake: BN
): AuthStakeSOLIxResponse {
const nativeSdk = new NativeStakingSDK()
return nativeSdk.buildCreateAuthorizedStakeInstructions(
userPublicKey,
amountToStake
)
}

/**
* Retrieves the transaction for staking SOL with Marinade Native using a referral code.
*
* @param {PublicKey} userPublicKey - The PublicKey associated with the user.
* @param {BN} amountToStake - The amount to be staked, specified in lamports.
* @param {string} mNativeRefCode - The Marinade Native referral code.
* @returns {Promise<VersionedTransaction>} - A promise that resolves to the transaction for staking SOL with Marinade Native using the referral code.
*/
export async function getRefNativeStakeSOLTx(
userPublicKey: PublicKey,
amountToStake: BN,
mNativeRefCode: string
): Promise<VersionedTransaction> {
const response = await fetch(
`https://native-staking-referral.marinade.finance/v1/tx/deposit-sol?amount=${amountToStake.toString()}&code=${mNativeRefCode}&user=${userPublicKey.toString()}`
)
const result = await response.json()

const txBuffer = Buffer.from(result.serializedTx, 'base64')
return VersionedTransaction.deserialize(txBuffer)
}

/**
* Retrieves the instruction for staking a Stake Account with Marinade Native.
*
* @param {PublicKey} userPublicKey - The PublicKey associated with the user.
* @param {PublicKey[]} stakeAccounts - The stake accounts to be used with Marinade Native.
* @returns {TransactionInstruction} - The instruction to include in the transaction for staking the Stake Account with Marinade Native.
*/
export function getAuthNativeStakeAccountIx(
userPublicKey: PublicKey,
stakeAccounts: PublicKey[]
): TransactionInstruction[] {
const nativeSdk = new NativeStakingSDK()
return nativeSdk.buildAuthorizeInstructions(userPublicKey, stakeAccounts)
}

/**
* Retrieves the transaction for using a Stake Account with Marinade Native via a referral code.
*
* @param {PublicKey} userPublicKey - The PublicKey associated with the user.
* @param {PublicKey} stakeAccountAddress - The address of the stake account intended to use with Marinade Native.
* @param {string} mNativeRefCode - The Marinade Native referral code.
* @returns {Promise<VersionedTransaction>} - A promise resolving to the transaction required for using the Stake Account with Marinade Native via the given referral code.
*/
export async function getRefNativeStakeAccountTx(
userPublicKey: PublicKey,
stakeAccountAddress: PublicKey,
mNativeRefCode: string
): Promise<VersionedTransaction> {
const response = await fetch(
`https://native-staking-referral.marinade.finance/v1/tx/deposit-stake-account?stake=${stakeAccountAddress.toString()}&code=${mNativeRefCode}&user=${userPublicKey.toString()}`
)

const result = await response.json()

const txBuffer = Buffer.from(result.serializedTx, 'base64')
return VersionedTransaction.deserialize(txBuffer)
}

/**
* Retrieves the instruction for unstaking from Marinade Native.
*
* @param {PublicKey} userPublicKey - The PublicKey associated with the user.
* @param {BN} amountToUnstake - The amount to be unstaked, specified in lamports.
* @returns {UnstakeSOLIxResponse} - The instructions for paying the unstaking fee and an optional event that can be called after the fee is paid to expedite the unstaking process (calling this event is optional but enhances the user experience).
*/
export async function getPrepareNativeUnstakeSOLIx(
userPublicKey: PublicKey,
amountToUnstake: BN
): Promise<UnstakeSOLIxResponse> {
const nativeSdk = new NativeStakingSDK()
return await nativeSdk.initPrepareForRevoke(userPublicKey, amountToUnstake)
}

/**
* Invokes the bot to rebalance the user's funds. This is particularly useful immediately following a deposit into Marinade Native, although it is not mandatory.
*
* @param {PublicKey} userPublicKey - The PublicKey associated with the user.
*/
export async function callRebalanceHint(
userPublicKey: PublicKey
): Promise<void> {
const nativeSdk = new NativeStakingSDK()
return await nativeSdk.callRebalanceHint(userPublicKey)
}
11 changes: 11 additions & 0 deletions src/marinade-native-stake.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Keypair, TransactionInstruction } from '@solana/web3.js'

export type AuthStakeSOLIxResponse = {
createAuthorizedStake: TransactionInstruction[]
stakeKeypair: Keypair
}

export type UnstakeSOLIxResponse = {
payFees: TransactionInstruction[]
onPaid: (signature: string) => Promise<unknown>
}
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"lib": ["es2021"],
"lib": ["es2021", "dom"],
"target": "ES6",
"module": "CommonJS",
"rootDir": ".",
Expand Down
Loading