@dalmore/api-contracts 0.0.0-dev.2dc8e92 → 0.0.0-dev.4eac826
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/activity.types.ts +1 -1
- package/common/types/api-key-logs.types.ts +1 -1
- package/common/types/asset.types.ts +14 -14
- package/common/types/disbursements.types.ts +22 -0
- package/common/types/file.types.ts +20 -4
- package/common/types/i-will-do-it-later.types.ts +68 -0
- package/common/types/index.ts +2 -0
- package/common/types/issuer-offering.types.ts +100 -13
- package/common/types/issuer-payment-method.types.ts +41 -0
- package/common/types/issuer.types.ts +9 -0
- package/common/types/offering.types.ts +102 -11
- package/common/types/trade.types.ts +70 -0
- package/contracts/clients/cart/index.ts +60 -0
- package/contracts/clients/index.ts +8 -0
- package/contracts/clients/issuer-payment-methods/index.ts +39 -0
- package/contracts/clients/payment-methods/index.ts +85 -0
- package/contracts/clients/trade-line-items/index.ts +66 -0
- package/contracts/clients/trades/index.ts +64 -0
- package/contracts/investors/individuals/index.ts +22 -0
- package/contracts/issuers/disbursements/index.ts +18 -0
- package/package.json +1 -1
|
@@ -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(),
|
|
@@ -12,7 +12,7 @@ export const ApiLogsFiltersZod = z.object({
|
|
|
12
12
|
endpoint: z.string().optional(),
|
|
13
13
|
apiKeyId: apiKeyIdSchema.optional(),
|
|
14
14
|
method: z.nativeEnum(HttpMethod).optional(),
|
|
15
|
-
status: z.nativeEnum(HttpStatus).optional(),
|
|
15
|
+
status: z.preprocess(Number, z.nativeEnum(HttpStatus)).optional(),
|
|
16
16
|
from: dateSchema.optional().openapi({ example: 'MM/DD/YYYY' }),
|
|
17
17
|
to: dateSchema.optional().openapi({ example: 'MM/DD/YYYY' }),
|
|
18
18
|
});
|
|
@@ -29,7 +29,7 @@ export const assetIdSchema = z.string().refine(
|
|
|
29
29
|
message: `Invalid asset ID format. Must be a valid TypeID with "asset" prefix. Example: asset_01j5y5ghx5fg68d663j1fvy2x7`,
|
|
30
30
|
},
|
|
31
31
|
);
|
|
32
|
-
export enum
|
|
32
|
+
export enum AssetTemplateType {
|
|
33
33
|
STANDARD = 'STANDARD',
|
|
34
34
|
TIERED = 'TIERED',
|
|
35
35
|
}
|
|
@@ -51,7 +51,7 @@ export const IAsset = IBaseEntity.extend({
|
|
|
51
51
|
.lazy(() => IOffering)
|
|
52
52
|
.optional()
|
|
53
53
|
.nullable(), // Use z.lazy here
|
|
54
|
-
template: z.nativeEnum(
|
|
54
|
+
template: z.nativeEnum(AssetTemplateType),
|
|
55
55
|
tiers: z.array(z.number().positive()).nullable(),
|
|
56
56
|
enableBonus: z.boolean(),
|
|
57
57
|
});
|
|
@@ -102,16 +102,16 @@ const PostAssetBase = z.object({
|
|
|
102
102
|
.optional()
|
|
103
103
|
.openapi({ example: DurationType.DAY }),
|
|
104
104
|
template: z
|
|
105
|
-
.nativeEnum(
|
|
106
|
-
.default(
|
|
107
|
-
.openapi({ example:
|
|
105
|
+
.nativeEnum(AssetTemplateType)
|
|
106
|
+
.default(AssetTemplateType.STANDARD)
|
|
107
|
+
.openapi({ example: AssetTemplateType.STANDARD }),
|
|
108
108
|
tiers: z.array(z.number().positive()).nullable().optional(),
|
|
109
109
|
enableBonus: z.boolean().default(false).openapi({ example: false }),
|
|
110
110
|
});
|
|
111
111
|
|
|
112
|
-
const postAssetRefinement = (data: any, ctx: any) => {
|
|
112
|
+
export const postAssetRefinement = (data: any, ctx: any) => {
|
|
113
113
|
// If type is bond, yield and duration must be provided (cannot be null or undefined)
|
|
114
|
-
if (data.type === AssetType.BOND) {
|
|
114
|
+
if (data.assetType === AssetType.BOND || data.type === AssetType.BOND) {
|
|
115
115
|
if (data.yield === null || data.yield === undefined) {
|
|
116
116
|
ctx.addIssue({
|
|
117
117
|
path: ['yield'],
|
|
@@ -139,7 +139,7 @@ const postAssetRefinement = (data: any, ctx: any) => {
|
|
|
139
139
|
}
|
|
140
140
|
|
|
141
141
|
// If type is stock, yield and duration must be either null or undefined
|
|
142
|
-
if (data.type === AssetType.STOCK) {
|
|
142
|
+
if (data.assetType === AssetType.STOCK || data.type === AssetType.STOCK) {
|
|
143
143
|
if (data.yield !== null && data.yield !== undefined) {
|
|
144
144
|
ctx.addIssue({
|
|
145
145
|
path: ['yield'],
|
|
@@ -162,7 +162,7 @@ const postAssetRefinement = (data: any, ctx: any) => {
|
|
|
162
162
|
});
|
|
163
163
|
}
|
|
164
164
|
}
|
|
165
|
-
if (data.template ===
|
|
165
|
+
if (data.template === AssetTemplateType.TIERED) {
|
|
166
166
|
if (data.tiers === null || data.tiers === undefined) {
|
|
167
167
|
ctx.addIssue({
|
|
168
168
|
path: ['tiers'],
|
|
@@ -172,7 +172,7 @@ const postAssetRefinement = (data: any, ctx: any) => {
|
|
|
172
172
|
}
|
|
173
173
|
}
|
|
174
174
|
// If template is STANDARD, tiers must be null or undefined
|
|
175
|
-
if (data.template ===
|
|
175
|
+
if (data.template === AssetTemplateType.STANDARD) {
|
|
176
176
|
if (data.tiers !== null && data.tiers !== undefined) {
|
|
177
177
|
ctx.addIssue({
|
|
178
178
|
path: ['tiers'],
|
|
@@ -233,9 +233,9 @@ export const PutAsset = z.object({
|
|
|
233
233
|
.optional()
|
|
234
234
|
.openapi({ example: DurationType.DAY }),
|
|
235
235
|
template: z
|
|
236
|
-
.nativeEnum(
|
|
237
|
-
.default(
|
|
238
|
-
.openapi({ example:
|
|
236
|
+
.nativeEnum(AssetTemplateType)
|
|
237
|
+
.default(AssetTemplateType.STANDARD)
|
|
238
|
+
.openapi({ example: AssetTemplateType.STANDARD })
|
|
239
239
|
.nullable()
|
|
240
240
|
.optional(),
|
|
241
241
|
tiers: z.array(z.number().positive()).nullable().optional(),
|
|
@@ -262,7 +262,7 @@ export const AssetsIncludeQuery = z.object({
|
|
|
262
262
|
assetsInclude.options.includes(include as any),
|
|
263
263
|
),
|
|
264
264
|
{
|
|
265
|
-
message: `Invalid include option provided. Valid options are: ${assetsInclude.options.join(',
|
|
265
|
+
message: `Invalid include option provided. Valid options are: ${assetsInclude.options.join(',')}`,
|
|
266
266
|
},
|
|
267
267
|
)
|
|
268
268
|
.openapi({
|
|
@@ -308,3 +308,25 @@ export const DisbursementSummaryZod = z.object({
|
|
|
308
308
|
amountToBeTransferred: z.number(),
|
|
309
309
|
});
|
|
310
310
|
export type DisbursementSummaryZod = z.infer<typeof DisbursementSummaryZod>;
|
|
311
|
+
|
|
312
|
+
export const EligibleOfferingZod = z.object({
|
|
313
|
+
offeringId: offeringIdSchema,
|
|
314
|
+
offeringName: z.string(),
|
|
315
|
+
availableAmount: z.number(),
|
|
316
|
+
});
|
|
317
|
+
export type EligibleOfferingZod = z.infer<typeof EligibleOfferingZod>;
|
|
318
|
+
|
|
319
|
+
export const IPaginatedEligibleOffering = z.object({
|
|
320
|
+
items: z.array(EligibleOfferingZod),
|
|
321
|
+
meta: IPaginationMeta,
|
|
322
|
+
});
|
|
323
|
+
export type IPaginatedEligibleOffering = z.infer<
|
|
324
|
+
typeof IPaginatedEligibleOffering
|
|
325
|
+
>;
|
|
326
|
+
|
|
327
|
+
export const EligibleOfferingsFiltersZod = z.object({
|
|
328
|
+
search: z.string().optional(),
|
|
329
|
+
});
|
|
330
|
+
export type EligibleOfferingsFiltersZod = z.infer<
|
|
331
|
+
typeof EligibleOfferingsFiltersZod
|
|
332
|
+
>;
|
|
@@ -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(),
|
|
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
|
+
};
|
package/common/types/index.ts
CHANGED
|
@@ -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',
|
|
@@ -8,10 +8,12 @@ import {
|
|
|
8
8
|
ManagedByType,
|
|
9
9
|
OfferingVersioningType,
|
|
10
10
|
ComplianceReview,
|
|
11
|
+
DurationType,
|
|
12
|
+
AssetType,
|
|
11
13
|
} from './common.types';
|
|
12
14
|
import { IBaseEntity } from './entity.types';
|
|
13
15
|
import { IIssuer, issuerIdSchema } from './issuer.types';
|
|
14
|
-
import { IAsset } from './asset.types';
|
|
16
|
+
import { IAsset, postAssetRefinement, AssetTemplateType } from './asset.types';
|
|
15
17
|
import { fileIdSchema, FileZod } from './file.types';
|
|
16
18
|
import { accountIdSchema } from './account.types';
|
|
17
19
|
|
|
@@ -128,20 +130,59 @@ export const PostIssuerOffering = z
|
|
|
128
130
|
.nullable()
|
|
129
131
|
.openapi({ example: 'This is a description of the offering.' }),
|
|
130
132
|
managedBy: z.nativeEnum(ManagedByType).optional(),
|
|
133
|
+
assetName: z.string().min(2).max(50).openapi({ example: 'Asset name' }),
|
|
134
|
+
assetType: z.nativeEnum(AssetType).openapi({ example: AssetType.STOCK }),
|
|
135
|
+
pricePerUnit: z
|
|
136
|
+
.number()
|
|
137
|
+
.min(0.01)
|
|
138
|
+
.max(10000000000)
|
|
139
|
+
.nullable()
|
|
140
|
+
.openapi({ example: 2000 }),
|
|
141
|
+
totalUnits: z
|
|
142
|
+
.number()
|
|
143
|
+
.min(1)
|
|
144
|
+
.max(10000000000)
|
|
145
|
+
.nullable()
|
|
146
|
+
.openapi({ example: 5200 }),
|
|
147
|
+
yield: z
|
|
148
|
+
.number()
|
|
149
|
+
.min(0.01)
|
|
150
|
+
.max(10000000000)
|
|
151
|
+
.nullable()
|
|
152
|
+
.optional()
|
|
153
|
+
.openapi({ example: 1200 }),
|
|
154
|
+
duration: z
|
|
155
|
+
.number()
|
|
156
|
+
.min(1)
|
|
157
|
+
.max(1000)
|
|
158
|
+
.nullable()
|
|
159
|
+
.optional()
|
|
160
|
+
.openapi({ example: 1 }),
|
|
161
|
+
durationType: z
|
|
162
|
+
.nativeEnum(DurationType)
|
|
163
|
+
.nullable()
|
|
164
|
+
.optional()
|
|
165
|
+
.openapi({ example: DurationType.DAY }),
|
|
166
|
+
template: z
|
|
167
|
+
.nativeEnum(AssetTemplateType)
|
|
168
|
+
.default(AssetTemplateType.STANDARD)
|
|
169
|
+
.openapi({ example: AssetTemplateType.STANDARD }),
|
|
170
|
+
tiers: z.array(z.number().positive()).nullable().optional(),
|
|
131
171
|
})
|
|
132
|
-
.
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
if (data.minInvestment
|
|
136
|
-
|
|
172
|
+
.superRefine((data, ctx) => {
|
|
173
|
+
// Check if both values are present, and if so, ensure minInvestment is less than maxInvestment
|
|
174
|
+
if (data.minInvestment && data.maxInvestment) {
|
|
175
|
+
if (data.minInvestment >= data.maxInvestment) {
|
|
176
|
+
ctx.addIssue({
|
|
177
|
+
path: ['minInvestment'],
|
|
178
|
+
message: 'Minimum investment must be less than maximum investment.',
|
|
179
|
+
code: z.ZodIssueCode.custom,
|
|
180
|
+
});
|
|
137
181
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
path: ['minInvestment'],
|
|
143
|
-
},
|
|
144
|
-
);
|
|
182
|
+
}
|
|
183
|
+
// Apply asset-specific refinements
|
|
184
|
+
postAssetRefinement(data, ctx);
|
|
185
|
+
});
|
|
145
186
|
|
|
146
187
|
export type PostIssuerOffering = z.infer<typeof PostIssuerOffering>;
|
|
147
188
|
export const PatchIssuerOffering = z.object({
|
|
@@ -212,6 +253,52 @@ export const PatchIssuerOffering = z.object({
|
|
|
212
253
|
managedBy: z.nativeEnum(ManagedByType).optional(),
|
|
213
254
|
showTotalRaised: z.boolean().optional(),
|
|
214
255
|
issuerId: issuerIdSchema.optional(),
|
|
256
|
+
assetName: z.string().min(2).max(50).optional().openapi({ example: 'Z' }),
|
|
257
|
+
assetType: z
|
|
258
|
+
.nativeEnum(AssetType)
|
|
259
|
+
.optional()
|
|
260
|
+
.openapi({ example: AssetType.STOCK }),
|
|
261
|
+
pricePerUnit: z
|
|
262
|
+
.number()
|
|
263
|
+
.min(0.01)
|
|
264
|
+
.max(10000000000)
|
|
265
|
+
.nullable()
|
|
266
|
+
.optional()
|
|
267
|
+
.openapi({ example: 2000 }),
|
|
268
|
+
totalUnits: z
|
|
269
|
+
.number()
|
|
270
|
+
.min(1)
|
|
271
|
+
.max(10000000000)
|
|
272
|
+
.nullable()
|
|
273
|
+
.optional()
|
|
274
|
+
.openapi({ example: 5200 }),
|
|
275
|
+
yield: z
|
|
276
|
+
.number()
|
|
277
|
+
.min(0.01)
|
|
278
|
+
.max(10000000000)
|
|
279
|
+
.nullable()
|
|
280
|
+
.optional()
|
|
281
|
+
.openapi({ example: 1200 }),
|
|
282
|
+
duration: z
|
|
283
|
+
.number()
|
|
284
|
+
.min(1)
|
|
285
|
+
.max(1000)
|
|
286
|
+
.nullable()
|
|
287
|
+
.optional()
|
|
288
|
+
.openapi({ example: 1 }),
|
|
289
|
+
durationType: z
|
|
290
|
+
.nativeEnum(DurationType)
|
|
291
|
+
.nullable()
|
|
292
|
+
.optional()
|
|
293
|
+
.openapi({ example: DurationType.DAY }),
|
|
294
|
+
template: z
|
|
295
|
+
.nativeEnum(AssetTemplateType)
|
|
296
|
+
.default(AssetTemplateType.STANDARD)
|
|
297
|
+
.openapi({ example: AssetTemplateType.STANDARD })
|
|
298
|
+
.nullable()
|
|
299
|
+
.optional(),
|
|
300
|
+
tiers: z.array(z.number().positive()).nullable().optional(),
|
|
301
|
+
enabled: z.boolean().optional(),
|
|
215
302
|
});
|
|
216
303
|
export type PatchIssuerOffering = z.infer<typeof PatchIssuerOffering>;
|
|
217
304
|
|
|
@@ -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 }),
|
|
@@ -15,6 +15,8 @@ import {
|
|
|
15
15
|
SortBy,
|
|
16
16
|
OfferingVersioningType,
|
|
17
17
|
OfferingOnboardingStatus,
|
|
18
|
+
AssetType,
|
|
19
|
+
DurationType,
|
|
18
20
|
} from './common.types';
|
|
19
21
|
import { IBaseEntity } from './entity.types';
|
|
20
22
|
import { fileIdSchema, FileZod } from './file.types';
|
|
@@ -24,6 +26,7 @@ import {
|
|
|
24
26
|
InvestorsOfferingsIncludeQuery,
|
|
25
27
|
} from './investors-offering.types';
|
|
26
28
|
import { OfferingStatus } from './issuer-offering.types';
|
|
29
|
+
import { postAssetRefinement, AssetTemplateType } from './asset.types';
|
|
27
30
|
|
|
28
31
|
export enum OfferingFeeType {
|
|
29
32
|
FIXED = 'FIXED',
|
|
@@ -115,7 +118,7 @@ export const IPaginatedOffering = z.object({
|
|
|
115
118
|
});
|
|
116
119
|
export type IPaginatedOffering = z.infer<typeof IPaginatedOffering>;
|
|
117
120
|
|
|
118
|
-
export const
|
|
121
|
+
export const PatchOfferingBase = z.object({
|
|
119
122
|
name: z.string().optional(),
|
|
120
123
|
description: z.string().nullable().optional(),
|
|
121
124
|
tid: z.string().optional(),
|
|
@@ -148,8 +151,8 @@ export const PatchOffering = z.object({
|
|
|
148
151
|
.openapi({ example: 5000 })
|
|
149
152
|
.optional()
|
|
150
153
|
.nullable(),
|
|
151
|
-
startAt: dateSchema.optional(),
|
|
152
|
-
endAt: dateSchema.optional(),
|
|
154
|
+
startAt: dateSchema.optional().openapi({ example: '10/20/2024' }),
|
|
155
|
+
endAt: dateSchema.optional().openapi({ example: '10/27/2024' }),
|
|
153
156
|
platform: z.string().optional(),
|
|
154
157
|
coverArtId: z
|
|
155
158
|
.lazy(() => fileIdSchema)
|
|
@@ -175,16 +178,106 @@ export const PatchOffering = z.object({
|
|
|
175
178
|
showTotalRaised: z.boolean().optional(),
|
|
176
179
|
issuerId: issuerIdSchema.optional(),
|
|
177
180
|
});
|
|
178
|
-
|
|
181
|
+
export const PatchOffering = PatchOfferingBase.merge(
|
|
182
|
+
z.object({
|
|
183
|
+
assetName: z
|
|
184
|
+
.string()
|
|
185
|
+
.min(2)
|
|
186
|
+
.max(50)
|
|
187
|
+
.optional()
|
|
188
|
+
.openapi({ example: 'Asset name' }),
|
|
189
|
+
assetType: z
|
|
190
|
+
.nativeEnum(AssetType)
|
|
191
|
+
.optional()
|
|
192
|
+
.openapi({ example: AssetType.STOCK }),
|
|
193
|
+
pricePerUnit: z
|
|
194
|
+
.number()
|
|
195
|
+
.min(0.01)
|
|
196
|
+
.max(10000000000)
|
|
197
|
+
.nullable()
|
|
198
|
+
.optional()
|
|
199
|
+
.openapi({ example: 2000 }),
|
|
200
|
+
totalUnits: z
|
|
201
|
+
.number()
|
|
202
|
+
.min(1)
|
|
203
|
+
.max(10000000000)
|
|
204
|
+
.nullable()
|
|
205
|
+
.optional()
|
|
206
|
+
.openapi({ example: 5200 }),
|
|
207
|
+
yield: z
|
|
208
|
+
.number()
|
|
209
|
+
.min(0.01)
|
|
210
|
+
.max(10000000000)
|
|
211
|
+
.nullable()
|
|
212
|
+
.optional()
|
|
213
|
+
.openapi({ example: 1200 }),
|
|
214
|
+
duration: z
|
|
215
|
+
.number()
|
|
216
|
+
.min(1)
|
|
217
|
+
.max(1000)
|
|
218
|
+
.nullable()
|
|
219
|
+
.optional()
|
|
220
|
+
.openapi({ example: 1 }),
|
|
221
|
+
durationType: z
|
|
222
|
+
.nativeEnum(DurationType)
|
|
223
|
+
.nullable()
|
|
224
|
+
.optional()
|
|
225
|
+
.openapi({ example: DurationType.DAY }),
|
|
226
|
+
template: z
|
|
227
|
+
.nativeEnum(AssetTemplateType)
|
|
228
|
+
.default(AssetTemplateType.STANDARD)
|
|
229
|
+
.openapi({ example: AssetTemplateType.STANDARD })
|
|
230
|
+
.nullable()
|
|
231
|
+
.optional(),
|
|
232
|
+
tiers: z.array(z.number().positive()).nullable().optional(),
|
|
233
|
+
}),
|
|
234
|
+
);
|
|
179
235
|
export type PatchOffering = z.infer<typeof PatchOffering>;
|
|
180
236
|
|
|
181
|
-
export const PostComplianceOffering =
|
|
237
|
+
export const PostComplianceOffering = PatchOfferingBase.merge(
|
|
182
238
|
z.object({
|
|
183
239
|
accountId: accountIdSchema,
|
|
240
|
+
managedBy: z.nativeEnum(ManagedByType).optional(),
|
|
241
|
+
assetName: z.string().min(2).max(50).openapi({ example: 'Asset name' }),
|
|
242
|
+
assetType: z.nativeEnum(AssetType).openapi({ example: AssetType.STOCK }),
|
|
243
|
+
pricePerUnit: z
|
|
244
|
+
.number()
|
|
245
|
+
.min(0.01)
|
|
246
|
+
.max(10000000000)
|
|
247
|
+
.nullable()
|
|
248
|
+
.openapi({ example: 2000 }),
|
|
249
|
+
totalUnits: z
|
|
250
|
+
.number()
|
|
251
|
+
.min(1)
|
|
252
|
+
.max(10000000000)
|
|
253
|
+
.nullable()
|
|
254
|
+
.openapi({ example: 5200 }),
|
|
255
|
+
yield: z
|
|
256
|
+
.number()
|
|
257
|
+
.min(0.01)
|
|
258
|
+
.max(10000000000)
|
|
259
|
+
.nullable()
|
|
260
|
+
.optional()
|
|
261
|
+
.openapi({ example: 1200 }),
|
|
262
|
+
duration: z
|
|
263
|
+
.number()
|
|
264
|
+
.min(1)
|
|
265
|
+
.max(1000)
|
|
266
|
+
.nullable()
|
|
267
|
+
.optional()
|
|
268
|
+
.openapi({ example: 1 }),
|
|
269
|
+
durationType: z
|
|
270
|
+
.nativeEnum(DurationType)
|
|
271
|
+
.nullable()
|
|
272
|
+
.optional()
|
|
273
|
+
.openapi({ example: DurationType.DAY }),
|
|
274
|
+
template: z
|
|
275
|
+
.nativeEnum(AssetTemplateType)
|
|
276
|
+
.default(AssetTemplateType.STANDARD)
|
|
277
|
+
.openapi({ example: AssetTemplateType.STANDARD }),
|
|
278
|
+
tiers: z.array(z.number().positive()).nullable().optional(),
|
|
184
279
|
}),
|
|
185
|
-
).
|
|
186
|
-
managedBy: z.nativeEnum(ManagedByType).optional(),
|
|
187
|
-
});
|
|
280
|
+
).superRefine(postAssetRefinement);
|
|
188
281
|
export type PostComplianceOffering = z.infer<typeof PostComplianceOffering>;
|
|
189
282
|
|
|
190
283
|
export const offeringsInclude = z.enum([
|
|
@@ -546,11 +639,9 @@ export type PaginatedPendingOfferingSummaryResponse = z.infer<
|
|
|
546
639
|
>;
|
|
547
640
|
|
|
548
641
|
export type OfferingUpdateFields = {
|
|
549
|
-
platform?: string;
|
|
550
|
-
platformSettings?: string | null;
|
|
551
642
|
managedBy?: ManagedByType | null;
|
|
552
|
-
enabled?: boolean;
|
|
553
643
|
showTotalRaised?: boolean;
|
|
644
|
+
enabled?: boolean;
|
|
554
645
|
};
|
|
555
646
|
|
|
556
647
|
export const ReviewOfferingOnboarding = z.object({
|
|
@@ -55,8 +55,71 @@ import {
|
|
|
55
55
|
} from './secondary-trade.types';
|
|
56
56
|
import { InvestorAccount } from '../../investor-accounts/entities/investor-account.entity';
|
|
57
57
|
import { Trade } from '../../trades/entities/trade.entity';
|
|
58
|
+
import { fileIdSchema } from './file.types';
|
|
58
59
|
|
|
59
60
|
extendZodWithOpenApi(z);
|
|
61
|
+
|
|
62
|
+
// Zod schemas for attach subdoc endpoints
|
|
63
|
+
export const PostAttachSubdocBody = z.object({
|
|
64
|
+
lineItemId: tradeLineItemIdSchema.openapi({
|
|
65
|
+
example: 'trade_line_item_01kctsycw3fq7sj6hedvy62cja',
|
|
66
|
+
}),
|
|
67
|
+
fileId: z
|
|
68
|
+
.lazy(() => fileIdSchema)
|
|
69
|
+
.openapi({ example: 'file_01je6ht4b8fbmttkzh2hs82xqp' }),
|
|
70
|
+
primarySignatureStatus: z
|
|
71
|
+
.nativeEnum(SignatureStatus)
|
|
72
|
+
.openapi({ example: 'SIGNED' }),
|
|
73
|
+
secondarySignatureStatus: z
|
|
74
|
+
.nativeEnum(SignatureStatus)
|
|
75
|
+
.optional()
|
|
76
|
+
.openapi({ example: 'SIGNED' }),
|
|
77
|
+
});
|
|
78
|
+
export type PostAttachSubdocBody = z.infer<typeof PostAttachSubdocBody>;
|
|
79
|
+
|
|
80
|
+
export const PutAttachSubdocBody = z.object({
|
|
81
|
+
lineItemId: tradeLineItemIdSchema
|
|
82
|
+
.optional()
|
|
83
|
+
.openapi({ example: 'trade_line_item_01kctsycw3fq7sj6hedvy62cja' }),
|
|
84
|
+
fileId: z
|
|
85
|
+
.lazy(() => fileIdSchema)
|
|
86
|
+
.optional()
|
|
87
|
+
.openapi({ example: 'file_01je6ht4b8fbmttkzh2hs82xqp' }),
|
|
88
|
+
primarySignatureStatus: z
|
|
89
|
+
.nativeEnum(SignatureStatus)
|
|
90
|
+
.optional()
|
|
91
|
+
.openapi({ example: 'SIGNED' }),
|
|
92
|
+
secondarySignatureStatus: z
|
|
93
|
+
.nativeEnum(SignatureStatus)
|
|
94
|
+
.optional()
|
|
95
|
+
.openapi({ example: 'SIGNED' }),
|
|
96
|
+
});
|
|
97
|
+
export type PutAttachSubdocBody = z.infer<typeof PutAttachSubdocBody>;
|
|
98
|
+
|
|
99
|
+
export const PatchSubdocSignatureBody = z.object({
|
|
100
|
+
lineItemId: tradeLineItemIdSchema.optional().openapi({
|
|
101
|
+
example: 'trade_line_item_01kctsycw3fq7sj6hedvy62cja',
|
|
102
|
+
description:
|
|
103
|
+
'Optional. If not provided, updates the first line item with an attached subdoc. Required for trades with multiple line items.',
|
|
104
|
+
}),
|
|
105
|
+
primarySignatureStatus: z.nativeEnum(SignatureStatus).optional().openapi({
|
|
106
|
+
example: 'SIGNED',
|
|
107
|
+
description: 'Primary signer signature status',
|
|
108
|
+
}),
|
|
109
|
+
secondarySignatureStatus: z.nativeEnum(SignatureStatus).optional().openapi({
|
|
110
|
+
example: 'SIGNED',
|
|
111
|
+
description:
|
|
112
|
+
'Secondary signer signature status. Only applicable for JOINT investor accounts.',
|
|
113
|
+
}),
|
|
114
|
+
});
|
|
115
|
+
export type PatchSubdocSignatureBody = z.infer<typeof PatchSubdocSignatureBody>;
|
|
116
|
+
|
|
117
|
+
export const AttachSubdocResponse = z.object({
|
|
118
|
+
success: z.boolean(),
|
|
119
|
+
message: z.string(),
|
|
120
|
+
});
|
|
121
|
+
export type AttachSubdocResponse = z.infer<typeof AttachSubdocResponse>;
|
|
122
|
+
|
|
60
123
|
export const CheckResultsSchema = z.object({
|
|
61
124
|
fundingStatus: z.boolean(),
|
|
62
125
|
agreementStatus: z.boolean(),
|
|
@@ -202,6 +265,13 @@ export const PatchSaLogSchema = z.object({
|
|
|
202
265
|
|
|
203
266
|
export type PatchSaLogSchema = z.infer<typeof PatchSaLogSchema>;
|
|
204
267
|
|
|
268
|
+
export const TradeBalanceResultZod = z.object({
|
|
269
|
+
tradeAdjustments: z.number().multipleOf(0.01),
|
|
270
|
+
chargedAmount: z.number().multipleOf(0.01),
|
|
271
|
+
balance: z.number().multipleOf(0.01),
|
|
272
|
+
});
|
|
273
|
+
export type TradeBalanceResultZod = z.infer<typeof TradeBalanceResultZod>;
|
|
274
|
+
|
|
205
275
|
export const TradeZod = IBaseEntity.extend({
|
|
206
276
|
investorAccountId: z.lazy(() => investorAccountIdSchema.nullable()),
|
|
207
277
|
accountId: accountIdSchema.nullable(),
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { initContract } from '@ts-rest/core';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import {
|
|
4
|
+
UnauthorizedError,
|
|
5
|
+
ForbiddenError,
|
|
6
|
+
NotFoundError,
|
|
7
|
+
BadRequestError,
|
|
8
|
+
InternalError,
|
|
9
|
+
TradeZod,
|
|
10
|
+
userIdSchema,
|
|
11
|
+
tradeIdSchema,
|
|
12
|
+
} from '../../../common/types';
|
|
13
|
+
import { PatchCartBody } from '../../../common/types/cart.types';
|
|
14
|
+
|
|
15
|
+
const c = initContract();
|
|
16
|
+
|
|
17
|
+
export const cartContract = c.router(
|
|
18
|
+
{
|
|
19
|
+
getTradeCart: {
|
|
20
|
+
summary: 'Get carts (Trade.status = CART)',
|
|
21
|
+
method: 'GET',
|
|
22
|
+
path: '',
|
|
23
|
+
metadata: {
|
|
24
|
+
auth: true,
|
|
25
|
+
},
|
|
26
|
+
query: z.object({
|
|
27
|
+
userId: userIdSchema,
|
|
28
|
+
}),
|
|
29
|
+
responses: {
|
|
30
|
+
200: TradeZod,
|
|
31
|
+
401: UnauthorizedError,
|
|
32
|
+
403: ForbiddenError,
|
|
33
|
+
404: NotFoundError,
|
|
34
|
+
500: InternalError,
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
patchCart: {
|
|
38
|
+
summary: 'Patch a cart',
|
|
39
|
+
method: 'PATCH',
|
|
40
|
+
path: '/:id',
|
|
41
|
+
metadata: {
|
|
42
|
+
auth: true,
|
|
43
|
+
},
|
|
44
|
+
pathParams: z.object({
|
|
45
|
+
id: tradeIdSchema,
|
|
46
|
+
}),
|
|
47
|
+
body: PatchCartBody,
|
|
48
|
+
responses: {
|
|
49
|
+
200: TradeZod,
|
|
50
|
+
400: BadRequestError,
|
|
51
|
+
401: UnauthorizedError,
|
|
52
|
+
403: ForbiddenError,
|
|
53
|
+
500: InternalError,
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
pathPrefix: 'carts',
|
|
59
|
+
},
|
|
60
|
+
);
|
|
@@ -3,6 +3,7 @@ import { accountsContract } from './accounts';
|
|
|
3
3
|
import { apiKeysContract } from './api-keys';
|
|
4
4
|
import { clientApiKeyLogsContract } from './api-key-logs';
|
|
5
5
|
import { assetsContract } from './assets';
|
|
6
|
+
import { cartContract } from './cart';
|
|
6
7
|
import { filesContract } from './files';
|
|
7
8
|
import { individualsContract } from './individuals';
|
|
8
9
|
import { investorAccountsContract } from './investor-accounts';
|
|
@@ -15,6 +16,9 @@ import { secureRequestContract } from './secure-requests';
|
|
|
15
16
|
import { aicContract } from './aic';
|
|
16
17
|
import { authContract } from './auth';
|
|
17
18
|
import { sitesContract } from './sites';
|
|
19
|
+
import { paymentMethodsContract } from './payment-methods';
|
|
20
|
+
import { issuerPaymentMethodsContract } from './issuer-payment-methods';
|
|
21
|
+
import { tradeLineItemsContract } from './trade-line-items';
|
|
18
22
|
|
|
19
23
|
const c = initContract();
|
|
20
24
|
|
|
@@ -27,15 +31,19 @@ export const clientsContract = c.router(
|
|
|
27
31
|
apiKeys: apiKeysContract,
|
|
28
32
|
apiKeyLogs: clientApiKeyLogsContract,
|
|
29
33
|
assets: assetsContract,
|
|
34
|
+
cart: cartContract,
|
|
30
35
|
files: filesContract,
|
|
31
36
|
filesPublic: filesPublicContract,
|
|
32
37
|
individuals: individualsContract,
|
|
33
38
|
investorAccounts: investorAccountsContract,
|
|
39
|
+
issuerPaymentMethods: issuerPaymentMethodsContract,
|
|
34
40
|
issuers: issuersContract,
|
|
35
41
|
legalEntities: legalEntityContract,
|
|
36
42
|
offerings: offeringsContract,
|
|
43
|
+
paymentMethods: paymentMethodsContract,
|
|
37
44
|
secureRequests: secureRequestContract,
|
|
38
45
|
sites: sitesContract,
|
|
46
|
+
tradeLineItems: tradeLineItemsContract,
|
|
39
47
|
trades: tradesContract,
|
|
40
48
|
},
|
|
41
49
|
{
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { initContract } from '@ts-rest/core';
|
|
2
|
+
import {
|
|
3
|
+
ForbiddenError,
|
|
4
|
+
InternalError,
|
|
5
|
+
NotFoundError,
|
|
6
|
+
UnauthorizedError,
|
|
7
|
+
GetIssuerPaymentMethodZod,
|
|
8
|
+
IPaginatedIssuerPaymentMethod,
|
|
9
|
+
IssuerPaymentMethodsIncludeQuery,
|
|
10
|
+
PaginationOptionsZod,
|
|
11
|
+
} from '../../../common/types';
|
|
12
|
+
|
|
13
|
+
const c = initContract();
|
|
14
|
+
|
|
15
|
+
export const issuerPaymentMethodsContract = c.router(
|
|
16
|
+
{
|
|
17
|
+
getIssuerPaymentMethods: {
|
|
18
|
+
summary: 'Get issuer payment methods',
|
|
19
|
+
method: 'GET',
|
|
20
|
+
path: '',
|
|
21
|
+
metadata: {
|
|
22
|
+
auth: true,
|
|
23
|
+
},
|
|
24
|
+
query: PaginationOptionsZod.merge(GetIssuerPaymentMethodZod).merge(
|
|
25
|
+
IssuerPaymentMethodsIncludeQuery,
|
|
26
|
+
),
|
|
27
|
+
responses: {
|
|
28
|
+
200: IPaginatedIssuerPaymentMethod,
|
|
29
|
+
401: UnauthorizedError,
|
|
30
|
+
403: ForbiddenError,
|
|
31
|
+
404: NotFoundError,
|
|
32
|
+
500: InternalError,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
pathPrefix: 'issuer-payment-methods',
|
|
38
|
+
},
|
|
39
|
+
);
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { initContract } from '@ts-rest/core';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import {
|
|
4
|
+
UnauthorizedError,
|
|
5
|
+
ForbiddenError,
|
|
6
|
+
NotFoundError,
|
|
7
|
+
userIdSchema,
|
|
8
|
+
BadRequestError,
|
|
9
|
+
InternalError,
|
|
10
|
+
} from '../../../common/types';
|
|
11
|
+
import {
|
|
12
|
+
PaymentMethodResponseArray,
|
|
13
|
+
PaymentMethodResponse,
|
|
14
|
+
PostPaymentMethod,
|
|
15
|
+
PostSetupIntentBody,
|
|
16
|
+
SetupIntentResponse,
|
|
17
|
+
} from '../../../common/types/payment-methods.types';
|
|
18
|
+
|
|
19
|
+
const c = initContract();
|
|
20
|
+
|
|
21
|
+
export const paymentMethodsContract = c.router(
|
|
22
|
+
{
|
|
23
|
+
getPaymentMethods: {
|
|
24
|
+
summary: 'Get payment methods for a user',
|
|
25
|
+
method: 'GET',
|
|
26
|
+
path: '',
|
|
27
|
+
metadata: {
|
|
28
|
+
auth: true,
|
|
29
|
+
},
|
|
30
|
+
query: z.object({
|
|
31
|
+
userId: userIdSchema,
|
|
32
|
+
}),
|
|
33
|
+
responses: {
|
|
34
|
+
200: PaymentMethodResponseArray,
|
|
35
|
+
401: UnauthorizedError,
|
|
36
|
+
403: ForbiddenError,
|
|
37
|
+
404: NotFoundError,
|
|
38
|
+
500: InternalError,
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
createPaymentMethod: {
|
|
42
|
+
summary: 'Create payment method for a user',
|
|
43
|
+
method: 'POST',
|
|
44
|
+
path: '',
|
|
45
|
+
metadata: {
|
|
46
|
+
auth: true,
|
|
47
|
+
},
|
|
48
|
+
query: z.object({
|
|
49
|
+
userId: userIdSchema,
|
|
50
|
+
}),
|
|
51
|
+
body: PostPaymentMethod,
|
|
52
|
+
responses: {
|
|
53
|
+
201: PaymentMethodResponse,
|
|
54
|
+
400: BadRequestError,
|
|
55
|
+
401: UnauthorizedError,
|
|
56
|
+
403: ForbiddenError,
|
|
57
|
+
404: NotFoundError,
|
|
58
|
+
500: InternalError,
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
createSetupIntent: {
|
|
62
|
+
summary: 'Create payment method setup intent for a user',
|
|
63
|
+
method: 'POST',
|
|
64
|
+
path: '/intent',
|
|
65
|
+
metadata: {
|
|
66
|
+
auth: true,
|
|
67
|
+
},
|
|
68
|
+
query: z.object({
|
|
69
|
+
userId: userIdSchema,
|
|
70
|
+
}),
|
|
71
|
+
body: PostSetupIntentBody,
|
|
72
|
+
responses: {
|
|
73
|
+
201: SetupIntentResponse,
|
|
74
|
+
400: BadRequestError,
|
|
75
|
+
401: UnauthorizedError,
|
|
76
|
+
403: ForbiddenError,
|
|
77
|
+
404: NotFoundError,
|
|
78
|
+
500: InternalError,
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
pathPrefix: 'payment-methods',
|
|
84
|
+
},
|
|
85
|
+
);
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { initContract } from '@ts-rest/core';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import {
|
|
4
|
+
BadRequestError,
|
|
5
|
+
ForbiddenError,
|
|
6
|
+
InternalError,
|
|
7
|
+
NotFoundError,
|
|
8
|
+
UnauthorizedError,
|
|
9
|
+
userIdSchema,
|
|
10
|
+
} from '../../../common/types';
|
|
11
|
+
import {
|
|
12
|
+
PostTradeLineItem,
|
|
13
|
+
TradeLineItemParams,
|
|
14
|
+
TradeLineItemQuery,
|
|
15
|
+
TradeLineItemResponse,
|
|
16
|
+
TradeLineItemUpdate,
|
|
17
|
+
} from '../../../common/types/trade-line-item.type';
|
|
18
|
+
|
|
19
|
+
const c = initContract();
|
|
20
|
+
|
|
21
|
+
export const tradeLineItemsContract = c.router(
|
|
22
|
+
{
|
|
23
|
+
postTradeLineItem: {
|
|
24
|
+
summary: 'Create Trade Line Item',
|
|
25
|
+
method: 'POST',
|
|
26
|
+
path: '/',
|
|
27
|
+
metadata: {
|
|
28
|
+
auth: true,
|
|
29
|
+
},
|
|
30
|
+
body: PostTradeLineItem,
|
|
31
|
+
query: TradeLineItemQuery.merge(
|
|
32
|
+
z.object({
|
|
33
|
+
userId: userIdSchema,
|
|
34
|
+
}),
|
|
35
|
+
),
|
|
36
|
+
responses: {
|
|
37
|
+
201: TradeLineItemResponse,
|
|
38
|
+
401: UnauthorizedError,
|
|
39
|
+
403: ForbiddenError,
|
|
40
|
+
400: BadRequestError,
|
|
41
|
+
500: InternalError,
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
updateTradeLineItem: {
|
|
45
|
+
summary: 'Update Trade Line Item - Can delete if you pass quantity = 0',
|
|
46
|
+
method: 'PATCH',
|
|
47
|
+
path: '/:id',
|
|
48
|
+
metadata: {
|
|
49
|
+
auth: true,
|
|
50
|
+
},
|
|
51
|
+
pathParams: TradeLineItemParams,
|
|
52
|
+
body: TradeLineItemUpdate,
|
|
53
|
+
responses: {
|
|
54
|
+
200: TradeLineItemResponse,
|
|
55
|
+
401: UnauthorizedError,
|
|
56
|
+
403: ForbiddenError,
|
|
57
|
+
404: NotFoundError,
|
|
58
|
+
500: InternalError,
|
|
59
|
+
400: BadRequestError,
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
pathPrefix: 'trade-line-items',
|
|
65
|
+
},
|
|
66
|
+
);
|
|
@@ -16,6 +16,10 @@ import {
|
|
|
16
16
|
tradeIdOrTidSchema,
|
|
17
17
|
TradesIncludeQuery,
|
|
18
18
|
TradeZod,
|
|
19
|
+
PostAttachSubdocBody,
|
|
20
|
+
PutAttachSubdocBody,
|
|
21
|
+
PatchSubdocSignatureBody,
|
|
22
|
+
AttachSubdocResponse,
|
|
19
23
|
} from '../../../common/types/trade.types';
|
|
20
24
|
import { z } from 'zod';
|
|
21
25
|
import {
|
|
@@ -115,6 +119,66 @@ export const tradesContract = c.router(
|
|
|
115
119
|
500: InternalError,
|
|
116
120
|
},
|
|
117
121
|
},
|
|
122
|
+
postAttachSubdoc: {
|
|
123
|
+
summary: 'Attach subdoc to trade',
|
|
124
|
+
method: 'POST',
|
|
125
|
+
path: '/:id/attach-subdoc',
|
|
126
|
+
pathParams: z.object({
|
|
127
|
+
id: tradeIdOrTidSchema,
|
|
128
|
+
}),
|
|
129
|
+
metadata: {
|
|
130
|
+
auth: true,
|
|
131
|
+
},
|
|
132
|
+
body: PostAttachSubdocBody,
|
|
133
|
+
responses: {
|
|
134
|
+
200: AttachSubdocResponse,
|
|
135
|
+
400: BadRequestError,
|
|
136
|
+
401: UnauthorizedError,
|
|
137
|
+
403: ForbiddenError,
|
|
138
|
+
404: NotFoundError,
|
|
139
|
+
500: InternalError,
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
putAttachSubdoc: {
|
|
143
|
+
summary: 'Update attached subdoc for trade',
|
|
144
|
+
method: 'PUT',
|
|
145
|
+
path: '/:id/attach-subdoc',
|
|
146
|
+
pathParams: z.object({
|
|
147
|
+
id: tradeIdOrTidSchema,
|
|
148
|
+
}),
|
|
149
|
+
metadata: {
|
|
150
|
+
auth: true,
|
|
151
|
+
},
|
|
152
|
+
body: PutAttachSubdocBody,
|
|
153
|
+
responses: {
|
|
154
|
+
200: AttachSubdocResponse,
|
|
155
|
+
400: BadRequestError,
|
|
156
|
+
401: UnauthorizedError,
|
|
157
|
+
403: ForbiddenError,
|
|
158
|
+
404: NotFoundError,
|
|
159
|
+
500: InternalError,
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
patchSubdocSign: {
|
|
163
|
+
summary: 'Update subdoc signature statuses for trade',
|
|
164
|
+
method: 'PATCH',
|
|
165
|
+
path: '/:id/sign',
|
|
166
|
+
pathParams: z.object({
|
|
167
|
+
id: tradeIdOrTidSchema,
|
|
168
|
+
}),
|
|
169
|
+
metadata: {
|
|
170
|
+
auth: true,
|
|
171
|
+
},
|
|
172
|
+
body: PatchSubdocSignatureBody,
|
|
173
|
+
responses: {
|
|
174
|
+
200: AttachSubdocResponse,
|
|
175
|
+
400: BadRequestError,
|
|
176
|
+
401: UnauthorizedError,
|
|
177
|
+
403: ForbiddenError,
|
|
178
|
+
404: NotFoundError,
|
|
179
|
+
500: InternalError,
|
|
180
|
+
},
|
|
181
|
+
},
|
|
118
182
|
},
|
|
119
183
|
{
|
|
120
184
|
pathPrefix: 'trades',
|
|
@@ -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',
|
|
@@ -19,7 +19,9 @@ import {
|
|
|
19
19
|
DisbursementsMissingConfigQuery,
|
|
20
20
|
DisbursementSummaryZod,
|
|
21
21
|
DisbursementZod,
|
|
22
|
+
EligibleOfferingsFiltersZod,
|
|
22
23
|
IPaginatedDisbursement,
|
|
24
|
+
IPaginatedEligibleOffering,
|
|
23
25
|
PostDisbursementBalanceZod,
|
|
24
26
|
PostDisbursementSummaryZod,
|
|
25
27
|
PostDisbursementZod,
|
|
@@ -146,6 +148,22 @@ export const disbursementsContract = c.router(
|
|
|
146
148
|
500: InternalError,
|
|
147
149
|
},
|
|
148
150
|
},
|
|
151
|
+
getEligibleOfferings: {
|
|
152
|
+
summary: 'Get eligible offerings for disbursement',
|
|
153
|
+
method: 'GET',
|
|
154
|
+
path: '/eligible-offerings',
|
|
155
|
+
metadata: {
|
|
156
|
+
auth: true,
|
|
157
|
+
},
|
|
158
|
+
query: PaginationOptionsZod.merge(EligibleOfferingsFiltersZod),
|
|
159
|
+
responses: {
|
|
160
|
+
200: IPaginatedEligibleOffering,
|
|
161
|
+
401: UnauthorizedError,
|
|
162
|
+
403: ForbiddenError,
|
|
163
|
+
404: NotFoundError,
|
|
164
|
+
500: InternalError,
|
|
165
|
+
},
|
|
166
|
+
},
|
|
149
167
|
},
|
|
150
168
|
{
|
|
151
169
|
pathPrefix: 'disbursements',
|
package/package.json
CHANGED