@coinbase/agentkit 0.3.0 → 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.
- package/README.md +17 -0
- package/dist/action-providers/defillama/constants.d.ts +8 -0
- package/dist/action-providers/defillama/constants.js +11 -0
- package/dist/action-providers/defillama/defillamaActionProvider.d.ts +54 -0
- package/dist/action-providers/defillama/defillamaActionProvider.js +180 -0
- package/dist/action-providers/defillama/defillamaActionProvider.test.d.ts +1 -0
- package/dist/action-providers/defillama/defillamaActionProvider.test.js +114 -0
- package/dist/action-providers/defillama/index.d.ts +1 -0
- package/dist/action-providers/defillama/index.js +17 -0
- package/dist/action-providers/defillama/schemas.d.ts +34 -0
- package/dist/action-providers/defillama/schemas.js +34 -0
- package/dist/action-providers/defillama/types.d.ts +73 -0
- package/dist/action-providers/defillama/types.js +2 -0
- package/dist/action-providers/defillama/utils.d.ts +10 -0
- package/dist/action-providers/defillama/utils.js +87 -0
- package/dist/action-providers/defillama/utils.test.d.ts +1 -0
- package/dist/action-providers/defillama/utils.test.js +124 -0
- package/dist/action-providers/index.d.ts +1 -0
- package/dist/action-providers/index.js +1 -0
- package/dist/action-providers/morpho/morphoActionProvider.js +11 -4
- package/dist/action-providers/morpho/morphoActionProvider.test.js +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -192,6 +192,23 @@ const agent = createReactAgent({
|
|
|
192
192
|
</table>
|
|
193
193
|
</details>
|
|
194
194
|
<details>
|
|
195
|
+
<summary><strong>DefiLlama</strong></summary>
|
|
196
|
+
<table width="100%">
|
|
197
|
+
<tr>
|
|
198
|
+
<td width="200"><code>find_protocol</code></td>
|
|
199
|
+
<td width="768">Searches for DeFi protocols on DefiLlama by name, returning protocol metadata including TVL, chain, and category.</td>
|
|
200
|
+
</tr>
|
|
201
|
+
<tr>
|
|
202
|
+
<td width="200"><code>get_protocol</code></td>
|
|
203
|
+
<td width="768">Fetches detailed information about a specific protocol from DefiLlama, including TVL, description, and historical data.</td>
|
|
204
|
+
</tr>
|
|
205
|
+
<tr>
|
|
206
|
+
<td width="200"><code>get_token_prices</code></td>
|
|
207
|
+
<td width="768">Fetches current token prices from DefiLlama for specified token addresses with chain prefixes.</td>
|
|
208
|
+
</tr>
|
|
209
|
+
</table>
|
|
210
|
+
</details>
|
|
211
|
+
<details>
|
|
195
212
|
<summary><strong>ERC20</strong></summary>
|
|
196
213
|
<table width="100%">
|
|
197
214
|
<tr>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEFILLAMA_PRICES_URL = exports.DEFILLAMA_BASE_URL = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Base URL for the DefiLlama API
|
|
6
|
+
*/
|
|
7
|
+
exports.DEFILLAMA_BASE_URL = "https://api.llama.fi";
|
|
8
|
+
/**
|
|
9
|
+
* URL for the DefiLlama price API
|
|
10
|
+
*/
|
|
11
|
+
exports.DEFILLAMA_PRICES_URL = "https://coins.llama.fi";
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { ActionProvider } from "../actionProvider";
|
|
3
|
+
import { GetTokenPricesSchema, GetProtocolSchema, SearchProtocolsSchema } from "./schemas";
|
|
4
|
+
/**
|
|
5
|
+
* DefiLlamaActionProvider is an action provider for DefiLlama API interactions.
|
|
6
|
+
* Provides functionality to fetch token prices, protocol information, and search protocols.
|
|
7
|
+
*/
|
|
8
|
+
export declare class DefiLlamaActionProvider extends ActionProvider {
|
|
9
|
+
/**
|
|
10
|
+
* Constructor for the DefiLlamaActionProvider class.
|
|
11
|
+
*/
|
|
12
|
+
constructor();
|
|
13
|
+
/**
|
|
14
|
+
* Searches for protocols on DefiLlama.
|
|
15
|
+
* Note: This performs a case-insensitive search on protocol names.
|
|
16
|
+
* Returns all protocols whose names contain the search query.
|
|
17
|
+
*
|
|
18
|
+
* @param args - The protocol search parameters
|
|
19
|
+
* @returns A JSON string containing matching protocols or error message
|
|
20
|
+
*/
|
|
21
|
+
searchProtocols(args: z.infer<typeof SearchProtocolsSchema>): Promise<string>;
|
|
22
|
+
/**
|
|
23
|
+
* Gets detailed information about a specific protocol.
|
|
24
|
+
* Note: Returns null if the protocol is not found.
|
|
25
|
+
* The response includes TVL, description, category, and other metadata.
|
|
26
|
+
* Time-series data is pruned to keep response size manageable.
|
|
27
|
+
*
|
|
28
|
+
* @param args - The protocol request parameters
|
|
29
|
+
* @returns A JSON string containing time-series pruned protocol information
|
|
30
|
+
*/
|
|
31
|
+
getProtocol(args: z.infer<typeof GetProtocolSchema>): Promise<string>;
|
|
32
|
+
/**
|
|
33
|
+
* Gets current token prices from DefiLlama.
|
|
34
|
+
* Note: Token addresses must include chain prefix (e.g., 'ethereum:0x...')
|
|
35
|
+
* The searchWidth parameter can be used to specify a time range in minutes.
|
|
36
|
+
*
|
|
37
|
+
* @param args - The token price request parameters
|
|
38
|
+
* @returns A JSON string containing token prices or error message
|
|
39
|
+
*/
|
|
40
|
+
getTokenPrices(args: z.infer<typeof GetTokenPricesSchema>): Promise<string>;
|
|
41
|
+
/**
|
|
42
|
+
* Checks if the DefiLlama action provider supports the given network.
|
|
43
|
+
* DefiLlama is network-agnostic, so this always returns true.
|
|
44
|
+
*
|
|
45
|
+
* @returns True, as DefiLlama actions are supported on all networks.
|
|
46
|
+
*/
|
|
47
|
+
supportsNetwork(): boolean;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Creates a new instance of the DefiLlama action provider.
|
|
51
|
+
*
|
|
52
|
+
* @returns A new DefiLlamaActionProvider instance
|
|
53
|
+
*/
|
|
54
|
+
export declare const defillamaActionProvider: () => DefiLlamaActionProvider;
|
|
@@ -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 @@
|
|
|
1
|
+
export {};
|
|
@@ -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,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 {};
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const utils_1 = require("./utils");
|
|
4
|
+
describe("DefiLlama Utilities", () => {
|
|
5
|
+
describe("pruneGetProtocolResponse", () => {
|
|
6
|
+
it("should handle null input", () => {
|
|
7
|
+
expect((0, utils_1.pruneGetProtocolResponse)(null)).toBeNull();
|
|
8
|
+
});
|
|
9
|
+
it("should not modify objects without time-series data", () => {
|
|
10
|
+
const input = {
|
|
11
|
+
id: "test-protocol",
|
|
12
|
+
name: "Protocol",
|
|
13
|
+
symbol: "ABC",
|
|
14
|
+
};
|
|
15
|
+
const result = (0, utils_1.pruneGetProtocolResponse)(input);
|
|
16
|
+
expect(result).not.toBeNull();
|
|
17
|
+
expect(result).toEqual(input);
|
|
18
|
+
});
|
|
19
|
+
it("should prune time-series arrays", () => {
|
|
20
|
+
const timeSeriesData = Array.from({ length: 20 }, (_, i) => ({
|
|
21
|
+
date: Date.now() - i * 86400000,
|
|
22
|
+
totalLiquidityUSD: 1000 + i,
|
|
23
|
+
}));
|
|
24
|
+
const input = {
|
|
25
|
+
id: "test-protocol",
|
|
26
|
+
name: "Protocol",
|
|
27
|
+
tvl: [...timeSeriesData],
|
|
28
|
+
};
|
|
29
|
+
const result = (0, utils_1.pruneGetProtocolResponse)(input, 5);
|
|
30
|
+
expect(result).not.toBeNull();
|
|
31
|
+
if (result) {
|
|
32
|
+
expect(result.name).toBe("Protocol");
|
|
33
|
+
expect(result.tvl).toHaveLength(5);
|
|
34
|
+
const resultDates = result.tvl.map(entry => entry.date);
|
|
35
|
+
const sortedDates = [...resultDates].sort((a, b) => b - a);
|
|
36
|
+
expect(resultDates).toEqual(sortedDates);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
it("should prune nested time-series arrays in chainTvls", () => {
|
|
40
|
+
const timeSeriesData = Array.from({ length: 20 }, (_, i) => ({
|
|
41
|
+
date: Date.now() - i * 86400000,
|
|
42
|
+
totalLiquidityUSD: 1000 + i,
|
|
43
|
+
}));
|
|
44
|
+
const tokenTimeSeriesData = Array.from({ length: 20 }, (_, i) => ({
|
|
45
|
+
date: Date.now() - i * 86400000,
|
|
46
|
+
tokens: { ETH: 1000 + i },
|
|
47
|
+
}));
|
|
48
|
+
const input = {
|
|
49
|
+
id: "test-protocol",
|
|
50
|
+
name: "Protocol",
|
|
51
|
+
chainTvls: {
|
|
52
|
+
Ethereum: {
|
|
53
|
+
tvl: [...timeSeriesData],
|
|
54
|
+
tokens: [...tokenTimeSeriesData],
|
|
55
|
+
},
|
|
56
|
+
Polygon: {
|
|
57
|
+
tvl: [...timeSeriesData],
|
|
58
|
+
tokensInUsd: [...tokenTimeSeriesData],
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
const result = (0, utils_1.pruneGetProtocolResponse)(input, 3);
|
|
63
|
+
expect(result).not.toBeNull();
|
|
64
|
+
if (result) {
|
|
65
|
+
expect(result.name).toBe("Protocol");
|
|
66
|
+
expect(result.chainTvls).toBeDefined();
|
|
67
|
+
if (result.chainTvls) {
|
|
68
|
+
expect(result.chainTvls.Ethereum.tvl).toHaveLength(3);
|
|
69
|
+
expect(result.chainTvls.Ethereum.tokens).toHaveLength(3);
|
|
70
|
+
expect(result.chainTvls.Polygon.tvl).toHaveLength(3);
|
|
71
|
+
expect(result.chainTvls.Polygon.tokensInUsd).toHaveLength(3);
|
|
72
|
+
const ethereumTvlDates = result.chainTvls.Ethereum.tvl.map(entry => entry.date);
|
|
73
|
+
const sortedDates = [...ethereumTvlDates].sort((a, b) => b - a);
|
|
74
|
+
expect(ethereumTvlDates).toEqual(sortedDates);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
it("should respect the maxEntries parameter", () => {
|
|
79
|
+
const timeSeriesData = Array.from({ length: 50 }, (_, i) => ({
|
|
80
|
+
date: Date.now() - i * 86400000,
|
|
81
|
+
totalLiquidityUSD: 1000 + i,
|
|
82
|
+
}));
|
|
83
|
+
const tokenTimeSeriesData = Array.from({ length: 50 }, (_, i) => ({
|
|
84
|
+
date: Date.now() - i * 86400000,
|
|
85
|
+
tokens: { ETH: 1000 + i },
|
|
86
|
+
}));
|
|
87
|
+
const input = {
|
|
88
|
+
id: "test-protocol",
|
|
89
|
+
name: "Protocol",
|
|
90
|
+
tvl: [...timeSeriesData],
|
|
91
|
+
tokens: [...tokenTimeSeriesData],
|
|
92
|
+
};
|
|
93
|
+
const result1 = (0, utils_1.pruneGetProtocolResponse)(input, 1);
|
|
94
|
+
expect(result1).not.toBeNull();
|
|
95
|
+
if (result1) {
|
|
96
|
+
expect(result1.tvl).toHaveLength(1);
|
|
97
|
+
expect(result1.tokens).toHaveLength(1);
|
|
98
|
+
}
|
|
99
|
+
const result10 = (0, utils_1.pruneGetProtocolResponse)(input, 10);
|
|
100
|
+
expect(result10).not.toBeNull();
|
|
101
|
+
if (result10) {
|
|
102
|
+
expect(result10.tvl).toHaveLength(10);
|
|
103
|
+
expect(result10.tokens).toHaveLength(10);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
it("should handle arrays without date property", () => {
|
|
107
|
+
const nonDateArray = Array.from({ length: 20 }, (_, i) => ({
|
|
108
|
+
value: 1000 + i,
|
|
109
|
+
name: `Item ${i}`,
|
|
110
|
+
}));
|
|
111
|
+
// Using a type assertion for this test case as it's testing a specific behavior
|
|
112
|
+
const input = {
|
|
113
|
+
id: "test-protocol",
|
|
114
|
+
name: "Protocol",
|
|
115
|
+
tvl: [...nonDateArray],
|
|
116
|
+
};
|
|
117
|
+
const result = (0, utils_1.pruneGetProtocolResponse)(input, 5);
|
|
118
|
+
expect(result).not.toBeNull();
|
|
119
|
+
if (result) {
|
|
120
|
+
expect(result.tvl).toHaveLength(5);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
});
|
|
@@ -21,6 +21,7 @@ __exportStar(require("./alchemy"), exports);
|
|
|
21
21
|
__exportStar(require("./basename"), exports);
|
|
22
22
|
__exportStar(require("./cdp"), exports);
|
|
23
23
|
__exportStar(require("./compound"), exports);
|
|
24
|
+
__exportStar(require("./defillama"), exports);
|
|
24
25
|
__exportStar(require("./erc20"), exports);
|
|
25
26
|
__exportStar(require("./erc721"), exports);
|
|
26
27
|
__exportStar(require("./farcaster"), exports);
|
|
@@ -13,11 +13,12 @@ exports.morphoActionProvider = exports.MorphoActionProvider = exports.SUPPORTED_
|
|
|
13
13
|
const zod_1 = require("zod");
|
|
14
14
|
const decimal_js_1 = require("decimal.js");
|
|
15
15
|
const viem_1 = require("viem");
|
|
16
|
+
const constants_1 = require("../erc20/constants");
|
|
16
17
|
const actionProvider_1 = require("../actionProvider");
|
|
17
18
|
const wallet_providers_1 = require("../../wallet-providers");
|
|
18
19
|
const actionDecorator_1 = require("../actionDecorator");
|
|
19
20
|
const utils_1 = require("../../utils");
|
|
20
|
-
const
|
|
21
|
+
const constants_2 = require("./constants");
|
|
21
22
|
const schemas_1 = require("./schemas");
|
|
22
23
|
exports.SUPPORTED_NETWORKS = ["base-mainnet", "base-sepolia"];
|
|
23
24
|
/**
|
|
@@ -50,13 +51,19 @@ class MorphoActionProvider extends actionProvider_1.ActionProvider {
|
|
|
50
51
|
return "Error: Assets amount must be greater than 0";
|
|
51
52
|
}
|
|
52
53
|
try {
|
|
53
|
-
const
|
|
54
|
+
const decimals = await wallet.readContract({
|
|
55
|
+
address: args.tokenAddress,
|
|
56
|
+
abi: constants_1.abi,
|
|
57
|
+
functionName: "decimals",
|
|
58
|
+
args: [],
|
|
59
|
+
});
|
|
60
|
+
const atomicAssets = (0, viem_1.parseUnits)(args.assets, decimals);
|
|
54
61
|
const approvalResult = await (0, utils_1.approve)(wallet, args.tokenAddress, args.vaultAddress, atomicAssets);
|
|
55
62
|
if (approvalResult.startsWith("Error")) {
|
|
56
63
|
return `Error approving Morpho Vault as spender: ${approvalResult}`;
|
|
57
64
|
}
|
|
58
65
|
const data = (0, viem_1.encodeFunctionData)({
|
|
59
|
-
abi:
|
|
66
|
+
abi: constants_2.METAMORPHO_ABI,
|
|
60
67
|
functionName: "deposit",
|
|
61
68
|
args: [atomicAssets, args.receiver],
|
|
62
69
|
});
|
|
@@ -84,7 +91,7 @@ class MorphoActionProvider extends actionProvider_1.ActionProvider {
|
|
|
84
91
|
}
|
|
85
92
|
try {
|
|
86
93
|
const data = (0, viem_1.encodeFunctionData)({
|
|
87
|
-
abi:
|
|
94
|
+
abi: constants_2.METAMORPHO_ABI,
|
|
88
95
|
functionName: "withdraw",
|
|
89
96
|
args: [BigInt(args.assets), args.receiver, args.receiver],
|
|
90
97
|
});
|
|
@@ -11,6 +11,7 @@ const MOCK_RECEIVER_ID = "0x9876543210987654321098765432109876543210";
|
|
|
11
11
|
const MOCK_TOKEN_ADDRESS = "0x4200000000000000000000000000000000000006";
|
|
12
12
|
const MOCK_TX_HASH = "0xabcdef1234567890";
|
|
13
13
|
const MOCK_RECEIPT = { status: 1, blockNumber: 1234567 };
|
|
14
|
+
const MOCK_DECIMALS = 18;
|
|
14
15
|
jest.mock("../../utils");
|
|
15
16
|
const mockApprove = utils_1.approve;
|
|
16
17
|
describe("Morpho Action Provider", () => {
|
|
@@ -22,6 +23,7 @@ describe("Morpho Action Provider", () => {
|
|
|
22
23
|
getNetwork: jest.fn().mockReturnValue({ protocolFamily: "evm", networkId: "1" }),
|
|
23
24
|
sendTransaction: jest.fn().mockResolvedValue(MOCK_TX_HASH),
|
|
24
25
|
waitForTransactionReceipt: jest.fn().mockResolvedValue(MOCK_RECEIPT),
|
|
26
|
+
readContract: jest.fn().mockResolvedValue(MOCK_DECIMALS),
|
|
25
27
|
};
|
|
26
28
|
mockApprove.mockResolvedValue("Approval successful");
|
|
27
29
|
});
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@coinbase/agentkit",
|
|
3
3
|
"description": "Coinbase AgentKit core primitives",
|
|
4
4
|
"repository": "https://github.com/coinbase/agentkit",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.4.0",
|
|
6
6
|
"author": "Coinbase Inc.",
|
|
7
7
|
"license": "Apache-2.0",
|
|
8
8
|
"main": "dist/index.js",
|