Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/src/controllers/stream.controller.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Request, Response } from 'express';

Check failure on line 1 in backend/src/controllers/stream.controller.ts

View workflow job for this annotation

GitHub Actions / Backend npm test

tests/integration/streams.test.ts

Error: [vitest] There was an error when mocking a module. If you are using "vi.mock" factory, make sure there are no top level variables inside, since this call is hoisted to top of the file. Read more: https://vitest.dev/api/vi.html#vi-mock ❯ src/controllers/stream.controller.ts:1:1 Caused by: Caused by: ReferenceError: Cannot access 'mockPrisma' before initialization ❯ tests/integration/streams.test.ts:12:12 ❯ src/controllers/stream.controller.ts:1:1
import { prisma } from '../lib/prisma.js';
import logger from '../logger.js';
import { claimableAmountService } from '../services/claimable.service.js';
Expand Down Expand Up @@ -374,7 +374,7 @@
/**
* Get user-level stream summary used by dashboard/profile cards.
*/
export const getUserStreamSummary = async (req: Request, res: Response) => {
export const getUserStreamSummary = async (req: Request<{ address: string }>, res: Response) => {
try {
const address = Array.isArray(req.params.address) ? req.params.address[0] : (req.params.address ?? '').trim();
if (!address) {
Expand Down
10 changes: 8 additions & 2 deletions backend/src/services/sse.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ interface SSECapacityCheckResult {
message?: string;
}

class SSEService {
export class SSEService {
private clients: Map<string, SSEClient> = new Map();
private readonly ipConnectionCounts: Map<string, number> = new Map();
private shuttingDown = false;
Expand Down Expand Up @@ -196,6 +196,13 @@ class SSEService {
}
}

broadcastToAdmin(event: string, data: unknown): void {
const adminKey = process.env.ADMIN_PUBLIC_KEY;
if (adminKey) {
this.broadcastToUser(adminKey, event, data);
}
}

private _localBroadcastToStream(streamId: string, event: string, data: unknown): void {
this.broadcast(event, data, (client) =>
client.subscriptions.has(streamId) || client.subscriptions.has('*')
Expand Down Expand Up @@ -225,5 +232,4 @@ class SSEService {
}
}

export { SSEService };
export const sseService = new SSEService();
87 changes: 0 additions & 87 deletions backend/src/test/sseService.test.ts

This file was deleted.

17 changes: 14 additions & 3 deletions backend/src/workers/soroban-event-worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,18 @@
let lastCursor: string | null = state.lastCursor;
let lastLedger: number = state.lastLedger;

for (const event of response.events) {
// Sort events so that 'stream_created' events are processed first in the batch.
// This ensures that subsequent events (like 'fee_collected') that depend on
// the stream existing in the DB can find it.
const sortedEvents = [...response.events].sort((a, b) => {
const aType = a.topic[0] ? decodeSymbol(a.topic[0]) : '';
const bType = b.topic[0] ? decodeSymbol(b.topic[0]) : '';
if (aType === 'stream_created' && bType !== 'stream_created') return -1;
if (bType === 'stream_created' && aType !== 'stream_created') return 1;
return 0;
});

for (const event of sortedEvents) {
// Only process events from successful contract calls.
if (!event.inSuccessfulContractCall) continue;

Expand Down Expand Up @@ -391,7 +402,7 @@
select: { ratePerSecond: true, startTime: true, totalPausedDuration: true }
});

const durationSeconds = Number(BigInt(newDepositedAmount) / BigInt(stream.ratePerSecond));

Check failure on line 405 in backend/src/workers/soroban-event-worker.ts

View workflow job for this annotation

GitHub Actions / Backend npm test

tests/soroban-event-worker.test.ts > handleStreamToppedUp > updates deposited amount

TypeError: Cannot convert undefined to a BigInt ❯ src/workers/soroban-event-worker.ts:405:67
const newEndTime = stream.startTime + durationSeconds + stream.totalPausedDuration;

await tx.stream.update({
Expand Down Expand Up @@ -607,15 +618,15 @@
});

// Broadcast to admin channel for treasury reporting
sseService.broadcast('stream.fee_collected', {
sseService.broadcastToAdmin('stream.fee_collected', {
streamId,
treasury,
feeAmount,
token,
transactionHash: event.txHash,
ledger: event.ledger,
timestamp,
}, (client) => client.subscriptions.has('admin') || client.subscriptions.has('*'));
});
}

private async handleStreamPaused(
Expand All @@ -626,7 +637,7 @@
const body = decodeMap(event.value);

if (!body['sender'] || !body['paused_at']) {
throw new Error(`StreamPaused #${streamId}: missing body fields`);

Check failure on line 640 in backend/src/workers/soroban-event-worker.ts

View workflow job for this annotation

GitHub Actions / Backend npm test

tests/soroban-event-worker.test.ts > handleStreamPaused > sets isPaused

Error: StreamPaused #77: missing body fields ❯ SorobanEventWorker.handleStreamPaused src/workers/soroban-event-worker.ts:640:13 ❯ tests/soroban-event-worker.test.ts:395:18
}

const sender = decodeAddress(body['sender']);
Expand Down
101 changes: 0 additions & 101 deletions backend/tests/integration/streamInter.test.ts

This file was deleted.

Loading