@dalmore/api-contracts 0.0.0-dev.2dc8e92 → 0.0.0-dev.3af7603
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/common/types/account-setting.types.ts +31 -0
- 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/bonus-tier.types.ts +33 -0
- package/common/types/cart.types.ts +4 -1
- package/common/types/common.types.ts +16 -6
- package/common/types/dashboard.types.ts +2 -9
- package/common/types/disbursements.types.ts +119 -3
- 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/individuals.types.ts +2 -15
- package/common/types/issuer-offering.types.ts +113 -30
- package/common/types/issuer-payment-method.types.ts +41 -0
- package/common/types/issuer.types.ts +9 -0
- package/common/types/notification.types.ts +239 -29
- package/common/types/offering.types.ts +106 -20
- 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 +71 -1
- package/common/types/transaction.types.ts +12 -1
- package/common/types/user.types.ts +15 -28
- package/contracts/clients/cart/index.ts +80 -0
- package/contracts/clients/index.ts +10 -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 +65 -1
- package/contracts/clients/transactions/index.ts +37 -0
- package/contracts/compliance/bonus-tiers/index.ts +21 -2
- 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 +36 -0
- package/package.json +1 -1
|
@@ -8,10 +8,13 @@ import {
|
|
|
8
8
|
ManagedByType,
|
|
9
9
|
OfferingVersioningType,
|
|
10
10
|
ComplianceReview,
|
|
11
|
+
DurationType,
|
|
12
|
+
AssetType,
|
|
13
|
+
StringToBooleanSchema,
|
|
11
14
|
} from './common.types';
|
|
12
15
|
import { IBaseEntity } from './entity.types';
|
|
13
16
|
import { IIssuer, issuerIdSchema } from './issuer.types';
|
|
14
|
-
import { IAsset } from './asset.types';
|
|
17
|
+
import { IAsset, postAssetRefinement, AssetTemplateType } from './asset.types';
|
|
15
18
|
import { fileIdSchema, FileZod } from './file.types';
|
|
16
19
|
import { accountIdSchema } from './account.types';
|
|
17
20
|
|
|
@@ -128,20 +131,60 @@ export const PostIssuerOffering = z
|
|
|
128
131
|
.nullable()
|
|
129
132
|
.openapi({ example: 'This is a description of the offering.' }),
|
|
130
133
|
managedBy: z.nativeEnum(ManagedByType).optional(),
|
|
134
|
+
assetName: z.string().min(2).max(50).openapi({ example: 'Asset name' }),
|
|
135
|
+
assetType: z.nativeEnum(AssetType).openapi({ example: AssetType.STOCK }),
|
|
136
|
+
pricePerUnit: z
|
|
137
|
+
.number()
|
|
138
|
+
.min(0.01)
|
|
139
|
+
.max(10000000000)
|
|
140
|
+
.nullable()
|
|
141
|
+
.openapi({ example: 2000 }),
|
|
142
|
+
totalUnits: z
|
|
143
|
+
.number()
|
|
144
|
+
.min(1)
|
|
145
|
+
.max(10000000000)
|
|
146
|
+
.nullable()
|
|
147
|
+
.openapi({ example: 5200 }),
|
|
148
|
+
yield: z
|
|
149
|
+
.number()
|
|
150
|
+
.min(0.01)
|
|
151
|
+
.max(10000000000)
|
|
152
|
+
.nullable()
|
|
153
|
+
.optional()
|
|
154
|
+
.openapi({ example: 1200 }),
|
|
155
|
+
duration: z
|
|
156
|
+
.number()
|
|
157
|
+
.min(1)
|
|
158
|
+
.max(1000)
|
|
159
|
+
.nullable()
|
|
160
|
+
.optional()
|
|
161
|
+
.openapi({ example: 1 }),
|
|
162
|
+
durationType: z
|
|
163
|
+
.nativeEnum(DurationType)
|
|
164
|
+
.nullable()
|
|
165
|
+
.optional()
|
|
166
|
+
.openapi({ example: DurationType.DAY }),
|
|
167
|
+
template: z
|
|
168
|
+
.nativeEnum(AssetTemplateType)
|
|
169
|
+
.default(AssetTemplateType.STANDARD)
|
|
170
|
+
.openapi({ example: AssetTemplateType.STANDARD }),
|
|
171
|
+
tiers: z.array(z.number().positive()).nullable().optional(),
|
|
172
|
+
enableBonus: z.boolean().default(false).optional(),
|
|
131
173
|
})
|
|
132
|
-
.
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
if (data.minInvestment
|
|
136
|
-
|
|
174
|
+
.superRefine((data, ctx) => {
|
|
175
|
+
// Check if both values are present, and if so, ensure minInvestment is less than maxInvestment
|
|
176
|
+
if (data.minInvestment && data.maxInvestment) {
|
|
177
|
+
if (data.minInvestment >= data.maxInvestment) {
|
|
178
|
+
ctx.addIssue({
|
|
179
|
+
path: ['minInvestment'],
|
|
180
|
+
message: 'Minimum investment must be less than maximum investment.',
|
|
181
|
+
code: z.ZodIssueCode.custom,
|
|
182
|
+
});
|
|
137
183
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
path: ['minInvestment'],
|
|
143
|
-
},
|
|
144
|
-
);
|
|
184
|
+
}
|
|
185
|
+
// Apply asset-specific refinements
|
|
186
|
+
postAssetRefinement(data, ctx);
|
|
187
|
+
});
|
|
145
188
|
|
|
146
189
|
export type PostIssuerOffering = z.infer<typeof PostIssuerOffering>;
|
|
147
190
|
export const PatchIssuerOffering = z.object({
|
|
@@ -151,38 +194,39 @@ export const PatchIssuerOffering = z.object({
|
|
|
151
194
|
.max(100)
|
|
152
195
|
.optional()
|
|
153
196
|
.openapi({ example: 'Airbnb IPO' }),
|
|
197
|
+
type: z
|
|
198
|
+
.nativeEnum(OfferingType)
|
|
199
|
+
.optional()
|
|
200
|
+
.openapi({ example: OfferingType.REG_D }),
|
|
154
201
|
targetAmount: z
|
|
155
202
|
.number()
|
|
156
203
|
.min(0)
|
|
157
204
|
.max(10000000000)
|
|
158
205
|
.optional()
|
|
159
206
|
.openapi({ example: 120000 }),
|
|
160
|
-
raiseAmount: z
|
|
161
|
-
.number()
|
|
162
|
-
.min(0)
|
|
163
|
-
.max(10000000000)
|
|
164
|
-
.optional()
|
|
165
|
-
.openapi({ example: 200000 }),
|
|
166
207
|
minInvestment: z
|
|
167
208
|
.number()
|
|
168
209
|
.min(0)
|
|
169
210
|
.max(10000000000)
|
|
211
|
+
.nullable()
|
|
170
212
|
.optional()
|
|
171
213
|
.openapi({ example: 1000 }),
|
|
172
214
|
maxInvestment: z
|
|
173
215
|
.number()
|
|
174
216
|
.min(0)
|
|
175
217
|
.max(10000000000)
|
|
218
|
+
.nullable()
|
|
176
219
|
.optional()
|
|
177
220
|
.openapi({ example: 20000 }),
|
|
178
221
|
contingencyAmount: z
|
|
179
222
|
.number()
|
|
180
223
|
.min(0)
|
|
181
224
|
.max(10000000000)
|
|
225
|
+
.nullable()
|
|
182
226
|
.optional()
|
|
183
227
|
.openapi({ example: 5000 }),
|
|
184
|
-
startAt: dateSchema.optional().openapi({ example: '10/20/2024' }),
|
|
185
|
-
endAt: dateSchema.optional().openapi({ example: '10/27/2024' }),
|
|
228
|
+
startAt: dateSchema.nullable().optional().openapi({ example: '10/20/2024' }),
|
|
229
|
+
endAt: dateSchema.nullable().optional().openapi({ example: '10/27/2024' }),
|
|
186
230
|
cancellationPeriod: z
|
|
187
231
|
.number()
|
|
188
232
|
.min(1)
|
|
@@ -212,6 +256,53 @@ export const PatchIssuerOffering = z.object({
|
|
|
212
256
|
managedBy: z.nativeEnum(ManagedByType).optional(),
|
|
213
257
|
showTotalRaised: z.boolean().optional(),
|
|
214
258
|
issuerId: issuerIdSchema.optional(),
|
|
259
|
+
assetName: z.string().min(2).max(50).optional().openapi({ example: 'Z' }),
|
|
260
|
+
assetType: z
|
|
261
|
+
.nativeEnum(AssetType)
|
|
262
|
+
.optional()
|
|
263
|
+
.openapi({ example: AssetType.STOCK }),
|
|
264
|
+
pricePerUnit: z
|
|
265
|
+
.number()
|
|
266
|
+
.min(0.01)
|
|
267
|
+
.max(10000000000)
|
|
268
|
+
.nullable()
|
|
269
|
+
.optional()
|
|
270
|
+
.openapi({ example: 2000 }),
|
|
271
|
+
totalUnits: z
|
|
272
|
+
.number()
|
|
273
|
+
.min(1)
|
|
274
|
+
.max(10000000000)
|
|
275
|
+
.nullable()
|
|
276
|
+
.optional()
|
|
277
|
+
.openapi({ example: 5200 }),
|
|
278
|
+
yield: z
|
|
279
|
+
.number()
|
|
280
|
+
.min(0.01)
|
|
281
|
+
.max(10000000000)
|
|
282
|
+
.nullable()
|
|
283
|
+
.optional()
|
|
284
|
+
.openapi({ example: 1200 }),
|
|
285
|
+
duration: z
|
|
286
|
+
.number()
|
|
287
|
+
.min(1)
|
|
288
|
+
.max(1000)
|
|
289
|
+
.nullable()
|
|
290
|
+
.optional()
|
|
291
|
+
.openapi({ example: 1 }),
|
|
292
|
+
durationType: z
|
|
293
|
+
.nativeEnum(DurationType)
|
|
294
|
+
.nullable()
|
|
295
|
+
.optional()
|
|
296
|
+
.openapi({ example: DurationType.DAY }),
|
|
297
|
+
template: z
|
|
298
|
+
.nativeEnum(AssetTemplateType)
|
|
299
|
+
.default(AssetTemplateType.STANDARD)
|
|
300
|
+
.openapi({ example: AssetTemplateType.STANDARD })
|
|
301
|
+
.nullable()
|
|
302
|
+
.optional(),
|
|
303
|
+
tiers: z.array(z.number().positive()).nullable().optional(),
|
|
304
|
+
enabled: z.boolean().optional(),
|
|
305
|
+
enableBonus: z.boolean().optional(),
|
|
215
306
|
});
|
|
216
307
|
export type PatchIssuerOffering = z.infer<typeof PatchIssuerOffering>;
|
|
217
308
|
|
|
@@ -281,15 +372,7 @@ export const IssuerOfferingsFilterZod = z.object({
|
|
|
281
372
|
issuerId: z.lazy(() => issuerIdSchema).optional(),
|
|
282
373
|
type: z.nativeEnum(OfferingType).optional(),
|
|
283
374
|
status: z.nativeEnum(ComplianceReview).optional(),
|
|
284
|
-
enabled:
|
|
285
|
-
(val) =>
|
|
286
|
-
val === 'true' || val === '1'
|
|
287
|
-
? true
|
|
288
|
-
: val === 'false' || val === '0'
|
|
289
|
-
? false
|
|
290
|
-
: val,
|
|
291
|
-
z.boolean().optional(),
|
|
292
|
-
),
|
|
375
|
+
enabled: StringToBooleanSchema.optional(),
|
|
293
376
|
managedBy: z.nativeEnum(ManagedByType).optional(),
|
|
294
377
|
versioningType: z.nativeEnum(OfferingVersioningType).optional(),
|
|
295
378
|
combinedStatus: z.nativeEnum(OfferingStatus).optional(),
|
|
@@ -222,10 +222,51 @@ export type IPaginatedIssuerPaymentMethod = z.infer<
|
|
|
222
222
|
typeof IPaginatedIssuerPaymentMethod
|
|
223
223
|
>;
|
|
224
224
|
|
|
225
|
+
const issuerPaymentMethodsInclude = z.enum(['issuer', 'integration']);
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* @description Query parameters for including related entities
|
|
229
|
+
* @example in contract use as -> query: PaginationOptionsZod.merge(GetIssuerPaymentMethodZod).merge(IssuerPaymentMethodsIncludeQuery)
|
|
230
|
+
*/
|
|
231
|
+
export const IssuerPaymentMethodsIncludeQuery = z.object({
|
|
232
|
+
include: z
|
|
233
|
+
.string()
|
|
234
|
+
.optional()
|
|
235
|
+
.transform((str) => (str ? str.split(',') : []))
|
|
236
|
+
.refine(
|
|
237
|
+
(includes) =>
|
|
238
|
+
includes.every((include) =>
|
|
239
|
+
issuerPaymentMethodsInclude.options.includes(include as any),
|
|
240
|
+
),
|
|
241
|
+
{
|
|
242
|
+
message: `Invalid include option provided. Valid options are: ${issuerPaymentMethodsInclude.options.join(',')}`,
|
|
243
|
+
},
|
|
244
|
+
)
|
|
245
|
+
.openapi({
|
|
246
|
+
example: `${issuerPaymentMethodsInclude.options.join(',')}`,
|
|
247
|
+
}),
|
|
248
|
+
});
|
|
249
|
+
export type IssuerPaymentMethodsIncludeQuery = z.infer<
|
|
250
|
+
typeof IssuerPaymentMethodsIncludeQuery
|
|
251
|
+
>;
|
|
252
|
+
|
|
225
253
|
export const GetIssuerPaymentMethodZod = z.object({
|
|
226
254
|
issuerId: issuerIdSchema.openapi({
|
|
227
255
|
example: 'issuer_01jdq2crwke8xskjd840cj79pw',
|
|
228
256
|
}),
|
|
257
|
+
enabled: z
|
|
258
|
+
.string()
|
|
259
|
+
.optional()
|
|
260
|
+
.refine((v) => !v || v === 'true' || v === 'false', {
|
|
261
|
+
message: 'enabled must be a boolean string',
|
|
262
|
+
})
|
|
263
|
+
.transform((v) => {
|
|
264
|
+
if (!v) return undefined;
|
|
265
|
+
return v === 'true';
|
|
266
|
+
})
|
|
267
|
+
.openapi({
|
|
268
|
+
example: 'true',
|
|
269
|
+
}),
|
|
229
270
|
});
|
|
230
271
|
export type GetIssuerPaymentMethodZod = z.infer<
|
|
231
272
|
typeof GetIssuerPaymentMethodZod
|
|
@@ -152,6 +152,10 @@ export const PutIssuerZod = z
|
|
|
152
152
|
.lazy(() => fileIdSchema)
|
|
153
153
|
.optional()
|
|
154
154
|
.nullable(),
|
|
155
|
+
formationDocumentFileId: z
|
|
156
|
+
.lazy(() => fileIdSchema)
|
|
157
|
+
.optional()
|
|
158
|
+
.nullable(),
|
|
155
159
|
coverArtId: z
|
|
156
160
|
.lazy(() => fileIdSchema)
|
|
157
161
|
.optional()
|
|
@@ -188,6 +192,11 @@ export const IIssuer = IBaseEntity.extend({
|
|
|
188
192
|
accountId: z.string(),
|
|
189
193
|
account: AccountZod.optional().nullable(),
|
|
190
194
|
ss4LetterFileId: z.string().nullable(),
|
|
195
|
+
formationDocumentFileId: z.string().nullable(),
|
|
196
|
+
formationDocument: z
|
|
197
|
+
.lazy(() => FileZod)
|
|
198
|
+
.nullable()
|
|
199
|
+
.optional(),
|
|
191
200
|
status: z
|
|
192
201
|
.nativeEnum(IssuerStatus)
|
|
193
202
|
.openapi({ example: IssuerStatus.SUBMITTED }),
|
|
@@ -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 {
|
|
4
|
+
import { IBaseEntity } from './entity.types';
|
|
5
5
|
|
|
6
6
|
extendZodWithOpenApi(z);
|
|
7
|
-
|
|
7
|
+
|
|
8
|
+
export enum NotificationChannelType {
|
|
8
9
|
EMAIL = 'EMAIL',
|
|
9
10
|
SLACK = 'SLACK',
|
|
11
|
+
WEBHOOK = 'WEBHOOK',
|
|
10
12
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
|
|
14
|
+
export enum NotificationRecordStatus {
|
|
15
|
+
PENDING = 'PENDING',
|
|
16
|
+
SENT = 'SENT',
|
|
17
|
+
FAILED = 'FAILED',
|
|
14
18
|
}
|
|
15
19
|
|
|
16
|
-
export const
|
|
20
|
+
export const notificationChannelIdSchema = z.string().refine(
|
|
17
21
|
(value) => {
|
|
18
22
|
try {
|
|
19
23
|
const tid = TypeID.fromString(value);
|
|
20
|
-
return tid.getType() === '
|
|
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 "
|
|
31
|
+
'Invalid notification channel ID format. Must be a valid TypeID with "notification_channel" prefix.',
|
|
28
32
|
},
|
|
29
33
|
);
|
|
30
34
|
|
|
31
|
-
export const
|
|
32
|
-
|
|
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
|
-
|
|
35
|
-
|
|
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
|
|
116
|
+
export type EmailNotificationPayload = z.infer<
|
|
117
|
+
typeof EmailNotificationPayloadSchema
|
|
118
|
+
>;
|
|
43
119
|
|
|
44
|
-
const
|
|
45
|
-
|
|
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
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
|
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>;
|