@dalmore/api-contracts 0.0.0-dev.4eac826 → 0.0.0-dev.4ec8ae0

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.
@@ -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>;
@@ -145,3 +145,27 @@ export const CompliancePostBonusTierZod = PostBonusTierZod.extend({
145
145
  export type CompliancePostBonusTierZod = z.infer<
146
146
  typeof CompliancePostBonusTierZod
147
147
  >;
148
+ export const PurchaseCalculationZod = z.object({
149
+ assetId: assetIdSchema,
150
+ totalAmount: z.number().positive().openapi({ example: 1000 }),
151
+ purchasedShares: z.number().positive().int().openapi({ example: 100 }),
152
+ });
153
+ export type PurchaseCalculationZod = z.infer<typeof PurchaseCalculationZod>;
154
+
155
+ export const PurchaseCalculationResponseZod = z.object({
156
+ bonusTierId: bonusTierIdSchema
157
+ .nullable()
158
+ .openapi({ example: 'bonus_tier_01j5y5ghx5fg68d663j1fvy2x7' }),
159
+ assetId: assetIdSchema.openapi({
160
+ example: 'asset_00041061050r3gg28a1c60t3gf',
161
+ }),
162
+ type: z
163
+ .nativeEnum(BonusType)
164
+ .nullable()
165
+ .openapi({ example: BonusType.PERCENTAGE }),
166
+ bonusShares: z.number().int().openapi({ example: 100 }),
167
+ });
168
+
169
+ export type PurchaseCalculationResponseZod = z.infer<
170
+ typeof PurchaseCalculationResponseZod
171
+ >;
@@ -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) => {
@@ -309,6 +312,97 @@ export const DisbursementSummaryZod = z.object({
309
312
  });
310
313
  export type DisbursementSummaryZod = z.infer<typeof DisbursementSummaryZod>;
311
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
+
312
406
  export const EligibleOfferingZod = z.object({
313
407
  offeringId: offeringIdSchema,
314
408
  offeringName: z.string(),
@@ -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,6 +10,7 @@ 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';
@@ -168,6 +169,7 @@ export const PostIssuerOffering = z
168
169
  .default(AssetTemplateType.STANDARD)
169
170
  .openapi({ example: AssetTemplateType.STANDARD }),
170
171
  tiers: z.array(z.number().positive()).nullable().optional(),
172
+ enableBonus: z.boolean().default(false).optional(),
171
173
  })
172
174
  .superRefine((data, ctx) => {
173
175
  // Check if both values are present, and if so, ensure minInvestment is less than maxInvestment
@@ -192,6 +194,10 @@ export const PatchIssuerOffering = z.object({
192
194
  .max(100)
193
195
  .optional()
194
196
  .openapi({ example: 'Airbnb IPO' }),
197
+ type: z
198
+ .nativeEnum(OfferingType)
199
+ .optional()
200
+ .openapi({ example: OfferingType.REG_D }),
195
201
  targetAmount: z
196
202
  .number()
197
203
  .min(0)
@@ -299,6 +305,7 @@ export const PatchIssuerOffering = z.object({
299
305
  .optional(),
300
306
  tiers: z.array(z.number().positive()).nullable().optional(),
301
307
  enabled: z.boolean().optional(),
308
+ enableBonus: z.boolean().optional(),
302
309
  });
303
310
  export type PatchIssuerOffering = z.infer<typeof PatchIssuerOffering>;
304
311
 
@@ -368,15 +375,7 @@ export const IssuerOfferingsFilterZod = z.object({
368
375
  issuerId: z.lazy(() => issuerIdSchema).optional(),
369
376
  type: z.nativeEnum(OfferingType).optional(),
370
377
  status: z.nativeEnum(ComplianceReview).optional(),
371
- enabled: z.preprocess(
372
- (val) =>
373
- val === 'true' || val === '1'
374
- ? true
375
- : val === 'false' || val === '0'
376
- ? false
377
- : val,
378
- z.boolean().optional(),
379
- ),
378
+ enabled: StringToBooleanSchema.optional(),
380
379
  managedBy: z.nativeEnum(ManagedByType).optional(),
381
380
  versioningType: z.nativeEnum(OfferingVersioningType).optional(),
382
381
  combinedStatus: z.nativeEnum(OfferingStatus).optional(),
@@ -1,58 +1,268 @@
1
1
  import { extendZodWithOpenApi } from '@anatine/zod-openapi';
2
2
  import { z } from 'zod';
3
3
  import { TypeID } from 'typeid-js';
4
- import { accountIdSchema } from './account.types';
4
+ import { IBaseEntity } from './entity.types';
5
5
 
6
6
  extendZodWithOpenApi(z);
7
- export enum NotificationChannel {
7
+
8
+ export enum NotificationChannelType {
8
9
  EMAIL = 'EMAIL',
9
10
  SLACK = 'SLACK',
11
+ WEBHOOK = 'WEBHOOK',
10
12
  }
11
- export enum NotificationType {
12
- COMPLIANCE_TRADE_ALERT = 'COMPLIANCE_TRADE_ALERT',
13
- TRADE_ALERT = 'TRADE_ALERT',
13
+
14
+ export enum NotificationRecordStatus {
15
+ PENDING = 'PENDING',
16
+ SENT = 'SENT',
17
+ FAILED = 'FAILED',
14
18
  }
15
19
 
16
- export const notificationIdSchema = z.string().refine(
20
+ export const notificationChannelIdSchema = z.string().refine(
17
21
  (value) => {
18
22
  try {
19
23
  const tid = TypeID.fromString(value);
20
- return tid.getType() === 'notification';
24
+ return tid.getType() === 'notification_channel';
21
25
  } catch {
22
26
  return false;
23
27
  }
24
28
  },
25
29
  {
26
30
  message:
27
- 'Invalid notification ID format. Must be a valid TypeID with "notification" prefix.',
31
+ 'Invalid notification channel ID format. Must be a valid TypeID with "notification_channel" prefix.',
28
32
  },
29
33
  );
30
34
 
31
- export const SendNotificationZod = z.object({
32
- message: z.string(),
35
+ export const notificationChannelTriggerIdSchema = z.string().refine(
36
+ (value) => {
37
+ try {
38
+ const tid = TypeID.fromString(value);
39
+ return tid.getType() === 'notification_channel_trigger';
40
+ } catch {
41
+ return false;
42
+ }
43
+ },
44
+ {
45
+ message:
46
+ 'Invalid notification channel trigger ID format. Must be a valid TypeID with "notification_channel_trigger" prefix.',
47
+ },
48
+ );
49
+
50
+ export const notificationRecordIdSchema = z.string().refine(
51
+ (value) => {
52
+ try {
53
+ const tid = TypeID.fromString(value);
54
+ return tid.getType() === 'notification_record';
55
+ } catch {
56
+ return false;
57
+ }
58
+ },
59
+ {
60
+ message:
61
+ 'Invalid notification record ID format. Must be a valid TypeID with "notification_record" prefix.',
62
+ },
63
+ );
64
+
65
+ export const EmailChannelSettingsSchema = z.object({
66
+ recipients: z.array(z.string().email()).min(1),
67
+ subjectTemplate: z.string().optional(),
68
+ });
69
+ export type EmailChannelSettings = z.infer<typeof EmailChannelSettingsSchema>;
70
+
71
+ export const SlackChannelSettingsSchema = z
72
+ .object({
73
+ webhookUrl: z.string().url().optional(),
74
+ channelEmail: z.string().email().optional(),
75
+ })
76
+ .refine((data) => data.webhookUrl || data.channelEmail, {
77
+ message: 'Either webhookUrl or channelEmail is required',
78
+ });
79
+ export type SlackChannelSettings = z.infer<typeof SlackChannelSettingsSchema>;
80
+
81
+ export const WebhookChannelSettingsSchema = z.object({
82
+ url: z.string().url(),
83
+ method: z.enum(['POST', 'PUT']),
84
+ headers: z.record(z.string()).optional(),
85
+ authType: z.enum(['none', 'bearer', 'basic', 'api_key']).default('none'),
86
+ authValue: z.string().optional(),
87
+ });
88
+ export type WebhookChannelSettings = z.infer<
89
+ typeof WebhookChannelSettingsSchema
90
+ >;
91
+
92
+ export const NotificationChannelSettingsSchema = z.discriminatedUnion('type', [
93
+ z.object({
94
+ type: z.literal(NotificationChannelType.EMAIL),
95
+ config: EmailChannelSettingsSchema,
96
+ }),
97
+ z.object({
98
+ type: z.literal(NotificationChannelType.SLACK),
99
+ config: SlackChannelSettingsSchema,
100
+ }),
101
+ z.object({
102
+ type: z.literal(NotificationChannelType.WEBHOOK),
103
+ config: WebhookChannelSettingsSchema,
104
+ }),
105
+ ]);
106
+ export type NotificationChannelSettings = z.infer<
107
+ typeof NotificationChannelSettingsSchema
108
+ >;
109
+
110
+ export const EmailNotificationPayloadSchema = z.object({
111
+ to: z.array(z.string().email()),
33
112
  subject: z.string(),
34
- buttonText: z.string(),
35
- link: z.string(),
36
- debug: z.boolean().default(false),
37
- notificationChannel: z.nativeEnum(NotificationChannel),
38
- channelName: z.string(),
39
- channelEmail: z.string().email(),
40
- notificationType: z.nativeEnum(NotificationType),
113
+ body: z.string(),
114
+ html: z.string().optional(),
41
115
  });
42
- export type SendNotificationZod = z.infer<typeof SendNotificationZod>;
116
+ export type EmailNotificationPayload = z.infer<
117
+ typeof EmailNotificationPayloadSchema
118
+ >;
43
119
 
44
- const SlackSettingsSchema = z.object({
45
- channelName: z.string().min(1).max(50),
46
- channelEmail: z.string().email(),
120
+ export const SlackNotificationPayloadSchema = z.object({
121
+ webhookUrl: z.string().url().optional(),
122
+ channelEmail: z.string().email().optional(),
123
+ message: z.string(),
124
+ blocks: z.array(z.record(z.unknown())).optional(),
47
125
  });
126
+ export type SlackNotificationPayload = z.infer<
127
+ typeof SlackNotificationPayloadSchema
128
+ >;
48
129
 
49
- export const PostNotificationZod = z.object({
50
- accountId: accountIdSchema,
51
- notificationChannel: z.literal(NotificationChannel.SLACK), // Only Slack for now
52
- notificationType: z.nativeEnum(NotificationType),
53
- enabled: z.boolean().default(true),
54
- debug: z.boolean().default(false),
55
- settings: SlackSettingsSchema,
130
+ export const WebhookNotificationPayloadSchema = z.object({
131
+ url: z.string().url(),
132
+ method: z.enum(['POST', 'PUT']),
133
+ headers: z.record(z.string()),
134
+ body: z.record(z.unknown()),
56
135
  });
136
+ export type WebhookNotificationPayload = z.infer<
137
+ typeof WebhookNotificationPayloadSchema
138
+ >;
139
+
140
+ export const NotificationPayloadSchema = z.discriminatedUnion('type', [
141
+ z.object({
142
+ type: z.literal(NotificationChannelType.EMAIL),
143
+ data: EmailNotificationPayloadSchema,
144
+ }),
145
+ z.object({
146
+ type: z.literal(NotificationChannelType.SLACK),
147
+ data: SlackNotificationPayloadSchema,
148
+ }),
149
+ z.object({
150
+ type: z.literal(NotificationChannelType.WEBHOOK),
151
+ data: WebhookNotificationPayloadSchema,
152
+ }),
153
+ ]);
154
+ export type NotificationPayload = z.infer<typeof NotificationPayloadSchema>;
57
155
 
58
- export type PostNotificationZod = z.infer<typeof PostNotificationZod>;
156
+ export const EmailNotificationResponseSchema = z.object({
157
+ messageId: z.string().optional(),
158
+ accepted: z.array(z.string()).optional(),
159
+ rejected: z.array(z.string()).optional(),
160
+ });
161
+ export type EmailNotificationResponse = z.infer<
162
+ typeof EmailNotificationResponseSchema
163
+ >;
164
+
165
+ export const SlackNotificationResponseSchema = z.object({
166
+ ok: z.boolean().optional(),
167
+ error: z.string().optional(),
168
+ responseBody: z.string().optional(),
169
+ });
170
+ export type SlackNotificationResponse = z.infer<
171
+ typeof SlackNotificationResponseSchema
172
+ >;
173
+
174
+ export const WebhookNotificationResponseSchema = z.object({
175
+ statusCode: z.number(),
176
+ headers: z.record(z.string()).optional(),
177
+ body: z.unknown().optional(),
178
+ });
179
+ export type WebhookNotificationResponse = z.infer<
180
+ typeof WebhookNotificationResponseSchema
181
+ >;
182
+
183
+ export const NotificationResponseSchema = z.discriminatedUnion('type', [
184
+ z.object({
185
+ type: z.literal(NotificationChannelType.EMAIL),
186
+ data: EmailNotificationResponseSchema,
187
+ }),
188
+ z.object({
189
+ type: z.literal(NotificationChannelType.SLACK),
190
+ data: SlackNotificationResponseSchema,
191
+ }),
192
+ z.object({
193
+ type: z.literal(NotificationChannelType.WEBHOOK),
194
+ data: WebhookNotificationResponseSchema,
195
+ }),
196
+ ]);
197
+ export type NotificationResponse = z.infer<typeof NotificationResponseSchema>;
198
+
199
+ export const INotificationChannelZod = IBaseEntity.extend({
200
+ id: notificationChannelIdSchema.openapi({
201
+ example: 'notification_channel_01j5y5ghx8fvc83dmx3pznq7hv',
202
+ }),
203
+ accountSettingsId: z.string().openapi({
204
+ example: 'account_setting_01j5y5ghx8fvc83dmx3pznq7hv',
205
+ }),
206
+ channelType: z.nativeEnum(NotificationChannelType).openapi({
207
+ example: NotificationChannelType.SLACK,
208
+ }),
209
+ name: z.string().openapi({
210
+ example: 'Compliance Alerts',
211
+ }),
212
+ enabled: z.boolean().openapi({
213
+ example: true,
214
+ }),
215
+ settings: NotificationChannelSettingsSchema,
216
+ });
217
+ export type INotificationChannelZod = z.infer<typeof INotificationChannelZod>;
218
+
219
+ export const INotificationChannelTriggerZod = IBaseEntity.extend({
220
+ id: notificationChannelTriggerIdSchema.openapi({
221
+ example: 'notification_channel_trigger_01j5y5ghx8fvc83dmx3pznq7hv',
222
+ }),
223
+ notificationChannelId: notificationChannelIdSchema.openapi({
224
+ example: 'notification_channel_01j5y5ghx8fvc83dmx3pznq7hv',
225
+ }),
226
+ activityTypeId: z.string().openapi({
227
+ example: 'activity_type_01j5y5ghx8fvc83dmx3pznq7hv',
228
+ }),
229
+ enabled: z.boolean().openapi({
230
+ example: true,
231
+ }),
232
+ });
233
+ export type INotificationChannelTriggerZod = z.infer<
234
+ typeof INotificationChannelTriggerZod
235
+ >;
236
+
237
+ export const INotificationRecordZod = IBaseEntity.extend({
238
+ id: notificationRecordIdSchema.openapi({
239
+ example: 'notification_record_01j5y5ghx8fvc83dmx3pznq7hv',
240
+ }),
241
+ notificationChannelId: notificationChannelIdSchema.openapi({
242
+ example: 'notification_channel_01j5y5ghx8fvc83dmx3pznq7hv',
243
+ }),
244
+ activityId: z.string().nullable().openapi({
245
+ example: 'activity_01j5y5ghx8fvc83dmx3pznq7hv',
246
+ }),
247
+ targetTable: z.string().openapi({
248
+ example: 'trades',
249
+ }),
250
+ targetId: z.string().openapi({
251
+ example: 'trade_01j5y5ghx8fvc83dmx3pznq7hv',
252
+ }),
253
+ status: z.nativeEnum(NotificationRecordStatus).openapi({
254
+ example: NotificationRecordStatus.SENT,
255
+ }),
256
+ payload: NotificationPayloadSchema,
257
+ response: NotificationResponseSchema.nullable(),
258
+ errorMessage: z.string().nullable().openapi({
259
+ example: null,
260
+ }),
261
+ retryCount: z.number().openapi({
262
+ example: 0,
263
+ }),
264
+ sentAt: z.date().nullable().openapi({
265
+ example: new Date(),
266
+ }),
267
+ });
268
+ export type INotificationRecordZod = z.infer<typeof INotificationRecordZod>;
@@ -17,6 +17,7 @@ import {
17
17
  OfferingOnboardingStatus,
18
18
  AssetType,
19
19
  DurationType,
20
+ StringToBooleanSchema,
20
21
  } from './common.types';
21
22
  import { IBaseEntity } from './entity.types';
22
23
  import { fileIdSchema, FileZod } from './file.types';
@@ -230,6 +231,7 @@ export const PatchOffering = PatchOfferingBase.merge(
230
231
  .nullable()
231
232
  .optional(),
232
233
  tiers: z.array(z.number().positive()).nullable().optional(),
234
+ enableBonus: z.boolean().optional(),
233
235
  }),
234
236
  );
235
237
  export type PatchOffering = z.infer<typeof PatchOffering>;
@@ -276,6 +278,7 @@ export const PostComplianceOffering = PatchOfferingBase.merge(
276
278
  .default(AssetTemplateType.STANDARD)
277
279
  .openapi({ example: AssetTemplateType.STANDARD }),
278
280
  tiers: z.array(z.number().positive()).nullable().optional(),
281
+ enableBonus: z.boolean().default(false).optional(),
279
282
  }),
280
283
  ).superRefine(postAssetRefinement);
281
284
  export type PostComplianceOffering = z.infer<typeof PostComplianceOffering>;
@@ -344,15 +347,7 @@ export const OfferingFiltersZod = z.object({
344
347
  issuerId: z.lazy(() => issuerIdSchema).optional(),
345
348
  type: z.nativeEnum(OfferingType).optional(),
346
349
  status: z.nativeEnum(ComplianceReview).optional(),
347
- enabled: z.preprocess(
348
- (val) =>
349
- val === 'true' || val === '1'
350
- ? true
351
- : val === 'false' || val === '0'
352
- ? false
353
- : val,
354
- z.boolean().optional(),
355
- ),
350
+ enabled: StringToBooleanSchema.optional(),
356
351
  managedBy: z.nativeEnum(ManagedByType).optional(),
357
352
  versioningType: z.nativeEnum(OfferingVersioningType).optional(),
358
353
  combinedStatus: z.nativeEnum(OfferingStatus).optional(),
@@ -5,6 +5,7 @@ import {
5
5
  AccountStatus,
6
6
  AccountZod,
7
7
  IPaginationMeta,
8
+ StringToBooleanSchema,
8
9
  UrlSchema,
9
10
  } from './common.types';
10
11
  import { accountIdSchema } from './account.types';
@@ -73,15 +74,7 @@ export const SitesParamSchema = z.object({
73
74
  export const SitesFiltersZod = z.object({
74
75
  url: z.string().optional(),
75
76
  accountId: accountIdSchema.optional(),
76
- enabled: z.preprocess(
77
- (val) =>
78
- val === 'true' || val === '1'
79
- ? true
80
- : val === 'false' || val === '0'
81
- ? false
82
- : val,
83
- z.boolean().optional(),
84
- ),
77
+ enabled: StringToBooleanSchema.optional(),
85
78
  });
86
79
 
87
80
  const sitesInclude = z.enum(['account']);
@@ -8,6 +8,7 @@ import {
8
8
  IPaginationMeta,
9
9
  OfferingType,
10
10
  SignatureStatus,
11
+ StringToBooleanSchema,
11
12
  } from './common.types';
12
13
  import { fileIdSchema } from './file.types';
13
14
  import { accountIdSchema } from './account.types';
@@ -107,15 +108,7 @@ export type TradeLineItemQuery = z.infer<typeof TradeLineItemQuery>;
107
108
 
108
109
  export const TradeLineItemFiltersQuery = z.object({
109
110
  accountId: accountIdSchema.optional(),
110
- hasSubdoc: z.preprocess(
111
- (val) =>
112
- val === 'true' || val === '1'
113
- ? true
114
- : val === 'false' || val === '0'
115
- ? false
116
- : val,
117
- z.boolean().optional(),
118
- ),
111
+ hasSubdoc: StringToBooleanSchema.optional(),
119
112
  saStatus: z.nativeEnum(SignatureStatus).optional(),
120
113
  offeringId: z.lazy(() => offeringIdSchema).optional(),
121
114
  search: z.string().max(50).optional(),
@@ -39,7 +39,7 @@ import {
39
39
  import {
40
40
  tradeLineItemIdSchema,
41
41
  TradeLineItemZod,
42
- } from './trade-line-item.type';
42
+ } from './trade-line-item.types';
43
43
  import { TradeAdjustmentZod } from './trade-adjustment.type';
44
44
  import { TransactionZod } from './transaction.types';
45
45
  import { accountIdSchema } from './account.types';
@@ -1,10 +1,11 @@
1
+ import { z } from 'zod';
2
+ import { extendZodWithOpenApi } from '@anatine/zod-openapi';
1
3
  import { TypeID } from 'typeid-js';
2
4
  import {
3
5
  dateSchema,
4
6
  InvestorAccountType,
5
7
  numberPrecisionSchema,
6
8
  } from './common.types';
7
- import { z } from 'zod';
8
9
  import { IBaseEntity } from './entity.types';
9
10
  import { accountIdSchema } from './account.types';
10
11
  import {
@@ -18,7 +19,9 @@ import {
18
19
  investorAccountIdSchema,
19
20
  } from './investor-account.types';
20
21
  import { TransactionStatus, TransactionType } from './common.types';
22
+ import { userIdSchema } from './user.types';
21
23
  export { TransactionStatus, TransactionType };
24
+ extendZodWithOpenApi(z);
22
25
 
23
26
  export enum RefundPaymentMethod {
24
27
  CHECK = 'CHECK',
@@ -115,6 +118,14 @@ export type InvestorPostTransactionZod = z.infer<
115
118
  typeof InvestorPostTransactionZod
116
119
  >;
117
120
 
121
+ export const ClientPostTransactionZod = InvestorPostTransactionZod.extend({
122
+ userId: z
123
+ .lazy(() => userIdSchema)
124
+ .openapi({ example: 'user_01j5y5ghx5fg68d663j1fvy2x7' }),
125
+ });
126
+
127
+ export type ClientPostTransactionZod = z.infer<typeof ClientPostTransactionZod>;
128
+
118
129
  export const refundTransactionIdSchema = z.string().refine(
119
130
  (value) => {
120
131
  try {
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
+ import { extendZodWithOpenApi } from '@anatine/zod-openapi';
2
3
  import {
3
4
  AccountStatus,
4
5
  AccountWithoutUsersZod,
@@ -7,12 +8,11 @@ import {
7
8
  ManagedByType,
8
9
  OfferingType,
9
10
  PortalType,
11
+ StringToBooleanSchema,
10
12
  UserRole,
11
- UserStatus,
12
13
  UserType,
13
14
  } from './common.types';
14
15
  import { dateOrString, IBaseEntity } from './entity.types';
15
- import { extendZodWithOpenApi } from '@anatine/zod-openapi';
16
16
  import { PhoneZodSchema } from './phone.type';
17
17
  import { IInvestorAccount } from './investor-account.types';
18
18
  import { TradeZod } from './trade.types';
@@ -51,6 +51,11 @@ export const UserDeleteResponse = z.object({
51
51
  });
52
52
  export type UserDeleteResponse = z.infer<typeof UserDeleteResponse>;
53
53
 
54
+ export const UserRestoreResponse = z.object({
55
+ message: z.string(),
56
+ });
57
+ export type UserRestoreResponse = z.infer<typeof UserRestoreResponse>;
58
+
54
59
  export const GetMeResponse = IBaseEntity.extend({
55
60
  accountId: z.string().nullable(),
56
61
  accountName: z.string().nullable(),
@@ -59,7 +64,7 @@ export const GetMeResponse = IBaseEntity.extend({
59
64
  email: z.string().email(),
60
65
  provider: z.string(),
61
66
  active: z.boolean(),
62
- status: z.lazy(() => z.nativeEnum(UserStatus)),
67
+ locked: z.boolean(),
63
68
  lastLoginAt: dateOrString.nullable(),
64
69
  loginCount: z.number(),
65
70
  role: z.string(),
@@ -157,7 +162,7 @@ export const UserZod = IBaseEntity.extend({
157
162
  onboarding: z.string().nullable(),
158
163
  account: AccountWithoutUsersZod.optional(),
159
164
  active: z.boolean(),
160
- status: z.nativeEnum(UserStatus),
165
+ locked: z.boolean(),
161
166
  userLogin: IBaseEntity.extend({
162
167
  firstName: z.string(),
163
168
  lastName: z.string(),
@@ -179,27 +184,9 @@ export const UserFiltersZod = z.object({
179
184
  search: z.string().max(50).optional(),
180
185
  role: z.nativeEnum(UserRole).optional(),
181
186
  portal: z.string().optional(),
182
- status: z.nativeEnum(UserStatus).optional(),
183
- active: z
184
- .string()
185
- .optional()
186
- .refine((v) => !v || v === 'true' || v === 'false', {
187
- message: 'active must be a boolean string',
188
- })
189
- .transform((v) => {
190
- if (!v) return undefined;
191
- return v === 'true';
192
- }),
193
- twoFactorEnabled: z
194
- .string()
195
- .optional()
196
- .refine((v) => !v || v === 'true' || v === 'false', {
197
- message: 'twoFactorEnabled must be a boolean string',
198
- })
199
- .transform((v) => {
200
- if (!v) return undefined;
201
- return v === 'true';
202
- }),
187
+ locked: StringToBooleanSchema.optional(),
188
+ active: StringToBooleanSchema.optional(),
189
+ twoFactorEnabled: StringToBooleanSchema.optional(),
203
190
  });
204
191
 
205
192
  const usersInclude = z.enum(['account', 'role']);
@@ -274,7 +261,7 @@ export type IssuerUsersStatusUpdateResponse = z.infer<
274
261
  >;
275
262
 
276
263
  export const UpdateLockedStatus = z.object({
277
- status: z.nativeEnum(UserStatus),
264
+ locked: z.boolean(),
278
265
  });
279
266
 
280
267
  export type UpdateLockedStatus = z.infer<typeof UpdateLockedStatus>;
@@ -285,7 +272,7 @@ export const UsersSummaryFilterZod = z.object({
285
272
  portalType: z.nativeEnum(PortalType).optional(),
286
273
  search: z.string().trim().max(50).optional(),
287
274
  selectRole: z.nativeEnum(UserRole).optional(),
288
- status: z.nativeEnum(UserStatus).optional(),
275
+ locked: StringToBooleanSchema.optional(),
289
276
  });
290
277
  export type UsersSummaryFilterZod = z.infer<typeof UsersSummaryFilterZod>;
291
278
 
@@ -299,7 +286,7 @@ export const UsersSummaryZod = z.object({
299
286
  portalType: z.string(),
300
287
  loginCount: z.number().int(),
301
288
  lastLogin: z.date(),
302
- status: z.nativeEnum(UserStatus),
289
+ locked: z.boolean(),
303
290
  });
304
291
  export type UsersSummaryZod = z.infer<typeof UsersSummaryZod>;
305
292
 
@@ -10,7 +10,11 @@ import {
10
10
  userIdSchema,
11
11
  tradeIdSchema,
12
12
  } from '../../../common/types';
13
- import { PatchCartBody } from '../../../common/types/cart.types';
13
+ import {
14
+ PatchCartBody,
15
+ ClientPlacetradeBody,
16
+ PlaceTradeResponse,
17
+ } from '../../../common/types/cart.types';
14
18
 
15
19
  const c = initContract();
16
20
 
@@ -34,6 +38,22 @@ export const cartContract = c.router(
34
38
  500: InternalError,
35
39
  },
36
40
  },
41
+ postCheckout: {
42
+ summary: 'Place a trade (checkout button)',
43
+ method: 'POST',
44
+ path: '/checkout',
45
+ metadata: {
46
+ auth: true,
47
+ },
48
+ body: ClientPlacetradeBody,
49
+ responses: {
50
+ 200: PlaceTradeResponse,
51
+ 400: BadRequestError,
52
+ 401: UnauthorizedError,
53
+ 403: ForbiddenError,
54
+ 500: InternalError,
55
+ },
56
+ },
37
57
  patchCart: {
38
58
  summary: 'Patch a cart',
39
59
  method: 'PATCH',
@@ -19,6 +19,7 @@ import { sitesContract } from './sites';
19
19
  import { paymentMethodsContract } from './payment-methods';
20
20
  import { issuerPaymentMethodsContract } from './issuer-payment-methods';
21
21
  import { tradeLineItemsContract } from './trade-line-items';
22
+ import { clientsTransactionsContract } from './transactions';
22
23
 
23
24
  const c = initContract();
24
25
 
@@ -45,6 +46,7 @@ export const clientsContract = c.router(
45
46
  sites: sitesContract,
46
47
  tradeLineItems: tradeLineItemsContract,
47
48
  trades: tradesContract,
49
+ transactions: clientsTransactionsContract,
48
50
  },
49
51
  {
50
52
  pathPrefix: '/clients/api/v1/',
@@ -14,7 +14,7 @@ import {
14
14
  TradeLineItemQuery,
15
15
  TradeLineItemResponse,
16
16
  TradeLineItemUpdate,
17
- } from '../../../common/types/trade-line-item.type';
17
+ } from '../../../common/types/trade-line-item.types';
18
18
 
19
19
  const c = initContract();
20
20
 
@@ -26,7 +26,7 @@ import {
26
26
  PostTradeLineItem,
27
27
  TradeLineItemQuery,
28
28
  TradeLineItemResponse,
29
- } from '../../../common/types/trade-line-item.type';
29
+ } from '../../../common/types/trade-line-item.types';
30
30
 
31
31
  const c = initContract();
32
32
 
@@ -0,0 +1,37 @@
1
+ import { initContract } from '@ts-rest/core';
2
+ import {
3
+ BadRequestError,
4
+ InternalError,
5
+ NotFoundError,
6
+ UnauthorizedError,
7
+ } from '../../../common/types';
8
+ import {
9
+ ClientPostTransactionZod,
10
+ TransactionZod,
11
+ } from '../../../common/types/transaction.types';
12
+
13
+ const c = initContract();
14
+
15
+ export const clientsTransactionsContract = c.router(
16
+ {
17
+ postTransaction: {
18
+ summary: 'Create a transaction',
19
+ method: 'POST',
20
+ path: '',
21
+ metadata: {
22
+ auth: true,
23
+ },
24
+ body: ClientPostTransactionZod,
25
+ responses: {
26
+ 201: TransactionZod,
27
+ 400: BadRequestError,
28
+ 401: UnauthorizedError,
29
+ 404: NotFoundError,
30
+ 500: InternalError,
31
+ },
32
+ },
33
+ },
34
+ {
35
+ pathPrefix: 'transactions',
36
+ },
37
+ );
@@ -10,6 +10,8 @@ import {
10
10
  EstimateBonusTierCalculationResponseZod,
11
11
  EstimateBonusTierCalculationZod,
12
12
  IBonusTierList,
13
+ PurchaseCalculationResponseZod,
14
+ PurchaseCalculationZod,
13
15
  } from '../../../common/types/bonus-tier.types';
14
16
 
15
17
  const c = initContract();
@@ -32,6 +34,23 @@ export const bonusTiersContract = c.router(
32
34
  500: InternalError,
33
35
  },
34
36
  },
37
+ purchaseCalculation: {
38
+ summary:
39
+ '[ADMIN] Calculate the bonus shares that would be awarded for a trade',
40
+ method: 'POST',
41
+ path: '/purchase-calculation',
42
+ metadata: {
43
+ auth: true,
44
+ },
45
+ body: PurchaseCalculationZod,
46
+ responses: {
47
+ 200: PurchaseCalculationResponseZod,
48
+ 400: BadRequestError,
49
+ 401: UnauthorizedError,
50
+ 403: ForbiddenError,
51
+ 500: InternalError,
52
+ },
53
+ },
35
54
  postBonusTier: {
36
55
  summary: 'Create a new bonus tier',
37
56
  method: 'POST',
@@ -13,7 +13,7 @@ import {
13
13
  ReviewTradeLineItemStatus,
14
14
  TradeLineItemFiltersQuery,
15
15
  TradeLineItemResponse,
16
- } from '../../../common/types/trade-line-item.type';
16
+ } from '../../../common/types/trade-line-item.types';
17
17
 
18
18
  import { z } from 'zod';
19
19
  const c = initContract();
@@ -21,6 +21,7 @@ import {
21
21
  IssuersActiveStatusUpdateZod,
22
22
  UpdateLockedStatus,
23
23
  UpdateUserRoleZod,
24
+ UserRestoreResponse,
24
25
  } from '../../../common/types';
25
26
  import { z } from 'zod';
26
27
 
@@ -143,6 +144,26 @@ export const usersContract = c.router(
143
144
  500: InternalError,
144
145
  },
145
146
  },
147
+ restoreUser: {
148
+ summary: 'Restore user by id',
149
+ method: 'POST',
150
+ path: '/:id/restore',
151
+ metadata: {
152
+ auth: true,
153
+ },
154
+ pathParams: z.object({
155
+ id: userIdSchema,
156
+ }),
157
+ body: z.object({}),
158
+ responses: {
159
+ 200: UserRestoreResponse,
160
+ 400: BadRequestError,
161
+ 401: UnauthorizedError,
162
+ 403: ForbiddenError,
163
+ 404: NotFoundError,
164
+ 500: InternalError,
165
+ },
166
+ },
146
167
  updateActiveStatus: {
147
168
  summary: '[Admin] Update user active status',
148
169
  method: 'PATCH',
@@ -8,6 +8,8 @@ import {
8
8
  import {
9
9
  EstimateBonusTierCalculationResponseZod,
10
10
  EstimateBonusTierCalculationZod,
11
+ PurchaseCalculationResponseZod,
12
+ PurchaseCalculationZod,
11
13
  } from '../../../common/types/bonus-tier.types';
12
14
 
13
15
  const c = initContract();
@@ -30,6 +32,22 @@ export const bonusTiersContract = c.router(
30
32
  500: InternalError,
31
33
  },
32
34
  },
35
+ purchaseCalculation: {
36
+ summary: 'Calculate the bonus shares that would be awarded for a trade',
37
+ method: 'POST',
38
+ path: '/purchase-calculation',
39
+ metadata: {
40
+ auth: true,
41
+ },
42
+ body: PurchaseCalculationZod,
43
+ responses: {
44
+ 200: PurchaseCalculationResponseZod,
45
+ 400: BadRequestError,
46
+ 401: UnauthorizedError,
47
+ 403: ForbiddenError,
48
+ 500: InternalError,
49
+ },
50
+ },
33
51
  },
34
52
  {
35
53
  pathPrefix: 'bonus-tiers',
@@ -13,7 +13,7 @@ import {
13
13
  TradeLineItemResponse,
14
14
  TradeLineItemUpdate,
15
15
  TradeLineItemSignStatusUpdate,
16
- } from '../../../common/types/trade-line-item.type';
16
+ } from '../../../common/types/trade-line-item.types';
17
17
 
18
18
  const c = initContract();
19
19
 
@@ -10,6 +10,8 @@ import {
10
10
  EstimateBonusTierCalculationZod,
11
11
  IBonusTierList,
12
12
  PostBonusTierZod,
13
+ PurchaseCalculationResponseZod,
14
+ PurchaseCalculationZod,
13
15
  } from '../../../common/types/bonus-tier.types';
14
16
 
15
17
  const c = initContract();
@@ -32,6 +34,22 @@ export const bonusTiersContract = c.router(
32
34
  500: InternalError,
33
35
  },
34
36
  },
37
+ purchaseCalculation: {
38
+ summary: 'Calculate the bonus shares that would be awarded for a trade',
39
+ method: 'POST',
40
+ path: '/purchase-calculation',
41
+ metadata: {
42
+ auth: true,
43
+ },
44
+ body: PurchaseCalculationZod,
45
+ responses: {
46
+ 200: PurchaseCalculationResponseZod,
47
+ 400: BadRequestError,
48
+ 401: UnauthorizedError,
49
+ 403: ForbiddenError,
50
+ 500: InternalError,
51
+ },
52
+ },
35
53
  postBonusTier: {
36
54
  summary: 'Create a new bonus tier',
37
55
  method: 'POST',
@@ -17,8 +17,10 @@ import {
17
17
  DisbursementMissingConfigZod,
18
18
  DisbursementsIncludeQuery,
19
19
  DisbursementsMissingConfigQuery,
20
+ DisbursementPreviewZod,
20
21
  DisbursementSummaryZod,
21
22
  DisbursementZod,
23
+ GetDisbursementPreviewQueryZod,
22
24
  EligibleOfferingsFiltersZod,
23
25
  IPaginatedDisbursement,
24
26
  IPaginatedEligibleOffering,
@@ -148,6 +150,22 @@ export const disbursementsContract = c.router(
148
150
  500: InternalError,
149
151
  },
150
152
  },
153
+ getDisbursementPreview: {
154
+ summary: 'Get disbursement preview data for Step 2',
155
+ method: 'GET',
156
+ path: '/preview',
157
+ metadata: {
158
+ auth: true,
159
+ },
160
+ query: GetDisbursementPreviewQueryZod,
161
+ responses: {
162
+ 200: DisbursementPreviewZod,
163
+ 400: BadRequestError,
164
+ 401: UnauthorizedError,
165
+ 404: NotFoundError,
166
+ 500: InternalError,
167
+ },
168
+ },
151
169
  getEligibleOfferings: {
152
170
  summary: 'Get eligible offerings for disbursement',
153
171
  method: 'GET',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dalmore/api-contracts",
3
- "version": "0.0.0-dev.4eac826",
3
+ "version": "0.0.0-dev.4ec8ae0",
4
4
  "description": "Type-safe API contracts for Dalmore Client Portal",
5
5
  "main": "./contracts/index.ts",
6
6
  "types": "./contracts/index.ts",