Skip to content

Commit ff69765

Browse files
committed
push
1 parent 3ca3e04 commit ff69765

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+3053
-690
lines changed

README.md

+6-12
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@ To run your XMTP agent, you must create a `.env` file with the following variabl
2121
```tsx
2222
WALLET_KEY= # the private key of the wallet
2323
ENCRYPTION_KEY= # encryption key for the local database
24+
XMTP_ENV= # local, dev, production
2425
```
2526

26-
You can generate random keys with the following command:
27+
You can generate random xmtp keys with the following command:
2728

2829
```tsx
2930
yarn gen:keys <name>
@@ -125,18 +126,11 @@ Interact with the XMTP network using [xmtp.chat](https://xmtp.chat), the officia
125126

126127
## Examples
127128

128-
- [gm](/examples/gm/): A simple agent that replies to all text messages with "gm".
129+
- [gm](/gm/): A simple agent that replies to all text messages with "gm".
129130
- [gpt](/examples/gpt/): An example using GPT API's to answer messages.
130131
- [gated-group](/examples/gated-group/): Add members to a group that hold a certain NFT.
132+
- [grok](/examples/grok/): Integrate your agent with the Grok API
133+
- [gaia](/examples/gaia/): Integrate with the Gaia API
134+
- [coinbase-langchain](/examples/coinbase-langchain/): Agent that uses a CDP for gassless USDC on base
131135

132136
> See all the available [examples](/examples/).
133-
134-
### Integrations
135-
136-
Examples integrating XMTP with external libraries from the ecosystem
137-
138-
- [grok](/integrations/grok/): Integrate your agent with the Grok API
139-
- [gaia](/integrations/gaia/): Integrate with the Gaia API
140-
- [coinbase-langchain](/integrations/coinbase-langchain/): Agent that uses a CDP for gassless USDC on base
141-
142-
> See all the available [integrations](/integrations/).

integrations/README.md examples/README.md

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# How to contribute an XMTP integration
1+
# How to contribute an XMTP example
22

3-
This guide explains how to help develop or improve an integration using the XMTP protocol.
3+
This guide explains how to help develop or improve an example using the XMTP protocol.
44

55
## Prerequisites
66

@@ -28,15 +28,15 @@ This guide explains how to help develop or improve an integration using the XMTP
2828
Make a new branch for your changes.
2929

3030
```bash
31-
git checkout -b integration/your-integration-name
31+
git checkout -b example/your-example-name
3232
```
3333

3434
4. **Install dependencies**
3535

36-
Go to the integration directory and install packages.
36+
Go to the example directory and install packages.
3737

3838
```bash
39-
cd integrations/your-integration
39+
cd examples/your-example
4040
yarn
4141
```
4242

@@ -46,7 +46,7 @@ This guide explains how to help develop or improve an integration using the XMTP
4646

4747
6. **Test changes**
4848

49-
Run the integration to check your changes.
49+
Run the example to check your changes.
5050

5151
```bash
5252
yarn dev
@@ -58,15 +58,15 @@ This guide explains how to help develop or improve an integration using the XMTP
5858

5959
```bash
6060
git add .
61-
git commit -m "Add integration: description of your integration"
61+
git commit -m "Add example: description of your example"
6262
```
6363

6464
8. **Push changes**
6565

6666
Send your changes to your forked repository.
6767

6868
```bash
69-
git push origin integration/your-integration-name
69+
git push origin example/your-example-name
7070
```
7171

7272
## Submit a Pull Request

integrations/coinbase-langchain/README.md examples/coinbase-langchain/README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ A DeFi agent built using Langchain and powered by CDP SDK, operating over the XM
77
- Process blockchain payments using natural language commands
88
- Advanced language processing using LangChain and OpenAI
99
- User-specific wallet management with flexible storage options (Redis or local file)
10-
- XMTP messaging integration for secure, decentralized chat interactions
10+
- XMTP messaging for secure, decentralized chat interactions
1111
- Powered by CDP SDK for reliable blockchain operations and Langchain for AI Agent
1212

1313
## Prerequisites
@@ -26,7 +26,7 @@ Follow these steps to get your x agent up and running:
2626

2727
```bash
2828
git clone https://github.com/ephemeraHQ/xmtp-agent-examples.git
29-
cd integrations/coinbase-langchain
29+
cd examples/coinbase-langchain
3030
```
3131

3232
2. **Install dependencies**:
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"name": "coinbase-langchain",
3+
"version": "0.0.1",
4+
"private": true,
5+
"type": "module",
6+
"scripts": {
7+
"build": "tsc",
8+
"dev": "tsx src/index.ts",
9+
"gen:keys": "tsx ../../scripts/generateKeys.ts",
10+
"lint": "cd ../.. && yarn eslint examples/coinbase-langchain"
11+
},
12+
"dependencies": {
13+
"@coinbase/agentkit": "^0.2.0",
14+
"@coinbase/agentkit-langchain": "^0.2.0",
15+
"@langchain/core": "^0.3.20",
16+
"@langchain/langgraph": "^0.2.24",
17+
"@langchain/openai": "^0.3.14",
18+
"@redis/client": "^1.6.0",
19+
"@xmtp/node-sdk": "1.0.0",
20+
"redis": "^4.7.0"
21+
},
22+
"devDependencies": {
23+
"tsx": "^4.19.2",
24+
"typescript": "^5.7.3"
25+
}
26+
}

integrations/coinbase-langchain/src/cdp.ts examples/coinbase-langchain/src/cdp.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
} from "@coinbase/coinbase-sdk";
88
import { isAddress } from "viem";
99
import { getWalletData, saveWalletData } from "./storage";
10+
import type { XMTPUser } from "./types";
1011

1112
const coinbaseApiKeyName = process.env.CDP_API_KEY_NAME;
1213
let coinbaseApiKeyPrivateKey = process.env.CDP_API_KEY_PRIVATE_KEY;
@@ -92,11 +93,11 @@ export class WalletService {
9293
private inboxId: string;
9394
private sdkInitialized: boolean;
9495

95-
constructor(inboxId: string, address: string) {
96+
constructor(xmtpUser: XMTPUser) {
9697
this.sdkInitialized = initializeCoinbaseSDK();
9798
this.walletStorage = new WalletStorage();
98-
this.humanAddress = address;
99-
this.inboxId = inboxId;
99+
this.humanAddress = xmtpUser.address;
100+
this.inboxId = xmtpUser.inboxId;
100101
console.log(
101102
"WalletService initialized with sender address",
102103
this.humanAddress,

integrations/coinbase-langchain/src/index.ts examples/coinbase-langchain/src/index.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import type { Conversation, DecodedMessage } from "@xmtp/node-sdk";
21
import "dotenv/config";
2+
import type { Conversation, DecodedMessage } from "@xmtp/node-sdk";
33
import { getAddressOfMember } from "@/helpers";
44
import { initializeAgent, processMessage } from "./langchain";
55
import { initializeStorage as initStorage } from "./storage";
6+
import type { XMTPUser } from "./types";
67
import { initializeXmtpClient, startMessageListener } from "./xmtp";
78

89
/**
@@ -51,8 +52,12 @@ async function handleMessage(
5152
console.log("Unable to find address, skipping");
5253
return;
5354
}
55+
const xmtpUser: XMTPUser = {
56+
inboxId,
57+
address,
58+
};
5459
// Initialize or get the agent for this user
55-
const { agent, config } = await initializeAgent(inboxId, address);
60+
const { agent, config } = await initializeAgent(xmtpUser);
5661

5762
// Process the message with the agent
5863
const response = await processMessage(

integrations/coinbase-langchain/src/langchain.ts examples/coinbase-langchain/src/langchain.ts

+35-55
Original file line numberDiff line numberDiff line change
@@ -5,40 +5,19 @@ import { createReactAgent } from "@langchain/langgraph/prebuilt";
55
import { ChatOpenAI } from "@langchain/openai";
66
import { z } from "zod";
77
import { WalletService } from "./cdp";
8-
9-
const memoryStore: Record<string, MemorySaver> = {};
10-
const agentStore: Record<string, Agent> = {};
11-
12-
interface AgentConfig {
13-
configurable: {
14-
thread_id: string;
15-
};
16-
}
17-
18-
type Agent = ReturnType<typeof createReactAgent>;
19-
20-
// Define transfer result structure
21-
interface TransferData {
22-
model?: {
23-
sponsored_send?: {
24-
transaction_link?: string;
25-
};
26-
};
27-
transactionLink?: string;
28-
}
29-
30-
// Define chunk structure for agent stream
31-
interface AgentChunk {
32-
agent?: {
33-
messages?: Array<{
34-
content?: string;
35-
}>;
36-
};
37-
}
38-
39-
function createWalletTools(inboxId: string, address: string) {
8+
import {
9+
agentStore,
10+
memoryStore,
11+
type Agent,
12+
type AgentChunk,
13+
type AgentConfig,
14+
type TransferData,
15+
type XMTPUser,
16+
} from "./types";
17+
18+
function createWalletTools(xmtpUser: XMTPUser) {
4019
// Create a properly typed WalletService instance
41-
const walletService = new WalletService(inboxId, address);
20+
const walletService = new WalletService(xmtpUser);
4221

4322
const getBalanceTool = new DynamicStructuredTool({
4423
name: "get_wallet_balance",
@@ -47,10 +26,10 @@ function createWalletTools(inboxId: string, address: string) {
4726
schema: z.object({}),
4827
func: async () => {
4928
try {
50-
console.log(`Checking balance for fixed inboxId: ${inboxId}`);
51-
const result = await walletService.checkBalance(inboxId);
29+
console.log(`Checking balance for fixed inboxId: ${xmtpUser.inboxId}`);
30+
const result = await walletService.checkBalance(xmtpUser.inboxId);
5231
if (!result.address) {
53-
return `No wallet found for user ${inboxId}`;
32+
return `No wallet found for user ${xmtpUser.inboxId}`;
5433
}
5534
return `Wallet address: ${result.address}\nUSDC Balance: ${result.balance} USDC`;
5635
} catch (error: unknown) {
@@ -75,11 +54,13 @@ function createWalletTools(inboxId: string, address: string) {
7554
return `Error: Invalid amount ${amount}`;
7655
}
7756

78-
console.log(`Transferring from ${address} to: ${recipientAddress}`);
57+
console.log(
58+
`Transferring from ${xmtpUser.address} to: ${recipientAddress}`,
59+
);
7960

8061
const result = await walletService.transfer(
81-
inboxId,
82-
address,
62+
xmtpUser.inboxId,
63+
xmtpUser.address,
8364
recipientAddress,
8465
numericAmount,
8566
);
@@ -111,50 +92,49 @@ function createWalletTools(inboxId: string, address: string) {
11192

11293
/**
11394
* Initialize the agent with LangChain and Coinbase SDK
114-
* @param userId - The user's identifier (XMTP address)
95+
* @param inboxId - The user's identifier (XMTP address)
11596
* @returns Agent executor and config
11697
*/
11798
export async function initializeAgent(
118-
inboxId: string,
119-
address: string,
99+
xmtpUser: XMTPUser,
120100
): Promise<{ agent: Agent; config: AgentConfig }> {
121101
try {
122102
// Check if we already have an agent for this user
123-
if (inboxId in agentStore) {
124-
console.log(`Using existing agent for user: ${inboxId}`);
103+
if (xmtpUser.inboxId in agentStore) {
104+
console.log(`Using existing agent for user: ${xmtpUser.inboxId}`);
125105
const agentConfig = {
126-
configurable: { thread_id: inboxId },
106+
configurable: { thread_id: xmtpUser.inboxId },
127107
};
128-
return { agent: agentStore[inboxId], config: agentConfig };
108+
return { agent: agentStore[xmtpUser.inboxId], config: agentConfig };
129109
}
130110

131111
console.log(
132-
`Creating new agent for user with inboxId: ${inboxId} and address: ${address}`,
112+
`Creating new agent for user with inboxId: ${xmtpUser.inboxId} and address: ${xmtpUser.address}`,
133113
);
134114

135115
const llm = new ChatOpenAI({
136116
model: "gpt-4o-mini",
137117
});
138118

139-
const tools = createWalletTools(inboxId, address);
119+
const tools = createWalletTools(xmtpUser);
140120

141-
if (!(inboxId in memoryStore)) {
142-
console.log(`Creating new memory store for user: ${inboxId}`);
143-
memoryStore[inboxId] = new MemorySaver();
121+
if (!(xmtpUser.inboxId in memoryStore)) {
122+
console.log(`Creating new memory store for user: ${xmtpUser.inboxId}`);
123+
memoryStore[xmtpUser.inboxId] = new MemorySaver();
144124
} else {
145-
console.log(`Using existing memory store for user: ${inboxId}`);
125+
console.log(`Using existing memory store for user: ${xmtpUser.inboxId}`);
146126
}
147127

148128
const agentConfig: AgentConfig = {
149-
configurable: { thread_id: inboxId },
129+
configurable: { thread_id: xmtpUser.inboxId },
150130
};
151131

152132
// Make sure we await the agent creation
153133
const agent = await Promise.resolve(
154134
createReactAgent({
155135
llm,
156136
tools,
157-
checkpointSaver: memoryStore[inboxId],
137+
checkpointSaver: memoryStore[xmtpUser.inboxId],
158138
messageModifier: `
159139
You are a DeFi Agent that assists users with sending payments to any wallet address using natural language instructions.
160140
@@ -180,7 +160,7 @@ export async function initializeAgent(
180160
);
181161

182162
// Store the agent for future use
183-
agentStore[inboxId] = agent;
163+
agentStore[xmtpUser.inboxId] = agent;
184164

185165
return { agent, config: agentConfig };
186166
} catch (error: unknown) {
+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import type { MemorySaver } from "@langchain/langgraph";
2+
import type { createReactAgent } from "@langchain/langgraph/prebuilt";
3+
4+
export const memoryStore: Record<string, MemorySaver> = {};
5+
export const agentStore: Record<string, Agent> = {};
6+
7+
export type XMTPUser = {
8+
inboxId: string;
9+
address: string;
10+
};
11+
export interface AgentConfig {
12+
configurable: {
13+
thread_id: string;
14+
};
15+
}
16+
17+
export type Agent = ReturnType<typeof createReactAgent>;
18+
19+
// Define transfer result structure
20+
export interface TransferData {
21+
model?: {
22+
sponsored_send?: {
23+
transaction_link?: string;
24+
};
25+
};
26+
transactionLink?: string;
27+
}
28+
29+
// Define chunk structure for agent stream
30+
export interface AgentChunk {
31+
agent?: {
32+
messages?: Array<{
33+
content?: string;
34+
}>;
35+
};
36+
}

integrations/coinbase-langchain/src/xmtp.ts examples/coinbase-langchain/src/xmtp.ts

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { IdentifierKind } from "@xmtp/node-bindings";
21
import {
32
Client,
43
type Conversation,

0 commit comments

Comments
 (0)