@zebpay_rajesh/zebpay-mcp-server 1.0.3
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/.env.example +14 -0
- package/README.md +223 -0
- package/dist/config.d.ts +19 -0
- package/dist/config.js +81 -0
- package/dist/config.js.map +1 -0
- package/dist/http/httpClient.d.ts +40 -0
- package/dist/http/httpClient.js +341 -0
- package/dist/http/httpClient.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +60 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/errors.d.ts +21 -0
- package/dist/mcp/errors.js +214 -0
- package/dist/mcp/errors.js.map +1 -0
- package/dist/mcp/logging.d.ts +21 -0
- package/dist/mcp/logging.js +241 -0
- package/dist/mcp/logging.js.map +1 -0
- package/dist/mcp/prompts.d.ts +9 -0
- package/dist/mcp/prompts.js +165 -0
- package/dist/mcp/prompts.js.map +1 -0
- package/dist/mcp/resources.d.ts +9 -0
- package/dist/mcp/resources.js +125 -0
- package/dist/mcp/resources.js.map +1 -0
- package/dist/mcp/tools_futures.d.ts +5 -0
- package/dist/mcp/tools_futures.js +694 -0
- package/dist/mcp/tools_futures.js.map +1 -0
- package/dist/mcp/tools_spot.d.ts +11 -0
- package/dist/mcp/tools_spot.js +2225 -0
- package/dist/mcp/tools_spot.js.map +1 -0
- package/dist/private/FuturesClient.d.ts +57 -0
- package/dist/private/FuturesClient.js +181 -0
- package/dist/private/FuturesClient.js.map +1 -0
- package/dist/private/SpotClient.d.ts +44 -0
- package/dist/private/SpotClient.js +201 -0
- package/dist/private/SpotClient.js.map +1 -0
- package/dist/private/ZebpayAPI.d.ts +19 -0
- package/dist/private/ZebpayAPI.js +172 -0
- package/dist/private/ZebpayAPI.js.map +1 -0
- package/dist/public/PublicClient.d.ts +79 -0
- package/dist/public/PublicClient.js +283 -0
- package/dist/public/PublicClient.js.map +1 -0
- package/dist/public/PublicFuturesClient.d.ts +27 -0
- package/dist/public/PublicFuturesClient.js +187 -0
- package/dist/public/PublicFuturesClient.js.map +1 -0
- package/dist/security/credentials.d.ts +42 -0
- package/dist/security/credentials.js +80 -0
- package/dist/security/credentials.js.map +1 -0
- package/dist/security/signing.d.ts +33 -0
- package/dist/security/signing.js +56 -0
- package/dist/security/signing.js.map +1 -0
- package/dist/types/responses.d.ts +130 -0
- package/dist/types/responses.js +6 -0
- package/dist/types/responses.js.map +1 -0
- package/dist/utils/cache.d.ts +29 -0
- package/dist/utils/cache.js +72 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/fileLogger.d.ts +10 -0
- package/dist/utils/fileLogger.js +81 -0
- package/dist/utils/fileLogger.js.map +1 -0
- package/dist/utils/metrics.d.ts +35 -0
- package/dist/utils/metrics.js +94 -0
- package/dist/utils/metrics.js.map +1 -0
- package/dist/utils/responseFormatter.d.ts +93 -0
- package/dist/utils/responseFormatter.js +268 -0
- package/dist/utils/responseFormatter.js.map +1 -0
- package/dist/validation/schemas.d.ts +70 -0
- package/dist/validation/schemas.js +48 -0
- package/dist/validation/schemas.js.map +1 -0
- package/dist/validation/validators.d.ts +28 -0
- package/dist/validation/validators.js +129 -0
- package/dist/validation/validators.js.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Public futures client for market data (no authentication required).
|
|
3
|
+
*/
|
|
4
|
+
import { HttpError } from "../http/httpClient.js";
|
|
5
|
+
import { tickerCache, orderBookCache, exchangeInfoCache } from "../utils/cache.js";
|
|
6
|
+
import { convertHttpErrorToMcpError } from "../mcp/errors.js";
|
|
7
|
+
import { McpError } from "@modelcontextprotocol/sdk/types.js";
|
|
8
|
+
export class PublicFuturesClient {
|
|
9
|
+
constructor(config, http) {
|
|
10
|
+
this.config = config;
|
|
11
|
+
this.http = http;
|
|
12
|
+
}
|
|
13
|
+
buildUrl(path, queryParams) {
|
|
14
|
+
const trimmed = path.startsWith("/") ? path : `/${path}`;
|
|
15
|
+
let url = `${this.config.futuresBaseUrl}${trimmed}`;
|
|
16
|
+
if (queryParams && Object.keys(queryParams).length > 0) {
|
|
17
|
+
const queryString = Object.entries(queryParams)
|
|
18
|
+
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
|
|
19
|
+
.join("&");
|
|
20
|
+
url += `?${queryString}`;
|
|
21
|
+
}
|
|
22
|
+
return url;
|
|
23
|
+
}
|
|
24
|
+
buildRootUrl(path) {
|
|
25
|
+
// Some endpoints (like healthCheckStatus) live at the root host, not under /api/v1
|
|
26
|
+
const base = this.config.futuresBaseUrl.replace(/\/api\/v1\/?$/, "");
|
|
27
|
+
const trimmed = path.startsWith("/") ? path : `/${path}`;
|
|
28
|
+
return `${base}${trimmed}`;
|
|
29
|
+
}
|
|
30
|
+
async handleRequest(requestFn) {
|
|
31
|
+
try {
|
|
32
|
+
const response = await requestFn();
|
|
33
|
+
return response.data;
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
if (err instanceof HttpError) {
|
|
37
|
+
let errorMessage = err.message || "Unknown API error";
|
|
38
|
+
if (err.details) {
|
|
39
|
+
if (typeof err.details === "string") {
|
|
40
|
+
errorMessage = err.details;
|
|
41
|
+
}
|
|
42
|
+
else if (typeof err.details === "object") {
|
|
43
|
+
const details = err.details;
|
|
44
|
+
errorMessage =
|
|
45
|
+
(typeof details.statusDescription === "string" && details.statusDescription) ||
|
|
46
|
+
(typeof details.error === "string" && details.error) ||
|
|
47
|
+
(typeof details.message === "string" && details.message) ||
|
|
48
|
+
(typeof details.msg === "string" && details.msg) ||
|
|
49
|
+
(typeof details.errorMessage === "string" && details.errorMessage) ||
|
|
50
|
+
errorMessage;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
throw convertHttpErrorToMcpError(err.status, errorMessage, err.details);
|
|
54
|
+
}
|
|
55
|
+
if (err instanceof McpError) {
|
|
56
|
+
throw err;
|
|
57
|
+
}
|
|
58
|
+
throw err;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// GET /healthCheckStatus (root host)
|
|
62
|
+
async getHealthCheckStatus() {
|
|
63
|
+
const url = this.buildRootUrl("/healthCheckStatus");
|
|
64
|
+
return this.handleRequest(() => this.http.request({
|
|
65
|
+
method: "GET",
|
|
66
|
+
url,
|
|
67
|
+
timeoutMs: this.config.timeoutMs,
|
|
68
|
+
retryCount: this.config.retryCount,
|
|
69
|
+
}));
|
|
70
|
+
}
|
|
71
|
+
// GET /api/v1/market/markets
|
|
72
|
+
async getMarkets() {
|
|
73
|
+
const cacheKey = "futures:markets";
|
|
74
|
+
const cached = tickerCache.get(cacheKey);
|
|
75
|
+
if (cached)
|
|
76
|
+
return cached;
|
|
77
|
+
const url = this.buildUrl("/market/markets");
|
|
78
|
+
const data = await this.handleRequest(() => this.http.request({
|
|
79
|
+
method: "GET",
|
|
80
|
+
url,
|
|
81
|
+
timeoutMs: this.config.timeoutMs,
|
|
82
|
+
retryCount: this.config.retryCount,
|
|
83
|
+
}));
|
|
84
|
+
tickerCache.set(cacheKey, data);
|
|
85
|
+
return data;
|
|
86
|
+
}
|
|
87
|
+
// GET /api/v1/market/marketInfo
|
|
88
|
+
async getMarketInfo() {
|
|
89
|
+
const cacheKey = "futures:marketInfo";
|
|
90
|
+
const cached = tickerCache.get(cacheKey);
|
|
91
|
+
if (cached)
|
|
92
|
+
return cached;
|
|
93
|
+
const url = this.buildUrl("/market/marketInfo");
|
|
94
|
+
const data = await this.handleRequest(() => this.http.request({
|
|
95
|
+
method: "GET",
|
|
96
|
+
url,
|
|
97
|
+
timeoutMs: this.config.timeoutMs,
|
|
98
|
+
retryCount: this.config.retryCount,
|
|
99
|
+
}));
|
|
100
|
+
tickerCache.set(cacheKey, data);
|
|
101
|
+
return data;
|
|
102
|
+
}
|
|
103
|
+
// GET /api/v1/market/orderBook?symbol=BTCUSDT
|
|
104
|
+
async getOrderBook(params) {
|
|
105
|
+
const symbol = params.symbol.trim().toUpperCase();
|
|
106
|
+
const cacheKey = `futures:orderbook:${symbol}:${params.limit ?? "default"}`;
|
|
107
|
+
const cached = orderBookCache.get(cacheKey);
|
|
108
|
+
if (cached)
|
|
109
|
+
return cached;
|
|
110
|
+
const query = { symbol };
|
|
111
|
+
if (params.limit !== undefined)
|
|
112
|
+
query.limit = String(params.limit);
|
|
113
|
+
const url = this.buildUrl("/market/orderBook", query);
|
|
114
|
+
const data = await this.handleRequest(() => this.http.request({
|
|
115
|
+
method: "GET",
|
|
116
|
+
url,
|
|
117
|
+
timeoutMs: this.config.timeoutMs,
|
|
118
|
+
retryCount: this.config.retryCount,
|
|
119
|
+
}));
|
|
120
|
+
orderBookCache.set(cacheKey, data);
|
|
121
|
+
return data;
|
|
122
|
+
}
|
|
123
|
+
// GET /api/v1/market/ticker24Hr?symbol=BTCUSDT
|
|
124
|
+
async getTicker24Hr(params) {
|
|
125
|
+
const symbol = params.symbol.trim().toUpperCase();
|
|
126
|
+
const cacheKey = `futures:ticker24h:${symbol}`;
|
|
127
|
+
const cached = tickerCache.get(cacheKey);
|
|
128
|
+
if (cached)
|
|
129
|
+
return cached;
|
|
130
|
+
const url = this.buildUrl("/market/ticker24Hr", { symbol });
|
|
131
|
+
const data = await this.handleRequest(() => this.http.request({
|
|
132
|
+
method: "GET",
|
|
133
|
+
url,
|
|
134
|
+
timeoutMs: this.config.timeoutMs,
|
|
135
|
+
retryCount: this.config.retryCount,
|
|
136
|
+
}));
|
|
137
|
+
tickerCache.set(cacheKey, data);
|
|
138
|
+
return data;
|
|
139
|
+
}
|
|
140
|
+
// GET /api/v1/market/aggTrade?symbol=BTCUSDT
|
|
141
|
+
async getAggregateTrades(params) {
|
|
142
|
+
const symbol = params.symbol.trim().toUpperCase();
|
|
143
|
+
const query = { symbol };
|
|
144
|
+
if (params.limit !== undefined)
|
|
145
|
+
query.limit = String(params.limit);
|
|
146
|
+
const url = this.buildUrl("/market/aggTrade", query);
|
|
147
|
+
return this.handleRequest(() => this.http.request({
|
|
148
|
+
method: "GET",
|
|
149
|
+
url,
|
|
150
|
+
timeoutMs: this.config.timeoutMs,
|
|
151
|
+
retryCount: this.config.retryCount,
|
|
152
|
+
}));
|
|
153
|
+
}
|
|
154
|
+
// GET /api/v1/exchange/exchangeInfo
|
|
155
|
+
async getExchangeInfo() {
|
|
156
|
+
const cacheKey = "futures:exchangeInfo";
|
|
157
|
+
const cached = exchangeInfoCache.get(cacheKey);
|
|
158
|
+
if (cached)
|
|
159
|
+
return cached;
|
|
160
|
+
const url = this.buildUrl("/exchange/exchangeInfo");
|
|
161
|
+
const data = await this.handleRequest(() => this.http.request({
|
|
162
|
+
method: "GET",
|
|
163
|
+
url,
|
|
164
|
+
timeoutMs: this.config.timeoutMs,
|
|
165
|
+
retryCount: this.config.retryCount,
|
|
166
|
+
}));
|
|
167
|
+
exchangeInfoCache.set(cacheKey, data);
|
|
168
|
+
return data;
|
|
169
|
+
}
|
|
170
|
+
// GET /api/v1/exchange/pairs
|
|
171
|
+
async getExchangePairs() {
|
|
172
|
+
const cacheKey = "futures:exchangePairs";
|
|
173
|
+
const cached = exchangeInfoCache.get(cacheKey);
|
|
174
|
+
if (cached)
|
|
175
|
+
return cached;
|
|
176
|
+
const url = this.buildUrl("/exchange/pairs");
|
|
177
|
+
const data = await this.handleRequest(() => this.http.request({
|
|
178
|
+
method: "GET",
|
|
179
|
+
url,
|
|
180
|
+
timeoutMs: this.config.timeoutMs,
|
|
181
|
+
retryCount: this.config.retryCount,
|
|
182
|
+
}));
|
|
183
|
+
exchangeInfoCache.set(cacheKey, data);
|
|
184
|
+
return data;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=PublicFuturesClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PublicFuturesClient.js","sourceRoot":"","sources":["../../src/public/PublicFuturesClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export interface CredentialsProvider {
|
|
2
|
+
getApiKey(): string;
|
|
3
|
+
getSecretKey(): string;
|
|
4
|
+
}
|
|
5
|
+
export declare class EnvCredentialsProvider implements CredentialsProvider {
|
|
6
|
+
private readonly apiKeyEnv;
|
|
7
|
+
private readonly secretKeyEnv;
|
|
8
|
+
constructor(apiKeyEnvName?: string, secretKeyEnvName?: string);
|
|
9
|
+
getApiKey(): string;
|
|
10
|
+
getSecretKey(): string;
|
|
11
|
+
/**
|
|
12
|
+
* Returns safe-to-log shapes for debugging without exposing secrets.
|
|
13
|
+
*/
|
|
14
|
+
describeRedacted(): {
|
|
15
|
+
apiKey: string;
|
|
16
|
+
secretKey: string;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Credentials provider that stores credentials in memory.
|
|
21
|
+
* Used for accepting credentials from client during initialization.
|
|
22
|
+
* Credentials are optional - if not provided, authenticated tools will fail with a clear error.
|
|
23
|
+
*/
|
|
24
|
+
export declare class InMemoryCredentialsProvider implements CredentialsProvider {
|
|
25
|
+
private apiKey;
|
|
26
|
+
private secretKey;
|
|
27
|
+
constructor(apiKey?: string, secretKey?: string);
|
|
28
|
+
setCredentials(apiKey: string, secretKey: string): void;
|
|
29
|
+
getApiKey(): string;
|
|
30
|
+
getSecretKey(): string;
|
|
31
|
+
/**
|
|
32
|
+
* Returns safe-to-log shapes for debugging without exposing secrets.
|
|
33
|
+
*/
|
|
34
|
+
describeRedacted(): {
|
|
35
|
+
apiKey: string;
|
|
36
|
+
secretKey: string;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Check if credentials are set
|
|
40
|
+
*/
|
|
41
|
+
hasCredentials(): boolean;
|
|
42
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Credential provider abstraction. Current implementation reads from env vars.
|
|
3
|
+
Secrets are never logged directly; use redact() for any visibility.
|
|
4
|
+
*/
|
|
5
|
+
import { redact } from "../config.js";
|
|
6
|
+
export class EnvCredentialsProvider {
|
|
7
|
+
constructor(apiKeyEnvName = "ZEBPAY_API_KEY", secretKeyEnvName = "ZEBPAY_API_SECRET") {
|
|
8
|
+
this.apiKeyEnv = apiKeyEnvName;
|
|
9
|
+
this.secretKeyEnv = secretKeyEnvName;
|
|
10
|
+
}
|
|
11
|
+
getApiKey() {
|
|
12
|
+
const value = process.env[this.apiKeyEnv];
|
|
13
|
+
if (!value) {
|
|
14
|
+
throw new Error(`Missing API key in env ${this.apiKeyEnv}. Configure securely.`);
|
|
15
|
+
}
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
getSecretKey() {
|
|
19
|
+
const value = process.env[this.secretKeyEnv];
|
|
20
|
+
if (!value) {
|
|
21
|
+
throw new Error(`Missing API secret in env ${this.secretKeyEnv}. Configure securely.`);
|
|
22
|
+
}
|
|
23
|
+
return value;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Returns safe-to-log shapes for debugging without exposing secrets.
|
|
27
|
+
*/
|
|
28
|
+
describeRedacted() {
|
|
29
|
+
return {
|
|
30
|
+
apiKey: redact(process.env[this.apiKeyEnv] ?? ""),
|
|
31
|
+
secretKey: redact(process.env[this.secretKeyEnv] ?? ""),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Credentials provider that stores credentials in memory.
|
|
37
|
+
* Used for accepting credentials from client during initialization.
|
|
38
|
+
* Credentials are optional - if not provided, authenticated tools will fail with a clear error.
|
|
39
|
+
*/
|
|
40
|
+
export class InMemoryCredentialsProvider {
|
|
41
|
+
constructor(apiKey, secretKey) {
|
|
42
|
+
this.apiKey = apiKey;
|
|
43
|
+
this.secretKey = secretKey;
|
|
44
|
+
}
|
|
45
|
+
setCredentials(apiKey, secretKey) {
|
|
46
|
+
if (!apiKey || !secretKey) {
|
|
47
|
+
throw new Error("API key and secret are required.");
|
|
48
|
+
}
|
|
49
|
+
this.apiKey = apiKey;
|
|
50
|
+
this.secretKey = secretKey;
|
|
51
|
+
}
|
|
52
|
+
getApiKey() {
|
|
53
|
+
if (!this.apiKey) {
|
|
54
|
+
throw new Error("API credentials are required for this operation. Please provide ZEBPAY_API_KEY and ZEBPAY_API_SECRET headers or include credentials in initialization params.");
|
|
55
|
+
}
|
|
56
|
+
return this.apiKey;
|
|
57
|
+
}
|
|
58
|
+
getSecretKey() {
|
|
59
|
+
if (!this.secretKey) {
|
|
60
|
+
throw new Error("API credentials are required for this operation. Please provide ZEBPAY_API_KEY and ZEBPAY_API_SECRET headers or include credentials in initialization params.");
|
|
61
|
+
}
|
|
62
|
+
return this.secretKey;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Returns safe-to-log shapes for debugging without exposing secrets.
|
|
66
|
+
*/
|
|
67
|
+
describeRedacted() {
|
|
68
|
+
return {
|
|
69
|
+
apiKey: redact(this.apiKey),
|
|
70
|
+
secretKey: redact(this.secretKey),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Check if credentials are set
|
|
75
|
+
*/
|
|
76
|
+
hasCredentials() {
|
|
77
|
+
return !!(this.apiKey && this.secretKey);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/security/credentials.ts"],"names":[],"mappings":"AAAA;;;EAGE;AAEF,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAOtC,MAAM,OAAO,sBAAsB;IAIjC,YACE,gBAAwB,gBAAgB,EACxC,mBAA2B,mBAAmB;QAE9C,IAAI,CAAC,SAAS,GAAG,aAAa,CAAC;QAC/B,IAAI,CAAC,YAAY,GAAG,gBAAgB,CAAC;IACvC,CAAC;IAED,SAAS;QACP,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC1C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CACb,0BAA0B,IAAI,CAAC,SAAS,uBAAuB,CAChE,CAAC;QACJ,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,YAAY;QACV,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC7C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CACb,6BAA6B,IAAI,CAAC,YAAY,uBAAuB,CACtE,CAAC;QACJ,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACH,gBAAgB;QACd,OAAO;YACL,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;YACjD,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;SACxD,CAAC;IACJ,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,2BAA2B;IAItC,YAAY,MAAe,EAAE,SAAkB;QAC7C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IAED,cAAc,CAAC,MAAc,EAAE,SAAiB;QAC9C,IAAI,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QACtD,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IAED,SAAS;QACP,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CACb,+JAA+J,CAChK,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,YAAY;QACV,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CACb,+JAA+J,CAChK,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED;;OAEG;IACH,gBAAgB;QACd,OAAO;YACL,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;YAC3B,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;SAClC,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,cAAc;QACZ,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC;IAC3C,CAAC;CACF"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { SigningHeaderNames } from "../config.js";
|
|
2
|
+
export interface SignatureResult {
|
|
3
|
+
signature: string;
|
|
4
|
+
timestamp: string;
|
|
5
|
+
}
|
|
6
|
+
export interface SigningOptions {
|
|
7
|
+
headers: SigningHeaderNames;
|
|
8
|
+
/** If true, include body in prehash; set false for GETs without body. */
|
|
9
|
+
includeBody?: boolean;
|
|
10
|
+
/** Allows overriding timestamp for testing. */
|
|
11
|
+
now?: () => number;
|
|
12
|
+
}
|
|
13
|
+
export declare function stableStringify(value: unknown): string;
|
|
14
|
+
/**
|
|
15
|
+
* Sign a query string using HMAC-SHA256 (Zebpay API format).
|
|
16
|
+
* This matches the Postman script format where query parameters are signed directly.
|
|
17
|
+
*/
|
|
18
|
+
export declare function signQueryString(queryString: string, secretKey: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* Sign a JSON payload string using HMAC-SHA256 (Zebpay API format for POST requests).
|
|
21
|
+
* This matches the Postman script format where the JSON body string is signed directly.
|
|
22
|
+
*/
|
|
23
|
+
export declare function signPayloadString(payloadString: string, secretKey: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Produce an HMAC-SHA256 signature. Default prehash: `${method}\n${path}\n${timestamp}\n${body}`.
|
|
26
|
+
*/
|
|
27
|
+
export declare function signRequest(method: string, path: string, body: unknown, secretKey: string, opts: SigningOptions): SignatureResult;
|
|
28
|
+
export declare function buildAuthHeaders(apiKey: string, sig: SignatureResult, headerNames: SigningHeaderNames): Record<string, string>;
|
|
29
|
+
/**
|
|
30
|
+
* Build auth headers for query-string based signing (Zebpay format).
|
|
31
|
+
* Only includes API key and signature headers, no timestamp header.
|
|
32
|
+
*/
|
|
33
|
+
export declare function buildQueryStringAuthHeaders(apiKey: string, signature: string, headerNames: SigningHeaderNames): Record<string, string>;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/*
|
|
2
|
+
HMAC signing utilities for ZebPay.
|
|
3
|
+
The exact prehash format and header names are configurable via config to match ZebPay docs.
|
|
4
|
+
*/
|
|
5
|
+
import crypto from "node:crypto";
|
|
6
|
+
export function stableStringify(value) {
|
|
7
|
+
// Deterministic JSON stringify for signing.
|
|
8
|
+
return JSON.stringify(value, Object.keys(value).sort());
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Sign a query string using HMAC-SHA256 (Zebpay API format).
|
|
12
|
+
* This matches the Postman script format where query parameters are signed directly.
|
|
13
|
+
*/
|
|
14
|
+
export function signQueryString(queryString, secretKey) {
|
|
15
|
+
return crypto.createHmac("sha256", secretKey).update(queryString).digest("hex");
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Sign a JSON payload string using HMAC-SHA256 (Zebpay API format for POST requests).
|
|
19
|
+
* This matches the Postman script format where the JSON body string is signed directly.
|
|
20
|
+
*/
|
|
21
|
+
export function signPayloadString(payloadString, secretKey) {
|
|
22
|
+
return crypto.createHmac("sha256", secretKey).update(payloadString).digest("hex");
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Produce an HMAC-SHA256 signature. Default prehash: `${method}\n${path}\n${timestamp}\n${body}`.
|
|
26
|
+
*/
|
|
27
|
+
export function signRequest(method, path, body, secretKey, opts) {
|
|
28
|
+
const timestamp = String((opts.now ? opts.now() : Date.now()));
|
|
29
|
+
const useBody = opts.includeBody ?? (method.toUpperCase() !== "GET" && body !== undefined && body !== null);
|
|
30
|
+
const bodyString = useBody ? (typeof body === "string" ? body : stableStringify(body)) : "";
|
|
31
|
+
const prehash = `${method.toUpperCase()}\n${path}\n${timestamp}\n${bodyString}`;
|
|
32
|
+
const signature = crypto.createHmac("sha256", secretKey).update(prehash).digest("hex");
|
|
33
|
+
return { signature, timestamp };
|
|
34
|
+
}
|
|
35
|
+
export function buildAuthHeaders(apiKey, sig, headerNames) {
|
|
36
|
+
const headers = {
|
|
37
|
+
[headerNames.apiKeyHeader]: apiKey,
|
|
38
|
+
[headerNames.signatureHeader]: sig.signature,
|
|
39
|
+
};
|
|
40
|
+
// Only include timestamp header if it's configured (for non-query-string signing)
|
|
41
|
+
if (headerNames.timestampHeader) {
|
|
42
|
+
headers[headerNames.timestampHeader] = sig.timestamp;
|
|
43
|
+
}
|
|
44
|
+
return headers;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Build auth headers for query-string based signing (Zebpay format).
|
|
48
|
+
* Only includes API key and signature headers, no timestamp header.
|
|
49
|
+
*/
|
|
50
|
+
export function buildQueryStringAuthHeaders(apiKey, signature, headerNames) {
|
|
51
|
+
return {
|
|
52
|
+
[headerNames.apiKeyHeader]: apiKey,
|
|
53
|
+
[headerNames.signatureHeader]: signature,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=signing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signing.js","sourceRoot":"","sources":["../../src/security/signing.ts"],"names":[],"mappings":"AAAA;;;EAGE;AAEF,OAAO,MAAM,MAAM,aAAa,CAAC;AAgBjC,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,4CAA4C;IAC5C,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,KAAe,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;AACpE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC7B,WAAmB,EACnB,SAAiB;IAEjB,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAClF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,aAAqB,EACrB,SAAiB;IAEjB,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACpF,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CACzB,MAAc,EACd,IAAY,EACZ,IAAa,EACb,SAAiB,EACjB,IAAoB;IAEpB,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,KAAK,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,IAAI,CAAC,CAAC;IAC5G,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5F,MAAM,OAAO,GAAG,GAAG,MAAM,CAAC,WAAW,EAAE,KAAK,IAAI,KAAK,SAAS,KAAK,UAAU,EAAE,CAAC;IAChF,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvF,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,MAAc,EACd,GAAoB,EACpB,WAA+B;IAE/B,MAAM,OAAO,GAA2B;QACtC,CAAC,WAAW,CAAC,YAAY,CAAC,EAAE,MAAM;QAClC,CAAC,WAAW,CAAC,eAAe,CAAC,EAAE,GAAG,CAAC,SAAS;KAC7C,CAAC;IACF,kFAAkF;IAClF,IAAI,WAAW,CAAC,eAAe,EAAE,CAAC;QAChC,OAAO,CAAC,WAAW,CAAC,eAAe,CAAC,GAAG,GAAG,CAAC,SAAS,CAAC;IACvD,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,2BAA2B,CACzC,MAAc,EACd,SAAiB,EACjB,WAA+B;IAE/B,OAAO;QACL,CAAC,WAAW,CAAC,YAAY,CAAC,EAAE,MAAM;QAClC,CAAC,WAAW,CAAC,eAAe,CAAC,EAAE,SAAS;KACzC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common response structure for order operations
|
|
3
|
+
*/
|
|
4
|
+
export interface OrderResponse {
|
|
5
|
+
orderId?: string;
|
|
6
|
+
clientOrderId?: string;
|
|
7
|
+
symbol: string;
|
|
8
|
+
side: "buy" | "sell";
|
|
9
|
+
type: "market" | "limit";
|
|
10
|
+
quantity: string;
|
|
11
|
+
price?: string;
|
|
12
|
+
status: string;
|
|
13
|
+
executedPrice?: string;
|
|
14
|
+
executedQuantity?: string;
|
|
15
|
+
timestamp?: number;
|
|
16
|
+
[key: string]: unknown;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Balance information for a single currency
|
|
20
|
+
*/
|
|
21
|
+
export interface CurrencyBalance {
|
|
22
|
+
currency: string;
|
|
23
|
+
available: string;
|
|
24
|
+
locked?: string;
|
|
25
|
+
total?: string;
|
|
26
|
+
[key: string]: unknown;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Balance response structure
|
|
30
|
+
*/
|
|
31
|
+
export interface BalanceResponse {
|
|
32
|
+
balances?: CurrencyBalance[];
|
|
33
|
+
currencies?: Record<string, CurrencyBalance>;
|
|
34
|
+
[key: string]: unknown;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Ticker information for a trading pair
|
|
38
|
+
*/
|
|
39
|
+
export interface TickerResponse {
|
|
40
|
+
symbol: string;
|
|
41
|
+
lastPrice: string;
|
|
42
|
+
bidPrice?: string;
|
|
43
|
+
askPrice?: string;
|
|
44
|
+
high24h?: string;
|
|
45
|
+
low24h?: string;
|
|
46
|
+
volume24h?: string;
|
|
47
|
+
priceChange24h?: string;
|
|
48
|
+
priceChangePercent24h?: string;
|
|
49
|
+
timestamp?: number;
|
|
50
|
+
[key: string]: unknown;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Order book entry
|
|
54
|
+
*/
|
|
55
|
+
export interface OrderBookEntry {
|
|
56
|
+
price: string;
|
|
57
|
+
quantity: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Order book response
|
|
61
|
+
*/
|
|
62
|
+
export interface OrderBookResponse {
|
|
63
|
+
symbol: string;
|
|
64
|
+
bids: OrderBookEntry[];
|
|
65
|
+
asks: OrderBookEntry[];
|
|
66
|
+
timestamp?: number;
|
|
67
|
+
[key: string]: unknown;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Trade information
|
|
71
|
+
*/
|
|
72
|
+
export interface TradeResponse {
|
|
73
|
+
symbol: string;
|
|
74
|
+
price: string;
|
|
75
|
+
quantity: string;
|
|
76
|
+
side: "buy" | "sell";
|
|
77
|
+
timestamp: number;
|
|
78
|
+
[key: string]: unknown;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Kline/Candlestick data
|
|
82
|
+
*/
|
|
83
|
+
export interface KlineResponse {
|
|
84
|
+
openTime: number;
|
|
85
|
+
open: string;
|
|
86
|
+
high: string;
|
|
87
|
+
low: string;
|
|
88
|
+
close: string;
|
|
89
|
+
volume: string;
|
|
90
|
+
closeTime: number;
|
|
91
|
+
[key: string]: unknown;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Exchange information
|
|
95
|
+
*/
|
|
96
|
+
export interface ExchangeInfoResponse {
|
|
97
|
+
symbols?: Array<{
|
|
98
|
+
symbol: string;
|
|
99
|
+
baseAsset: string;
|
|
100
|
+
quoteAsset: string;
|
|
101
|
+
status: string;
|
|
102
|
+
[key: string]: unknown;
|
|
103
|
+
}>;
|
|
104
|
+
[key: string]: unknown;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Currency information
|
|
108
|
+
*/
|
|
109
|
+
export interface CurrencyInfo {
|
|
110
|
+
currency: string;
|
|
111
|
+
name?: string;
|
|
112
|
+
fullName?: string;
|
|
113
|
+
precision?: number;
|
|
114
|
+
type?: string;
|
|
115
|
+
chains?: Array<{
|
|
116
|
+
chainName: string;
|
|
117
|
+
withdrawalFee?: string;
|
|
118
|
+
depositMinSize?: string;
|
|
119
|
+
withdrawalMinSize?: string;
|
|
120
|
+
[key: string]: unknown;
|
|
121
|
+
}>;
|
|
122
|
+
[key: string]: unknown;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Currencies response
|
|
126
|
+
*/
|
|
127
|
+
export interface CurrenciesResponse {
|
|
128
|
+
currencies?: CurrencyInfo[];
|
|
129
|
+
[key: string]: unknown;
|
|
130
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"responses.js","sourceRoot":"","sources":["../../src/types/responses.ts"],"names":[],"mappings":"AAAA;;;EAGE"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export declare class SimpleCache<T = unknown> {
|
|
2
|
+
private cache;
|
|
3
|
+
private defaultTtl;
|
|
4
|
+
constructor(defaultTtlMs?: number);
|
|
5
|
+
/**
|
|
6
|
+
* Get cached value if not expired
|
|
7
|
+
*/
|
|
8
|
+
get(key: string): T | null;
|
|
9
|
+
/**
|
|
10
|
+
* Set cached value with optional TTL
|
|
11
|
+
*/
|
|
12
|
+
set(key: string, data: T, ttlMs?: number): void;
|
|
13
|
+
/**
|
|
14
|
+
* Clear expired entries
|
|
15
|
+
*/
|
|
16
|
+
clearExpired(): void;
|
|
17
|
+
/**
|
|
18
|
+
* Clear all cache entries
|
|
19
|
+
*/
|
|
20
|
+
clear(): void;
|
|
21
|
+
/**
|
|
22
|
+
* Get cache size
|
|
23
|
+
*/
|
|
24
|
+
size(): number;
|
|
25
|
+
}
|
|
26
|
+
export declare const tickerCache: SimpleCache<unknown>;
|
|
27
|
+
export declare const orderBookCache: SimpleCache<unknown>;
|
|
28
|
+
export declare const exchangeInfoCache: SimpleCache<unknown>;
|
|
29
|
+
export declare const currenciesCache: SimpleCache<unknown>;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Simple in-memory cache for public endpoints to reduce API calls.
|
|
3
|
+
*/
|
|
4
|
+
export class SimpleCache {
|
|
5
|
+
constructor(defaultTtlMs = 5000) {
|
|
6
|
+
this.cache = new Map();
|
|
7
|
+
this.defaultTtl = defaultTtlMs;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Get cached value if not expired
|
|
11
|
+
*/
|
|
12
|
+
get(key) {
|
|
13
|
+
const entry = this.cache.get(key);
|
|
14
|
+
if (!entry) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
const now = Date.now();
|
|
18
|
+
if (now - entry.timestamp > entry.ttl) {
|
|
19
|
+
this.cache.delete(key);
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
return entry.data;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Set cached value with optional TTL
|
|
26
|
+
*/
|
|
27
|
+
set(key, data, ttlMs) {
|
|
28
|
+
this.cache.set(key, {
|
|
29
|
+
data,
|
|
30
|
+
timestamp: Date.now(),
|
|
31
|
+
ttl: ttlMs || this.defaultTtl,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Clear expired entries
|
|
36
|
+
*/
|
|
37
|
+
clearExpired() {
|
|
38
|
+
const now = Date.now();
|
|
39
|
+
for (const [key, entry] of this.cache.entries()) {
|
|
40
|
+
if (now - entry.timestamp > entry.ttl) {
|
|
41
|
+
this.cache.delete(key);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Clear all cache entries
|
|
47
|
+
*/
|
|
48
|
+
clear() {
|
|
49
|
+
this.cache.clear();
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Get cache size
|
|
53
|
+
*/
|
|
54
|
+
size() {
|
|
55
|
+
return this.cache.size;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Cache instances for different endpoint types
|
|
59
|
+
export const tickerCache = new SimpleCache(5000); // 5 seconds for tickers
|
|
60
|
+
export const orderBookCache = new SimpleCache(2000); // 2 seconds for order books
|
|
61
|
+
export const exchangeInfoCache = new SimpleCache(60000); // 1 minute for exchange info
|
|
62
|
+
export const currenciesCache = new SimpleCache(300000); // 5 minutes for currencies
|
|
63
|
+
// Clean up expired entries periodically
|
|
64
|
+
if (typeof setInterval !== "undefined") {
|
|
65
|
+
setInterval(() => {
|
|
66
|
+
tickerCache.clearExpired();
|
|
67
|
+
orderBookCache.clearExpired();
|
|
68
|
+
exchangeInfoCache.clearExpired();
|
|
69
|
+
currenciesCache.clearExpired();
|
|
70
|
+
}, 10000); // Clean every 10 seconds
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/utils/cache.ts"],"names":[],"mappings":"AAAA;;EAEE;AAQF,MAAM,OAAO,WAAW;IAItB,YAAY,eAAuB,IAAI;QAH/B,UAAK,GAAG,IAAI,GAAG,EAAyB,CAAC;QAI/C,IAAI,CAAC,UAAU,GAAG,YAAY,CAAC;IACjC,CAAC;IAED;;OAEG;IACH,GAAG,CAAC,GAAW;QACb,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,IAAI,GAAG,GAAG,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC;YACtC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC;IACpB,CAAC;IAED;;OAEG;IACH,GAAG,CAAC,GAAW,EAAE,IAAO,EAAE,KAAc;QACtC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE;YAClB,IAAI;YACJ,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,GAAG,EAAE,KAAK,IAAI,IAAI,CAAC,UAAU;SAC9B,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,YAAY;QACV,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;YAChD,IAAI,GAAG,GAAG,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC;gBACtC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,IAAI;QACF,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;CACF;AAED,+CAA+C;AAC/C,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,wBAAwB;AAC1E,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,4BAA4B;AACjF,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,6BAA6B;AACtF,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,2BAA2B;AAEnF,wCAAwC;AACxC,IAAI,OAAO,WAAW,KAAK,WAAW,EAAE,CAAC;IACvC,WAAW,CAAC,GAAG,EAAE;QACf,WAAW,CAAC,YAAY,EAAE,CAAC;QAC3B,cAAc,CAAC,YAAY,EAAE,CAAC;QAC9B,iBAAiB,CAAC,YAAY,EAAE,CAAC;QACjC,eAAe,CAAC,YAAY,EAAE,CAAC;IACjC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,yBAAyB;AACtC,CAAC"}
|