Skip to content

Commit

Permalink
feat: add GraphQL response processing and tests
Browse files Browse the repository at this point in the history
- Add processCompactDetails function to extract and sum deltas
- Add tests using example data from architecture document
- Handle missing allocatorId, withdrawal status, and balance
- Fix TypeScript types and linting issues
  • Loading branch information
0age committed Dec 4, 2024
1 parent 28c0586 commit 131bf5e
Show file tree
Hide file tree
Showing 2 changed files with 178 additions and 0 deletions.
138 changes: 138 additions & 0 deletions src/__tests__/graphql.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import {
graphqlClient,
getCompactDetails,
processCompactDetails,
} from '../graphql';
import type {
AllocatorResponse,
AccountDeltasResponse,
AccountResponse,
} from '../graphql';

describe('GraphQL Functions', () => {
// Store original request method
const originalRequest = graphqlClient.request;

beforeEach(() => {
// Replace request method with a spy
(graphqlClient as { request: unknown }).request = async (
_query: string,
_variables: unknown
): Promise<AllocatorResponse & AccountDeltasResponse & AccountResponse> => {
return Promise.resolve(mockResponse);
};
});

afterEach(() => {
// Restore original request method
(graphqlClient as { request: unknown }).request = originalRequest;
});

const mockVariables = {
allocator: '0x0734d56da60852a03e2aafae8a36ffd8c12b32f1',
sponsor: '0x899ee89dbe7e74dae12e20cc255cec0d59b5d4fc',
lockId:
'21792518056623590435587568419860581671612179420134533156813620419438053425152',
chainId: '10',
};

const mockResponse = {
allocator: {
supportedChains: {
items: [
{
allocatorId: '55765469257802026776384764',
},
],
},
},
accountDeltas: {
items: [
{
delta: '700000000000',
},
{
delta: '400000000000',
},
],
},
account: {
resourceLocks: {
items: [
{
withdrawalStatus: 0,
balance: '8000000000000',
},
],
},
claims: {
items: [
{
claimHash:
'0x2fcfd671637371ee10057d03662323b457ebd6eb38c09231cc7dd6c65ac50761',
},
{
claimHash:
'0xfa156004548126208463b1212a2bacb2a10357d211b15ea9419a41acfbabf4b7',
},
],
},
},
};

it('should fetch and process compact details correctly', async () => {
// Fetch and process the data
const response = await getCompactDetails(mockVariables);
const processed = processCompactDetails(response);

// Verify the processed data
expect(processed.allocatorId).toBe('55765469257802026776384764');
expect(processed.totalDelta.toString()).toBe('1100000000000'); // 700000000000 + 400000000000
expect(processed.withdrawalStatus).toBe(0);
expect(processed.balance).toBe('8000000000000');
expect(processed.claimHashes).toEqual([
'0x2fcfd671637371ee10057d03662323b457ebd6eb38c09231cc7dd6c65ac50761',
'0xfa156004548126208463b1212a2bacb2a10357d211b15ea9419a41acfbabf4b7',
]);
});

it('should handle missing data gracefully', async () => {
const emptyResponse = {
allocator: {
supportedChains: {
items: [],
},
},
accountDeltas: {
items: [],
},
account: {
resourceLocks: {
items: [],
},
claims: {
items: [],
},
},
};

// Override mock response for this test
(graphqlClient as { request: unknown }).request = async (
_query: string,
_variables: unknown
): Promise<AllocatorResponse & AccountDeltasResponse & AccountResponse> => {
return Promise.resolve(emptyResponse);
};

// Fetch and process the data
const response = await getCompactDetails(mockVariables);
const processed = processCompactDetails(response);

// Verify the processed data handles missing values
expect(processed.allocatorId).toBeNull();
expect(processed.totalDelta.toString()).toBe('0');
expect(processed.withdrawalStatus).toBeNull();
expect(processed.balance).toBeNull();
expect(processed.claimHashes).toEqual([]);
});
});
40 changes: 40 additions & 0 deletions src/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,43 @@ export async function getCompactDetails(
throw error;
}
}

export interface ProcessedCompactDetails {
totalDelta: bigint;
allocatorId: string | null;
withdrawalStatus: number | null;
balance: string | null;
claimHashes: string[];
}

export function processCompactDetails(
response: AllocatorResponse & AccountDeltasResponse & AccountResponse
): ProcessedCompactDetails {
// Extract allocatorId (may not be present if no supported chains found)
const allocatorId =
response.allocator.supportedChains.items[0]?.allocatorId ?? null;

// Sum up all deltas
const totalDelta = response.accountDeltas.items.reduce(
(sum, item) => sum + BigInt(item.delta),
BigInt(0)
);

// Extract withdrawal status and balance (may not be present if no resource locks found)
const resourceLock = response.account.resourceLocks.items[0];
const withdrawalStatus = resourceLock?.withdrawalStatus ?? null;
const balance = resourceLock?.balance ?? null;

// Extract all claim hashes
const claimHashes = response.account.claims.items.map(
(item) => item.claimHash
);

return {
totalDelta,
allocatorId,
withdrawalStatus,
balance,
claimHashes,
};
}

0 comments on commit 131bf5e

Please sign in to comment.