feat: add staking

This commit is contained in:
Arihant Bansal
2024-12-12 01:26:12 +05:30
parent d4e17ad0e7
commit 91f7b8a478
5 changed files with 121 additions and 12 deletions

View File

@@ -8,6 +8,7 @@ A powerful toolkit for interacting with the Solana blockchain, providing easy-to
- Deploy new SPL tokens
- Transfer SOL and SPL tokens
- Check token balances
- Stake SOL
- 🖼️ NFT Management
- Deploy NFT collections
@@ -110,6 +111,17 @@ const signature = await lendAsset(
);
```
### Stake SOL
```typescript
import { stakeWithJup } from 'solana-agent-kit';
const signature = await stakeWithJup(
agent,
1 // amount in SOL
);
```
## API Reference
### Core Functions
@@ -135,6 +147,9 @@ Check SOL or token balance for the agent's wallet.
#### `lendAsset(agent, assetMint, amount, apiKey)`
Lend idle assets to earn interest with Lulo.
#### `stakeWithJup(agent, amount)`
Stake SOL with Jupiter to earn rewards.
## Dependencies
The toolkit relies on several key Solana and Metaplex libraries:

View File

@@ -10,6 +10,7 @@ import {
trade,
registerDomain,
launchPumpFunToken,
stakeWithJup,
} from "../tools";
import { CollectionOptions, PumpFunTokenOptions } from "../types";
import { DEFAULT_OPTIONS } from "../constants";
@@ -101,4 +102,10 @@ export class SolanaAgentKit {
options
);
}
async stake(
amount: number,
) {
return stakeWithJup(this, amount);
}
}

View File

@@ -42,7 +42,7 @@ export class SolanaTransferTool extends Tool {
name = "solana_transfer";
description = `Transfer tokens or SOL to another address ( also called as wallet address ).
Inputs ( input is a JSON string ):
Inputs ( input is a JSON string ):
to: string, eg "8x2dR8Mpzuz2YqyZyZjUbYWKSWesBo5jMx2Q9Y86udVk" (required)
amount: number, eg 1 (required)
mint?: string, eg "So11111111111111111111111111111111111111112" or "SENDdRQtYMWaQrBroBrJ2Q53fgVuq95CV9UPGEvpCxa" (optional)`;
@@ -64,7 +64,7 @@ export class SolanaTransferTool extends Tool {
const tx = await this.solanaKit.transfer(
recipient,
parsedInput.amount,
mintAddress
mintAddress,
);
return JSON.stringify({
@@ -102,7 +102,7 @@ export class SolanaDeployTokenTool extends Tool {
input.decimals > 9)
) {
throw new Error(
"decimals must be a number between 0 and 9 when provided"
"decimals must be a number between 0 and 9 when provided",
);
}
if (
@@ -159,7 +159,7 @@ export class SolanaDeployCollectionTool extends Tool {
input.royaltyBasisPoints > 10000)
) {
throw new Error(
"royaltyBasisPoints must be a number between 0 and 10000 when provided"
"royaltyBasisPoints must be a number between 0 and 10000 when provided",
);
}
if (input.creators) {
@@ -169,7 +169,7 @@ export class SolanaDeployCollectionTool extends Tool {
input.creators.forEach((creator: any, index: number) => {
if (!creator.address || typeof creator.address !== "string") {
throw new Error(
`creator[${index}].address is required and must be a string`
`creator[${index}].address is required and must be a string`,
);
}
if (
@@ -178,7 +178,7 @@ export class SolanaDeployCollectionTool extends Tool {
creator.percentage > 100
) {
throw new Error(
`creator[${index}].percentage must be a number between 0 and 100`
`creator[${index}].percentage must be a number between 0 and 100`,
);
}
});
@@ -246,7 +246,9 @@ export class SolanaMintNFTTool extends Tool {
const result = await this.solanaKit.mintNFT(
new PublicKey(parsedInput.collectionMint),
parsedInput.metadata,
parsedInput.recipient ? new PublicKey(parsedInput.recipient) : undefined
parsedInput.recipient
? new PublicKey(parsedInput.recipient)
: undefined,
);
return JSON.stringify({
@@ -290,7 +292,7 @@ export class SolanaTradeTool extends Tool {
parsedInput.inputMint
? new PublicKey(parsedInput.inputMint)
: new PublicKey("So11111111111111111111111111111111111111112"),
parsedInput.slippageBps
parsedInput.slippageBps,
);
return JSON.stringify({
@@ -371,7 +373,7 @@ export class SolanaRegisterDomainTool extends Tool {
const tx = await this.solanaKit.registerDomain(
parsedInput.name,
parsedInput.spaceKB || 1
parsedInput.spaceKB || 1,
);
return JSON.stringify({
@@ -409,9 +411,9 @@ export class SolanaPumpfunTokenLaunchTool extends Tool {
description = `This tool can be used to launch a token on Pump.fun,
do not use this tool for any other purpose, or for creating SPL tokens.
If the user asks you to chose the parameters, you should generate valid values.
If the user asks you to chose the parameters, you should generate valid values.
For generating the image, you can use the solana_create_image tool.
Inputs:
tokenName: string, eg "PumpFun Token",
tokenTicker: string, eg "PUMP",
@@ -463,7 +465,7 @@ export class SolanaPumpfunTokenLaunchTool extends Tool {
telegram: parsedInput.telegram,
website: parsedInput.website,
initialLiquiditySOL: parsedInput.initialLiquiditySOL,
}
},
);
return JSON.stringify({
@@ -517,6 +519,50 @@ export class SolanaCreateImageTool extends Tool {
}
}
export class SolanaStakeTool extends Tool {
name = "solana_stake";
description = `This tool can be used to stake your SOL (Solana)
Inputs ( input is a JSON string ):
amount: number, eg 1 or 0.01 (required)`;
constructor(private solanaKit: SolanaAgentKit) {
super();
}
private validateInput(input: any): void {
if (
input.amount !== undefined &&
(typeof input.amount !== "number" || input.amount <= 0)
) {
throw new Error("amount must be a positive number when provided");
}
}
protected async _call(input: string): Promise<string> {
try {
const parsedInput = toJSON(input);
this.validateInput(parsedInput);
const tx = await this.solanaKit.stake(parsedInput.amount);
return JSON.stringify({
status: "success",
message: "Staked successfully",
transaction: tx,
amount: parsedInput.amount,
});
} catch (error: any) {
console.log(error);
return JSON.stringify({
status: "error",
message: error.message,
code: error.code || "UNKNOWN_ERROR",
});
}
}
}
export function createSolanaTools(solanaKit: SolanaAgentKit) {
return [
new SolanaBalanceTool(solanaKit),
@@ -530,5 +576,6 @@ export function createSolanaTools(solanaKit: SolanaAgentKit) {
new SolanaGetWalletAddressTool(solanaKit),
new SolanaPumpfunTokenLaunchTool(solanaKit),
new SolanaCreateImageTool(solanaKit),
new SolanaStakeTool(solanaKit),
];
}

View File

@@ -7,3 +7,4 @@ export * from './transfer';
export * from './trade';
export * from './register_domain';
export * from './launch_pumpfun_token';
export * from './stake_with_jup';

View File

@@ -0,0 +1,39 @@
import { VersionedTransaction } from "@solana/web3.js";
import { SolanaAgentKit } from "../agent";
/**
* Stake SOL with Jup validator
* @param agent SolanaAgentKit instance
* @param amount Amount of SOL to stake
* @returns Transaction signature
*/
export async function stakeWithJup(
agent: SolanaAgentKit,
amount: number,
): Promise<string> {
try {
const res = await fetch(
`https://worker.jup.ag/blinks/swap/So11111111111111111111111111111111111111112/jupSoLaHXQiZZTSfEWMTRRgpnyFm8f6sZdosWBjx93v/${amount}`,
{
method: "POST",
body: JSON.stringify({
account: agent.wallet.publicKey.toBase58(),
}),
},
);
const data = await res.json();
const txn = VersionedTransaction.deserialize(
Buffer.from(data.transaction, "base64"),
);
// Sign and send transaction
txn.sign([agent.wallet]);
const signature = await agent.connection.sendTransaction(txn);
return signature;
} catch (error: any) {
console.error(error);
throw new Error(`jupSOL staking failed: ${error.message}`);
}
}