@dalmore/api-contracts 0.0.0-dev.b5e5f0c → 0.0.0-dev.d070175
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.
- package/common/types/bonus-tier.types.ts +24 -0
- package/common/types/cart.types.ts +4 -1
- package/common/types/common.types.ts +12 -6
- package/common/types/dashboard.types.ts +2 -9
- package/common/types/disbursements.types.ts +97 -3
- package/common/types/i-will-do-it-later.types.ts +68 -0
- package/common/types/index.ts +1 -0
- package/common/types/individuals.types.ts +2 -15
- package/common/types/issuer-offering.types.ts +8 -9
- package/common/types/offering.types.ts +4 -9
- package/common/types/site.types.ts +2 -9
- package/common/types/{trade-line-item.type.ts → trade-line-item.types.ts} +2 -9
- package/common/types/trade.types.ts +1 -1
- package/common/types/transaction.types.ts +12 -1
- package/common/types/user.types.ts +15 -28
- package/contracts/clients/cart/index.ts +21 -1
- package/contracts/clients/index.ts +2 -0
- package/contracts/clients/trade-line-items/index.ts +1 -1
- package/contracts/clients/trades/index.ts +1 -1
- package/contracts/clients/transactions/index.ts +37 -0
- package/contracts/compliance/bonus-tiers/index.ts +19 -0
- package/contracts/compliance/trade-line-items/index.ts +1 -1
- package/contracts/compliance/users/index.ts +21 -0
- package/contracts/investors/bonus-tiers/index.ts +18 -0
- package/contracts/investors/individuals/index.ts +22 -0
- package/contracts/investors/trade-line-items/index.ts +1 -1
- package/contracts/issuers/bonus-tiers/index.ts +18 -0
- package/contracts/issuers/disbursements/index.ts +18 -0
- package/package.json +1 -1
|
@@ -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(),
|
|
@@ -200,11 +200,6 @@ export enum UserType {
|
|
|
200
200
|
DEMO = 'DEMO',
|
|
201
201
|
}
|
|
202
202
|
|
|
203
|
-
export enum UserStatus {
|
|
204
|
-
ACTIVE = 'ACTIVE',
|
|
205
|
-
LOCKED = 'LOCKED',
|
|
206
|
-
}
|
|
207
|
-
|
|
208
203
|
export enum UserRole {
|
|
209
204
|
API_KEY = 'API_KEY',
|
|
210
205
|
IMPORT = 'IMPORT',
|
|
@@ -306,7 +301,7 @@ export const AuthUserReq = BaseAuthReq.extend({
|
|
|
306
301
|
lastName: z.string(),
|
|
307
302
|
email: z.string().email(),
|
|
308
303
|
provider: z.string(),
|
|
309
|
-
|
|
304
|
+
locked: z.boolean(),
|
|
310
305
|
lastLoginAt: z.date().nullable(),
|
|
311
306
|
loginCount: z.number(),
|
|
312
307
|
requiresTwoFactorSetup: z.boolean().optional(),
|
|
@@ -1518,3 +1513,14 @@ export const SUBJECT_TYPE_MAP: Record<BulkExportType, string> = {
|
|
|
1518
1513
|
[BulkExportType.SECONDARY_CUSTOMERS]: 'Secondary Customers',
|
|
1519
1514
|
[BulkExportType.SECONDARY_TRADES]: 'Secondary Trades',
|
|
1520
1515
|
};
|
|
1516
|
+
|
|
1517
|
+
export const StringToBooleanSchema = z.preprocess(
|
|
1518
|
+
(val) =>
|
|
1519
|
+
val === 'true' || val === '1'
|
|
1520
|
+
? true
|
|
1521
|
+
: val === 'false' || val === '0'
|
|
1522
|
+
? false
|
|
1523
|
+
: val,
|
|
1524
|
+
z.boolean(),
|
|
1525
|
+
);
|
|
1526
|
+
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:
|
|
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 {
|
|
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(),
|
|
@@ -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
|
+
};
|
package/common/types/index.ts
CHANGED
|
@@ -42,6 +42,7 @@ 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';
|
|
45
46
|
export * from './payment-methods.types';
|
|
46
47
|
|
|
47
48
|
export enum Versions {
|
|
@@ -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
|
-
|
|
64
|
-
|
|
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:
|
|
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(),
|
|
@@ -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:
|
|
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:
|
|
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:
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
183
|
-
active:
|
|
184
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
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/',
|
|
@@ -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.
|
|
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',
|
|
@@ -14,6 +14,8 @@ import {
|
|
|
14
14
|
IIndividualZod,
|
|
15
15
|
BadRequestError,
|
|
16
16
|
InternalError,
|
|
17
|
+
IWillDoItLaterBodySchema,
|
|
18
|
+
IWillDoItLaterResponseSchema,
|
|
17
19
|
} from '../../../common/types';
|
|
18
20
|
import { z } from 'zod';
|
|
19
21
|
|
|
@@ -92,6 +94,26 @@ export const individualsContract = c.router(
|
|
|
92
94
|
403: ForbiddenError,
|
|
93
95
|
},
|
|
94
96
|
},
|
|
97
|
+
iWillDoItLater: {
|
|
98
|
+
summary: "I'll do it later - Create a task for later completion",
|
|
99
|
+
method: 'POST',
|
|
100
|
+
path: '/:id/defer',
|
|
101
|
+
metadata: {
|
|
102
|
+
auth: true,
|
|
103
|
+
},
|
|
104
|
+
pathParams: z.object({
|
|
105
|
+
id: individualIdSchema,
|
|
106
|
+
}),
|
|
107
|
+
body: IWillDoItLaterBodySchema,
|
|
108
|
+
responses: {
|
|
109
|
+
201: IWillDoItLaterResponseSchema,
|
|
110
|
+
400: BadRequestError,
|
|
111
|
+
401: UnauthorizedError,
|
|
112
|
+
403: ForbiddenError,
|
|
113
|
+
404: NotFoundError,
|
|
114
|
+
500: InternalError,
|
|
115
|
+
},
|
|
116
|
+
},
|
|
95
117
|
},
|
|
96
118
|
{
|
|
97
119
|
pathPrefix: 'individuals',
|
|
@@ -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