sol-trade-sdk 0.1.0
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/README.md +390 -0
- package/dist/chunk-MMQAMIKR.mjs +3735 -0
- package/dist/chunk-NEZDFAYA.mjs +7744 -0
- package/dist/clients-VITWK7B6.mjs +1370 -0
- package/dist/index-1BK_FXsW.d.mts +2327 -0
- package/dist/index-1BK_FXsW.d.ts +2327 -0
- package/dist/index.d.mts +2659 -0
- package/dist/index.d.ts +2659 -0
- package/dist/index.js +13265 -0
- package/dist/index.mjs +562 -0
- package/dist/perf/index.d.mts +2 -0
- package/dist/perf/index.d.ts +2 -0
- package/dist/perf/index.js +3742 -0
- package/dist/perf/index.mjs +214 -0
- package/package.json +101 -0
- package/src/__tests__/complete_sdk.test.ts +354 -0
- package/src/__tests__/hotpath.test.ts +486 -0
- package/src/__tests__/nonce.test.ts +45 -0
- package/src/__tests__/sdk.test.ts +425 -0
- package/src/address-lookup/index.ts +197 -0
- package/src/cache/cache.ts +308 -0
- package/src/calc/index.ts +1058 -0
- package/src/calc/pumpfun.ts +124 -0
- package/src/common/bonding_curve.ts +272 -0
- package/src/common/compute-budget.ts +148 -0
- package/src/common/confirm-any-signature.ts +184 -0
- package/src/common/fast-timing.ts +481 -0
- package/src/common/fast_fn.ts +150 -0
- package/src/common/gas-fee-strategy.ts +253 -0
- package/src/common/map-pool.ts +23 -0
- package/src/common/nonce.ts +40 -0
- package/src/common/sdk-log.ts +460 -0
- package/src/common/seed.ts +381 -0
- package/src/common/spl-token.ts +578 -0
- package/src/common/subscription-handle.ts +644 -0
- package/src/common/trading-utils.ts +239 -0
- package/src/common/wsol-manager.ts +325 -0
- package/src/compute/compute_budget_manager.ts +187 -0
- package/src/compute/index.ts +21 -0
- package/src/constants/index.ts +96 -0
- package/src/execution/execution.ts +532 -0
- package/src/execution/index.ts +42 -0
- package/src/hotpath/executor.ts +464 -0
- package/src/hotpath/index.ts +64 -0
- package/src/hotpath/state.ts +435 -0
- package/src/index.ts +2117 -0
- package/src/instruction/bonk_builder.ts +730 -0
- package/src/instruction/index.ts +24 -0
- package/src/instruction/meteora_damm_v2_builder.ts +509 -0
- package/src/instruction/pumpfun_builder.ts +1183 -0
- package/src/instruction/pumpswap.ts +1123 -0
- package/src/instruction/raydium_amm_v4_builder.ts +692 -0
- package/src/instruction/raydium_cpmm_builder.ts +795 -0
- package/src/middleware/traits.ts +407 -0
- package/src/params/index.ts +483 -0
- package/src/perf/compiler-optimization.ts +529 -0
- package/src/perf/hardware.ts +631 -0
- package/src/perf/index.ts +9 -0
- package/src/perf/kernel-bypass.ts +656 -0
- package/src/perf/protocol.ts +682 -0
- package/src/perf/realtime.ts +592 -0
- package/src/perf/simd.ts +668 -0
- package/src/perf/syscall-bypass.ts +331 -0
- package/src/perf/ultra-low-latency.ts +505 -0
- package/src/perf/zero-copy.ts +589 -0
- package/src/pool/pool.ts +294 -0
- package/src/rpc/client.ts +345 -0
- package/src/sdk-errors.ts +13 -0
- package/src/security/index.ts +26 -0
- package/src/security/secure-key.ts +303 -0
- package/src/security/validators.ts +281 -0
- package/src/seed/pda.ts +262 -0
- package/src/serialization/index.ts +28 -0
- package/src/serialization/serialization.ts +288 -0
- package/src/swqos/clients.ts +1754 -0
- package/src/swqos/index.ts +50 -0
- package/src/swqos/providers.ts +1707 -0
- package/src/trading/core/async-executor.ts +702 -0
- package/src/trading/core/confirmation-monitor.ts +711 -0
- package/src/trading/core/index.ts +82 -0
- package/src/trading/core/retry-handler.ts +683 -0
- package/src/trading/core/transaction-pool.ts +780 -0
- package/src/trading/executor.ts +385 -0
- package/src/trading/factory.ts +282 -0
- package/src/trading/index.ts +30 -0
- package/src/types.ts +8 -0
- package/src/utils/index.ts +155 -0
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Middleware trait definitions.
|
|
3
|
+
* Based on sol-trade-sdk Rust implementation.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { TransactionInstruction, PublicKey, AccountMeta } from '@solana/web3.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Instruction middleware interface
|
|
10
|
+
* Used to modify, add or remove instructions before transaction execution
|
|
11
|
+
*/
|
|
12
|
+
export interface InstructionMiddleware {
|
|
13
|
+
/** Middleware name */
|
|
14
|
+
name(): string;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Process protocol instructions
|
|
18
|
+
* @param protocolInstructions - Current instruction list
|
|
19
|
+
* @param protocolName - Protocol name
|
|
20
|
+
* @param isBuy - Whether the transaction is a buy transaction
|
|
21
|
+
* @returns Modified instruction list
|
|
22
|
+
*/
|
|
23
|
+
processProtocolInstructions(
|
|
24
|
+
protocolInstructions: TransactionInstruction[],
|
|
25
|
+
protocolName: string,
|
|
26
|
+
isBuy: boolean,
|
|
27
|
+
): TransactionInstruction[];
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Process full instructions
|
|
31
|
+
* @param fullInstructions - Current instruction list
|
|
32
|
+
* @param protocolName - Protocol name
|
|
33
|
+
* @param isBuy - Whether the transaction is a buy transaction
|
|
34
|
+
* @returns Modified instruction list
|
|
35
|
+
*/
|
|
36
|
+
processFullInstructions(
|
|
37
|
+
fullInstructions: TransactionInstruction[],
|
|
38
|
+
protocolName: string,
|
|
39
|
+
isBuy: boolean,
|
|
40
|
+
): TransactionInstruction[];
|
|
41
|
+
|
|
42
|
+
/** Clone middleware */
|
|
43
|
+
clone(): InstructionMiddleware;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Middleware manager
|
|
48
|
+
*/
|
|
49
|
+
export class MiddlewareManager {
|
|
50
|
+
private middlewares: InstructionMiddleware[] = [];
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Create new middleware manager
|
|
54
|
+
*/
|
|
55
|
+
constructor() {}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Add middleware
|
|
59
|
+
*/
|
|
60
|
+
addMiddleware(middleware: InstructionMiddleware): this {
|
|
61
|
+
this.middlewares.push(middleware);
|
|
62
|
+
return this;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Apply all middlewares to process protocol instructions
|
|
67
|
+
*/
|
|
68
|
+
applyMiddlewaresProcessProtocolInstructions(
|
|
69
|
+
protocolInstructions: TransactionInstruction[],
|
|
70
|
+
protocolName: string,
|
|
71
|
+
isBuy: boolean,
|
|
72
|
+
): TransactionInstruction[] {
|
|
73
|
+
let result = protocolInstructions;
|
|
74
|
+
for (const middleware of this.middlewares) {
|
|
75
|
+
result = middleware.processProtocolInstructions(result, protocolName, isBuy);
|
|
76
|
+
if (result.length === 0) {
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return result;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Apply all middlewares to process full instructions
|
|
85
|
+
*/
|
|
86
|
+
applyMiddlewaresProcessFullInstructions(
|
|
87
|
+
fullInstructions: TransactionInstruction[],
|
|
88
|
+
protocolName: string,
|
|
89
|
+
isBuy: boolean,
|
|
90
|
+
): TransactionInstruction[] {
|
|
91
|
+
let result = fullInstructions;
|
|
92
|
+
for (const middleware of this.middlewares) {
|
|
93
|
+
result = middleware.processFullInstructions(result, protocolName, isBuy);
|
|
94
|
+
if (result.length === 0) {
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return result;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Clone the manager
|
|
103
|
+
*/
|
|
104
|
+
clone(): MiddlewareManager {
|
|
105
|
+
const cloned = new MiddlewareManager();
|
|
106
|
+
for (const mw of this.middlewares) {
|
|
107
|
+
cloned.middlewares.push(mw.clone());
|
|
108
|
+
}
|
|
109
|
+
return cloned;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Create manager with common middlewares
|
|
114
|
+
*/
|
|
115
|
+
static withCommonMiddlewares(): MiddlewareManager {
|
|
116
|
+
return new MiddlewareManager().addMiddleware(new LoggingMiddleware());
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Logging middleware - Records instruction information
|
|
122
|
+
*/
|
|
123
|
+
export class LoggingMiddleware implements InstructionMiddleware {
|
|
124
|
+
name(): string {
|
|
125
|
+
return 'LoggingMiddleware';
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
processProtocolInstructions(
|
|
129
|
+
protocolInstructions: TransactionInstruction[],
|
|
130
|
+
protocolName: string,
|
|
131
|
+
isBuy: boolean,
|
|
132
|
+
): TransactionInstruction[] {
|
|
133
|
+
console.log(`-------------------[${this.name()}]-------------------`);
|
|
134
|
+
console.log('process_protocol_instructions');
|
|
135
|
+
console.log(`[${this.name()}] Instruction count: ${protocolInstructions.length}`);
|
|
136
|
+
console.log(`[${this.name()}] Protocol name: ${protocolName}\n`);
|
|
137
|
+
console.log(`[${this.name()}] Is buy: ${isBuy}`);
|
|
138
|
+
for (let i = 0; i < protocolInstructions.length; i++) {
|
|
139
|
+
const ix = protocolInstructions[i];
|
|
140
|
+
if (!ix) continue;
|
|
141
|
+
console.log(`Instruction ${i + 1}:`);
|
|
142
|
+
console.log(` ProgramID: ${ix.programId.toBase58()}`);
|
|
143
|
+
console.log(` Accounts: ${ix.keys.length}`);
|
|
144
|
+
console.log(` Data length: ${ix.data.length}\n`);
|
|
145
|
+
}
|
|
146
|
+
return protocolInstructions;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
processFullInstructions(
|
|
150
|
+
fullInstructions: TransactionInstruction[],
|
|
151
|
+
protocolName: string,
|
|
152
|
+
isBuy: boolean,
|
|
153
|
+
): TransactionInstruction[] {
|
|
154
|
+
console.log(`-------------------[${this.name()}]-------------------`);
|
|
155
|
+
console.log('process_full_instructions');
|
|
156
|
+
console.log(`[${this.name()}] Instruction count: ${fullInstructions.length}`);
|
|
157
|
+
console.log(`[${this.name()}] Protocol name: ${protocolName}\n`);
|
|
158
|
+
console.log(`[${this.name()}] Is buy: ${isBuy}`);
|
|
159
|
+
for (let i = 0; i < fullInstructions.length; i++) {
|
|
160
|
+
const ix = fullInstructions[i];
|
|
161
|
+
if (!ix) continue;
|
|
162
|
+
console.log(`Instruction ${i + 1}:`);
|
|
163
|
+
console.log(` ProgramID: ${ix.programId.toBase58()}`);
|
|
164
|
+
console.log(` Accounts: ${ix.keys.length}`);
|
|
165
|
+
console.log(` Data length: ${ix.data.length}\n`);
|
|
166
|
+
}
|
|
167
|
+
return fullInstructions;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
clone(): InstructionMiddleware {
|
|
171
|
+
return new LoggingMiddleware();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Timer middleware - Measures execution time
|
|
177
|
+
*/
|
|
178
|
+
export class TimerMiddleware implements InstructionMiddleware {
|
|
179
|
+
private enabled: boolean = true;
|
|
180
|
+
|
|
181
|
+
name(): string {
|
|
182
|
+
return 'TimerMiddleware';
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
setEnabled(enabled: boolean): void {
|
|
186
|
+
this.enabled = enabled;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
processProtocolInstructions(
|
|
190
|
+
protocolInstructions: TransactionInstruction[],
|
|
191
|
+
protocolName: string,
|
|
192
|
+
isBuy: boolean,
|
|
193
|
+
): TransactionInstruction[] {
|
|
194
|
+
if (!this.enabled) return protocolInstructions;
|
|
195
|
+
|
|
196
|
+
const start = Date.now();
|
|
197
|
+
console.log(`[${this.name()}] Processing protocol instructions for ${protocolName} (buy: ${isBuy})`);
|
|
198
|
+
console.log(`[${this.name()}] Processing time: ${Date.now() - start}ms`);
|
|
199
|
+
return protocolInstructions;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
processFullInstructions(
|
|
203
|
+
fullInstructions: TransactionInstruction[],
|
|
204
|
+
protocolName: string,
|
|
205
|
+
isBuy: boolean,
|
|
206
|
+
): TransactionInstruction[] {
|
|
207
|
+
if (!this.enabled) return fullInstructions;
|
|
208
|
+
|
|
209
|
+
const start = Date.now();
|
|
210
|
+
console.log(`[${this.name()}] Processing full instructions for ${protocolName} (buy: ${isBuy})`);
|
|
211
|
+
console.log(`[${this.name()}] Processing time: ${Date.now() - start}ms`);
|
|
212
|
+
return fullInstructions;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
clone(): InstructionMiddleware {
|
|
216
|
+
const copy = new TimerMiddleware();
|
|
217
|
+
copy.enabled = this.enabled;
|
|
218
|
+
return copy;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Validation middleware - Validates instructions before processing
|
|
224
|
+
*/
|
|
225
|
+
export class ValidationMiddleware implements InstructionMiddleware {
|
|
226
|
+
constructor(
|
|
227
|
+
private maxInstructions: number = 100,
|
|
228
|
+
private maxDataSize: number = 10000,
|
|
229
|
+
) {}
|
|
230
|
+
|
|
231
|
+
name(): string {
|
|
232
|
+
return 'ValidationMiddleware';
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
private validate(instructions: TransactionInstruction[]): void {
|
|
236
|
+
if (this.maxInstructions > 0 && instructions.length > this.maxInstructions) {
|
|
237
|
+
throw new Error(`[${this.name()}] Too many instructions: ${instructions.length} > ${this.maxInstructions}`);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
for (let i = 0; i < instructions.length; i++) {
|
|
241
|
+
const ix = instructions[i];
|
|
242
|
+
if (!ix) continue;
|
|
243
|
+
if (this.maxDataSize > 0 && ix.data.length > this.maxDataSize) {
|
|
244
|
+
throw new Error(`[${this.name()}] Instruction ${i} data too large: ${ix.data.length} > ${this.maxDataSize}`);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
processProtocolInstructions(
|
|
250
|
+
protocolInstructions: TransactionInstruction[],
|
|
251
|
+
protocolName: string,
|
|
252
|
+
isBuy: boolean,
|
|
253
|
+
): TransactionInstruction[] {
|
|
254
|
+
this.validate(protocolInstructions);
|
|
255
|
+
return protocolInstructions;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
processFullInstructions(
|
|
259
|
+
fullInstructions: TransactionInstruction[],
|
|
260
|
+
protocolName: string,
|
|
261
|
+
isBuy: boolean,
|
|
262
|
+
): TransactionInstruction[] {
|
|
263
|
+
this.validate(fullInstructions);
|
|
264
|
+
return fullInstructions;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
clone(): InstructionMiddleware {
|
|
268
|
+
return new ValidationMiddleware(this.maxInstructions, this.maxDataSize);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Filter middleware - Filters instructions based on program ID
|
|
274
|
+
*/
|
|
275
|
+
export class FilterMiddleware implements InstructionMiddleware {
|
|
276
|
+
private allowedPrograms: Set<string>;
|
|
277
|
+
|
|
278
|
+
constructor(
|
|
279
|
+
programs: PublicKey[],
|
|
280
|
+
private mode: 'allow' | 'block' = 'allow',
|
|
281
|
+
) {
|
|
282
|
+
this.allowedPrograms = new Set(programs.map(p => p.toBase58()));
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
name(): string {
|
|
286
|
+
return 'FilterMiddleware';
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
private filter(instructions: TransactionInstruction[]): TransactionInstruction[] {
|
|
290
|
+
return instructions.filter(ix => {
|
|
291
|
+
const programId = ix.programId.toBase58();
|
|
292
|
+
const isAllowed = this.allowedPrograms.has(programId);
|
|
293
|
+
return this.mode === 'allow' ? isAllowed : !isAllowed;
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
processProtocolInstructions(
|
|
298
|
+
protocolInstructions: TransactionInstruction[],
|
|
299
|
+
protocolName: string,
|
|
300
|
+
isBuy: boolean,
|
|
301
|
+
): TransactionInstruction[] {
|
|
302
|
+
return this.filter(protocolInstructions);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
processFullInstructions(
|
|
306
|
+
fullInstructions: TransactionInstruction[],
|
|
307
|
+
protocolName: string,
|
|
308
|
+
isBuy: boolean,
|
|
309
|
+
): TransactionInstruction[] {
|
|
310
|
+
return this.filter(fullInstructions);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
clone(): InstructionMiddleware {
|
|
314
|
+
const programs = Array.from(this.allowedPrograms).map(p => new PublicKey(p));
|
|
315
|
+
return new FilterMiddleware(programs, this.mode);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Metrics middleware - Collects metrics about instruction processing
|
|
321
|
+
*/
|
|
322
|
+
export class MetricsMiddleware implements InstructionMiddleware {
|
|
323
|
+
private instructionCounts: Map<string, number> = new Map();
|
|
324
|
+
private totalInstructions: number = 0;
|
|
325
|
+
private totalDataSize: number = 0;
|
|
326
|
+
|
|
327
|
+
name(): string {
|
|
328
|
+
return 'MetricsMiddleware';
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
private record(protocolName: string, instructions: TransactionInstruction[]): void {
|
|
332
|
+
const current = this.instructionCounts.get(protocolName) || 0;
|
|
333
|
+
this.instructionCounts.set(protocolName, current + instructions.length);
|
|
334
|
+
this.totalInstructions += instructions.length;
|
|
335
|
+
|
|
336
|
+
for (const ix of instructions) {
|
|
337
|
+
this.totalDataSize += ix.data.length;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
processProtocolInstructions(
|
|
342
|
+
protocolInstructions: TransactionInstruction[],
|
|
343
|
+
protocolName: string,
|
|
344
|
+
isBuy: boolean,
|
|
345
|
+
): TransactionInstruction[] {
|
|
346
|
+
this.record(protocolName, protocolInstructions);
|
|
347
|
+
return protocolInstructions;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
processFullInstructions(
|
|
351
|
+
fullInstructions: TransactionInstruction[],
|
|
352
|
+
protocolName: string,
|
|
353
|
+
isBuy: boolean,
|
|
354
|
+
): TransactionInstruction[] {
|
|
355
|
+
this.record(protocolName, fullInstructions);
|
|
356
|
+
return fullInstructions;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
clone(): InstructionMiddleware {
|
|
360
|
+
return new MetricsMiddleware();
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Get collected metrics
|
|
365
|
+
*/
|
|
366
|
+
getMetrics(): {
|
|
367
|
+
instructionCounts: Record<string, number>;
|
|
368
|
+
totalInstructions: number;
|
|
369
|
+
totalDataSize: number;
|
|
370
|
+
} {
|
|
371
|
+
return {
|
|
372
|
+
instructionCounts: Object.fromEntries(this.instructionCounts),
|
|
373
|
+
totalInstructions: this.totalInstructions,
|
|
374
|
+
totalDataSize: this.totalDataSize,
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Reset metrics
|
|
380
|
+
*/
|
|
381
|
+
reset(): void {
|
|
382
|
+
this.instructionCounts.clear();
|
|
383
|
+
this.totalInstructions = 0;
|
|
384
|
+
this.totalDataSize = 0;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Create manager with standard middlewares
|
|
390
|
+
*/
|
|
391
|
+
export function withStandardMiddlewares(): MiddlewareManager {
|
|
392
|
+
return new MiddlewareManager()
|
|
393
|
+
.addMiddleware(new ValidationMiddleware())
|
|
394
|
+
.addMiddleware(new LoggingMiddleware())
|
|
395
|
+
.addMiddleware(new TimerMiddleware());
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Create manager with all builtin middlewares
|
|
400
|
+
*/
|
|
401
|
+
export function withAllBuiltinMiddlewares(): MiddlewareManager {
|
|
402
|
+
return new MiddlewareManager()
|
|
403
|
+
.addMiddleware(new ValidationMiddleware())
|
|
404
|
+
.addMiddleware(new LoggingMiddleware())
|
|
405
|
+
.addMiddleware(new TimerMiddleware())
|
|
406
|
+
.addMiddleware(new MetricsMiddleware());
|
|
407
|
+
}
|