@dalmore/api-contracts 0.0.0-dev.2047f71 → 0.0.0-dev.3af7603

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/common/types/account-setting.types.ts +31 -0
  2. package/common/types/activity.types.ts +1 -1
  3. package/common/types/bonus-tier.types.ts +33 -0
  4. package/common/types/cart.types.ts +4 -1
  5. package/common/types/common.types.ts +16 -6
  6. package/common/types/dashboard.types.ts +2 -9
  7. package/common/types/disbursements.types.ts +119 -3
  8. package/common/types/file.types.ts +20 -4
  9. package/common/types/i-will-do-it-later.types.ts +68 -0
  10. package/common/types/index.ts +2 -0
  11. package/common/types/individuals.types.ts +2 -15
  12. package/common/types/issuer-offering.types.ts +14 -24
  13. package/common/types/issuer-payment-method.types.ts +41 -0
  14. package/common/types/issuer.types.ts +9 -0
  15. package/common/types/notification.types.ts +239 -29
  16. package/common/types/offering.types.ts +5 -15
  17. package/common/types/site.types.ts +2 -9
  18. package/common/types/{trade-line-item.type.ts → trade-line-item.types.ts} +2 -9
  19. package/common/types/trade.types.ts +64 -1
  20. package/common/types/transaction.types.ts +12 -1
  21. package/common/types/user.types.ts +15 -28
  22. package/contracts/clients/cart/index.ts +80 -0
  23. package/contracts/clients/index.ts +10 -0
  24. package/contracts/clients/issuer-payment-methods/index.ts +39 -0
  25. package/contracts/clients/payment-methods/index.ts +85 -0
  26. package/contracts/clients/trade-line-items/index.ts +66 -0
  27. package/contracts/clients/trades/index.ts +65 -1
  28. package/contracts/clients/transactions/index.ts +37 -0
  29. package/contracts/compliance/bonus-tiers/index.ts +21 -2
  30. package/contracts/compliance/trade-line-items/index.ts +1 -1
  31. package/contracts/compliance/users/index.ts +21 -0
  32. package/contracts/investors/bonus-tiers/index.ts +18 -0
  33. package/contracts/investors/individuals/index.ts +22 -0
  34. package/contracts/investors/trade-line-items/index.ts +1 -1
  35. package/contracts/issuers/bonus-tiers/index.ts +18 -0
  36. package/contracts/issuers/disbursements/index.ts +36 -0
  37. package/package.json +1 -1
@@ -0,0 +1,31 @@
1
+ import { extendZodWithOpenApi } from '@anatine/zod-openapi';
2
+ import { z } from 'zod';
3
+ import { TypeID } from 'typeid-js';
4
+ import { IBaseEntity } from './entity.types';
5
+
6
+ extendZodWithOpenApi(z);
7
+
8
+ export const accountSettingIdSchema = z.string().refine(
9
+ (value) => {
10
+ try {
11
+ const tid = TypeID.fromString(value);
12
+ return tid.getType() === 'account_setting';
13
+ } catch {
14
+ return false;
15
+ }
16
+ },
17
+ {
18
+ message:
19
+ 'Invalid account setting ID format. Must be a valid TypeID with "account_setting" prefix.',
20
+ },
21
+ );
22
+
23
+ export const IAccountSettingZod = IBaseEntity.extend({
24
+ id: accountSettingIdSchema.openapi({
25
+ example: 'account_setting_01j5y5ghx8fvc83dmx3pznq7hv',
26
+ }),
27
+ accountId: z.string().openapi({
28
+ example: 'account_01j5y5ghx8fvc83dmx3pznq7hv',
29
+ }),
30
+ });
31
+ export type IAccountSettingZod = z.infer<typeof IAccountSettingZod>;
@@ -199,7 +199,7 @@ export const ActivityZod = IBaseEntity.extend({
199
199
  userId: z.string().nullable(),
200
200
  activityTypeId: z.string(),
201
201
  accountId: z.string().nullable(),
202
- user: UserForActivityZod,
202
+ user: UserForActivityZod.nullable(),
203
203
  activityType: ActivityTypeZod,
204
204
  targetObject: z.string().nullable().optional(),
205
205
  __entity: z.string().optional(),
@@ -98,6 +98,15 @@ export type EstimateBonusTierCalculationZod = z.infer<
98
98
  typeof EstimateBonusTierCalculationZod
99
99
  >;
100
100
 
101
+ export const ComplianceEstimateBonusTierCalculationZod =
102
+ EstimateBonusTierCalculationZod.and(
103
+ z.object({
104
+ accountId: accountIdSchema,
105
+ }),
106
+ );
107
+ export type ComplianceEstimateBonusTierCalculationZod = z.infer<
108
+ typeof ComplianceEstimateBonusTierCalculationZod
109
+ >;
101
110
  export const EstimateBonusTierCalculationResponseZod = z.object({
102
111
  bonusTierId: bonusTierIdSchema
103
112
  .nullable()
@@ -145,3 +154,27 @@ export const CompliancePostBonusTierZod = PostBonusTierZod.extend({
145
154
  export type CompliancePostBonusTierZod = z.infer<
146
155
  typeof CompliancePostBonusTierZod
147
156
  >;
157
+ export const PurchaseCalculationZod = z.object({
158
+ assetId: assetIdSchema,
159
+ totalAmount: z.number().positive().openapi({ example: 1000 }),
160
+ purchasedShares: z.number().positive().int().openapi({ example: 100 }),
161
+ });
162
+ export type PurchaseCalculationZod = z.infer<typeof PurchaseCalculationZod>;
163
+
164
+ export const PurchaseCalculationResponseZod = z.object({
165
+ bonusTierId: bonusTierIdSchema
166
+ .nullable()
167
+ .openapi({ example: 'bonus_tier_01j5y5ghx5fg68d663j1fvy2x7' }),
168
+ assetId: assetIdSchema.openapi({
169
+ example: 'asset_00041061050r3gg28a1c60t3gf',
170
+ }),
171
+ type: z
172
+ .nativeEnum(BonusType)
173
+ .nullable()
174
+ .openapi({ example: BonusType.PERCENTAGE }),
175
+ bonusShares: z.number().int().openapi({ example: 100 }),
176
+ });
177
+
178
+ export type PurchaseCalculationResponseZod = z.infer<
179
+ typeof PurchaseCalculationResponseZod
180
+ >;
@@ -3,6 +3,7 @@ import { extendZodWithOpenApi } from '@anatine/zod-openapi';
3
3
  import { TradeStatus } from './common.types';
4
4
  import { investorAccountIdSchema } from './investor-account.types';
5
5
  import { paymentMethodIdSchema } from './payment-methods.types';
6
+ import { userIdSchema } from './user.types';
6
7
 
7
8
  extendZodWithOpenApi(z);
8
9
 
@@ -10,7 +11,9 @@ export const PlaceTradeResponse = z.object({
10
11
  tradeStatus: z.nativeEnum(TradeStatus).optional(),
11
12
  });
12
13
  export const PlaceTradeBody = z.object({});
13
-
14
+ export const ClientPlacetradeBody = z.object({
15
+ userId: userIdSchema,
16
+ });
14
17
  export const PatchCartBody = z.object({
15
18
  investorAccountId: investorAccountIdSchema.optional(),
16
19
  paymentMethodId: paymentMethodIdSchema.optional(),
@@ -111,6 +111,10 @@ export enum HttpMethod {
111
111
  OPTIONS = 'OPTIONS',
112
112
  }
113
113
 
114
+ export enum UserStatus {
115
+ ACTIVE = 'ACTIVE',
116
+ LOCKED = 'LOCKED',
117
+ }
114
118
  export const SENSITIVE_PATTERNS = [
115
119
  /password/i,
116
120
  /credit.*card/i,
@@ -200,11 +204,6 @@ export enum UserType {
200
204
  DEMO = 'DEMO',
201
205
  }
202
206
 
203
- export enum UserStatus {
204
- ACTIVE = 'ACTIVE',
205
- LOCKED = 'LOCKED',
206
- }
207
-
208
207
  export enum UserRole {
209
208
  API_KEY = 'API_KEY',
210
209
  IMPORT = 'IMPORT',
@@ -306,7 +305,7 @@ export const AuthUserReq = BaseAuthReq.extend({
306
305
  lastName: z.string(),
307
306
  email: z.string().email(),
308
307
  provider: z.string(),
309
- status: z.lazy(() => z.nativeEnum(UserStatus)),
308
+ locked: z.boolean(),
310
309
  lastLoginAt: z.date().nullable(),
311
310
  loginCount: z.number(),
312
311
  requiresTwoFactorSetup: z.boolean().optional(),
@@ -1518,3 +1517,14 @@ export const SUBJECT_TYPE_MAP: Record<BulkExportType, string> = {
1518
1517
  [BulkExportType.SECONDARY_CUSTOMERS]: 'Secondary Customers',
1519
1518
  [BulkExportType.SECONDARY_TRADES]: 'Secondary Trades',
1520
1519
  };
1520
+
1521
+ export const StringToBooleanSchema = z.preprocess(
1522
+ (val) =>
1523
+ val === 'true' || val === '1'
1524
+ ? true
1525
+ : val === 'false' || val === '0'
1526
+ ? false
1527
+ : val,
1528
+ z.boolean(),
1529
+ );
1530
+ export type StringToBooleanSchema = z.infer<typeof StringToBooleanSchema>;
@@ -7,6 +7,7 @@ import {
7
7
  FileLabels,
8
8
  IPaginationMeta,
9
9
  OfferingType,
10
+ StringToBooleanSchema,
10
11
  } from './common.types';
11
12
  import { accountIdSchema } from './account.types';
12
13
 
@@ -330,15 +331,7 @@ export const GetInvestmentDashboardQueryZod = z.object({
330
331
  offerings: OfferingsArrayQueryZod.optional(),
331
332
  offeringTypes: OfferingTypesQueryZod.optional(),
332
333
  timeFilteringType: z.nativeEnum(DashboardTimeFilteringType),
333
- debug: z.preprocess(
334
- (val) =>
335
- val === 'true' || val === '1'
336
- ? true
337
- : val === 'false' || val === '0'
338
- ? false
339
- : val,
340
- z.boolean().optional(),
341
- ),
334
+ debug: StringToBooleanSchema.optional(),
342
335
  });
343
336
  export type GetInvestmentDashboardQueryZod = z.infer<
344
337
  typeof GetInvestmentDashboardQueryZod
@@ -11,14 +11,17 @@ import {
11
11
  import { tradeIdSchema } from './trade.types';
12
12
  import { accountIdSchema } from './account.types';
13
13
  import { TypeID } from 'typeid-js';
14
- import { issuerIdSchema } from './issuer.types';
15
- import { issuerBankAccountIdSchema } from './issuer-bank-account.types';
14
+ import { IIssuer, issuerIdSchema } from './issuer.types';
15
+ import {
16
+ IIssuerBankAccount,
17
+ issuerBankAccountIdSchema,
18
+ } from './issuer-bank-account.types';
16
19
  import { userIdSchema, UserZod } from './user.types';
17
20
  import {
18
21
  PostDisbursementAdjustmentZod,
19
22
  DisbursementAdjustmentType,
20
23
  } from './disbursement-adjustment.types';
21
- import { escrowAccountIdSchema } from './escrow-account.types';
24
+ import { IEscrowAccount, escrowAccountIdSchema } from './escrow-account.types';
22
25
 
23
26
  export const disbursementIdSchema = z.string().refine(
24
27
  (value) => {
@@ -308,3 +311,116 @@ export const DisbursementSummaryZod = z.object({
308
311
  amountToBeTransferred: z.number(),
309
312
  });
310
313
  export type DisbursementSummaryZod = z.infer<typeof DisbursementSummaryZod>;
314
+
315
+ // GET /disbursements/preview query parameters
316
+ export const GetDisbursementPreviewQueryZod = z.object({
317
+ offeringId: offeringIdSchema,
318
+ selectedTrades: z
319
+ .string()
320
+ .optional()
321
+ .transform((str) => (str ? str.split(',') : []))
322
+ .refine(
323
+ (ids) =>
324
+ ids.every((id) => {
325
+ try {
326
+ const tid = TypeID.fromString(id);
327
+ return tid.getType() === 'trade';
328
+ } catch {
329
+ return false;
330
+ }
331
+ }),
332
+ {
333
+ message: 'All selected trades must be valid trade IDs',
334
+ },
335
+ )
336
+ .openapi({
337
+ example: 'trade_01abc123,trade_01def456',
338
+ }),
339
+ });
340
+ export type GetDisbursementPreviewQueryZod = z.infer<
341
+ typeof GetDisbursementPreviewQueryZod
342
+ >;
343
+
344
+ // Context fields for disbursement preview
345
+ export const DisbursementPreviewContextZod = z.object({
346
+ issuer: z.lazy(() => IIssuer).nullable(),
347
+ offering: z.lazy(() => IOffering).nullable(),
348
+ escrowAccount: z.lazy(() => IEscrowAccount).nullable(),
349
+ destinationBank: z.lazy(() => IIssuerBankAccount).nullable(),
350
+ });
351
+ export type DisbursementPreviewContextZod = z.infer<
352
+ typeof DisbursementPreviewContextZod
353
+ >;
354
+
355
+ // Balance values for disbursement preview
356
+ export const DisbursementPreviewBalanceZod = z.object({
357
+ totalRaised: z.number(),
358
+ totalDisbursed: z.number(),
359
+ pending: z.number(),
360
+ refundPool: z.number(),
361
+ availableForDisbursement: z.number(),
362
+ });
363
+ export type DisbursementPreviewBalanceZod = z.infer<
364
+ typeof DisbursementPreviewBalanceZod
365
+ >;
366
+
367
+ // Trade summary for disbursement preview
368
+ export const DisbursementPreviewTradeSummaryZod = z.object({
369
+ selectedTradesCount: z.number(),
370
+ selectedTradesTotalAmount: z.number(),
371
+ });
372
+ export type DisbursementPreviewTradeSummaryZod = z.infer<
373
+ typeof DisbursementPreviewTradeSummaryZod
374
+ >;
375
+
376
+ // Contingency validation result
377
+ export const DisbursementPreviewContingencyZod = z.object({
378
+ contingencyPassed: z.boolean(),
379
+ contingencyMessage: z.string().nullable(),
380
+ contingencyAmount: z.number(),
381
+ });
382
+ export type DisbursementPreviewContingencyZod = z.infer<
383
+ typeof DisbursementPreviewContingencyZod
384
+ >;
385
+
386
+ // Amount defaults and constraints
387
+ export const DisbursementPreviewAmountZod = z.object({
388
+ defaultAmount: z.number(),
389
+ minAmount: z.number(),
390
+ maxAmount: z.number(),
391
+ });
392
+ export type DisbursementPreviewAmountZod = z.infer<
393
+ typeof DisbursementPreviewAmountZod
394
+ >;
395
+
396
+ // Complete response for GET /disbursements/preview
397
+ export const DisbursementPreviewZod = z.object({
398
+ context: DisbursementPreviewContextZod,
399
+ balance: DisbursementPreviewBalanceZod,
400
+ tradeSummary: DisbursementPreviewTradeSummaryZod,
401
+ contingency: DisbursementPreviewContingencyZod,
402
+ amount: DisbursementPreviewAmountZod,
403
+ });
404
+ export type DisbursementPreviewZod = z.infer<typeof DisbursementPreviewZod>;
405
+
406
+ export const EligibleOfferingZod = z.object({
407
+ offeringId: offeringIdSchema,
408
+ offeringName: z.string(),
409
+ availableAmount: z.number(),
410
+ });
411
+ export type EligibleOfferingZod = z.infer<typeof EligibleOfferingZod>;
412
+
413
+ export const IPaginatedEligibleOffering = z.object({
414
+ items: z.array(EligibleOfferingZod),
415
+ meta: IPaginationMeta,
416
+ });
417
+ export type IPaginatedEligibleOffering = z.infer<
418
+ typeof IPaginatedEligibleOffering
419
+ >;
420
+
421
+ export const EligibleOfferingsFiltersZod = z.object({
422
+ search: z.string().optional(),
423
+ });
424
+ export type EligibleOfferingsFiltersZod = z.infer<
425
+ typeof EligibleOfferingsFiltersZod
426
+ >;
@@ -17,7 +17,7 @@ import { KybZod } from './kyb.types';
17
17
  import { IIndividualZod, individualIdSchema } from './individuals.types';
18
18
  import { LegalEntityZod } from './legal-entity.types';
19
19
  import { IInvestorAccount } from './investor-account.types';
20
- import { TradeZod } from './trade.types';
20
+ import { tradeIdSchema, TradeZod } from './trade.types';
21
21
 
22
22
  extendZodWithOpenApi(z);
23
23
 
@@ -168,13 +168,13 @@ export type PostFileQueryParams = z.infer<typeof PostFileQueryParams>;
168
168
 
169
169
  /**
170
170
  * CLIENT portal specific schema for file uploads
171
- * Only allows INDIVIDUALS as target for file uploads
171
+ * Only allows INDIVIDUALS and TRADES as target for file uploads
172
172
  */
173
173
  export const ClientPostFileQueryParams = z.object({
174
174
  name: z.string().min(1).max(100).openapi({ example: 'file_name' }),
175
175
  category: z.string().max(50).openapi({ example: 'application' }),
176
176
  label: FileLabelsEnum.openapi({ example: FileLabels.OTHER }),
177
- targetId: individualIdSchema.openapi({
177
+ targetId: z.union([individualIdSchema, tradeIdSchema]).openapi({
178
178
  example: 'individual_01kcrsny60fb9rjc8bbqc3b80c',
179
179
  }),
180
180
  metadata: metadataSchema.nullable().optional(),
@@ -314,8 +314,23 @@ export const reviewFiles = z.object({
314
314
  });
315
315
  export type reviewFiles = z.infer<typeof reviewFiles>;
316
316
 
317
+ /**
318
+ * Zod preprocessor that trims strings and converts empty/whitespace-only strings to null
319
+ */
320
+ const trimAndNullifyString = z.preprocess((val) => {
321
+ if (typeof val === 'string') {
322
+ const trimmed = val.trim();
323
+ return trimmed === '' ? null : trimmed;
324
+ }
325
+ return val;
326
+ }, z.unknown());
327
+
317
328
  export const PatchFileMetadata = z.object({
318
- corrected: z.record(z.string(), z.unknown()),
329
+ corrected: z.record(z.string(), trimAndNullifyString),
330
+ expectedCorrected: z
331
+ .record(z.string(), trimAndNullifyString)
332
+ .nullable()
333
+ .optional(),
319
334
  });
320
335
  export type PatchFileMetadata = z.infer<typeof PatchFileMetadata>;
321
336
 
@@ -343,6 +358,7 @@ export const FileMetadataSchema = z.object({
343
358
  },
344
359
  ),
345
360
  corrected: z.record(z.any()).optional(),
361
+ expectedCorrected: z.record(z.any()).optional(),
346
362
  });
347
363
  export type FileMetadata = z.infer<typeof FileMetadataSchema>;
348
364
 
@@ -0,0 +1,68 @@
1
+ import { z } from 'zod';
2
+ import { PortalType, TargetTableEnum } from './common.types';
3
+ import { TaskPriority, TaskType } from './task.types';
4
+
5
+ export enum IWillDoItLaterType {
6
+ KYC = 'KYC',
7
+ // Future types can be added here:
8
+ // AIC = 'AIC',
9
+ // AML = 'AML',
10
+ }
11
+
12
+ export const IWillDoItLaterBodySchema = z.object({
13
+ type: z.nativeEnum(IWillDoItLaterType).default(IWillDoItLaterType.KYC),
14
+ });
15
+
16
+ export type IWillDoItLaterBodyType = z.infer<typeof IWillDoItLaterBodySchema>;
17
+
18
+ export const IWillDoItLaterResponseSchema = z.object({
19
+ message: z.string(),
20
+ });
21
+
22
+ export type IWillDoItLaterResponseType = z.infer<
23
+ typeof IWillDoItLaterResponseSchema
24
+ >;
25
+
26
+ /**
27
+ * @description Context required for processing "I'll do it later" actions.
28
+ */
29
+ export interface IWillDoItLaterContext {
30
+ /** The ID of the target entity */
31
+ targetId: string;
32
+ /** The table name of the target entity */
33
+ targetTable: (typeof TargetTableEnum)[number];
34
+ /** The account ID associated with the action */
35
+ accountId: string;
36
+ /** The user ID who will be assigned the task */
37
+ assigneeId: string;
38
+ }
39
+
40
+ /**
41
+ * @description Configuration for each "I'll do it later" action type.
42
+ * Maps action types to their corresponding task configuration.
43
+ */
44
+ export interface IWillDoItLaterTaskConfig {
45
+ taskType: TaskType;
46
+ portalType: PortalType;
47
+ title: string;
48
+ description: string;
49
+ priority: TaskPriority;
50
+ }
51
+
52
+ /**
53
+ * @description Mapping of "I'll do it later" types to their task configurations.
54
+ * This allows for easy extension of new action types without modifying the service logic.
55
+ */
56
+ export const IWillDoItLaterTaskConfigMap: Record<
57
+ IWillDoItLaterType,
58
+ IWillDoItLaterTaskConfig
59
+ > = {
60
+ [IWillDoItLaterType.KYC]: {
61
+ taskType: TaskType.COMPLETE_KYC,
62
+ portalType: PortalType.INVESTOR,
63
+ title: 'Complete KYC',
64
+ description:
65
+ 'We are unable to verify your KYC information. Please complete your KYC.',
66
+ priority: TaskPriority.HIGH,
67
+ },
68
+ };
@@ -42,6 +42,8 @@ export * from './domain-filter.types';
42
42
  export * from './aic.types';
43
43
  export * from './default-theme-config.types';
44
44
  export * from './offering-reports.types';
45
+ export * from './i-will-do-it-later.types';
46
+ export * from './payment-methods.types';
45
47
 
46
48
  export enum Versions {
47
49
  V1 = 'v1',
@@ -12,9 +12,7 @@ import {
12
12
  InvestorAccountType,
13
13
  SetupStatusType,
14
14
  SetupStepType,
15
- ComplianceReview,
16
15
  RetirementAccountType,
17
- TradeStatus,
18
16
  EmploymentStatus,
19
17
  SourceOfIncome,
20
18
  AMLProvider,
@@ -60,8 +58,8 @@ export enum aicQuestionnaireQuestionType {
60
58
  }
61
59
 
62
60
  export enum FilterBy {
63
- TRADE = 'TRADE',
64
- INVESTOR = 'INVESTOR',
61
+ ALL = 'ALL',
62
+ PENDING_TRADES = 'PENDING_TRADES',
65
63
  }
66
64
 
67
65
  export const aicQuestionnaireQuestion = z.object({
@@ -243,17 +241,6 @@ export const IndividualFiltersZod = z.object({
243
241
 
244
242
  export const ComplianceIndividualFiltersZod = IndividualFiltersZod.extend({
245
243
  filterBy: z.nativeEnum(FilterBy).optional(),
246
- tradeStatus: z.nativeEnum(TradeStatus).optional(),
247
- complianceReview: z.nativeEnum(ComplianceReview).optional(),
248
- hasPendingTrades: z.preprocess(
249
- (val) =>
250
- val === 'true' || val === '1'
251
- ? true
252
- : val === 'false' || val === '0'
253
- ? false
254
- : val,
255
- z.boolean().optional(),
256
- ),
257
244
  });
258
245
 
259
246
  /**
@@ -10,15 +10,11 @@ import {
10
10
  ComplianceReview,
11
11
  DurationType,
12
12
  AssetType,
13
+ StringToBooleanSchema,
13
14
  } from './common.types';
14
15
  import { IBaseEntity } from './entity.types';
15
16
  import { IIssuer, issuerIdSchema } from './issuer.types';
16
- import {
17
- IAsset,
18
- postAssetRefinement,
19
- AssetTemplateType,
20
- assetIdSchema,
21
- } from './asset.types';
17
+ import { IAsset, postAssetRefinement, AssetTemplateType } from './asset.types';
22
18
  import { fileIdSchema, FileZod } from './file.types';
23
19
  import { accountIdSchema } from './account.types';
24
20
 
@@ -173,6 +169,7 @@ export const PostIssuerOffering = z
173
169
  .default(AssetTemplateType.STANDARD)
174
170
  .openapi({ example: AssetTemplateType.STANDARD }),
175
171
  tiers: z.array(z.number().positive()).nullable().optional(),
172
+ enableBonus: z.boolean().default(false).optional(),
176
173
  })
177
174
  .superRefine((data, ctx) => {
178
175
  // Check if both values are present, and if so, ensure minInvestment is less than maxInvestment
@@ -197,38 +194,39 @@ export const PatchIssuerOffering = z.object({
197
194
  .max(100)
198
195
  .optional()
199
196
  .openapi({ example: 'Airbnb IPO' }),
197
+ type: z
198
+ .nativeEnum(OfferingType)
199
+ .optional()
200
+ .openapi({ example: OfferingType.REG_D }),
200
201
  targetAmount: z
201
202
  .number()
202
203
  .min(0)
203
204
  .max(10000000000)
204
205
  .optional()
205
206
  .openapi({ example: 120000 }),
206
- raiseAmount: z
207
- .number()
208
- .min(0)
209
- .max(10000000000)
210
- .optional()
211
- .openapi({ example: 200000 }),
212
207
  minInvestment: z
213
208
  .number()
214
209
  .min(0)
215
210
  .max(10000000000)
211
+ .nullable()
216
212
  .optional()
217
213
  .openapi({ example: 1000 }),
218
214
  maxInvestment: z
219
215
  .number()
220
216
  .min(0)
221
217
  .max(10000000000)
218
+ .nullable()
222
219
  .optional()
223
220
  .openapi({ example: 20000 }),
224
221
  contingencyAmount: z
225
222
  .number()
226
223
  .min(0)
227
224
  .max(10000000000)
225
+ .nullable()
228
226
  .optional()
229
227
  .openapi({ example: 5000 }),
230
- startAt: dateSchema.optional().openapi({ example: '10/20/2024' }),
231
- endAt: dateSchema.optional().openapi({ example: '10/27/2024' }),
228
+ startAt: dateSchema.nullable().optional().openapi({ example: '10/20/2024' }),
229
+ endAt: dateSchema.nullable().optional().openapi({ example: '10/27/2024' }),
232
230
  cancellationPeriod: z
233
231
  .number()
234
232
  .min(1)
@@ -258,7 +256,6 @@ export const PatchIssuerOffering = z.object({
258
256
  managedBy: z.nativeEnum(ManagedByType).optional(),
259
257
  showTotalRaised: z.boolean().optional(),
260
258
  issuerId: issuerIdSchema.optional(),
261
- assetId: assetIdSchema,
262
259
  assetName: z.string().min(2).max(50).optional().openapi({ example: 'Z' }),
263
260
  assetType: z
264
261
  .nativeEnum(AssetType)
@@ -305,6 +302,7 @@ export const PatchIssuerOffering = z.object({
305
302
  .optional(),
306
303
  tiers: z.array(z.number().positive()).nullable().optional(),
307
304
  enabled: z.boolean().optional(),
305
+ enableBonus: z.boolean().optional(),
308
306
  });
309
307
  export type PatchIssuerOffering = z.infer<typeof PatchIssuerOffering>;
310
308
 
@@ -374,15 +372,7 @@ export const IssuerOfferingsFilterZod = z.object({
374
372
  issuerId: z.lazy(() => issuerIdSchema).optional(),
375
373
  type: z.nativeEnum(OfferingType).optional(),
376
374
  status: z.nativeEnum(ComplianceReview).optional(),
377
- enabled: z.preprocess(
378
- (val) =>
379
- val === 'true' || val === '1'
380
- ? true
381
- : val === 'false' || val === '0'
382
- ? false
383
- : val,
384
- z.boolean().optional(),
385
- ),
375
+ enabled: StringToBooleanSchema.optional(),
386
376
  managedBy: z.nativeEnum(ManagedByType).optional(),
387
377
  versioningType: z.nativeEnum(OfferingVersioningType).optional(),
388
378
  combinedStatus: z.nativeEnum(OfferingStatus).optional(),
@@ -222,10 +222,51 @@ export type IPaginatedIssuerPaymentMethod = z.infer<
222
222
  typeof IPaginatedIssuerPaymentMethod
223
223
  >;
224
224
 
225
+ const issuerPaymentMethodsInclude = z.enum(['issuer', 'integration']);
226
+
227
+ /**
228
+ * @description Query parameters for including related entities
229
+ * @example in contract use as -> query: PaginationOptionsZod.merge(GetIssuerPaymentMethodZod).merge(IssuerPaymentMethodsIncludeQuery)
230
+ */
231
+ export const IssuerPaymentMethodsIncludeQuery = z.object({
232
+ include: z
233
+ .string()
234
+ .optional()
235
+ .transform((str) => (str ? str.split(',') : []))
236
+ .refine(
237
+ (includes) =>
238
+ includes.every((include) =>
239
+ issuerPaymentMethodsInclude.options.includes(include as any),
240
+ ),
241
+ {
242
+ message: `Invalid include option provided. Valid options are: ${issuerPaymentMethodsInclude.options.join(',')}`,
243
+ },
244
+ )
245
+ .openapi({
246
+ example: `${issuerPaymentMethodsInclude.options.join(',')}`,
247
+ }),
248
+ });
249
+ export type IssuerPaymentMethodsIncludeQuery = z.infer<
250
+ typeof IssuerPaymentMethodsIncludeQuery
251
+ >;
252
+
225
253
  export const GetIssuerPaymentMethodZod = z.object({
226
254
  issuerId: issuerIdSchema.openapi({
227
255
  example: 'issuer_01jdq2crwke8xskjd840cj79pw',
228
256
  }),
257
+ enabled: z
258
+ .string()
259
+ .optional()
260
+ .refine((v) => !v || v === 'true' || v === 'false', {
261
+ message: 'enabled must be a boolean string',
262
+ })
263
+ .transform((v) => {
264
+ if (!v) return undefined;
265
+ return v === 'true';
266
+ })
267
+ .openapi({
268
+ example: 'true',
269
+ }),
229
270
  });
230
271
  export type GetIssuerPaymentMethodZod = z.infer<
231
272
  typeof GetIssuerPaymentMethodZod
@@ -152,6 +152,10 @@ export const PutIssuerZod = z
152
152
  .lazy(() => fileIdSchema)
153
153
  .optional()
154
154
  .nullable(),
155
+ formationDocumentFileId: z
156
+ .lazy(() => fileIdSchema)
157
+ .optional()
158
+ .nullable(),
155
159
  coverArtId: z
156
160
  .lazy(() => fileIdSchema)
157
161
  .optional()
@@ -188,6 +192,11 @@ export const IIssuer = IBaseEntity.extend({
188
192
  accountId: z.string(),
189
193
  account: AccountZod.optional().nullable(),
190
194
  ss4LetterFileId: z.string().nullable(),
195
+ formationDocumentFileId: z.string().nullable(),
196
+ formationDocument: z
197
+ .lazy(() => FileZod)
198
+ .nullable()
199
+ .optional(),
191
200
  status: z
192
201
  .nativeEnum(IssuerStatus)
193
202
  .openapi({ example: IssuerStatus.SUBMITTED }),