forked from StellarSplit/StellarSplit
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpayments.controller.ts
More file actions
149 lines (129 loc) · 4.7 KB
/
Copy pathpayments.controller.ts
File metadata and controls
149 lines (129 loc) · 4.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import {
Body,
Controller,
Get,
Headers,
Logger,
Param,
Post,
Query,
UseGuards,
UseInterceptors,
ValidationPipe,
} from "@nestjs/common";
import { PaymentRequestContext } from "./payment-request-context";
import {
Permissions,
RequirePermissions,
} from "../auth/decorators/permissions.decorator";
import { AuthorizationGuard } from "../auth/guards/authorization.guard";
import { JwtAuthGuard } from "../auth/guards/jwt-auth.guard";
import { IdempotencyInterceptor } from "../common/idempotency/idempotency.interceptor";
import { MultiCurrencyService } from "../multi-currency/multi-currency.service";
import { SubmitPaymentDto } from "./dto/submit-payment.dto";
import { PaymentsService } from "./payments.service";
@Controller("payments")
@UseGuards(JwtAuthGuard, AuthorizationGuard)
export class PaymentsController {
private readonly logger = new Logger(PaymentsController.name);
constructor(
private readonly paymentsService: PaymentsService,
private readonly multiCurrencyService: MultiCurrencyService,
) {}
@Post("/submit")
@UseInterceptors(IdempotencyInterceptor)
@RequirePermissions(Permissions.CAN_CREATE_PAYMENT)
async submitPayment(
@Body(ValidationPipe) submitPaymentDto: SubmitPaymentDto,
@Headers("idempotency-key") idempotencyKeyHeader?: string,
) {
this.logger.log(
`Received payment submission: ${JSON.stringify(submitPaymentDto)}`,
);
const { splitId, participantId, stellarTxHash, externalReference } = submitPaymentDto;
// Idempotency key comes exclusively from the header — the DTO no longer
// carries it to prevent mismatched-source replay semantics (issue #369).
const context: PaymentRequestContext = {
idempotencyKey: idempotencyKeyHeader,
externalReference,
};
return await this.paymentsService.submitPayment(
splitId,
participantId,
stellarTxHash,
context,
);
}
@Get("/verify/:txHash")
async verifyTransaction(@Param("txHash") txHash: string) {
this.logger.log(`Verifying transaction: ${txHash}`);
return await this.paymentsService.verifyTransaction(txHash);
}
@Get("/:txHash")
async getPaymentByTxHash(@Param("txHash") txHash: string) {
this.logger.log(`Getting payment for transaction: ${txHash}`);
return await this.paymentsService.getPaymentByTxHash(txHash);
}
@Get("/split/:splitId")
@RequirePermissions(Permissions.CAN_READ_SPLIT_PAYMENTS)
async getPaymentsBySplitId(@Param("splitId") splitId: string) {
this.logger.log(`Getting payments for split: ${splitId}`);
return await this.paymentsService.getPaymentsBySplitId(splitId);
}
@Get("/participant/:participantId")
@RequirePermissions(Permissions.CAN_READ_PARTICIPANT_PAYMENTS)
async getPaymentsByParticipantId(
@Param("participantId") participantId: string,
) {
this.logger.log(`Getting payments for participant: ${participantId}`);
return await this.paymentsService.getPaymentsByParticipantId(participantId);
}
@Get("/stats/:splitId")
@RequirePermissions(Permissions.CAN_READ_SPLIT_PAYMENTS)
async getPaymentStatsForSplit(@Param("splitId") splitId: string) {
this.logger.log(`Getting payment stats for split: ${splitId}`);
return await this.paymentsService.getPaymentStatsForSplit(splitId);
}
/**
* Get path payment transaction for multi-currency conversion
* Builds a path payment transaction that the client can sign and submit
*/
@Get("/path-payment/:splitId/:participantId")
@RequirePermissions(Permissions.CAN_CREATE_PAYMENT)
async getPathPaymentTransaction(
@Param("splitId") splitId: string,
@Param("participantId") participantId: string,
@Query("sourceAsset") sourceAsset: string,
@Query("destinationAmount") destinationAmount: string,
@Query("slippageTolerance") slippageTolerance?: string,
) {
this.logger.log(
`Getting path payment transaction for split ${splitId}, participant ${participantId}`,
);
return await this.multiCurrencyService.getPathPaymentTransaction(
splitId,
participantId,
sourceAsset,
parseFloat(destinationAmount),
slippageTolerance ? parseFloat(slippageTolerance) : 0.01,
);
}
/**
* Get supported assets for multi-currency payments
*/
@Get("/supported-assets")
async getSupportedAssets() {
this.logger.log("Getting supported assets");
return {
assets: this.multiCurrencyService.getSupportedAssets(),
};
}
/**
* Get multi-currency payment details
*/
@Get("/multi-currency/:paymentId")
async getMultiCurrencyPayment(@Param("paymentId") paymentId: string) {
this.logger.log(`Getting multi-currency payment details for ${paymentId}`);
return await this.multiCurrencyService.getMultiCurrencyPayment(paymentId);
}
}