Skip to content

Commit

Permalink
add suggested-nonce endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
0age committed Dec 8, 2024
1 parent 537b68a commit 5c35b41
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 0 deletions.
31 changes: 31 additions & 0 deletions src/__tests__/routes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,37 @@ describe('API Routes', () => {
sessionId = result.session.id;
});

describe('GET /suggested-nonce/:chainId', () => {
it('should return a valid nonce for authenticated user', async () => {
const response = await server.inject({
method: 'GET',
url: '/suggested-nonce/1',
headers: {
'x-session-id': sessionId,
},
});

expect(response.statusCode).toBe(200);
const result = JSON.parse(response.payload);
expect(result).toHaveProperty('nonce');
expect(result.nonce).toMatch(/^0x[0-9a-f]{64}$/i);

// Verify nonce format: first 20 bytes should match sponsor address
const nonceHex = BigInt(result.nonce).toString(16).padStart(64, '0');
const sponsorHex = validPayload.address.toLowerCase().slice(2);
expect(nonceHex.slice(0, 40)).toBe(sponsorHex);
});

it('should reject request without session', async () => {
const response = await server.inject({
method: 'GET',
url: '/suggested-nonce/1',
});

expect(response.statusCode).toBe(401);
});
});

describe('POST /compact', () => {
it('should submit valid compact', async () => {
const freshCompact = getFreshCompact();
Expand Down
41 changes: 41 additions & 0 deletions src/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
} from './compact';
import { getCompactDetails, getAllResourceLocks } from './graphql';
import { getAllocatedBalance } from './balance';
import { generateNonce } from './validation';

// Declare db property on FastifyInstance
declare module 'fastify' {
Expand Down Expand Up @@ -484,6 +485,46 @@ export async function setupRoutes(server: FastifyInstance): Promise<void> {
// Add authentication to all routes in this context
protectedRoutes.addHook('preHandler', authenticateRequest);

// Get suggested nonce for a chain
protectedRoutes.get<{
Params: { chainId: string };
}>(
'/suggested-nonce/:chainId',
async (
request: FastifyRequest<{
Params: { chainId: string };
}>,
reply: FastifyReply
) => {
if (!request.session) {
reply.code(401);
return { error: 'Unauthorized' };
}

try {
const { chainId } = request.params;
const sponsor = request.session.address;

// Generate a nonce for the sponsor
const nonce = await generateNonce(sponsor, chainId, server.db);

// Return the nonce in hex format with 0x prefix
return {
nonce: '0x' + nonce.toString(16).padStart(64, '0'),
};
} catch (error) {
server.log.error('Failed to generate nonce:', error);
reply.code(500);
return {
error:
error instanceof Error
? error.message
: 'Failed to generate nonce',
};
}
}
);

// Get available balance for a specific lock
protectedRoutes.get<{
Params: { chainId: string; lockId: string };
Expand Down

0 comments on commit 5c35b41

Please sign in to comment.