Skip to content
Open
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
28 changes: 27 additions & 1 deletion apps/backend/src/modules/auth/controllers/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@ import {
Req,
HttpCode,
HttpStatus,
Param,
BadRequestException,
NotFoundException,
} from '@nestjs/common';
import { Request } from 'express';
import { ThrottlerGuard } from '@nestjs/throttler';
import { StrKey } from '@stellar/stellar-sdk';
import { AuthService } from '../services/auth.service';
import { UserService } from '../../user/user.service';
import {
ChallengeDto,
VerifyDto,
Expand All @@ -22,7 +27,28 @@ import { AuthGuard } from '../middleware/auth.guard';
@Controller('auth')
@UseGuards(ThrottlerGuard)
export class AuthController {
constructor(private readonly authService: AuthService) {}
constructor(
private readonly authService: AuthService,
private readonly userService: UserService,
) {}

/**
* Resolve a Vaultix user id by Stellar wallet address (counterparty must have signed in once).
*/
@Get('wallet/:address')
@UseGuards(AuthGuard)
async getUserByWallet(@Param('address') address: string) {
if (!StrKey.isValidEd25519PublicKey(address)) {
throw new BadRequestException('Invalid Stellar address');
}
const user = await this.userService.findByWalletAddress(address);
if (!user) {
throw new NotFoundException(
'No Vaultix account exists for this wallet address',
);
}
return { id: user.id, walletAddress: user.walletAddress };
}

@Post('challenge')
@HttpCode(HttpStatus.OK)
Expand Down
5 changes: 4 additions & 1 deletion apps/backend/src/modules/auth/middleware/auth.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ export class AuthGuard implements CanActivate {

try {
const payload = await this.authService.validateToken(token);
request['user'] = payload;
request['user'] = {
...payload,
sub: payload.userId,
};
return true;
} catch {
throw new UnauthorizedException('Invalid or expired token');
Expand Down
16 changes: 16 additions & 0 deletions apps/backend/src/modules/escrow/controllers/escrow.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,22 @@ export class EscrowController {
return this.escrowService.findOverview(userId, query);
}

@Get(':id/fund/prepare')
@UseGuards(EscrowAccessGuard)
@ApiOperation({
summary: 'Get unsigned funding transaction XDR for wallet signing',
})
async prepareFund(
@Param('id') id: string,
@Request() req: AuthenticatedRequest,
) {
return this.escrowService.prepareFund(
id,
req.user.sub,
req.user.walletAddress,
);
}

@Get(':id')
@UseGuards(EscrowAccessGuard)
async findOne(@Param('id') id: string) {
Expand Down
7 changes: 6 additions & 1 deletion apps/backend/src/modules/escrow/dto/fund-escrow.dto.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { IsNumber, IsPositive } from 'class-validator';
import { IsNumber, IsOptional, IsPositive, IsString } from 'class-validator';

export class FundEscrowDto {
@IsNumber()
@IsPositive()
amount: number;

/** Base64-encoded signed transaction envelope (wallet-signed funding tx). */
@IsOptional()
@IsString()
signedTransactionXdr?: string;
}
Loading