@coinbase/agentkit 0.0.0-nightly-20250716210450 → 0.0.0-nightly-20250724210458
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 +9 -1
- package/dist/action-providers/cdp/index.d.ts +0 -3
- package/dist/action-providers/cdp/index.js +0 -3
- package/dist/action-providers/farcaster/farcasterActionProvider.js +2 -0
- package/dist/action-providers/farcaster/farcasterActionProvider.test.js +55 -0
- package/dist/action-providers/farcaster/schemas.d.ts +13 -0
- package/dist/action-providers/farcaster/schemas.js +6 -0
- package/dist/action-providers/twitter/schemas.d.ts +16 -0
- package/dist/action-providers/twitter/schemas.js +23 -1
- package/dist/action-providers/twitter/twitterActionProvider.d.ts +8 -1
- package/dist/action-providers/twitter/twitterActionProvider.js +56 -5
- package/dist/action-providers/twitter/twitterActionProvider.test.js +52 -2
- package/dist/action-providers/weth/constants.d.ts +9 -0
- package/dist/action-providers/weth/constants.js +12 -0
- package/dist/action-providers/weth/schemas.d.ts +7 -0
- package/dist/action-providers/weth/schemas.js +7 -1
- package/dist/action-providers/weth/wethActionProvider.d.ts +9 -1
- package/dist/action-providers/weth/wethActionProvider.js +50 -1
- package/dist/action-providers/weth/wethActionProvider.test.js +60 -0
- package/dist/action-providers/x402/schemas.d.ts +9 -45
- package/dist/action-providers/x402/schemas.js +53 -17
- package/dist/action-providers/x402/x402ActionProvider.js +24 -19
- package/dist/action-providers/x402/x402ActionProvider.test.js +4 -35
- package/dist/wallet-providers/cdpEvmWalletProvider.d.ts +4 -4
- package/dist/wallet-providers/cdpEvmWalletProvider.js +4 -4
- package/dist/wallet-providers/cdpShared.d.ts +2 -2
- package/dist/wallet-providers/cdpSmartWalletProvider.d.ts +2 -2
- package/dist/wallet-providers/cdpSmartWalletProvider.js +11 -4
- package/dist/wallet-providers/cdpSmartWalletProvider.test.js +31 -11
- package/dist/wallet-providers/legacyCdpWalletProvider.d.ts +1 -1
- package/dist/wallet-providers/legacyCdpWalletProvider.js +1 -1
- package/package.json +2 -2
- package/dist/action-providers/cdp/cdpEvmWalletActionProvider.d.ts +0 -17
- package/dist/action-providers/cdp/cdpEvmWalletActionProvider.js +0 -20
- package/dist/action-providers/cdp/cdpSmartWalletActionProvider.d.ts +0 -17
- package/dist/action-providers/cdp/cdpSmartWalletActionProvider.js +0 -20
- package/dist/action-providers/cdp/cdpSolanaWalletActionProvider.d.ts +0 -17
- package/dist/action-providers/cdp/cdpSolanaWalletActionProvider.js +0 -20
package/README.md
CHANGED
|
@@ -261,7 +261,7 @@ const agent = createReactAgent({
|
|
|
261
261
|
</tr>
|
|
262
262
|
<tr>
|
|
263
263
|
<td width="200"><code>post_cast</code></td>
|
|
264
|
-
<td width="768">Creates a new cast (message) on Farcaster with up to 280 characters.</td>
|
|
264
|
+
<td width="768">Creates a new cast (message) on Farcaster with up to 280 characters and support for up to 2 embedded URLs.</td>
|
|
265
265
|
</tr>
|
|
266
266
|
</table>
|
|
267
267
|
</details>
|
|
@@ -362,6 +362,10 @@ const agent = createReactAgent({
|
|
|
362
362
|
<td width="200"><code>post_tweet_reply</code></td>
|
|
363
363
|
<td width="768">Creates a reply to an existing tweet using the tweet's unique identifier.</td>
|
|
364
364
|
</tr>
|
|
365
|
+
<tr>
|
|
366
|
+
<td width="200"><code>upload_media</code></td>
|
|
367
|
+
<td width="768">Uploads media (images, videos) to Twitter that can be attached to tweets.</td>
|
|
368
|
+
</tr>
|
|
365
369
|
</table>
|
|
366
370
|
</details>
|
|
367
371
|
<details>
|
|
@@ -384,6 +388,10 @@ const agent = createReactAgent({
|
|
|
384
388
|
<td width="200"><code>wrap_eth</code></td>
|
|
385
389
|
<td width="768">Converts native ETH to Wrapped ETH (WETH) on Base Sepolia or Base Mainnet.</td>
|
|
386
390
|
</tr>
|
|
391
|
+
<tr>
|
|
392
|
+
<td width="200"><code>unwrap_eth</code></td>
|
|
393
|
+
<td width="768">Converts Wrapped ETH (WETH) to Native ETH on Base Sepolia or Base Mainnet.</td>
|
|
394
|
+
</tr>
|
|
387
395
|
</table>
|
|
388
396
|
</details>
|
|
389
397
|
<details>
|
|
@@ -16,6 +16,3 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./schemas"), exports);
|
|
18
18
|
__exportStar(require("./cdpApiActionProvider"), exports);
|
|
19
|
-
__exportStar(require("./cdpEvmWalletActionProvider"), exports);
|
|
20
|
-
__exportStar(require("./cdpSolanaWalletActionProvider"), exports);
|
|
21
|
-
__exportStar(require("./cdpSmartWalletActionProvider"), exports);
|
|
@@ -90,6 +90,7 @@ class FarcasterActionProvider extends actionProvider_1.ActionProvider {
|
|
|
90
90
|
body: JSON.stringify({
|
|
91
91
|
signer_uuid: this.signerUuid,
|
|
92
92
|
text: args.castText,
|
|
93
|
+
embeds: args.embeds,
|
|
93
94
|
}),
|
|
94
95
|
});
|
|
95
96
|
const data = await response.json();
|
|
@@ -125,6 +126,7 @@ __decorate([
|
|
|
125
126
|
name: "post_cast",
|
|
126
127
|
description: `
|
|
127
128
|
This tool will post a cast to Farcaster. The tool takes the text of the cast as input. Casts can be maximum 280 characters.
|
|
129
|
+
Optionally, up to 2 embeds (links to websites or mini apps) can be attached to the cast by providing an array of URLs in the embeds parameter.
|
|
128
130
|
|
|
129
131
|
A successful response will return a message with the API response as a JSON payload:
|
|
130
132
|
{}
|
|
@@ -23,6 +23,35 @@ describe("Farcaster Action Provider Input Schemas", () => {
|
|
|
23
23
|
expect(result.success).toBe(true);
|
|
24
24
|
expect(result.data).toEqual(validInput);
|
|
25
25
|
});
|
|
26
|
+
it("should successfully parse valid cast text with embeds", () => {
|
|
27
|
+
const validInput = {
|
|
28
|
+
castText: "Hello, Farcaster!",
|
|
29
|
+
embeds: [{ url: "https://example.com" }],
|
|
30
|
+
};
|
|
31
|
+
const result = schemas_1.FarcasterPostCastSchema.safeParse(validInput);
|
|
32
|
+
expect(result.success).toBe(true);
|
|
33
|
+
expect(result.data).toEqual(validInput);
|
|
34
|
+
});
|
|
35
|
+
it("should fail when embed URL is invalid", () => {
|
|
36
|
+
const invalidInput = {
|
|
37
|
+
castText: "Hello, Farcaster!",
|
|
38
|
+
embeds: [{ url: "invalid-url" }],
|
|
39
|
+
};
|
|
40
|
+
const result = schemas_1.FarcasterPostCastSchema.safeParse(invalidInput);
|
|
41
|
+
expect(result.success).toBe(false);
|
|
42
|
+
});
|
|
43
|
+
it("should fail when there are more than 2 embeds", () => {
|
|
44
|
+
const invalidInput = {
|
|
45
|
+
castText: "Hello, Farcaster!",
|
|
46
|
+
embeds: [
|
|
47
|
+
{ url: "https://example1.com" },
|
|
48
|
+
{ url: "https://example2.com" },
|
|
49
|
+
{ url: "https://example3.com" },
|
|
50
|
+
],
|
|
51
|
+
};
|
|
52
|
+
const result = schemas_1.FarcasterPostCastSchema.safeParse(invalidInput);
|
|
53
|
+
expect(result.success).toBe(false);
|
|
54
|
+
});
|
|
26
55
|
it("should fail parsing cast text over 280 characters", () => {
|
|
27
56
|
const invalidInput = {
|
|
28
57
|
castText: "a".repeat(281),
|
|
@@ -100,6 +129,32 @@ describe("Farcaster Action Provider", () => {
|
|
|
100
129
|
body: JSON.stringify({
|
|
101
130
|
signer_uuid: mockConfig.signerUuid,
|
|
102
131
|
text: args.castText,
|
|
132
|
+
embeds: undefined,
|
|
133
|
+
}),
|
|
134
|
+
});
|
|
135
|
+
expect(mockFetch).toHaveBeenCalledTimes(1);
|
|
136
|
+
expect(result).toContain("Successfully posted cast to Farcaster");
|
|
137
|
+
expect(result).toContain(JSON.stringify(mockCastResponse));
|
|
138
|
+
});
|
|
139
|
+
it("should successfully post a cast with embeds", async () => {
|
|
140
|
+
mockFetch.mockResolvedValueOnce({
|
|
141
|
+
json: () => Promise.resolve(mockCastResponse),
|
|
142
|
+
});
|
|
143
|
+
const args = {
|
|
144
|
+
castText: "Hello, Farcaster!",
|
|
145
|
+
embeds: [{ url: "https://example.com" }],
|
|
146
|
+
};
|
|
147
|
+
const result = await actionProvider.postCast(args);
|
|
148
|
+
expect(mockFetch).toHaveBeenCalledWith("https://api.neynar.com/v2/farcaster/cast", {
|
|
149
|
+
method: "POST",
|
|
150
|
+
headers: {
|
|
151
|
+
api_key: mockConfig.neynarApiKey,
|
|
152
|
+
"Content-Type": "application/json",
|
|
153
|
+
},
|
|
154
|
+
body: JSON.stringify({
|
|
155
|
+
signer_uuid: mockConfig.signerUuid,
|
|
156
|
+
text: args.castText,
|
|
157
|
+
embeds: args.embeds,
|
|
103
158
|
}),
|
|
104
159
|
});
|
|
105
160
|
expect(mockFetch).toHaveBeenCalledTimes(1);
|
|
@@ -8,8 +8,21 @@ export declare const FarcasterAccountDetailsSchema: z.ZodObject<{}, "strip", z.Z
|
|
|
8
8
|
*/
|
|
9
9
|
export declare const FarcasterPostCastSchema: z.ZodObject<{
|
|
10
10
|
castText: z.ZodString;
|
|
11
|
+
embeds: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
12
|
+
url: z.ZodString;
|
|
13
|
+
}, "strip", z.ZodTypeAny, {
|
|
14
|
+
url: string;
|
|
15
|
+
}, {
|
|
16
|
+
url: string;
|
|
17
|
+
}>, "many">>;
|
|
11
18
|
}, "strip", z.ZodTypeAny, {
|
|
12
19
|
castText: string;
|
|
20
|
+
embeds?: {
|
|
21
|
+
url: string;
|
|
22
|
+
}[] | undefined;
|
|
13
23
|
}, {
|
|
14
24
|
castText: string;
|
|
25
|
+
embeds?: {
|
|
26
|
+
url: string;
|
|
27
|
+
}[] | undefined;
|
|
15
28
|
}>;
|
|
@@ -15,6 +15,12 @@ exports.FarcasterAccountDetailsSchema = zod_1.z
|
|
|
15
15
|
exports.FarcasterPostCastSchema = zod_1.z
|
|
16
16
|
.object({
|
|
17
17
|
castText: zod_1.z.string().max(280, "Cast text must be a maximum of 280 characters."),
|
|
18
|
+
embeds: zod_1.z
|
|
19
|
+
.array(zod_1.z.object({
|
|
20
|
+
url: zod_1.z.string().url("Embed URL must be a valid URL"),
|
|
21
|
+
}))
|
|
22
|
+
.max(2, "Maximum of 2 embeds allowed")
|
|
23
|
+
.optional(),
|
|
18
24
|
})
|
|
19
25
|
.strip()
|
|
20
26
|
.describe("Input schema for posting a text-based cast");
|
|
@@ -18,10 +18,13 @@ export declare const TwitterAccountMentionsSchema: z.ZodObject<{
|
|
|
18
18
|
*/
|
|
19
19
|
export declare const TwitterPostTweetSchema: z.ZodObject<{
|
|
20
20
|
tweet: z.ZodString;
|
|
21
|
+
mediaIds: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
21
22
|
}, "strip", z.ZodTypeAny, {
|
|
22
23
|
tweet: string;
|
|
24
|
+
mediaIds?: string[] | undefined;
|
|
23
25
|
}, {
|
|
24
26
|
tweet: string;
|
|
27
|
+
mediaIds?: string[] | undefined;
|
|
25
28
|
}>;
|
|
26
29
|
/**
|
|
27
30
|
* Input schema for posting a tweet reply.
|
|
@@ -29,10 +32,23 @@ export declare const TwitterPostTweetSchema: z.ZodObject<{
|
|
|
29
32
|
export declare const TwitterPostTweetReplySchema: z.ZodObject<{
|
|
30
33
|
tweetId: z.ZodString;
|
|
31
34
|
tweetReply: z.ZodString;
|
|
35
|
+
mediaIds: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
32
36
|
}, "strip", z.ZodTypeAny, {
|
|
33
37
|
tweetId: string;
|
|
34
38
|
tweetReply: string;
|
|
39
|
+
mediaIds?: string[] | undefined;
|
|
35
40
|
}, {
|
|
36
41
|
tweetId: string;
|
|
37
42
|
tweetReply: string;
|
|
43
|
+
mediaIds?: string[] | undefined;
|
|
44
|
+
}>;
|
|
45
|
+
/**
|
|
46
|
+
* Input schema for uploading media.
|
|
47
|
+
*/
|
|
48
|
+
export declare const TwitterUploadMediaSchema: z.ZodObject<{
|
|
49
|
+
filePath: z.ZodString;
|
|
50
|
+
}, "strip", z.ZodTypeAny, {
|
|
51
|
+
filePath: string;
|
|
52
|
+
}, {
|
|
53
|
+
filePath: string;
|
|
38
54
|
}>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.TwitterPostTweetReplySchema = exports.TwitterPostTweetSchema = exports.TwitterAccountMentionsSchema = exports.TwitterAccountDetailsSchema = void 0;
|
|
3
|
+
exports.TwitterUploadMediaSchema = exports.TwitterPostTweetReplySchema = exports.TwitterPostTweetSchema = exports.TwitterAccountMentionsSchema = exports.TwitterAccountDetailsSchema = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
/**
|
|
6
6
|
* Input schema for retrieving account details.
|
|
@@ -27,6 +27,11 @@ exports.TwitterAccountMentionsSchema = zod_1.z
|
|
|
27
27
|
exports.TwitterPostTweetSchema = zod_1.z
|
|
28
28
|
.object({
|
|
29
29
|
tweet: zod_1.z.string().max(280, "Tweet must be a maximum of 280 characters."),
|
|
30
|
+
mediaIds: zod_1.z
|
|
31
|
+
.array(zod_1.z.string())
|
|
32
|
+
.max(4, "Maximum of 4 media IDs allowed")
|
|
33
|
+
.optional()
|
|
34
|
+
.describe("Optional array of 1-4 media IDs to attach to the tweet"),
|
|
30
35
|
})
|
|
31
36
|
.strip()
|
|
32
37
|
.describe("Input schema for posting a tweet");
|
|
@@ -39,6 +44,23 @@ exports.TwitterPostTweetReplySchema = zod_1.z
|
|
|
39
44
|
tweetReply: zod_1.z
|
|
40
45
|
.string()
|
|
41
46
|
.max(280, "The reply to the tweet which must be a maximum of 280 characters."),
|
|
47
|
+
mediaIds: zod_1.z
|
|
48
|
+
.array(zod_1.z.string())
|
|
49
|
+
.max(4, "Maximum of 4 media IDs allowed")
|
|
50
|
+
.optional()
|
|
51
|
+
.describe("Optional array of 1-4 media IDs to attach to the tweet"),
|
|
42
52
|
})
|
|
43
53
|
.strip()
|
|
44
54
|
.describe("Input schema for posting a tweet reply");
|
|
55
|
+
/**
|
|
56
|
+
* Input schema for uploading media.
|
|
57
|
+
*/
|
|
58
|
+
exports.TwitterUploadMediaSchema = zod_1.z
|
|
59
|
+
.object({
|
|
60
|
+
filePath: zod_1.z
|
|
61
|
+
.string()
|
|
62
|
+
.min(1, "File path is required.")
|
|
63
|
+
.describe("The path to the media file to upload"),
|
|
64
|
+
})
|
|
65
|
+
.strip()
|
|
66
|
+
.describe("Input schema for uploading media to Twitter");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { ActionProvider } from "../actionProvider";
|
|
3
3
|
import { Network } from "../../network";
|
|
4
|
-
import { TwitterAccountDetailsSchema, TwitterAccountMentionsSchema, TwitterPostTweetSchema, TwitterPostTweetReplySchema } from "./schemas";
|
|
4
|
+
import { TwitterAccountDetailsSchema, TwitterAccountMentionsSchema, TwitterPostTweetSchema, TwitterPostTweetReplySchema, TwitterUploadMediaSchema } from "./schemas";
|
|
5
5
|
/**
|
|
6
6
|
* Configuration options for the TwitterActionProvider.
|
|
7
7
|
*/
|
|
@@ -65,6 +65,13 @@ export declare class TwitterActionProvider extends ActionProvider {
|
|
|
65
65
|
* @returns A JSON string containing the posted reply details or error message
|
|
66
66
|
*/
|
|
67
67
|
postTweetReply(args: z.infer<typeof TwitterPostTweetReplySchema>): Promise<string>;
|
|
68
|
+
/**
|
|
69
|
+
* Upload media to Twitter.
|
|
70
|
+
*
|
|
71
|
+
* @param args - The arguments containing the file path
|
|
72
|
+
* @returns A JSON string containing the media ID or error message
|
|
73
|
+
*/
|
|
74
|
+
uploadMedia(args: z.infer<typeof TwitterUploadMediaSchema>): Promise<string>;
|
|
68
75
|
/**
|
|
69
76
|
* Checks if the Twitter action provider supports the given network.
|
|
70
77
|
* Twitter actions don't depend on blockchain networks, so always return true.
|
|
@@ -90,11 +90,19 @@ class TwitterActionProvider extends actionProvider_1.ActionProvider {
|
|
|
90
90
|
*/
|
|
91
91
|
async postTweet(args) {
|
|
92
92
|
try {
|
|
93
|
-
|
|
93
|
+
let mediaOptions = {};
|
|
94
|
+
if (args.mediaIds && args.mediaIds.length > 0) {
|
|
95
|
+
// Convert array to tuple format expected by the Twitter API
|
|
96
|
+
const mediaIdsTuple = args.mediaIds;
|
|
97
|
+
mediaOptions = {
|
|
98
|
+
media: { media_ids: mediaIdsTuple },
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
const response = await this.getClient().v2.tweet(args.tweet, mediaOptions);
|
|
94
102
|
return `Successfully posted to Twitter:\n${JSON.stringify(response)}`;
|
|
95
103
|
}
|
|
96
104
|
catch (error) {
|
|
97
|
-
return `Error posting to Twitter:\n${error}`;
|
|
105
|
+
return `Error posting to Twitter:\n${error} with media ids: ${args.mediaIds}`;
|
|
98
106
|
}
|
|
99
107
|
}
|
|
100
108
|
/**
|
|
@@ -105,15 +113,36 @@ class TwitterActionProvider extends actionProvider_1.ActionProvider {
|
|
|
105
113
|
*/
|
|
106
114
|
async postTweetReply(args) {
|
|
107
115
|
try {
|
|
108
|
-
const
|
|
116
|
+
const options = {
|
|
109
117
|
reply: { in_reply_to_tweet_id: args.tweetId },
|
|
110
|
-
}
|
|
118
|
+
};
|
|
119
|
+
if (args.mediaIds && args.mediaIds.length > 0) {
|
|
120
|
+
// Convert array to tuple format expected by the Twitter API
|
|
121
|
+
const mediaIdsTuple = args.mediaIds;
|
|
122
|
+
options.media = { media_ids: mediaIdsTuple };
|
|
123
|
+
}
|
|
124
|
+
const response = await this.getClient().v2.tweet(args.tweetReply, options);
|
|
111
125
|
return `Successfully posted reply to Twitter:\n${JSON.stringify(response)}`;
|
|
112
126
|
}
|
|
113
127
|
catch (error) {
|
|
114
128
|
return `Error posting reply to Twitter: ${error}`;
|
|
115
129
|
}
|
|
116
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* Upload media to Twitter.
|
|
133
|
+
*
|
|
134
|
+
* @param args - The arguments containing the file path
|
|
135
|
+
* @returns A JSON string containing the media ID or error message
|
|
136
|
+
*/
|
|
137
|
+
async uploadMedia(args) {
|
|
138
|
+
try {
|
|
139
|
+
const mediaId = await this.getClient().v1.uploadMedia(args.filePath);
|
|
140
|
+
return `Successfully uploaded media to Twitter: ${mediaId}`;
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
return `Error uploading media to Twitter: ${error}`;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
117
146
|
/**
|
|
118
147
|
* Checks if the Twitter action provider supports the given network.
|
|
119
148
|
* Twitter actions don't depend on blockchain networks, so always return true.
|
|
@@ -183,6 +212,8 @@ __decorate([
|
|
|
183
212
|
name: "post_tweet",
|
|
184
213
|
description: `
|
|
185
214
|
This tool will post a tweet on Twitter. The tool takes the text of the tweet as input. Tweets can be maximum 280 characters.
|
|
215
|
+
Optionally, up to 4 media items (images, videos) can be attached to the tweet by providing their media IDs in the mediaIds array.
|
|
216
|
+
Media IDs are obtained by first uploading the media using the upload_media action.
|
|
186
217
|
|
|
187
218
|
A successful response will return a message with the API response as a JSON payload:
|
|
188
219
|
{"data": {"text": "hello, world!", "id": "0123456789012345678", "edit_history_tweet_ids": ["0123456789012345678"]}}
|
|
@@ -199,7 +230,10 @@ __decorate([
|
|
|
199
230
|
(0, actionDecorator_1.CreateAction)({
|
|
200
231
|
name: "post_tweet_reply",
|
|
201
232
|
description: `
|
|
202
|
-
This tool will post a tweet on Twitter. The tool takes the text of the
|
|
233
|
+
This tool will post a reply to a tweet on Twitter. The tool takes the text of the reply and the ID of the tweet to reply to as input.
|
|
234
|
+
Replies can be maximum 280 characters.
|
|
235
|
+
Optionally, up to 4 media items (images, videos) can be attached to the reply by providing their media IDs in the mediaIds array.
|
|
236
|
+
Media IDs can be obtained by first uploading the media using the upload_media action.
|
|
203
237
|
|
|
204
238
|
A successful response will return a message with the API response as a JSON payload:
|
|
205
239
|
{"data": {"text": "hello, world!", "id": "0123456789012345678", "edit_history_tweet_ids": ["0123456789012345678"]}}
|
|
@@ -212,6 +246,23 @@ A failure response will return a message with the Twitter API request error:
|
|
|
212
246
|
__metadata("design:paramtypes", [void 0]),
|
|
213
247
|
__metadata("design:returntype", Promise)
|
|
214
248
|
], TwitterActionProvider.prototype, "postTweetReply", null);
|
|
249
|
+
__decorate([
|
|
250
|
+
(0, actionDecorator_1.CreateAction)({
|
|
251
|
+
name: "upload_media",
|
|
252
|
+
description: `
|
|
253
|
+
This tool will upload media (images, videos, etc.) to Twitter.
|
|
254
|
+
|
|
255
|
+
A successful response will return a message with the media ID:
|
|
256
|
+
Successfully uploaded media to Twitter: 1234567890
|
|
257
|
+
|
|
258
|
+
A failure response will return a message with the Twitter API request error:
|
|
259
|
+
Error uploading media to Twitter: Invalid file format`,
|
|
260
|
+
schema: schemas_1.TwitterUploadMediaSchema,
|
|
261
|
+
}),
|
|
262
|
+
__metadata("design:type", Function),
|
|
263
|
+
__metadata("design:paramtypes", [void 0]),
|
|
264
|
+
__metadata("design:returntype", Promise)
|
|
265
|
+
], TwitterActionProvider.prototype, "uploadMedia", null);
|
|
215
266
|
/**
|
|
216
267
|
* Factory function to create a new TwitterActionProvider instance.
|
|
217
268
|
*
|
|
@@ -14,16 +14,24 @@ const MOCK_USERNAME = "CDPAgentkit";
|
|
|
14
14
|
const MOCK_TWEET = "Hello, world!";
|
|
15
15
|
const MOCK_TWEET_ID = "0123456789012345678";
|
|
16
16
|
const MOCK_TWEET_REPLY = "Hello again!";
|
|
17
|
+
const MOCK_MEDIA_ID = "987654321";
|
|
18
|
+
const MOCK_FILE_PATH = "/path/to/image.jpg";
|
|
17
19
|
describe("TwitterActionProvider", () => {
|
|
18
20
|
let mockClient;
|
|
19
21
|
let provider;
|
|
22
|
+
let mockUploadMedia;
|
|
20
23
|
beforeEach(() => {
|
|
21
24
|
mockClient = {
|
|
22
25
|
me: jest.fn(),
|
|
23
26
|
userMentionTimeline: jest.fn(),
|
|
24
27
|
tweet: jest.fn(),
|
|
25
28
|
};
|
|
29
|
+
mockUploadMedia = jest.fn();
|
|
26
30
|
jest.spyOn(twitter_api_v2_1.TwitterApi.prototype, "v2", "get").mockReturnValue(mockClient);
|
|
31
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
32
|
+
jest.spyOn(twitter_api_v2_1.TwitterApi.prototype, "v1", "get").mockReturnValue({
|
|
33
|
+
uploadMedia: mockUploadMedia,
|
|
34
|
+
});
|
|
27
35
|
provider = new twitterActionProvider_1.TwitterActionProvider(MOCK_CONFIG);
|
|
28
36
|
});
|
|
29
37
|
describe("Constructor", () => {
|
|
@@ -145,7 +153,16 @@ describe("TwitterActionProvider", () => {
|
|
|
145
153
|
});
|
|
146
154
|
it("should successfully post a tweet", async () => {
|
|
147
155
|
const response = await provider.postTweet({ tweet: MOCK_TWEET });
|
|
148
|
-
expect(mockClient.tweet).toHaveBeenCalledWith(MOCK_TWEET);
|
|
156
|
+
expect(mockClient.tweet).toHaveBeenCalledWith(MOCK_TWEET, {});
|
|
157
|
+
expect(response).toContain("Successfully posted to Twitter");
|
|
158
|
+
expect(response).toContain(JSON.stringify(mockResponse));
|
|
159
|
+
});
|
|
160
|
+
it("should successfully post a tweet with media", async () => {
|
|
161
|
+
const mediaIds = [MOCK_MEDIA_ID];
|
|
162
|
+
const response = await provider.postTweet({ tweet: MOCK_TWEET, mediaIds });
|
|
163
|
+
expect(mockClient.tweet).toHaveBeenCalledWith(MOCK_TWEET, {
|
|
164
|
+
media: { media_ids: mediaIds },
|
|
165
|
+
});
|
|
149
166
|
expect(response).toContain("Successfully posted to Twitter");
|
|
150
167
|
expect(response).toContain(JSON.stringify(mockResponse));
|
|
151
168
|
});
|
|
@@ -153,7 +170,7 @@ describe("TwitterActionProvider", () => {
|
|
|
153
170
|
const error = new Error("An error has occurred");
|
|
154
171
|
mockClient.tweet.mockRejectedValue(error);
|
|
155
172
|
const response = await provider.postTweet({ tweet: MOCK_TWEET });
|
|
156
|
-
expect(mockClient.tweet).toHaveBeenCalledWith(MOCK_TWEET);
|
|
173
|
+
expect(mockClient.tweet).toHaveBeenCalledWith(MOCK_TWEET, {});
|
|
157
174
|
expect(response).toContain("Error posting to Twitter");
|
|
158
175
|
expect(response).toContain(error.message);
|
|
159
176
|
});
|
|
@@ -180,6 +197,20 @@ describe("TwitterActionProvider", () => {
|
|
|
180
197
|
expect(response).toContain("Successfully posted reply to Twitter");
|
|
181
198
|
expect(response).toContain(JSON.stringify(mockResponse));
|
|
182
199
|
});
|
|
200
|
+
it("should successfully post a tweet reply with media", async () => {
|
|
201
|
+
const mediaIds = [MOCK_MEDIA_ID];
|
|
202
|
+
const response = await provider.postTweetReply({
|
|
203
|
+
tweetId: MOCK_TWEET_ID,
|
|
204
|
+
tweetReply: MOCK_TWEET_REPLY,
|
|
205
|
+
mediaIds,
|
|
206
|
+
});
|
|
207
|
+
expect(mockClient.tweet).toHaveBeenCalledWith(MOCK_TWEET_REPLY, {
|
|
208
|
+
reply: { in_reply_to_tweet_id: MOCK_TWEET_ID },
|
|
209
|
+
media: { media_ids: mediaIds },
|
|
210
|
+
});
|
|
211
|
+
expect(response).toContain("Successfully posted reply to Twitter");
|
|
212
|
+
expect(response).toContain(JSON.stringify(mockResponse));
|
|
213
|
+
});
|
|
183
214
|
it("should handle errors when posting a tweet reply", async () => {
|
|
184
215
|
const error = new Error("An error has occurred");
|
|
185
216
|
mockClient.tweet.mockRejectedValue(error);
|
|
@@ -194,6 +225,25 @@ describe("TwitterActionProvider", () => {
|
|
|
194
225
|
expect(response).toContain(error.message);
|
|
195
226
|
});
|
|
196
227
|
});
|
|
228
|
+
describe("Upload Media Action", () => {
|
|
229
|
+
beforeEach(() => {
|
|
230
|
+
mockUploadMedia.mockResolvedValue(MOCK_MEDIA_ID);
|
|
231
|
+
});
|
|
232
|
+
it("should successfully upload media", async () => {
|
|
233
|
+
const response = await provider.uploadMedia({ filePath: MOCK_FILE_PATH });
|
|
234
|
+
expect(mockUploadMedia).toHaveBeenCalledWith(MOCK_FILE_PATH);
|
|
235
|
+
expect(response).toContain("Successfully uploaded media to Twitter");
|
|
236
|
+
expect(response).toContain(MOCK_MEDIA_ID);
|
|
237
|
+
});
|
|
238
|
+
it("should handle errors when uploading media", async () => {
|
|
239
|
+
const error = new Error("Invalid file format");
|
|
240
|
+
mockUploadMedia.mockRejectedValue(error);
|
|
241
|
+
const response = await provider.uploadMedia({ filePath: MOCK_FILE_PATH });
|
|
242
|
+
expect(mockUploadMedia).toHaveBeenCalledWith(MOCK_FILE_PATH);
|
|
243
|
+
expect(response).toContain("Error uploading media to Twitter");
|
|
244
|
+
expect(response).toContain(error.message);
|
|
245
|
+
});
|
|
246
|
+
});
|
|
197
247
|
describe("Network Support", () => {
|
|
198
248
|
it("should always return true for network support", () => {
|
|
199
249
|
expect(provider.supportsNetwork({ protocolFamily: "evm", networkId: "1" })).toBe(true);
|
|
@@ -5,6 +5,15 @@ export declare const WETH_ABI: readonly [{
|
|
|
5
5
|
readonly outputs: readonly [];
|
|
6
6
|
readonly stateMutability: "payable";
|
|
7
7
|
readonly type: "function";
|
|
8
|
+
}, {
|
|
9
|
+
readonly inputs: readonly [{
|
|
10
|
+
readonly name: "wad";
|
|
11
|
+
readonly type: "uint256";
|
|
12
|
+
}];
|
|
13
|
+
readonly name: "withdraw";
|
|
14
|
+
readonly outputs: readonly [];
|
|
15
|
+
readonly stateMutability: "nonpayable";
|
|
16
|
+
readonly type: "function";
|
|
8
17
|
}, {
|
|
9
18
|
readonly inputs: readonly [{
|
|
10
19
|
readonly name: "account";
|
|
@@ -10,6 +10,18 @@ exports.WETH_ABI = [
|
|
|
10
10
|
stateMutability: "payable",
|
|
11
11
|
type: "function",
|
|
12
12
|
},
|
|
13
|
+
{
|
|
14
|
+
inputs: [
|
|
15
|
+
{
|
|
16
|
+
name: "wad",
|
|
17
|
+
type: "uint256",
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
name: "withdraw",
|
|
21
|
+
outputs: [],
|
|
22
|
+
stateMutability: "nonpayable",
|
|
23
|
+
type: "function",
|
|
24
|
+
},
|
|
13
25
|
{
|
|
14
26
|
inputs: [
|
|
15
27
|
{
|
|
@@ -6,3 +6,10 @@ export declare const WrapEthSchema: z.ZodObject<{
|
|
|
6
6
|
}, {
|
|
7
7
|
amountToWrap: string;
|
|
8
8
|
}>;
|
|
9
|
+
export declare const UnwrapEthSchema: z.ZodObject<{
|
|
10
|
+
amountToUnwrap: z.ZodString;
|
|
11
|
+
}, "strip", z.ZodTypeAny, {
|
|
12
|
+
amountToUnwrap: string;
|
|
13
|
+
}, {
|
|
14
|
+
amountToUnwrap: string;
|
|
15
|
+
}>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.WrapEthSchema = void 0;
|
|
3
|
+
exports.UnwrapEthSchema = exports.WrapEthSchema = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
exports.WrapEthSchema = zod_1.z
|
|
6
6
|
.object({
|
|
@@ -8,3 +8,9 @@ exports.WrapEthSchema = zod_1.z
|
|
|
8
8
|
})
|
|
9
9
|
.strip()
|
|
10
10
|
.describe("Instructions for wrapping ETH to WETH");
|
|
11
|
+
exports.UnwrapEthSchema = zod_1.z
|
|
12
|
+
.object({
|
|
13
|
+
amountToUnwrap: zod_1.z.string().describe("Amount of WETH to unwrap in wei"),
|
|
14
|
+
})
|
|
15
|
+
.strip()
|
|
16
|
+
.describe("Instructions for unwrapping WETH to ETH");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { ActionProvider } from "../actionProvider";
|
|
3
3
|
import { Network } from "../../network";
|
|
4
|
-
import { WrapEthSchema } from "./schemas";
|
|
4
|
+
import { WrapEthSchema, UnwrapEthSchema } from "./schemas";
|
|
5
5
|
import { EvmWalletProvider } from "../../wallet-providers";
|
|
6
6
|
/**
|
|
7
7
|
* WethActionProvider is an action provider for WETH.
|
|
@@ -19,6 +19,14 @@ export declare class WethActionProvider extends ActionProvider<EvmWalletProvider
|
|
|
19
19
|
* @returns A message containing the transaction hash.
|
|
20
20
|
*/
|
|
21
21
|
wrapEth(walletProvider: EvmWalletProvider, args: z.infer<typeof WrapEthSchema>): Promise<string>;
|
|
22
|
+
/**
|
|
23
|
+
* Unwraps WETH to ETH.
|
|
24
|
+
*
|
|
25
|
+
* @param walletProvider - The wallet provider to use for the action.
|
|
26
|
+
* @param args - The input arguments for the action.
|
|
27
|
+
* @returns A message containing the transaction hash.
|
|
28
|
+
*/
|
|
29
|
+
unwrapEth(walletProvider: EvmWalletProvider, args: z.infer<typeof UnwrapEthSchema>): Promise<string>;
|
|
22
30
|
/**
|
|
23
31
|
* Checks if the Weth action provider supports the given network.
|
|
24
32
|
*
|
|
@@ -58,6 +58,30 @@ class WethActionProvider extends actionProvider_1.ActionProvider {
|
|
|
58
58
|
return `Error wrapping ETH: ${error}`;
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Unwraps WETH to ETH.
|
|
63
|
+
*
|
|
64
|
+
* @param walletProvider - The wallet provider to use for the action.
|
|
65
|
+
* @param args - The input arguments for the action.
|
|
66
|
+
* @returns A message containing the transaction hash.
|
|
67
|
+
*/
|
|
68
|
+
async unwrapEth(walletProvider, args) {
|
|
69
|
+
try {
|
|
70
|
+
const hash = await walletProvider.sendTransaction({
|
|
71
|
+
to: constants_1.WETH_ADDRESS,
|
|
72
|
+
data: (0, viem_1.encodeFunctionData)({
|
|
73
|
+
abi: constants_1.WETH_ABI,
|
|
74
|
+
functionName: "withdraw",
|
|
75
|
+
args: [BigInt(args.amountToUnwrap)],
|
|
76
|
+
}),
|
|
77
|
+
});
|
|
78
|
+
await walletProvider.waitForTransactionReceipt(hash);
|
|
79
|
+
return `Unwrapped WETH with transaction hash: ${hash}`;
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
return `Error unwrapping WETH: ${error}`;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
61
85
|
}
|
|
62
86
|
exports.WethActionProvider = WethActionProvider;
|
|
63
87
|
__decorate([
|
|
@@ -74,7 +98,7 @@ Important notes:
|
|
|
74
98
|
- The amount is a string and cannot have any decimal points, since the unit of measurement is wei.
|
|
75
99
|
- Make sure to use the exact amount provided, and if there's any doubt, check by getting more information before continuing with the action.
|
|
76
100
|
- 1 wei = 0.000000000000000001 WETH
|
|
77
|
-
- Minimum purchase amount is
|
|
101
|
+
- Minimum purchase amount is 100000000000 wei (0.0000001 WETH)
|
|
78
102
|
- Only supported on the following networks:
|
|
79
103
|
- Base Sepolia (ie, 'base-sepolia')
|
|
80
104
|
- Base Mainnet (ie, 'base', 'base-mainnet')
|
|
@@ -85,5 +109,30 @@ Important notes:
|
|
|
85
109
|
__metadata("design:paramtypes", [wallet_providers_1.EvmWalletProvider, void 0]),
|
|
86
110
|
__metadata("design:returntype", Promise)
|
|
87
111
|
], WethActionProvider.prototype, "wrapEth", null);
|
|
112
|
+
__decorate([
|
|
113
|
+
(0, actionDecorator_1.CreateAction)({
|
|
114
|
+
name: "unwrap_eth",
|
|
115
|
+
description: `
|
|
116
|
+
This tool can only be used to unwrap WETH to ETH.
|
|
117
|
+
Do not use this tool for any other purpose, or trading other assets.
|
|
118
|
+
|
|
119
|
+
Inputs:
|
|
120
|
+
- Amount of WETH to unwrap.
|
|
121
|
+
|
|
122
|
+
Important notes:
|
|
123
|
+
- The amount is a string and cannot have any decimal points, since the unit of measurement is wei.
|
|
124
|
+
- Make sure to use the exact amount provided, and if there's any doubt, check by getting more information before continuing with the action.
|
|
125
|
+
- 1 wei = 0.000000000000000001 WETH
|
|
126
|
+
- Minimum unwrap amount is 100000000000 wei (0.0000001 WETH)
|
|
127
|
+
- Only supported on the following networks:
|
|
128
|
+
- Base Sepolia (ie, 'base-sepolia')
|
|
129
|
+
- Base Mainnet (ie, 'base', 'base-mainnet')
|
|
130
|
+
`,
|
|
131
|
+
schema: schemas_1.UnwrapEthSchema,
|
|
132
|
+
}),
|
|
133
|
+
__metadata("design:type", Function),
|
|
134
|
+
__metadata("design:paramtypes", [wallet_providers_1.EvmWalletProvider, void 0]),
|
|
135
|
+
__metadata("design:returntype", Promise)
|
|
136
|
+
], WethActionProvider.prototype, "unwrapEth", null);
|
|
88
137
|
const wethActionProvider = () => new WethActionProvider();
|
|
89
138
|
exports.wethActionProvider = wethActionProvider;
|