Add limit order support on Manifest

This commit is contained in:
DonDuala
2024-12-29 21:57:51 -04:00
parent 4ae9051957
commit 284338af54
4 changed files with 138 additions and 2 deletions

View File

@@ -20,6 +20,7 @@ import {
registerDomain,
request_faucet_funds,
trade,
limitOrder,
transfer,
getTokenDataByAddress,
getTokenDataByTicker,
@@ -138,6 +139,15 @@ export class SolanaAgentKit {
return trade(this, outputMint, inputAmount, inputMint, slippageBps);
}
async limitOrder(
marketId: PublicKey,
quantity: number,
side: string,
price: number,
): Promise<string> {
return limitOrder(this, marketId, quantity, side, price);
}
async lendAssets(amount: number): Promise<string> {
return lendAsset(this, amount);
}

View File

@@ -264,6 +264,50 @@ export class SolanaTradeTool extends Tool {
}
}
export class SolanaLimitOrderTool extends Tool {
name = "solana_limit_order";
description = `This tool can be used to place limit orders using Manifest.
Inputs ( input is a JSON string ):
marketId: PublicKey, eg "ENhU8LsaR7vDD2G1CsWcsuSGNrih9Cv5WZEk7q9kPapQ" for SOL/USDC (required)
quantity: number, eg 1 or 0.01 (required)
side: string, eg "Buy" or "Sell" (required)
price: number, in tokens eg 200 for SOL/USDC (required)`;
constructor(private solanaKit: SolanaAgentKit) {
super();
}
protected async _call(input: string): Promise<string> {
try {
const parsedInput = JSON.parse(input);
const tx = await this.solanaKit.limitOrder(
parsedInput.marketId,
parsedInput.quantity,
parsedInput.side,
parsedInput.price,
);
return JSON.stringify({
status: "success",
message: "Trade executed successfully",
transaction: tx,
marketId: parsedInput.marketId,
quantity: parsedInput.quantity,
side: parsedInput.side,
price: parsedInput.price,
});
} catch (error: any) {
return JSON.stringify({
status: "error",
message: error.message,
code: error.code || "UNKNOWN_ERROR",
});
}
}
}
export class SolanaRequestFundsTool extends Tool {
name = "solana_request_funds";
description = "Request SOL from Solana faucet (devnet/testnet only)";
@@ -1026,8 +1070,6 @@ export class SolanaManifestCreateMarket extends Tool {
}
}
// TODO: Add limit order support
export class SolanaPythFetchPrice extends Tool {
name = "solana_pyth_fetch_price";
description = `Fetch the price of a given price feed from Pyth's Hermes service

View File

@@ -5,6 +5,7 @@ export * from "./get_balance";
export * from "./mint_nft";
export * from "./transfer";
export * from "./trade";
export * from "./limit_order";
export * from "./register_domain";
export * from "./resolve_sol_domain";
export * from "./get_primary_domain";

83
src/tools/limit_order.ts Normal file
View File

@@ -0,0 +1,83 @@
import {
PublicKey,
Transaction,
sendAndConfirmTransaction,
TransactionInstruction,
} from "@solana/web3.js";
import { SolanaAgentKit } from "../index";
import {
ManifestClient,
WrapperPlaceOrderParamsExternal,
} from "@cks-systems/manifest-sdk";
import { sleep } from "openai/core";
import { OrderType } from "@cks-systems/manifest-sdk/dist/types/src/manifest";
/**
* Place limit orders using Manifest
* @param agent SolanaAgentKit instance
* @param marketId Public key for the manifest market
* @param quantity Amount to trade in tokens
* @param side Buy or Sell
* @param price Price in tokens ie. SOL/USDC
* @returns Transaction signature
*/
export async function limitOrder(
agent: SolanaAgentKit,
marketId: PublicKey,
quantity: number,
side: string,
price: number,
): Promise<string> {
try {
const { setupNeeded, instructions, wrapperKeypair } =
await ManifestClient.getSetupIxs(
agent.connection,
marketId,
agent.wallet.publicKey,
);
if (setupNeeded) {
const tx = new Transaction().add(...instructions);
const { blockhash } = await agent.connection.getLatestBlockhash();
tx.recentBlockhash = blockhash;
tx.feePayer = agent.wallet.publicKey!;
if (wrapperKeypair) {
tx.sign(wrapperKeypair);
}
await sendAndConfirmTransaction(agent.connection, tx, [agent.wallet]);
await sleep(5_000);
}
const mfxClient = await ManifestClient.getClientForMarket(
agent.connection,
marketId,
agent.wallet,
);
const orderParams: WrapperPlaceOrderParamsExternal = {
numBaseTokens: quantity,
tokenPrice: price,
isBid: side === "buy",
lastValidSlot: 0,
orderType: OrderType.Limit,
clientOrderId: Number(Math.random() * 1000),
};
const depositPlaceOrderIx: TransactionInstruction[] =
await mfxClient.placeOrderWithRequiredDepositIx(
agent.wallet.publicKey,
orderParams,
);
const signature = await sendAndConfirmTransaction(
agent.connection,
new Transaction().add(...depositPlaceOrderIx),
[agent.wallet],
);
return signature;
} catch (error: any) {
throw new Error(`Limit Order failed: ${error.message}`);
}
}