166 lines
4.3 KiB
JavaScript
166 lines
4.3 KiB
JavaScript
![]() |
import { tool } from "ai";
|
||
|
import { z } from "zod";
|
||
|
import { queryBirdeye } from "./client.js";
|
||
|
|
||
|
|
||
|
const OHLCVTimeframe = {
|
||
|
OneMinute: "1m",
|
||
|
ThreeMinutes: "3m",
|
||
|
FiveMinutes: "5m",
|
||
|
FifteenMinutes: "15m",
|
||
|
ThirtyMinutes: "30m",
|
||
|
OneHour: "1H",
|
||
|
TwoHours: "2H",
|
||
|
FourHours: "4H",
|
||
|
SixHours: "6H",
|
||
|
EightHours: "8H",
|
||
|
TwelveHours: "12H",
|
||
|
OneDay: "1D",
|
||
|
ThreeDays: "3D",
|
||
|
OneWeek: "1W",
|
||
|
OneMonth: "1M",
|
||
|
};
|
||
|
|
||
|
const parseTimeString = (timeString) => {
|
||
|
//console.log(timeString);
|
||
|
|
||
|
const now = new Date();
|
||
|
|
||
|
if (timeString === "NOW") {
|
||
|
return Math.floor(now.getTime() / 1000); // Return in seconds for consistency
|
||
|
}
|
||
|
|
||
|
const regex = /^(\d+)([smHDWMy])$/;
|
||
|
const match = timeString.match(regex);
|
||
|
|
||
|
if (!match) {
|
||
|
throw new Error("Invalid time string format");
|
||
|
}
|
||
|
|
||
|
const value = parseInt(match[1]);
|
||
|
const unit = match[2];
|
||
|
|
||
|
switch (unit) {
|
||
|
case "m": // minutes
|
||
|
now.setMinutes(now.getMinutes() - value);
|
||
|
break;
|
||
|
case "H": // hours
|
||
|
now.setHours(now.getHours() - value);
|
||
|
break;
|
||
|
case "D": // days
|
||
|
now.setDate(now.getDate() - value);
|
||
|
break;
|
||
|
case "W": // weeks
|
||
|
now.setDate(now.getDate() - value * 7);
|
||
|
break;
|
||
|
case "M": // months
|
||
|
now.setMonth(now.getMonth() - value);
|
||
|
break;
|
||
|
case "Y": // years
|
||
|
now.setFullYear(now.getFullYear() - value);
|
||
|
break;
|
||
|
default:
|
||
|
return Math.floor(now.getTime() / 1000);
|
||
|
}
|
||
|
|
||
|
return Math.floor(now.getTime() / 1000);
|
||
|
};
|
||
|
|
||
|
const timeSchema = z.union([
|
||
|
z.literal("NOW"),
|
||
|
z.enum(Object.values(OHLCVTimeframe)),
|
||
|
]);
|
||
|
|
||
|
const timeEnum = z.enum([
|
||
|
"NOW",
|
||
|
OHLCVTimeframe.OneMinute,
|
||
|
OHLCVTimeframe.ThreeMinutes,
|
||
|
OHLCVTimeframe.FiveMinutes,
|
||
|
OHLCVTimeframe.FifteenMinutes,
|
||
|
OHLCVTimeframe.ThirtyMinutes,
|
||
|
OHLCVTimeframe.OneHour,
|
||
|
OHLCVTimeframe.TwoHours,
|
||
|
OHLCVTimeframe.FourHours,
|
||
|
OHLCVTimeframe.SixHours,
|
||
|
OHLCVTimeframe.EightHours,
|
||
|
OHLCVTimeframe.TwelveHours,
|
||
|
OHLCVTimeframe.OneDay,
|
||
|
OHLCVTimeframe.ThreeDays,
|
||
|
OHLCVTimeframe.OneWeek,
|
||
|
OHLCVTimeframe.OneMonth,
|
||
|
]);
|
||
|
|
||
|
const fetchOHLCVData = async ({
|
||
|
address,
|
||
|
timeframe = OHLCVTimeframe.FifteenMinutes,
|
||
|
timeFrom,
|
||
|
timeTo,
|
||
|
}) => {
|
||
|
const timeFromTimestamp = parseTimeString(timeFrom);
|
||
|
const timeToTimestamp = parseTimeString(timeTo);
|
||
|
|
||
|
//console.log(`Fetching OHLCV data for address: ${address}, timeframe: ${timeframe}, from: ${timeFromTimestamp} to: ${timeToTimestamp}`);
|
||
|
|
||
|
const response = await queryBirdeye("defi/ohlcv", {
|
||
|
address,
|
||
|
type: timeframe,
|
||
|
time_from: timeFromTimestamp,
|
||
|
time_to: timeToTimestamp,
|
||
|
});
|
||
|
|
||
|
if (response?.items) {
|
||
|
const last25Items = response.items.slice(-25);
|
||
|
// console.log(last25Items);
|
||
|
|
||
|
return {
|
||
|
type: timeframe,
|
||
|
items: last25Items.map(({ address, type, ...rest }) => rest),
|
||
|
};
|
||
|
}
|
||
|
|
||
|
return [];
|
||
|
};
|
||
|
|
||
|
export const getFetchOHLCVTool = (userId, chatId, responseId, dataStream) =>
|
||
|
tool({
|
||
|
description:
|
||
|
"Fetch OHLCV (Open, High, Low, Close, Volume) data for a given address and timeframe. The function returns 25 candlesticks maximum, so be sure to choose your time parameters wisely.",
|
||
|
parameters: z.object({
|
||
|
address: z.string().describe("The address to fetch OHLCV data for"),
|
||
|
timeframe: timeSchema
|
||
|
.describe("The timeframe for the OHLCV data (default is 15 minutes)")
|
||
|
.optional()
|
||
|
.default("15m"),
|
||
|
timeFrom: timeEnum.describe(
|
||
|
"The start time, either a timeframe or 'NOW'",
|
||
|
),
|
||
|
timeTo: timeEnum.describe("The end time, either a timeframe or 'NOW'"),
|
||
|
}),
|
||
|
execute: async ({ address, timeframe, timeFrom, timeTo }) => {
|
||
|
try {
|
||
|
console.log(
|
||
|
`${userId} ${chatId} called fetchOHLCVData with address: ${address} | timeframe: ${timeframe} | timeFrom: ${timeFrom} | timeTo: ${timeTo}`,
|
||
|
);
|
||
|
const ohlcvData = await fetchOHLCVData({
|
||
|
address,
|
||
|
timeframe,
|
||
|
timeFrom,
|
||
|
timeTo,
|
||
|
});
|
||
|
if (ohlcvData) {
|
||
|
dataStream.writeMessageAnnotation({
|
||
|
id: responseId,
|
||
|
tool_type: 'chart',
|
||
|
content: address,
|
||
|
});
|
||
|
}
|
||
|
return JSON.stringify(ohlcvData);
|
||
|
} catch (error) {
|
||
|
console.error(
|
||
|
`Error occurred while fetching OHLCV data: ${error.message}`,
|
||
|
);
|
||
|
return "Failed to fetch OHLCV data.";
|
||
|
}
|
||
|
},
|
||
|
});
|