diff --git a/.changeset/unlucky-chairs-protect.md b/.changeset/unlucky-chairs-protect.md new file mode 100644 index 0000000..b5b75a5 --- /dev/null +++ b/.changeset/unlucky-chairs-protect.md @@ -0,0 +1,5 @@ +--- +"@xmtp/agent-starter": patch +--- + +New tests. Cleaner types. diff --git a/README.md b/README.md index 2a6cd76..1bee76c 100644 --- a/README.md +++ b/README.md @@ -225,10 +225,3 @@ yarn build # or run a specific example yarn examples gm ``` - -Use a `.env` file for your environment variables: - -```bash -WALLET_KEY= # the private key of the wallet -ENCRYPTION_KEY= # a second fixed or random 32 bytes encryption key for the local db -``` diff --git a/packages/agent-starter/src/lib/types.ts b/packages/agent-starter/src/lib/types.ts index 1001767..9d71a7b 100644 --- a/packages/agent-starter/src/lib/types.ts +++ b/packages/agent-starter/src/lib/types.ts @@ -31,24 +31,26 @@ export interface UserReturnType { wallet: ReturnType; } -export type xmtpConfig = { - path?: string; - hideInitLogMessage?: boolean; -} & ClientOptions; - export type Agent = { name?: string; walletKey?: string; encryptionKey?: string; onMessage?: (message: Message) => Promise; - config?: xmtpConfig; + config?: ClientOptions; }; export type Conversation = { id: string; createdAt: Date; topic?: string; - members?: User[]; + members?: { + address: string; + inboxId: string; + installationIds: string[]; + accountAddresses: string[]; + username?: string; + ensDomain?: string; + }[]; admins?: string[]; name?: string; superAdmins?: string[]; @@ -57,7 +59,6 @@ export type Conversation = { export type Message = { id: string; // Unique identifier for the message sent: Date; // Date when the message was sent - isDM: boolean; // Whether the message is a direct message content: { text?: string | undefined; // Text content of the message reply?: string | undefined; // Reply content if the message is a reply @@ -67,19 +68,17 @@ export type Message = { reference?: string | undefined; // Reference ID for the message }; group?: Conversation; // Group the message belongs to - sender: User; // Sender of the message + sender: { + address: string; + inboxId: string; + installationIds: string[]; + accountAddresses: string[]; + username?: string; + ensDomain?: string; + }; // Sender of the message typeId: string; // Type identifier for the message client: { address: string; inboxId: string; }; }; - -export interface User { - address: string; - inboxId: string; - installationIds: string[]; - accountAddresses: string[]; - username?: string; - ensDomain?: string; -} diff --git a/packages/agent-starter/src/lib/xmtp.ts b/packages/agent-starter/src/lib/xmtp.ts index 5c8e184..16cf39a 100644 --- a/packages/agent-starter/src/lib/xmtp.ts +++ b/packages/agent-starter/src/lib/xmtp.ts @@ -37,13 +37,7 @@ import { AgentMessageCodec, ContentTypeAgentMessage, } from "../content-types/agent-message.js"; -import type { - Agent, - clientMessage, - Message, - User, - UserReturnType, -} from "./types.js"; +import type { Agent, clientMessage, Message, UserReturnType } from "./types.js"; dotenv.config(); @@ -92,7 +86,7 @@ export class XMTP { const volumePath = process.env.RAILWAY_VOLUME_MOUNT_PATH ?? - this.agent?.config?.path ?? + this.agent?.config?.dbPath ?? ".data/xmtp"; if (!fs.existsSync(volumePath)) { @@ -484,6 +478,7 @@ async function streamMessages( ) { continue; } + const parsedMessage = await parseMessage( message, conversation, @@ -587,7 +582,16 @@ export async function parseMessage( }; } const date = message.sentAt; - let sender: User | undefined = undefined; + let sender: + | { + inboxId: string; + address: string; + accountAddresses: string[]; + installationIds: string[]; + username?: string; + ensDomain?: string; + } + | undefined = undefined; await conversation?.sync(); const members = await conversation?.members(); @@ -596,14 +600,26 @@ export async function parseMessage( address: member.accountAddresses[0], accountAddresses: member.accountAddresses, installationIds: member.installationIds, - })) as User[]; + })) as { + inboxId: string; + address: string; + accountAddresses: string[]; + installationIds: string[]; + }[]; sender = membersArray.find( - (member: User) => member.inboxId === message.senderInboxId, + (member: { inboxId: string }) => member.inboxId === message.senderInboxId, ); return { id: message.id, - sender, + sender: { + inboxId: sender?.inboxId || "", + address: sender?.address || "", + accountAddresses: sender?.accountAddresses || [], + installationIds: sender?.installationIds || [], + username: sender?.username || "", + ensDomain: sender?.ensDomain || "", + }, group: { id: conversation?.id, createdAt: conversation?.createdAt, diff --git a/packages/agent-starter/tests/Client.test.ts b/packages/agent-starter/tests/Client.test.ts index a9223ac..40c5d5c 100644 --- a/packages/agent-starter/tests/Client.test.ts +++ b/packages/agent-starter/tests/Client.test.ts @@ -1,6 +1,6 @@ -import { createUser, XMTP, xmtpClient } from "@xmtp/agent-starter"; import { generatePrivateKey } from "viem/accounts"; import { describe, expect, test } from "vitest"; +import { createUser, XMTP, xmtpClient } from "../src/lib/xmtp"; describe("Client Private Key Configuration Tests", () => { test("creates a client with a random generated key", async () => { @@ -29,7 +29,7 @@ describe("Client Private Key Configuration Tests", () => { }, 15000); // Added 15 second timeout test("Creates a key with a agent name", async () => { - const agentName = "bob1"; + const agentName = "bob3"; const xmtp = await xmtpClient({ name: agentName, }); diff --git a/packages/agent-starter/tests/Message.test.ts b/packages/agent-starter/tests/Message.test.ts new file mode 100644 index 0000000..9f624e6 --- /dev/null +++ b/packages/agent-starter/tests/Message.test.ts @@ -0,0 +1,45 @@ +import { describe, expect, test } from "vitest"; +import type { Message } from "../src/lib/types"; +import { xmtpClient } from "../src/lib/xmtp"; + +describe("Client Private Key Configuration Tests", async () => { + const xmtp = await xmtpClient({ + name: "bob2", + onMessage: async (message: Message) => { + await new Promise((resolve) => setTimeout(resolve, 1000)); + expect(message.content.text).toBe("Hello, Alice!"); + expect(message.sender.address).toBe(xmtp2.address); + }, + }); + console.log("Bob's client initialized"); + + const xmtp2 = await xmtpClient({ + name: "alice2", + onMessage: async (message: Message) => { + console.log( + "Alice received message:", + message.content.text, + "from", + message.sender.address, + ); + await new Promise((resolve) => setTimeout(resolve, 1000)); + expect(message.content.text).toBe("Hello, Bob!"); + expect(message.sender.address).toBe(xmtp.address); + }, + }); + + test("Send a message to a client", async () => { + const message = await xmtp.send({ + message: "Hello, Alice!", + receivers: [xmtp2.address as string], + metadata: {}, + }); + const message2 = await xmtp2.send({ + message: "Hello, Bob!", + receivers: [xmtp.address as string], + metadata: {}, + }); + expect(message).toBeDefined(); + expect(message2).toBeDefined(); + }, 25000); +});