11import { ApiProperty , ApiPropertyOptional } from '@nestjs/swagger' ;
22import { Expose } from 'class-transformer' ;
3+ import {
4+ IsInt ,
5+ IsPositive ,
6+ IsString ,
7+ IsUUID ,
8+ IsEnum ,
9+ IsOptional ,
10+ IsDate ,
11+ MaxLength ,
12+ Matches ,
13+ ValidateNested ,
14+ IsBoolean ,
15+ IsNumber ,
16+ Min ,
17+ Max ,
18+ } from 'class-validator' ;
19+ import { Type } from 'class-transformer' ;
320
421export class ClaimMetadataDto {
522 @ApiProperty ( { description : 'Unique claim identifier' } )
623 @Expose ( )
24+ @IsInt ( )
25+ @IsPositive ( )
726 id ! : number ;
827
928 @ApiProperty ( { description : 'Policy ID this claim belongs to' } )
1029 @Expose ( )
30+ @IsString ( )
31+ @IsUUID ( )
1132 policyId ! : string ;
1233
1334 @ApiProperty ( { description : 'Creator wallet address' } )
1435 @Expose ( )
36+ @IsString ( )
37+ @Matches ( / ^ G [ A - Z 2 - 7 ] { 55 } $ / )
1538 creatorAddress ! : string ;
1639
1740 @ApiProperty ( { description : 'Current claim status' } )
@@ -20,134 +43,192 @@ export class ClaimMetadataDto {
2043
2144 @ApiProperty ( { description : 'Claim amount requested' } )
2245 @Expose ( )
46+ @IsString ( )
47+ @Matches ( / ^ \d + $ / )
2348 amount ! : string ;
2449
2550 @ApiPropertyOptional ( { description : 'Claim description/reason' } )
2651 @Expose ( )
52+ @IsOptional ( )
53+ @IsString ( )
54+ @MaxLength ( 1000 )
2755 description ?: string ;
2856
2957 @ApiProperty ( { description : 'IPFS hash for evidence' } )
3058 @Expose ( )
59+ @IsString ( )
60+ @Matches ( / ^ Q m [ 1 - 9 A - Z a - z ] [ 1 - 9 A - Z a - z 0 - 9 ] { 44 } $ / i)
3161 evidenceHash ! : string ;
3262
3363 @ApiProperty ( { description : 'Stellar ledger number when created' } )
3464 @Expose ( )
65+ @IsInt ( )
66+ @IsPositive ( )
3567 createdAtLedger ! : number ;
3668
3769 @ApiProperty ( { description : 'Creation timestamp' } )
3870 @Expose ( )
71+ @IsDate ( )
3972 createdAt ! : Date ;
4073
4174 @ApiProperty ( { description : 'Last update timestamp' } )
4275 @Expose ( )
76+ @IsDate ( )
4377 updatedAt ! : Date ;
4478}
4579
4680export class VoteTalliesDto {
4781 @ApiProperty ( { description : 'Number of yes votes' } )
4882 @Expose ( )
83+ @IsInt ( )
84+ @IsPositive ( )
4985 yesVotes ! : number ;
5086
5187 @ApiProperty ( { description : 'Number of no votes' } )
5288 @Expose ( )
89+ @IsInt ( )
90+ @IsPositive ( )
5391 noVotes ! : number ;
5492
5593 @ApiProperty ( { description : 'Total votes cast' } )
5694 @Expose ( )
95+ @IsInt ( )
96+ @IsPositive ( )
5797 totalVotes ! : number ;
5898}
5999
60100export class QuorumProgressDto {
61101 @ApiProperty ( { description : 'Required votes for quorum' } )
62102 @Expose ( )
103+ @IsInt ( )
104+ @IsPositive ( )
63105 required ! : number ;
64106
65107 @ApiProperty ( { description : 'Current vote count' } )
66108 @Expose ( )
109+ @IsInt ( )
110+ @Min ( 0 )
67111 current ! : number ;
68112
69113 @ApiProperty ( { description : 'Progress percentage toward quorum (0-100)' } )
70114 @Expose ( )
115+ @IsNumber ( )
116+ @Min ( 0 )
117+ @Max ( 100 )
71118 percentage ! : number ;
72119
73120 @ApiProperty ( { description : 'Whether quorum has been reached' } )
74121 @Expose ( )
122+ @IsBoolean ( )
75123 reached ! : boolean ;
76124}
77125
78126export class DeadlineDto {
79127 @ApiProperty ( { description : 'Voting deadline ledger number' } )
80128 @Expose ( )
129+ @IsInt ( )
130+ @IsPositive ( )
81131 votingDeadlineLedger ! : number ;
82132
83133 @ApiProperty ( { description : 'Voting deadline timestamp' } )
84134 @Expose ( )
135+ @IsDate ( )
85136 votingDeadlineTime ! : Date ;
86137
87138 @ApiProperty ( { description : 'Is voting still open' } )
88139 @Expose ( )
140+ @IsBoolean ( )
89141 isOpen ! : boolean ;
90142
91143 @ApiPropertyOptional ( { description : 'Time remaining in seconds (null if closed)' } )
92144 @Expose ( )
145+ @IsOptional ( )
146+ @IsNumber ( )
93147 remainingSeconds ?: number ;
94148}
95149
96150export class SanitizedEvidenceDto {
97151 @ApiProperty ( { description : 'IPFS gateway URL' } )
98152 @Expose ( )
153+ @IsString ( )
154+ @Matches ( / ^ h t t p s ? : \/ \/ .+ / i)
99155 gatewayUrl ! : string ;
100156
101157 @ApiProperty ( { description : 'Sanitized IPFS hash' } )
102158 @Expose ( )
159+ @IsString ( )
160+ @Matches ( / ^ Q m [ 1 - 9 A - Z a - z ] [ 1 - 9 A - Z a - z 0 - 9 ] { 44 } $ / i)
103161 hash ! : string ;
104162
105163 @ApiPropertyOptional ( { description : 'Cached content URL (if available)' } )
106164 @Expose ( )
165+ @IsOptional ( )
166+ @IsString ( )
167+ @Matches ( / ^ h t t p s ? : \/ \/ .+ / i)
107168 cachedUrl ?: string ;
108169}
109170
110171export class ConsistencyMetadataDto {
111172 @ApiProperty ( { description : 'Whether claim is finalized on-chain' } )
112173 @Expose ( )
174+ @IsBoolean ( )
113175 isFinalized ! : boolean ;
114176
115177 @ApiPropertyOptional ( { description : 'Indexer lag in ledgers (null if synced)' } )
116178 @Expose ( )
179+ @IsOptional ( )
180+ @IsInt ( )
181+ @Min ( 0 )
117182 indexerLag ?: number ;
118183
119184 @ApiPropertyOptional ( { description : 'Last indexed ledger number' } )
120185 @Expose ( )
186+ @IsOptional ( )
187+ @IsInt ( )
188+ @Min ( 0 )
121189 lastIndexedLedger ?: number ;
122190
123191 @ApiProperty ( { description : 'Whether data is potentially stale' } )
124192 @Expose ( )
193+ @IsBoolean ( )
125194 isStale ! : boolean ;
126195}
127196
128197export class ClaimListItemDto {
129198 @ApiProperty ( { description : 'Claim metadata' } )
130199 @Expose ( )
200+ @ValidateNested ( )
201+ @Type ( ( ) => ClaimMetadataDto )
131202 metadata ! : ClaimMetadataDto ;
132203
133204 @ApiProperty ( { description : 'Vote tallies' } )
134205 @Expose ( )
206+ @ValidateNested ( )
207+ @Type ( ( ) => VoteTalliesDto )
135208 votes ! : VoteTalliesDto ;
136209
137210 @ApiProperty ( { description : 'Quorum progress' } )
138211 @Expose ( )
212+ @ValidateNested ( )
213+ @Type ( ( ) => QuorumProgressDto )
139214 quorum ! : QuorumProgressDto ;
140215
141216 @ApiProperty ( { description : 'Voting deadline information' } )
142217 @Expose ( )
218+ @ValidateNested ( )
219+ @Type ( ( ) => DeadlineDto )
143220 deadline ! : DeadlineDto ;
144221
145222 @ApiProperty ( { description : 'Sanitized evidence URL' } )
146223 @Expose ( )
224+ @ValidateNested ( )
225+ @Type ( ( ) => SanitizedEvidenceDto )
147226 evidence ! : SanitizedEvidenceDto ;
148227
149228 @ApiProperty ( { description : 'Consistency metadata' } )
150229 @Expose ( )
230+ @ValidateNested ( )
231+ @Type ( ( ) => ConsistencyMetadataDto )
151232 consistency ! : ConsistencyMetadataDto ;
152233}
153234
@@ -168,12 +249,16 @@ export class CursorPageDto {
168249 example : 42 ,
169250 } )
170251 @Expose ( )
252+ @IsInt ( )
253+ @Min ( 0 )
171254 total ! : number ;
172255}
173256
174257export class ClaimsListResponseDto {
175258 @ApiProperty ( { description : 'Array of claims' , type : [ ClaimListItemDto ] } )
176259 @Expose ( )
260+ @ValidateNested ( { each : true } )
261+ @Type ( ( ) => ClaimListItemDto )
177262 data ! : ClaimListItemDto [ ] ;
178263
179264 @ApiProperty ( { description : 'Cursor pagination metadata' , type : CursorPageDto } )
0 commit comments