@coinbase/agentkit 0.2.3 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +30 -0
  2. package/dist/action-providers/allora/alloraActionProvider.d.ts +44 -0
  3. package/dist/action-providers/allora/alloraActionProvider.js +195 -0
  4. package/dist/action-providers/allora/alloraActionProvider.test.d.ts +1 -0
  5. package/dist/action-providers/allora/alloraActionProvider.test.js +109 -0
  6. package/dist/action-providers/allora/index.d.ts +2 -0
  7. package/dist/action-providers/allora/index.js +18 -0
  8. package/dist/action-providers/allora/schemas.d.ts +28 -0
  9. package/dist/action-providers/allora/schemas.js +30 -0
  10. package/dist/action-providers/defillama/constants.d.ts +8 -0
  11. package/dist/action-providers/defillama/constants.js +11 -0
  12. package/dist/action-providers/defillama/defillamaActionProvider.d.ts +54 -0
  13. package/dist/action-providers/defillama/defillamaActionProvider.js +180 -0
  14. package/dist/action-providers/defillama/defillamaActionProvider.test.d.ts +1 -0
  15. package/dist/action-providers/defillama/defillamaActionProvider.test.js +114 -0
  16. package/dist/action-providers/defillama/index.d.ts +1 -0
  17. package/dist/action-providers/defillama/index.js +17 -0
  18. package/dist/action-providers/defillama/schemas.d.ts +34 -0
  19. package/dist/action-providers/defillama/schemas.js +34 -0
  20. package/dist/action-providers/defillama/types.d.ts +73 -0
  21. package/dist/action-providers/defillama/types.js +2 -0
  22. package/dist/action-providers/defillama/utils.d.ts +10 -0
  23. package/dist/action-providers/defillama/utils.js +87 -0
  24. package/dist/action-providers/defillama/utils.test.d.ts +1 -0
  25. package/dist/action-providers/defillama/utils.test.js +124 -0
  26. package/dist/action-providers/erc721/constants.d.ts +0 -4
  27. package/dist/action-providers/erc721/constants.js +1 -4
  28. package/dist/action-providers/erc721/erc721ActionProvider.js +1 -1
  29. package/dist/action-providers/erc721/erc721ActionProvider.test.js +1 -1
  30. package/dist/action-providers/index.d.ts +3 -0
  31. package/dist/action-providers/index.js +3 -0
  32. package/dist/action-providers/morpho/morphoActionProvider.js +11 -4
  33. package/dist/action-providers/morpho/morphoActionProvider.test.js +2 -0
  34. package/dist/action-providers/opensea/index.d.ts +1 -0
  35. package/dist/action-providers/opensea/index.js +17 -0
  36. package/dist/action-providers/opensea/openseaActionProvider.d.ts +59 -0
  37. package/dist/action-providers/opensea/openseaActionProvider.js +146 -0
  38. package/dist/action-providers/opensea/openseaActionProvider.test.d.ts +1 -0
  39. package/dist/action-providers/opensea/openseaActionProvider.test.js +201 -0
  40. package/dist/action-providers/opensea/schemas.d.ts +30 -0
  41. package/dist/action-providers/opensea/schemas.js +33 -0
  42. package/dist/action-providers/opensea/utils.d.ts +12 -0
  43. package/dist/action-providers/opensea/utils.js +47 -0
  44. package/dist/wallet-providers/cdpWalletProvider.d.ts +6 -0
  45. package/dist/wallet-providers/cdpWalletProvider.js +11 -0
  46. package/package.json +13 -2
@@ -0,0 +1,180 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ 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;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.defillamaActionProvider = exports.DefiLlamaActionProvider = void 0;
13
+ const zod_1 = require("zod");
14
+ const actionProvider_1 = require("../actionProvider");
15
+ const actionDecorator_1 = require("../actionDecorator");
16
+ const schemas_1 = require("./schemas");
17
+ const constants_1 = require("./constants");
18
+ const utils_1 = require("./utils");
19
+ /**
20
+ * DefiLlamaActionProvider is an action provider for DefiLlama API interactions.
21
+ * Provides functionality to fetch token prices, protocol information, and search protocols.
22
+ */
23
+ class DefiLlamaActionProvider extends actionProvider_1.ActionProvider {
24
+ /**
25
+ * Constructor for the DefiLlamaActionProvider class.
26
+ */
27
+ constructor() {
28
+ super("defillama", []);
29
+ }
30
+ /**
31
+ * Searches for protocols on DefiLlama.
32
+ * Note: This performs a case-insensitive search on protocol names.
33
+ * Returns all protocols whose names contain the search query.
34
+ *
35
+ * @param args - The protocol search parameters
36
+ * @returns A JSON string containing matching protocols or error message
37
+ */
38
+ async searchProtocols(args) {
39
+ try {
40
+ const url = `${constants_1.DEFILLAMA_BASE_URL}/protocols`;
41
+ const response = await fetch(url);
42
+ if (!response.ok) {
43
+ throw new Error(`HTTP error! status: ${response.status}`);
44
+ }
45
+ const protocols = await response.json();
46
+ const searchResults = protocols.filter((protocol) => protocol.name.toLowerCase().includes(args.query.toLowerCase()));
47
+ if (searchResults.length === 0) {
48
+ return `No protocols found matching "${args.query}"`;
49
+ }
50
+ return JSON.stringify(searchResults, null, 2);
51
+ }
52
+ catch (error) {
53
+ return `Error searching protocols: ${error}`;
54
+ }
55
+ }
56
+ /**
57
+ * Gets detailed information about a specific protocol.
58
+ * Note: Returns null if the protocol is not found.
59
+ * The response includes TVL, description, category, and other metadata.
60
+ * Time-series data is pruned to keep response size manageable.
61
+ *
62
+ * @param args - The protocol request parameters
63
+ * @returns A JSON string containing time-series pruned protocol information
64
+ */
65
+ async getProtocol(args) {
66
+ try {
67
+ const url = `${constants_1.DEFILLAMA_BASE_URL}/protocol/${args.protocolId}`;
68
+ const response = await fetch(url);
69
+ if (!response.ok) {
70
+ throw new Error(`HTTP error! status: ${response.status}`);
71
+ }
72
+ const data = (await response.json());
73
+ const prunedData = (0, utils_1.pruneGetProtocolResponse)(data);
74
+ return JSON.stringify(prunedData, null, 2);
75
+ }
76
+ catch (error) {
77
+ return `Error fetching protocol information: ${error instanceof Error ? error.message : String(error)}`;
78
+ }
79
+ }
80
+ /**
81
+ * Gets current token prices from DefiLlama.
82
+ * Note: Token addresses must include chain prefix (e.g., 'ethereum:0x...')
83
+ * The searchWidth parameter can be used to specify a time range in minutes.
84
+ *
85
+ * @param args - The token price request parameters
86
+ * @returns A JSON string containing token prices or error message
87
+ */
88
+ async getTokenPrices(args) {
89
+ try {
90
+ const params = new URLSearchParams({});
91
+ const tokens = args.tokens.join(",");
92
+ if (args.searchWidth) {
93
+ params.set("searchWidth", args.searchWidth);
94
+ }
95
+ const url = `${constants_1.DEFILLAMA_PRICES_URL}/prices/current/${tokens}?${params.toString()}`;
96
+ const response = await fetch(url);
97
+ if (!response.ok) {
98
+ throw new Error(`HTTP error! status: ${response.status}`);
99
+ }
100
+ const data = await response.json();
101
+ return JSON.stringify(data, null, 2);
102
+ }
103
+ catch (error) {
104
+ return `Error fetching token prices: ${error instanceof Error ? error.message : String(error)}`;
105
+ }
106
+ }
107
+ /**
108
+ * Checks if the DefiLlama action provider supports the given network.
109
+ * DefiLlama is network-agnostic, so this always returns true.
110
+ *
111
+ * @returns True, as DefiLlama actions are supported on all networks.
112
+ */
113
+ supportsNetwork() {
114
+ return true;
115
+ }
116
+ }
117
+ exports.DefiLlamaActionProvider = DefiLlamaActionProvider;
118
+ __decorate([
119
+ (0, actionDecorator_1.CreateAction)({
120
+ name: "find_protocol",
121
+ description: `This tool will search for DeFi protocols on DefiLlama by name.
122
+ It takes the following inputs:
123
+ - A search query string to match against protocol names
124
+
125
+ Important notes:
126
+ - The search is case-insensitive
127
+ - Returns all protocols whose names contain the search query
128
+ - Returns metadata including TVL, chain, category, and other protocol details
129
+ - Returns a "No protocols found" message if no matches are found`,
130
+ schema: schemas_1.SearchProtocolsSchema,
131
+ }),
132
+ __metadata("design:type", Function),
133
+ __metadata("design:paramtypes", [void 0]),
134
+ __metadata("design:returntype", Promise)
135
+ ], DefiLlamaActionProvider.prototype, "searchProtocols", null);
136
+ __decorate([
137
+ (0, actionDecorator_1.CreateAction)({
138
+ name: "get_protocol",
139
+ description: `This tool will fetch detailed information about a specific protocol from DefiLlama.
140
+ It takes the following inputs:
141
+ - The protocol identifier from DefiLlama (e.g. uniswap)
142
+
143
+ Important notes:
144
+ - Returns null if the protocol is not found
145
+ - Returns comprehensive data including TVL, description, category, and other metadata
146
+ - Includes historical TVL data and chain-specific breakdowns where available
147
+ - Returns error message if the protocol ID is invalid or the request fails
148
+ - Prunes time-series data to 5 most recent entries to make the response more manageable`,
149
+ schema: schemas_1.GetProtocolSchema,
150
+ }),
151
+ __metadata("design:type", Function),
152
+ __metadata("design:paramtypes", [void 0]),
153
+ __metadata("design:returntype", Promise)
154
+ ], DefiLlamaActionProvider.prototype, "getProtocol", null);
155
+ __decorate([
156
+ (0, actionDecorator_1.CreateAction)({
157
+ name: "get_token_prices",
158
+ description: `This tool will fetch current token prices from DefiLlama.
159
+ It takes the following inputs:
160
+ - An array of token addresses with chain prefixes
161
+ - Optional time range in minutes for historical prices
162
+
163
+ Important notes:
164
+ - Token addresses MUST include chain prefix (e.g., 'ethereum:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48')
165
+ - The searchWidth parameter is optional, it's default api value is '4h', leave this blank if unspecified
166
+ - Returns current prices for all specified tokens
167
+ - Returns error message if any token address is invalid or the request fails`,
168
+ schema: schemas_1.GetTokenPricesSchema,
169
+ }),
170
+ __metadata("design:type", Function),
171
+ __metadata("design:paramtypes", [void 0]),
172
+ __metadata("design:returntype", Promise)
173
+ ], DefiLlamaActionProvider.prototype, "getTokenPrices", null);
174
+ /**
175
+ * Creates a new instance of the DefiLlama action provider.
176
+ *
177
+ * @returns A new DefiLlamaActionProvider instance
178
+ */
179
+ const defillamaActionProvider = () => new DefiLlamaActionProvider();
180
+ exports.defillamaActionProvider = defillamaActionProvider;
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const defillamaActionProvider_1 = require("./defillamaActionProvider");
4
+ describe("DefiLlamaActionProvider", () => {
5
+ const fetchMock = jest.fn();
6
+ global.fetch = fetchMock;
7
+ const provider = (0, defillamaActionProvider_1.defillamaActionProvider)();
8
+ beforeEach(() => {
9
+ jest.resetAllMocks();
10
+ });
11
+ describe("getTokenPrices", () => {
12
+ it("should return token prices when API call is successful", async () => {
13
+ const mockResponse = {
14
+ "ethereum:0x1234": { price: 1800 },
15
+ };
16
+ fetchMock.mockResolvedValue({ ok: true, json: jest.fn().mockResolvedValue(mockResponse) });
17
+ const result = await provider.getTokenPrices({
18
+ tokens: ["ethereum:0x1234"],
19
+ });
20
+ expect(JSON.parse(result)).toEqual(mockResponse);
21
+ });
22
+ it("should handle API errors gracefully", async () => {
23
+ fetchMock.mockResolvedValue({ ok: false, status: 404 });
24
+ const result = await provider.getTokenPrices({
25
+ tokens: ["ethereum:0x1234"],
26
+ });
27
+ expect(result).toContain("Error fetching token prices");
28
+ });
29
+ it("should handle network errors", async () => {
30
+ const error = new Error("Network error");
31
+ fetchMock.mockRejectedValue(error);
32
+ const result = await provider.getTokenPrices({
33
+ tokens: ["ethereum:0x1234"],
34
+ });
35
+ expect(result).toContain("Error fetching token prices");
36
+ expect(result).toContain("Network error");
37
+ });
38
+ });
39
+ describe("getProtocol", () => {
40
+ const mockProtocol = {
41
+ name: "Uniswap",
42
+ symbol: "UNI",
43
+ description: "Decentralized exchange protocol",
44
+ category: "DEX",
45
+ chain: "Ethereum",
46
+ tvl: 1000000,
47
+ url: "https://uniswap.org",
48
+ logo: "https://example.com/logo.png",
49
+ };
50
+ it("should return protocol information when API call is successful", async () => {
51
+ fetchMock.mockResolvedValue({ ok: true, json: jest.fn().mockResolvedValue(mockProtocol) });
52
+ const result = await provider.getProtocol({ protocolId: "uniswap" });
53
+ expect(JSON.parse(result)).toEqual(mockProtocol);
54
+ });
55
+ it("should handle API errors gracefully", async () => {
56
+ fetchMock.mockResolvedValue({ ok: false, status: 500 });
57
+ const result = await provider.getProtocol({ protocolId: "invalid-protocol" });
58
+ expect(result).toContain("Error fetching protocol information");
59
+ expect(result).toContain("500");
60
+ });
61
+ it("should handle empty response", async () => {
62
+ fetchMock.mockResolvedValue({ ok: true, json: jest.fn().mockResolvedValue(null) });
63
+ const result = await provider.getProtocol({ protocolId: "non-existent" });
64
+ expect(JSON.parse(result)).toEqual(null);
65
+ });
66
+ });
67
+ describe("searchProtocols", () => {
68
+ const mockProtocols = [
69
+ {
70
+ name: "Uniswap",
71
+ symbol: "UNI",
72
+ category: "DEX",
73
+ chain: "Ethereum",
74
+ tvl: 1000000,
75
+ },
76
+ {
77
+ name: "UniswapV3",
78
+ symbol: "UNI",
79
+ category: "DEX",
80
+ chain: "Ethereum",
81
+ tvl: 2000000,
82
+ },
83
+ ];
84
+ it("should return matching protocols", async () => {
85
+ fetchMock.mockResolvedValue({ ok: true, json: jest.fn().mockResolvedValue(mockProtocols) });
86
+ const result = await provider.searchProtocols({ query: "uniswap" });
87
+ expect(JSON.parse(result)).toEqual(mockProtocols);
88
+ });
89
+ it("should handle API errors gracefully", async () => {
90
+ fetchMock.mockResolvedValue({ ok: false, status: 429 });
91
+ const result = await provider.searchProtocols({ query: "uniswap" });
92
+ expect(result).toContain("Error searching protocols");
93
+ expect(result).toContain("429");
94
+ });
95
+ it("should handle empty search results", async () => {
96
+ fetchMock.mockResolvedValue({ ok: true, json: jest.fn().mockResolvedValue([]) });
97
+ const result = await provider.searchProtocols({ query: "nonexistentprotocol" });
98
+ expect(result).toContain('No protocols found matching "nonexistentprotocol"');
99
+ });
100
+ it("should handle malformed response", async () => {
101
+ fetchMock.mockResolvedValue({
102
+ ok: true,
103
+ json: jest.fn().mockResolvedValue({ invalid: "response" }),
104
+ });
105
+ const result = await provider.searchProtocols({ query: "uniswap" });
106
+ expect(result).toContain("Error searching protocols");
107
+ });
108
+ it("should filter protocols case-insensitively", async () => {
109
+ fetchMock.mockResolvedValue({ ok: true, json: jest.fn().mockResolvedValue(mockProtocols) });
110
+ const result = await provider.searchProtocols({ query: "UNISWAP" });
111
+ expect(JSON.parse(result)).toEqual(mockProtocols);
112
+ });
113
+ });
114
+ });
@@ -0,0 +1 @@
1
+ export * from "./defillamaActionProvider";
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./defillamaActionProvider"), exports);
@@ -0,0 +1,34 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Input schema for getting protocol information
4
+ */
5
+ export declare const GetProtocolSchema: z.ZodObject<{
6
+ protocolId: z.ZodString;
7
+ }, "strict", z.ZodTypeAny, {
8
+ protocolId: string;
9
+ }, {
10
+ protocolId: string;
11
+ }>;
12
+ /**
13
+ * Input schema for getting token prices
14
+ */
15
+ export declare const GetTokenPricesSchema: z.ZodObject<{
16
+ tokens: z.ZodArray<z.ZodString, "many">;
17
+ searchWidth: z.ZodOptional<z.ZodString>;
18
+ }, "strict", z.ZodTypeAny, {
19
+ tokens: string[];
20
+ searchWidth?: string | undefined;
21
+ }, {
22
+ tokens: string[];
23
+ searchWidth?: string | undefined;
24
+ }>;
25
+ /**
26
+ * Input schema for searching protocols
27
+ */
28
+ export declare const SearchProtocolsSchema: z.ZodObject<{
29
+ query: z.ZodString;
30
+ }, "strict", z.ZodTypeAny, {
31
+ query: string;
32
+ }, {
33
+ query: string;
34
+ }>;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SearchProtocolsSchema = exports.GetTokenPricesSchema = exports.GetProtocolSchema = void 0;
4
+ const zod_1 = require("zod");
5
+ /**
6
+ * Input schema for getting protocol information
7
+ */
8
+ exports.GetProtocolSchema = zod_1.z
9
+ .object({
10
+ protocolId: zod_1.z.string().describe("The protocol identifier from DefiLlama"),
11
+ })
12
+ .strict();
13
+ /**
14
+ * Input schema for getting token prices
15
+ */
16
+ exports.GetTokenPricesSchema = zod_1.z
17
+ .object({
18
+ tokens: zod_1.z
19
+ .array(zod_1.z.string())
20
+ .describe("Array of token addresses with chain prefix, e.g., ['ethereum:0x...']"),
21
+ searchWidth: zod_1.z
22
+ .string()
23
+ .optional()
24
+ .describe("Optional time range in minutes to search for prices, default api value is '4h'"),
25
+ })
26
+ .strict();
27
+ /**
28
+ * Input schema for searching protocols
29
+ */
30
+ exports.SearchProtocolsSchema = zod_1.z
31
+ .object({
32
+ query: zod_1.z.string().describe("Search query to find protocols"),
33
+ })
34
+ .strict();
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Interface representing a DeFi protocol from DefiLlama
3
+ */
4
+ export interface Protocol {
5
+ name: string;
6
+ address?: string;
7
+ symbol?: string;
8
+ url?: string;
9
+ description?: string;
10
+ chain?: string;
11
+ logo?: string;
12
+ audits?: string;
13
+ category?: string;
14
+ tvl?: number;
15
+ }
16
+ /**
17
+ * Interface representing a time-series data point with a date
18
+ */
19
+ export interface TimeSeriesDataPoint {
20
+ date: number;
21
+ totalLiquidityUSD: number;
22
+ }
23
+ /**
24
+ * Interface representing a time-series data point with tokens
25
+ */
26
+ export interface TokenTimeSeriesDataPoint {
27
+ date: number;
28
+ tokens: Record<string, number>;
29
+ }
30
+ /**
31
+ * Type for representing generic metadata values that can be returned by DefiLlama API
32
+ */
33
+ export type MetadataValue = string | number | boolean | null | Record<string, unknown> | unknown[];
34
+ /**
35
+ * Interface representing DefiLlama protocol response
36
+ */
37
+ export interface ProtocolResponse {
38
+ id: string;
39
+ name: string;
40
+ address?: string;
41
+ symbol?: string;
42
+ url?: string;
43
+ description?: string;
44
+ chain?: string;
45
+ logo?: string;
46
+ audits?: string;
47
+ audit_note?: string | null;
48
+ gecko_id?: string | null;
49
+ cmcId?: string | null;
50
+ category?: string;
51
+ chains?: string[];
52
+ oracles?: string[];
53
+ forkedFrom?: string[];
54
+ audit_links?: string[];
55
+ github?: string[];
56
+ tvl?: TimeSeriesDataPoint[];
57
+ tokensInUsd?: TokenTimeSeriesDataPoint[];
58
+ tokens?: TokenTimeSeriesDataPoint[];
59
+ chainTvls?: Record<string, {
60
+ tvl?: TimeSeriesDataPoint[];
61
+ tokensInUsd?: TokenTimeSeriesDataPoint[];
62
+ tokens?: TokenTimeSeriesDataPoint[];
63
+ }>;
64
+ currentChainTvls?: Record<string, number>;
65
+ raises?: Record<string, MetadataValue>[];
66
+ metrics?: Record<string, MetadataValue>;
67
+ mcap?: number;
68
+ methodology?: string;
69
+ }
70
+ /**
71
+ * Type for the pruned protocol response - same structure as the input
72
+ */
73
+ export type PrunedProtocolResponse = ProtocolResponse;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,10 @@
1
+ import { ProtocolResponse, PrunedProtocolResponse } from "./types";
2
+ /**
3
+ * Prunes the protocol response by limiting time-series data arrays
4
+ * to show only the most recent entries.
5
+ *
6
+ * @param data - The original protocol data from DefiLlama API
7
+ * @param maxEntries - The maximum number of time-series entries to keep (default: 5)
8
+ * @returns A pruned copy of the protocol data
9
+ */
10
+ export declare const pruneGetProtocolResponse: (data: ProtocolResponse | null, maxEntries?: number) => PrunedProtocolResponse | null;
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.pruneGetProtocolResponse = void 0;
4
+ /**
5
+ * Processes a time-series array by sorting by date (newest first) and limiting to maxEntries
6
+ *
7
+ * @param array - The time-series array to process
8
+ * @param maxEntries - Maximum number of entries to keep
9
+ * @returns The processed array (sorted and limited)
10
+ */
11
+ const processTimeSeriesArray = (array, maxEntries) => {
12
+ if (array.length <= maxEntries) {
13
+ return array;
14
+ }
15
+ // Sort by date if array items have date property
16
+ if (array.length > 0 && typeof array[0] === "object" && array[0] !== null && "date" in array[0]) {
17
+ array.sort((a, b) => {
18
+ if (a &&
19
+ b &&
20
+ typeof a === "object" &&
21
+ typeof b === "object" &&
22
+ "date" in a &&
23
+ "date" in b &&
24
+ typeof a.date === "number" &&
25
+ typeof b.date === "number") {
26
+ return b.date - a.date;
27
+ }
28
+ return 0;
29
+ });
30
+ }
31
+ return array.slice(0, maxEntries);
32
+ };
33
+ /**
34
+ * Prunes the protocol response by limiting time-series data arrays
35
+ * to show only the most recent entries.
36
+ *
37
+ * @param data - The original protocol data from DefiLlama API
38
+ * @param maxEntries - The maximum number of time-series entries to keep (default: 5)
39
+ * @returns A pruned copy of the protocol data
40
+ */
41
+ const pruneGetProtocolResponse = (data, maxEntries = 5) => {
42
+ if (!data) {
43
+ return null;
44
+ }
45
+ const result = { ...data };
46
+ const timeSeriesArrayPaths = ["tvl", "tokens", "tokensInUsd"];
47
+ const processNestedObject = (obj, currentPath = "") => {
48
+ if (!obj || typeof obj !== "object") {
49
+ return obj;
50
+ }
51
+ if (Array.isArray(obj)) {
52
+ const isTimeSeriesArray = timeSeriesArrayPaths.some(path => currentPath === path || currentPath.endsWith(`.${path}`));
53
+ if (isTimeSeriesArray) {
54
+ return processTimeSeriesArray(obj, maxEntries);
55
+ }
56
+ for (let i = 0; i < obj.length; i++) {
57
+ obj[i] = processNestedObject(obj[i], `${currentPath}[${i}]`);
58
+ }
59
+ }
60
+ else if (obj !== null) {
61
+ // Safe to cast to Record<string, unknown> since we know it's an object and not null
62
+ const record = obj;
63
+ for (const key of Object.keys(record)) {
64
+ const newPath = currentPath ? `${currentPath}.${key}` : key;
65
+ const value = record[key];
66
+ if (value && typeof value === "object") {
67
+ record[key] = processNestedObject(value, newPath);
68
+ }
69
+ }
70
+ }
71
+ return obj;
72
+ };
73
+ // Special handling for chainTvls if it exists
74
+ if (result.chainTvls) {
75
+ for (const chain of Object.keys(result.chainTvls)) {
76
+ const chainData = result.chainTvls[chain];
77
+ for (const timeSeriesKey of timeSeriesArrayPaths) {
78
+ if (chainData[timeSeriesKey] && Array.isArray(chainData[timeSeriesKey])) {
79
+ chainData[timeSeriesKey] = processTimeSeriesArray(chainData[timeSeriesKey], maxEntries);
80
+ }
81
+ }
82
+ }
83
+ }
84
+ processNestedObject(result);
85
+ return result;
86
+ };
87
+ exports.pruneGetProtocolResponse = pruneGetProtocolResponse;
@@ -0,0 +1 @@
1
+ export {};