Add Jup Fees to the platform (#98)

# Pull Request Description

## Related Issue
Fixes # (issue number)

## Changes Made
This PR adds the following changes:
<!-- List the key changes made in this PR -->
- Added jupReferralAccount to allow devs to set Fee Accounts on trade
API (optional parameter)
- Added jupFeeBps to allow devs to set fee in bps  (optional parameter)
  
## Implementation Details
<!-- Provide technical details about the implementation -->
- Added optional Parameter to trade API

## Transaction executed by agent 
<!-- If applicable, provide example usage, transactions, or screenshots
-->
Example transaction: 

https://solscan.io/tx/35b1wz1LjU5pEALq6m5Q6Gyc3QB3ejvsjNAYoy9PdHu9WP8SzGLjHi59sRPj8hvtntVMDMEguWuu273FZ3EbUSoZ
## Prompt Used
<!-- If relevant, include the prompt or configuration used -->
```
```

## Additional Notes
<!-- Any additional information that reviewers should know -->

## Checklist
- [x] I have tested these changes locally
- [x] I have updated the documentation
- [x] I have added a transaction link
- [ ] I have added the prompt used to test it
This commit is contained in:
aryan
2024-12-31 16:29:40 +05:30
committed by GitHub
9 changed files with 634 additions and 13 deletions

View File

@@ -1,3 +1,5 @@
OPENAI_API_KEY=
RPC_URL=
SOLANA_PRIVATE_KEY=
JUPITER_REFERRAL_ACCOUNT=
JUPITER_FEE_BPS=

590
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -2,6 +2,7 @@ import { Connection, Keypair, PublicKey } from "@solana/web3.js";
import bs58 from "bs58";
import Decimal from "decimal.js";
import { DEFAULT_OPTIONS } from "../constants";
import { Config } from "../types";
import {
deploy_collection,
deploy_token,
@@ -71,17 +72,17 @@ export class SolanaAgentKit {
public connection: Connection;
public wallet: Keypair;
public wallet_address: PublicKey;
public openai_api_key: string | null;
public config: Config;
constructor(
private_key: string,
rpc_url = "https://api.mainnet-beta.solana.com",
openai_api_key: string | null = null,
config: Config,
) {
this.connection = new Connection(rpc_url);
this.wallet = Keypair.fromSecretKey(bs58.decode(private_key));
this.wallet_address = this.wallet.publicKey;
this.openai_api_key = openai_api_key;
this.config = config;
}
// Tool methods
@@ -414,10 +415,7 @@ export class SolanaAgentKit {
return create_TipLink(this, amount, splmintAddress);
}
async tensorListNFT(
nftMint: PublicKey,
price: number,
): Promise<string> {
async tensorListNFT(nftMint: PublicKey, price: number): Promise<string> {
return listNFTForSale(this, nftMint, price);
}

View File

@@ -22,9 +22,12 @@ export const TOKENS = {
export const DEFAULT_OPTIONS = {
SLIPPAGE_BPS: 300,
TOKEN_DECIMALS: 9,
RERERRAL_FEE: 200,
} as const;
/**
* Jupiter API URL
*/
export const JUP_API = "https://quote-api.jup.ag/v6";
export const JUP_REFERRAL_ADDRESS =
"REFER4ZgmyYx9c6He5XfaTMiGfdLwRnkV4RPp9t9iF3";

View File

@@ -16,12 +16,12 @@ export async function create_image(
n: number = 1,
) {
try {
if (!agent.openai_api_key) {
if (!agent.config.OPENAI_API_KEY) {
throw new Error("OpenAI API key not found in agent configuration");
}
const openai = new OpenAI({
apiKey: agent.openai_api_key,
apiKey: agent.config.OPENAI_API_KEY,
});
const response = await openai.images.generate({

View File

@@ -32,7 +32,7 @@ export async function listNFTForSale(
if (!tokenAccount || tokenAccount.amount <= 0) {
throw new Error(`You don't own this NFT (${nftMint.toString()})`);
}
} catch (e) {
} catch (error: any) {
throw new Error(
`No token account found for mint ${nftMint.toString()}. Make sure you own this NFT.`,
);

View File

@@ -1,6 +1,11 @@
import { VersionedTransaction, PublicKey } from "@solana/web3.js";
import { SolanaAgentKit } from "../index";
import { TOKENS, DEFAULT_OPTIONS, JUP_API } from "../constants";
import {
TOKENS,
DEFAULT_OPTIONS,
JUP_API,
JUP_REFERRAL_ADDRESS,
} from "../constants";
import { getMint } from "@solana/spl-token";
/**
* Swap tokens using Jupiter Exchange
@@ -11,6 +16,7 @@ import { getMint } from "@solana/spl-token";
* @param slippageBps Slippage tolerance in basis points (default: 300 = 3%)
* @returns Transaction signature
*/
export async function trade(
agent: SolanaAgentKit,
outputMint: PublicKey,
@@ -38,11 +44,24 @@ export async function trade(
`&amount=${scaledAmount}` +
`&slippageBps=${slippageBps}` +
`&onlyDirectRoutes=true` +
`&maxAccounts=20`,
`&maxAccounts=20` +
`${agent.config.JUPITER_FEE_BPS ? `&platformFeeBps=${agent.config.JUPITER_FEE_BPS}` : ""}`,
)
).json();
// Get serialized transaction
let feeAccount;
if (agent.config.JUPITER_REFERRAL_ACCOUNT) {
[feeAccount] = PublicKey.findProgramAddressSync(
[
Buffer.from("referral_ata"),
new PublicKey(agent.config.JUPITER_REFERRAL_ACCOUNT).toBuffer(),
TOKENS.SOL.toBuffer(),
],
new PublicKey(JUP_REFERRAL_ADDRESS),
);
}
const { swapTransaction } = await (
await fetch("https://quote-api.jup.ag/v6/swap", {
method: "POST",
@@ -55,6 +74,7 @@ export async function trade(
wrapAndUnwrapSol: true,
dynamicComputeUnitLimit: true,
prioritizationFeeLamports: "auto",
feeAccount: feeAccount ? feeAccount.toString() : null,
}),
})
).json();

View File

@@ -1,5 +1,11 @@
import { PublicKey } from "@solana/web3.js";
export interface Config {
OPENAI_API_KEY?: string;
JUPITER_REFERRAL_ACCOUNT?: string;
JUPITER_FEE_BPS?: number;
}
export interface Creator {
address: string;
percentage: number;

View File

@@ -53,7 +53,9 @@ async function initializeAgent() {
const solanaAgent = new SolanaAgentKit(
process.env.SOLANA_PRIVATE_KEY!,
process.env.RPC_URL,
process.env.OPENAI_API_KEY!,
{
OPENAI_API_KEY: process.env.OPENAI_API_KEY!,
},
);
const tools = createSolanaTools(solanaAgent);