@coinbase/agentkit 0.8.2 → 0.9.1
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 +404 -235
- package/dist/action-providers/cdp/cdpApiActionProvider.d.ts +15 -15
- package/dist/action-providers/cdp/cdpApiActionProvider.js +110 -63
- package/dist/action-providers/cdp/cdpApiActionProvider.test.js +205 -124
- package/dist/action-providers/cdp/index.d.ts +0 -1
- package/dist/action-providers/cdp/index.js +0 -1
- package/dist/action-providers/cdp/schemas.d.ts +9 -70
- package/dist/action-providers/cdp/schemas.js +12 -61
- package/dist/action-providers/cdp-legacy/index.d.ts +3 -0
- package/dist/action-providers/cdp-legacy/index.js +19 -0
- package/dist/action-providers/cdp-legacy/legacyCdpApiActionProvider.d.ts +45 -0
- package/dist/action-providers/cdp-legacy/legacyCdpApiActionProvider.js +130 -0
- package/dist/action-providers/cdp-legacy/legacyCdpApiActionProvider.test.js +146 -0
- package/dist/action-providers/{cdp/cdpWalletActionProvider.d.ts → cdp-legacy/legacyCdpWalletActionProvider.d.ts} +8 -8
- package/dist/action-providers/{cdp/cdpWalletActionProvider.js → cdp-legacy/legacyCdpWalletActionProvider.js} +14 -14
- package/dist/action-providers/{cdp/cdpWalletActionProvider.test.js → cdp-legacy/legacyCdpWalletActionProvider.test.js} +3 -3
- package/dist/action-providers/cdp-legacy/schemas.d.ts +91 -0
- package/dist/action-providers/cdp-legacy/schemas.js +77 -0
- package/dist/action-providers/erc20/erc20ActionProvider.js +1 -1
- 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/index.d.ts +3 -1
- package/dist/action-providers/index.js +3 -1
- package/dist/action-providers/jupiter/jupiterActionProvider.test.js +2 -4
- package/dist/action-providers/truemarkets/constants.d.ts +179 -0
- package/dist/action-providers/truemarkets/constants.js +46 -0
- package/dist/action-providers/truemarkets/index.d.ts +1 -0
- package/dist/action-providers/truemarkets/index.js +17 -0
- package/dist/action-providers/truemarkets/schemas.d.ts +21 -0
- package/dist/action-providers/truemarkets/schemas.js +29 -0
- package/dist/action-providers/truemarkets/truemarketsActionProvider.d.ts +51 -0
- package/dist/action-providers/truemarkets/truemarketsActionProvider.js +469 -0
- package/dist/action-providers/truemarkets/truemarketsActionProvider.test.js +217 -0
- package/dist/action-providers/truemarkets/utils.d.ts +10 -0
- package/dist/action-providers/truemarkets/utils.js +9 -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 +58 -11
- package/dist/action-providers/x402/schemas.js +60 -8
- package/dist/action-providers/x402/x402ActionProvider.d.ts +33 -16
- package/dist/action-providers/x402/x402ActionProvider.js +203 -153
- package/dist/action-providers/x402/x402ActionProvider.test.js +78 -225
- package/dist/action-providers/zora/index.d.ts +3 -0
- package/dist/action-providers/{cdp-v2 → zora}/index.js +2 -1
- package/dist/action-providers/zora/schemas.d.ts +29 -0
- package/dist/action-providers/zora/schemas.js +31 -0
- package/dist/action-providers/zora/utils.d.ts +28 -0
- package/dist/action-providers/zora/utils.js +200 -0
- package/dist/action-providers/zora/zoraActionProvider.d.ts +36 -0
- package/dist/action-providers/zora/zoraActionProvider.js +151 -0
- package/dist/action-providers/zora/zoraActionProvider.test.js +205 -0
- package/dist/agentkit.d.ts +1 -0
- package/dist/agentkit.js +3 -2
- package/dist/wallet-providers/{cdpV2EvmWalletProvider.d.ts → cdpEvmWalletProvider.d.ts} +16 -7
- package/dist/wallet-providers/{cdpV2EvmWalletProvider.js → cdpEvmWalletProvider.js} +50 -39
- package/dist/wallet-providers/{cdpV2EvmWalletProvider.test.js → cdpEvmWalletProvider.test.js} +7 -7
- package/dist/wallet-providers/{cdpV2Shared.d.ts → cdpShared.d.ts} +15 -4
- package/dist/wallet-providers/cdpSmartWalletProvider.d.ts +115 -0
- package/dist/wallet-providers/cdpSmartWalletProvider.js +263 -0
- package/dist/wallet-providers/cdpSmartWalletProvider.test.d.ts +1 -0
- package/dist/wallet-providers/cdpSmartWalletProvider.test.js +287 -0
- package/dist/wallet-providers/{cdpV2SolanaWalletProvider.d.ts → cdpSolanaWalletProvider.d.ts} +16 -7
- package/dist/wallet-providers/{cdpV2SolanaWalletProvider.js → cdpSolanaWalletProvider.js} +43 -32
- package/dist/wallet-providers/cdpSolanaWalletProvider.test.d.ts +1 -0
- package/dist/wallet-providers/{cdpV2SolanaWalletProvider.test.js → cdpSolanaWalletProvider.test.js} +7 -7
- package/dist/wallet-providers/index.d.ts +6 -6
- package/dist/wallet-providers/index.js +6 -6
- package/dist/wallet-providers/{smartWalletProvider.d.ts → legacyCdpSmartWalletProvider.d.ts} +3 -3
- package/dist/wallet-providers/{smartWalletProvider.js → legacyCdpSmartWalletProvider.js} +21 -21
- package/dist/wallet-providers/legacyCdpSmartWalletProvider.test.d.ts +1 -0
- package/dist/wallet-providers/{smartWalletProvider.test.js → legacyCdpSmartWalletProvider.test.js} +2 -2
- package/dist/wallet-providers/{cdpWalletProvider.d.ts → legacyCdpWalletProvider.d.ts} +15 -11
- package/dist/wallet-providers/{cdpWalletProvider.js → legacyCdpWalletProvider.js} +72 -70
- package/dist/wallet-providers/legacyCdpWalletProvider.test.d.ts +1 -0
- package/dist/wallet-providers/{cdpWalletProvider.test.js → legacyCdpWalletProvider.test.js} +10 -10
- package/package.json +4 -2
- package/dist/action-providers/cdp-v2/cdpApiV2ActionProvider.d.ts +0 -34
- package/dist/action-providers/cdp-v2/cdpApiV2ActionProvider.js +0 -98
- package/dist/action-providers/cdp-v2/index.d.ts +0 -2
- package/dist/action-providers/cdp-v2/schemas.d.ts +0 -11
- package/dist/action-providers/cdp-v2/schemas.js +0 -13
- package/dist/wallet-providers/cdpV2WalletProvider.d.ts +0 -35
- package/dist/wallet-providers/cdpV2WalletProvider.js +0 -42
- /package/dist/action-providers/{cdp → cdp-legacy}/constants.d.ts +0 -0
- /package/dist/action-providers/{cdp → cdp-legacy}/constants.js +0 -0
- /package/dist/action-providers/{cdp/cdpWalletActionProvider.test.d.ts → cdp-legacy/legacyCdpApiActionProvider.test.d.ts} +0 -0
- /package/dist/{wallet-providers/cdpV2EvmWalletProvider.test.d.ts → action-providers/cdp-legacy/legacyCdpWalletActionProvider.test.d.ts} +0 -0
- /package/dist/{wallet-providers/cdpV2SolanaWalletProvider.test.d.ts → action-providers/truemarkets/truemarketsActionProvider.test.d.ts} +0 -0
- /package/dist/{wallet-providers/cdpWalletProvider.test.d.ts → action-providers/zora/zoraActionProvider.test.d.ts} +0 -0
- /package/dist/wallet-providers/{smartWalletProvider.test.d.ts → cdpEvmWalletProvider.test.d.ts} +0 -0
- /package/dist/wallet-providers/{cdpV2Shared.js → cdpShared.js} +0 -0
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const truemarketsActionProvider_1 = require("./truemarketsActionProvider");
|
|
4
|
+
const constants_1 = require("./constants");
|
|
5
|
+
const viem_1 = require("viem");
|
|
6
|
+
// Mock viem's createPublicClient
|
|
7
|
+
jest.mock("viem", () => {
|
|
8
|
+
const originalModule = jest.requireActual("viem");
|
|
9
|
+
return {
|
|
10
|
+
...originalModule,
|
|
11
|
+
createPublicClient: jest.fn().mockImplementation(() => ({
|
|
12
|
+
// Mock public client methods as needed
|
|
13
|
+
multicall: jest.fn().mockImplementation(({ contracts }) => {
|
|
14
|
+
// Create mock responses with success status
|
|
15
|
+
return contracts.map(() => ({
|
|
16
|
+
status: "success",
|
|
17
|
+
result: "mock result",
|
|
18
|
+
}));
|
|
19
|
+
}),
|
|
20
|
+
readContract: jest.fn(),
|
|
21
|
+
})),
|
|
22
|
+
http: jest.fn().mockImplementation(url => ({ url })),
|
|
23
|
+
};
|
|
24
|
+
});
|
|
25
|
+
describe("TrueMarketsActionProvider", () => {
|
|
26
|
+
let provider;
|
|
27
|
+
let mockWallet;
|
|
28
|
+
// Mock addresses and data for tests
|
|
29
|
+
const MOCK_MARKET_ADDRESS = "0x1234567890123456789012345678901234567890";
|
|
30
|
+
const MOCK_YES_POOL_ADDRESS = "0x2345678901234567890123456789012345678901";
|
|
31
|
+
const MOCK_NO_POOL_ADDRESS = "0x3456789012345678901234567890123456789012";
|
|
32
|
+
const MOCK_YES_TOKEN_ADDRESS = "0x4567890123456789012345678901234567890123";
|
|
33
|
+
const MOCK_NO_TOKEN_ADDRESS = "0x5678901234567890123456789012345678901234";
|
|
34
|
+
const MOCK_MARKET_QUESTION = "Will this test pass?";
|
|
35
|
+
const MOCK_ADDITIONAL_INFO = "Test additional info";
|
|
36
|
+
const MOCK_MARKET_SOURCE = "Test source";
|
|
37
|
+
const MOCK_STATUS_NUM = 0n; // Created status
|
|
38
|
+
const MOCK_END_OF_TRADING = 1717171717n; // Unix timestamp
|
|
39
|
+
describe("constructor", () => {
|
|
40
|
+
it("should use the provided RPC_URL for the public client", () => {
|
|
41
|
+
const customRpcUrl = "https://custom-rpc.example.com";
|
|
42
|
+
(0, truemarketsActionProvider_1.truemarketsActionProvider)({ RPC_URL: customRpcUrl });
|
|
43
|
+
// Verify createPublicClient was called with the correct URL
|
|
44
|
+
expect(viem_1.createPublicClient).toHaveBeenCalledWith(expect.objectContaining({
|
|
45
|
+
chain: expect.anything(),
|
|
46
|
+
transport: expect.objectContaining({ url: customRpcUrl }),
|
|
47
|
+
}));
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
beforeEach(() => {
|
|
51
|
+
jest.clearAllMocks();
|
|
52
|
+
provider = (0, truemarketsActionProvider_1.truemarketsActionProvider)();
|
|
53
|
+
mockWallet = {
|
|
54
|
+
readContract: jest.fn(),
|
|
55
|
+
getName: jest.fn().mockReturnValue("evm_wallet_provider"),
|
|
56
|
+
getNetwork: jest.fn().mockReturnValue({
|
|
57
|
+
networkId: "base-mainnet",
|
|
58
|
+
}),
|
|
59
|
+
};
|
|
60
|
+
});
|
|
61
|
+
afterEach(() => {
|
|
62
|
+
jest.clearAllMocks();
|
|
63
|
+
});
|
|
64
|
+
describe("getPredictionMarkets", () => {
|
|
65
|
+
it("should successfully fetch active markets", async () => {
|
|
66
|
+
// Mock readContract calls
|
|
67
|
+
mockWallet.readContract
|
|
68
|
+
// First call: numberOfActiveMarkets
|
|
69
|
+
.mockResolvedValueOnce(2n);
|
|
70
|
+
// Create a spy on the actual implementation
|
|
71
|
+
const getPredictionMarketsSpy = jest.spyOn(provider, "getPredictionMarkets");
|
|
72
|
+
// Replace the original implementation with our mocked version to return JSON string
|
|
73
|
+
getPredictionMarketsSpy.mockImplementation(async () => {
|
|
74
|
+
return JSON.stringify({
|
|
75
|
+
success: true,
|
|
76
|
+
totalMarkets: 2,
|
|
77
|
+
markets: [
|
|
78
|
+
{
|
|
79
|
+
id: 1,
|
|
80
|
+
address: MOCK_MARKET_ADDRESS,
|
|
81
|
+
marketQuestion: MOCK_MARKET_QUESTION,
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
id: 0,
|
|
85
|
+
address: "0x6789012345678901234567890123456789012345",
|
|
86
|
+
marketQuestion: "Will this other test pass?",
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
const args = {
|
|
92
|
+
limit: 10,
|
|
93
|
+
offset: 0,
|
|
94
|
+
sortOrder: "desc",
|
|
95
|
+
};
|
|
96
|
+
const responseString = await provider.getPredictionMarkets(mockWallet, args);
|
|
97
|
+
const response = JSON.parse(responseString);
|
|
98
|
+
// Verify response contains expected data
|
|
99
|
+
expect(response.success).toBe(true);
|
|
100
|
+
expect(response.totalMarkets).toBe(2);
|
|
101
|
+
expect(response.markets.length).toBe(2);
|
|
102
|
+
expect(response.markets[0].marketQuestion).toBe(MOCK_MARKET_QUESTION);
|
|
103
|
+
expect(response.markets[0].address).toBe(MOCK_MARKET_ADDRESS);
|
|
104
|
+
// Restore the original implementation
|
|
105
|
+
getPredictionMarketsSpy.mockRestore();
|
|
106
|
+
});
|
|
107
|
+
it("should handle no active markets", async () => {
|
|
108
|
+
mockWallet.readContract.mockResolvedValueOnce(0n);
|
|
109
|
+
const args = {
|
|
110
|
+
limit: 10,
|
|
111
|
+
offset: 0,
|
|
112
|
+
sortOrder: "desc",
|
|
113
|
+
};
|
|
114
|
+
const responseString = await provider.getPredictionMarkets(mockWallet, args);
|
|
115
|
+
const response = JSON.parse(responseString);
|
|
116
|
+
expect(response.success).toBe(true);
|
|
117
|
+
expect(response.totalMarkets).toBe(0);
|
|
118
|
+
expect(response.markets.length).toBe(0);
|
|
119
|
+
});
|
|
120
|
+
it("should handle errors", async () => {
|
|
121
|
+
const error = new Error("Failed to fetch active markets");
|
|
122
|
+
mockWallet.readContract.mockRejectedValueOnce(error);
|
|
123
|
+
const args = {
|
|
124
|
+
limit: 10,
|
|
125
|
+
offset: 0,
|
|
126
|
+
sortOrder: "desc",
|
|
127
|
+
};
|
|
128
|
+
const responseString = await provider.getPredictionMarkets(mockWallet, args);
|
|
129
|
+
const response = JSON.parse(responseString);
|
|
130
|
+
expect(response.success).toBe(false);
|
|
131
|
+
expect(response.error).toBe("Error retrieving active markets: Error: Failed to fetch active markets");
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
describe("getPredictionMarketDetails", () => {
|
|
135
|
+
let mockPublicClient;
|
|
136
|
+
beforeEach(() => {
|
|
137
|
+
// Access the mocked public client
|
|
138
|
+
mockPublicClient = viem_1.createPublicClient.mock.results[0].value;
|
|
139
|
+
// Setup multicall mock responses
|
|
140
|
+
mockPublicClient.multicall
|
|
141
|
+
// Basic info calls
|
|
142
|
+
.mockResolvedValueOnce([
|
|
143
|
+
{ status: "success", result: MOCK_MARKET_QUESTION },
|
|
144
|
+
{ status: "success", result: MOCK_ADDITIONAL_INFO },
|
|
145
|
+
{ status: "success", result: MOCK_MARKET_SOURCE },
|
|
146
|
+
{ status: "success", result: MOCK_STATUS_NUM },
|
|
147
|
+
{ status: "success", result: MOCK_END_OF_TRADING },
|
|
148
|
+
{ status: "success", result: [MOCK_YES_POOL_ADDRESS, MOCK_NO_POOL_ADDRESS] },
|
|
149
|
+
{ status: "success", result: 0n },
|
|
150
|
+
])
|
|
151
|
+
// Pool info calls
|
|
152
|
+
.mockResolvedValueOnce([
|
|
153
|
+
{ status: "success", result: constants_1.USDC_ADDRESS },
|
|
154
|
+
{ status: "success", result: MOCK_YES_TOKEN_ADDRESS },
|
|
155
|
+
{ status: "success", result: MOCK_NO_TOKEN_ADDRESS },
|
|
156
|
+
{ status: "success", result: constants_1.USDC_ADDRESS },
|
|
157
|
+
{ status: "success", result: [79228162514264337593543950336n, 0, 0, 0, 0, 0, true] },
|
|
158
|
+
{ status: "success", result: [79228162514264337593543950336n, 0, 0, 0, 0, 0, true] },
|
|
159
|
+
])
|
|
160
|
+
// Balance calls
|
|
161
|
+
.mockResolvedValueOnce([
|
|
162
|
+
{ status: "success", result: 1000000n },
|
|
163
|
+
{ status: "success", result: 500000000000000000000n },
|
|
164
|
+
{ status: "success", result: 2000000n },
|
|
165
|
+
{ status: "success", result: 1000000000000000000000n },
|
|
166
|
+
]);
|
|
167
|
+
});
|
|
168
|
+
it("should successfully fetch market details", async () => {
|
|
169
|
+
const args = MOCK_MARKET_ADDRESS;
|
|
170
|
+
const responseString = await provider.getPredictionMarketDetails(mockWallet, args);
|
|
171
|
+
const response = JSON.parse(responseString);
|
|
172
|
+
// Verify the expected JSON structure
|
|
173
|
+
expect(response.success).toBe(true);
|
|
174
|
+
expect(response.marketAddress).toBe(MOCK_MARKET_ADDRESS);
|
|
175
|
+
expect(response.question).toBe(MOCK_MARKET_QUESTION);
|
|
176
|
+
expect(response.additionalInfo).toBe(MOCK_ADDITIONAL_INFO);
|
|
177
|
+
expect(response.source).toBe(MOCK_MARKET_SOURCE);
|
|
178
|
+
expect(response.status).toBe(0);
|
|
179
|
+
// Verify tokens
|
|
180
|
+
expect(response.tokens.yes.lpAddress).toBe(MOCK_YES_POOL_ADDRESS);
|
|
181
|
+
expect(response.tokens.yes.tokenAddress).toBe(MOCK_YES_TOKEN_ADDRESS);
|
|
182
|
+
expect(response.tokens.no.lpAddress).toBe(MOCK_NO_POOL_ADDRESS);
|
|
183
|
+
expect(response.tokens.no.tokenAddress).toBe(MOCK_NO_TOKEN_ADDRESS);
|
|
184
|
+
// Verify prices and tvl exist
|
|
185
|
+
expect(typeof response.prices.yes).toBe("number");
|
|
186
|
+
expect(typeof response.prices.no).toBe("number");
|
|
187
|
+
expect(typeof response.tvl).toBe("number");
|
|
188
|
+
});
|
|
189
|
+
it("should handle errors", async () => {
|
|
190
|
+
const error = new Error("Failed to fetch market details");
|
|
191
|
+
mockWallet.readContract.mockReset();
|
|
192
|
+
mockPublicClient.multicall.mockReset();
|
|
193
|
+
mockPublicClient.multicall.mockRejectedValueOnce(error);
|
|
194
|
+
const args = MOCK_MARKET_ADDRESS;
|
|
195
|
+
const responseString = await provider.getPredictionMarketDetails(mockWallet, args);
|
|
196
|
+
const response = JSON.parse(responseString);
|
|
197
|
+
expect(response.success).toBe(false);
|
|
198
|
+
expect(response.error).toBe("Error retrieving market details: Error: Failed to fetch market details");
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
describe("supportsNetwork", () => {
|
|
202
|
+
it("should return true for base-mainnet", () => {
|
|
203
|
+
const network = {
|
|
204
|
+
networkId: "base-mainnet",
|
|
205
|
+
protocolFamily: "evm",
|
|
206
|
+
};
|
|
207
|
+
expect(provider.supportsNetwork(network)).toBe(true);
|
|
208
|
+
});
|
|
209
|
+
it("should return false for other networks", () => {
|
|
210
|
+
const network = {
|
|
211
|
+
networkId: "ethereum-mainnet",
|
|
212
|
+
protocolFamily: "evm",
|
|
213
|
+
};
|
|
214
|
+
expect(provider.supportsNetwork(network)).toBe(false);
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type Slot0Result = readonly [bigint, number, number, number, number, number, boolean];
|
|
2
|
+
export declare const GetMarketStatus: Record<number, string>;
|
|
3
|
+
/**
|
|
4
|
+
* Interface representing a TruthMarket
|
|
5
|
+
*/
|
|
6
|
+
export interface TruthMarket {
|
|
7
|
+
id: number;
|
|
8
|
+
address: string;
|
|
9
|
+
marketQuestion: string;
|
|
10
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GetMarketStatus = void 0;
|
|
4
|
+
const constants_1 = require("./constants");
|
|
5
|
+
// Create mapping for status lookup
|
|
6
|
+
exports.GetMarketStatus = Object.entries(constants_1.MarketStatus).reduce((acc, [key, value]) => {
|
|
7
|
+
acc[value] = key;
|
|
8
|
+
return acc;
|
|
9
|
+
}, {});
|
|
@@ -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
|
*
|