added get account groups and group members messages

This commit is contained in:
2025-08-03 07:21:31 +03:00
parent 3ae82e4781
commit 9569cffba5
5 changed files with 181 additions and 9 deletions

View File

@@ -7,6 +7,7 @@ import {
handleAddressGroupInvitesMessage,
handleGroupBansMessage,
handleGroupJoinRequestsMessage,
handleGroupMembersMessage,
handleGroupsMessage,
handleLastReference,
handleNamesMessage,
@@ -18,12 +19,14 @@ import { getRandomClient } from '../peerService';
import { MessageType } from '../protocol/messageTypes';
import {
createGetAccountBalancePayload,
createGetAccountGroupsPayload,
createGetAccountMessagePayload,
createGetAddressGroupInvitesPayload,
createGetAddressNamesPayload,
createGetBansPayload,
createGetGroupInvitesPayload,
createGetGroupJoinRequestsPayload,
createGetGroupMembersPayload,
createGetGroupPayload,
createGetGroupsPayload,
createGetLastReferencePayload,
@@ -73,7 +76,25 @@ export async function getGroups(
createGetGroupsPayload(limit, offset, reverse)
);
return handleGroupsMessage(res);
return handleGroupsMessage(res, false);
}
export async function getGroupMembers(
groupId: number,
onlyAdmins: boolean,
limit: number,
offset: number,
reverse: boolean
): Promise<any> {
const client = getRandomClient();
if (!client) throw new Error('No available peers');
const res: Buffer = await client.sendRequest(
MessageType.GET_GROUP_MEMBERS,
createGetGroupMembersPayload(groupId, onlyAdmins, limit, offset, reverse)
);
return handleGroupMembersMessage(res);
}
export async function getGroup(groupId: number): Promise<any> {
@@ -85,7 +106,7 @@ export async function getGroup(groupId: number): Promise<any> {
createGetGroupPayload(groupId)
);
const data = handleGroupsMessage(res);
const data = handleGroupsMessage(res, false);
if (Array.isArray(data) && data.length > 0) {
return data[0];
@@ -120,6 +141,18 @@ export async function getAddressGroupInvites(address: string): Promise<any> {
return handleAddressGroupInvitesMessage(res);
}
export async function getAccountGroups(address: string): Promise<any> {
const client = getRandomClient();
if (!client) throw new Error('No available peers');
const res: Buffer = await client.sendRequest(
MessageType.GET_ACCOUNT_GROUPS,
createGetAccountGroupsPayload(address)
);
return handleGroupsMessage(res, true);
}
export async function getGroupInvites(groupId: number): Promise<any> {
const client = getRandomClient();
if (!client) throw new Error('No available peers');

View File

@@ -4,11 +4,13 @@ import { WebSocketServer } from 'ws';
import {
getAccount,
getAccountBalance,
getAccountGroups,
getAddressGroupInvites,
getBans,
getGroup,
getGroupInvites,
getGroupJoinRequests,
getGroupMembers,
getGroups,
getLastReference,
getNameInfo,
@@ -83,9 +85,9 @@ export async function createHttpServer() {
app.get('/groups', async (req, res) => {
try {
const limit = req.query.limit || 100;
const offset = req.query.offset || 0;
const reverse = req.query.reverse || false;
const limit = req.query.limit ?? 100;
const offset = req.query.offset ?? 0;
const reverse = req.query.reverse ?? false;
const groups = await getGroups(limit, offset, reverse);
res.json(groups);
@@ -135,6 +137,36 @@ export async function createHttpServer() {
}
});
app.get('/groups/member/:address', async (req, res) => {
const address = req.params.address;
try {
const groups = await getAccountGroups(address);
res.json(groups);
} catch (err: any) {
res.status(500).type('text').send(`Error: ${err.message}`);
}
});
app.get('/groups/members/:groupId', async (req, res) => {
const groupId = req.params.groupId;
const onlyAdmins = req.query.onlyAdmins ?? false;
const limit = req.query.limit ?? 100;
const offset = req.query.offset ?? 0;
const reverse = req.query.reverse ?? false;
try {
const members = await getGroupMembers(
groupId,
onlyAdmins,
limit,
offset,
reverse
);
res.json(members);
} catch (err: any) {
res.status(500).type('text').send(`Error: ${err.message}`);
}
});
app.get('/groups/joinrequests/:groupId', async (req, res) => {
const groupId = req.params.groupId;
try {

View File

@@ -347,7 +347,7 @@ export function handleUnitFee(payload: Buffer): bigint {
return unitFee;
}
export function handleGroupsMessage(buffer) {
export function handleGroupsMessage(buffer, includeAdmin) {
let offset = 0;
const { value: count, size: countSize } = readInt(buffer, offset);
@@ -423,14 +423,14 @@ export function handleGroupsMessage(buffer) {
const { value: isAdminFlag, size: s12 } = readInt(buffer, offset);
offset += s12;
let isAdmin = null;
let isAdmin = false;
if (isAdminFlag === 1) isAdmin = false;
if (isAdminFlag === 2) isAdmin = true;
const { value: memberCount, size: s13 } = readInt(buffer, offset);
offset += s13;
groups.push({
const groupData: any = {
groupId,
owner,
groupName,
@@ -442,7 +442,13 @@ export function handleGroupsMessage(buffer) {
minimumBlockDelay,
maximumBlockDelay,
memberCount,
});
};
if (includeAdmin) {
groupData.isAdmin = isAdmin;
}
groups.push(groupData);
}
return groups;
@@ -574,3 +580,59 @@ export function handleGroupJoinRequestsMessage(buffer) {
return joinRequests;
}
export function handleGroupMembersMessage(buffer) {
let offset = 0;
// Read memberCount
const { value: memberCount, size: s1 } = readInt(buffer, offset);
offset += s1;
// Read adminCount
const { value: adminCount, size: s2 } = readInt(buffer, offset);
offset += s2;
// Read members count
const { value: membersCount, size: s3 } = readInt(buffer, offset);
offset += s3;
const members = [];
for (let i = 0; i < membersCount; i++) {
// member (25 bytes base58 address)
const memberBytes = buffer.subarray(offset, offset + 25);
const member = bs58.encode(memberBytes);
offset += 25;
// joined (nullable long)
const { value: hasJoined, size: s4 } = readInt(buffer, offset);
offset += s4;
let joined = null;
if (hasJoined === 1) {
const { value: joinedValue, size: s5 } = readLong(buffer, offset);
joined = joinedValue;
offset += s5;
}
// isAdmin (nullable flag: 0 = null, 1 = false, 2 = true)
const { value: isAdminFlag, size: s6 } = readInt(buffer, offset);
offset += s6;
let isAdmin = false;
if (isAdminFlag === 1) isAdmin = false;
if (isAdminFlag === 2) isAdmin = true;
members.push({
member,
joined,
isAdmin,
});
}
return {
memberCount,
adminCount,
members,
};
}

View File

@@ -36,4 +36,7 @@ export enum MessageType {
GET_GROUP_INVITES = 317,
GROUP_JOIN_REQUESTS = 318,
GET_GROUP_JOIN_REQUESTS = 319,
GET_ACCOUNT_GROUPS = 320,
GROUP_MEMBERS = 321,
GET_GROUP_MEMBERS = 322,
}

View File

@@ -66,6 +66,17 @@ export function createGetAddressGroupInvitesPayload(address: string): Buffer {
return Buffer.from(addressBytes); // ✅ Just raw payload
}
export function createGetAccountGroupsPayload(address: string): Buffer {
const addressBytes = bs58.decode(address);
if (addressBytes.length !== ADDRESS_LENGTH) {
throw new Error(
`Invalid address length. Expected ${ADDRESS_LENGTH}, got ${addressBytes.length}`
);
}
return Buffer.from(addressBytes); // ✅ Just raw payload
}
export function createProcessTransactionMessagePayload(
signedBytes: string
): Buffer {
@@ -135,6 +146,37 @@ export function createGetGroupsPayload(
return Buffer.concat([limitBuffer, offsetBuffer, reverseBuffer]);
}
export function createGetGroupMembersPayload(
groupId: number,
onlyAdmins: boolean,
limit: number,
offset: number,
reverse: boolean
): Buffer {
const groupIdBuffer = Buffer.alloc(4);
groupIdBuffer.writeInt32BE(groupId);
const onlyAdminsBuffer = Buffer.alloc(4);
onlyAdminsBuffer.writeInt32BE(onlyAdmins ? 1 : 0);
const limitBuffer = Buffer.alloc(4);
limitBuffer.writeInt32BE(limit);
const offsetBuffer = Buffer.alloc(4);
offsetBuffer.writeInt32BE(offset);
const reverseBuffer = Buffer.alloc(4);
reverseBuffer.writeInt32BE(reverse ? 1 : 0);
return Buffer.concat([
groupIdBuffer,
onlyAdminsBuffer,
limitBuffer,
offsetBuffer,
reverseBuffer,
]);
}
export function createGetGroupPayload(groupId: number): Buffer {
const groupIdBuffer = Buffer.alloc(4);
groupIdBuffer.writeInt32BE(groupId);