UNPKG

@coinbase/agentkit

Version:

Coinbase AgentKit core primitives

179 lines (174 loc) 7.72 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.pythActionProvider = exports.PythActionProvider = void 0; const zod_1 = require("zod"); const actionProvider_1 = require("../actionProvider"); const actionDecorator_1 = require("../actionDecorator"); const schemas_1 = require("./schemas"); /** * PythActionProvider is an action provider for Pyth. */ class PythActionProvider extends actionProvider_1.ActionProvider { /** * Constructs a new PythActionProvider. */ constructor() { super("pyth", []); /** * Checks if the Pyth action provider supports the given network. * * @returns True if the Pyth action provider supports the network, false otherwise. */ this.supportsNetwork = () => true; } /** * Fetch the price feed ID for a given token symbol from Pyth. * * @param args - The arguments for the action. * @returns The price feed ID as stringified JSON. */ async fetchPriceFeed(args) { const url = `https://hermes.pyth.network/v2/price_feeds?query=${args.tokenSymbol}&asset_type=${args.assetType}`; const response = await fetch(url); if (!response.ok) { return JSON.stringify({ success: false, error: `HTTP error! status: ${response.status}`, }); } const data = await response.json(); if (data.length === 0) { return JSON.stringify({ success: false, error: `No price feed found for ${args.tokenSymbol}`, }); } const filteredData = data.filter( // eslint-disable-next-line @typescript-eslint/no-explicit-any (item) => item.attributes.base.toLowerCase() === args.tokenSymbol.toLowerCase() && item.attributes.quote_currency.toLowerCase() === args.quoteCurrency.toLowerCase()); if (filteredData.length === 0) { return JSON.stringify({ success: false, error: `No price feed found for ${args.tokenSymbol}/${args.quoteCurrency}`, }); } // For equities, select the regular feed over special market hours feeds let selectedFeed = filteredData[0]; if (args.assetType === "equity") { // Look for regular market feed (no PRE, POST, ON, EXT suffixes) const regularMarketFeed = filteredData.find( // eslint-disable-next-line @typescript-eslint/no-explicit-any (item) => !item.attributes.symbol.includes(".PRE") && !item.attributes.symbol.includes(".POST") && !item.attributes.symbol.includes(".ON") && !item.attributes.symbol.includes(".EXT")); if (regularMarketFeed) { selectedFeed = regularMarketFeed; } } return JSON.stringify({ success: true, priceFeedID: selectedFeed.id, tokenSymbol: args.tokenSymbol, quoteCurrency: args.quoteCurrency, feedType: selectedFeed.attributes.display_symbol, }); } /** * Fetches the price from Pyth given a Pyth price feed ID. * * @param args - The arguments for the action. * @returns The price as stringified JSON. */ async fetchPrice(args) { const url = `https://hermes.pyth.network/v2/updates/price/latest?ids[]=${args.priceFeedID}`; const response = await fetch(url); if (!response.ok) { return JSON.stringify({ success: false, error: `HTTP error! status: ${response.status}`, }); } const data = await response.json(); const parsedData = data.parsed; if (parsedData.length === 0) { return JSON.stringify({ success: false, error: `No price data found for ${args.priceFeedID}`, }); } // Helper function to format price // eslint-disable-next-line @typescript-eslint/no-explicit-any const formatPrice = (priceInfo) => { const price = BigInt(priceInfo.price); const exponent = priceInfo.expo; if (exponent < 0) { const adjustedPrice = price * BigInt(100); const divisor = BigInt(10) ** BigInt(-exponent); const scaledPrice = adjustedPrice / BigInt(divisor); const priceStr = scaledPrice.toString(); const formattedPrice = `${priceStr.slice(0, -2)}.${priceStr.slice(-2)}`; return formattedPrice.startsWith(".") ? `0${formattedPrice}` : formattedPrice; } const scaledPrice = price / BigInt(10) ** BigInt(exponent); return scaledPrice.toString(); }; const priceInfo = parsedData[0].price; return JSON.stringify({ success: true, priceFeedID: args.priceFeedID, price: formatPrice(priceInfo), }); } } exports.PythActionProvider = PythActionProvider; __decorate([ (0, actionDecorator_1.CreateAction)({ name: "fetch_price_feed", description: `Fetch the price feed ID for a given token symbol from Pyth. Inputs: - tokenSymbol: The asset ticker/symbol to fetch the price feed ID for (e.g. BTC, ETH, COIN, XAU, EUR, etc.) - quoteCurrency: The quote currency to filter by (defaults to USD) - assetType: The asset type to search for (crypto, equity, fx, metal) - defaults to crypto Examples: - Crypto: BTC, ETH, SOL - Equities: COIN, AAPL, TSLA - FX: EUR, GBP, JPY - Metals: XAU (Gold), XAG (Silver), XPT (Platinum), XPD (Palladium) `, schema: schemas_1.PythFetchPriceFeedIDSchema, }), __metadata("design:type", Function), __metadata("design:paramtypes", [void 0]), __metadata("design:returntype", Promise) ], PythActionProvider.prototype, "fetchPriceFeed", null); __decorate([ (0, actionDecorator_1.CreateAction)({ name: "fetch_price", description: `Fetch the price of a price feed from Pyth. Inputs: - priceFeedID: Price feed ID (string) Important notes: - Do not assume that a random ID is a Pyth price feed ID. If you are confused, ask a clarifying question. - This action only fetches price inputs from Pyth price feeds. No other source. - If you are asked to fetch the price from Pyth for a ticker symbol such as BTC, you must first use the pyth_fetch_price_feed_id action to retrieve the price feed ID before invoking the pyth_fetch_price action `, schema: schemas_1.PythFetchPriceSchema, }), __metadata("design:type", Function), __metadata("design:paramtypes", [void 0]), __metadata("design:returntype", Promise) ], PythActionProvider.prototype, "fetchPrice", null); const pythActionProvider = () => new PythActionProvider(); exports.pythActionProvider = pythActionProvider;