Stream group updates with XMTP
Stream group metadata changes (name, description, members) in real-time using the group_updated
native content type.
Stream group updates
on('group-update', async (ctx) => {
console.log('Group updated:', ctx.message.content);
});
Conversation type will show as group_updated
.
const type = ctx.message.contentType;
Group update message structure
{
conversationId: string,
contentType: { typeId: "group_updated" },
content: {
metadataFieldChanges?: Array<{
fieldName: string, // "group_name", "group_description", etc.
oldValue: string,
newValue: string
}>,
addedInboxes?: Array<{ // New members added
inboxId: string
}>,
initiatedByInboxId?: string // Who triggered the update
}
}
Usage examples
Monitor group name changes
on('group-update', async (ctx) => {
const content = ctx.message.content as any;
const nameChange = content.metadataFieldChanges?.find(
(change) => change.fieldName === 'group_name'
);
if (nameChange) {
console.log(
`Group renamed: ${nameChange.oldValue} → ${nameChange.newValue}`
);
}
});
Monitor member additions
on('group-update', async (ctx) => {
const content = ctx.message.content as any;
if (content.addedInboxes?.length > 0) {
console.log(`New members added:`, content.addedInboxes);
}
});
Monitor member removals
on('group-update', async (ctx) => {
const content = ctx.message.content as any;
if (content.removedInboxes?.length > 0) {
console.log(`Members removed:`, content.removedInboxes);
}
});
Filter by specific group
const targetGroupId = 'your-group-conversation-id';
on('group-update', async (ctx) => {
if (ctx.message.conversationId === targetGroupId) {
console.log('Target group updated:', ctx.message.content);
}
});