@metamask-previews/shield-controller 5.1.3-preview-316ba6af0 → 5.1.3-preview-e57e5c3dc
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/CHANGELOG.md +1 -16
- package/dist/ShieldController.cjs +9 -7
- package/dist/ShieldController.cjs.map +1 -1
- package/dist/ShieldController.d.cts +3 -7
- package/dist/ShieldController.d.cts.map +1 -1
- package/dist/ShieldController.d.mts +3 -7
- package/dist/ShieldController.d.mts.map +1 -1
- package/dist/ShieldController.mjs +9 -7
- package/dist/ShieldController.mjs.map +1 -1
- package/dist/backend.cjs +289 -0
- package/dist/backend.cjs.map +1 -0
- package/dist/backend.d.cts +72 -0
- package/dist/backend.d.cts.map +1 -0
- package/dist/backend.d.mts +72 -0
- package/dist/backend.d.mts.map +1 -0
- package/dist/backend.mjs +283 -0
- package/dist/backend.mjs.map +1 -0
- package/dist/constants.cjs +1 -33
- package/dist/constants.cjs.map +1 -1
- package/dist/constants.d.cts +0 -20
- package/dist/constants.d.cts.map +1 -1
- package/dist/constants.d.mts +0 -20
- package/dist/constants.d.mts.map +1 -1
- package/dist/constants.mjs +0 -31
- package/dist/constants.mjs.map +1 -1
- package/dist/index.cjs +4 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -5
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +2 -5
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -2
- package/dist/index.mjs.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +6 -0
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +6 -0
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/package.json +2 -5
- package/dist/shield-api-service-method-action-types.cjs +0 -7
- package/dist/shield-api-service-method-action-types.cjs.map +0 -1
- package/dist/shield-api-service-method-action-types.d.cts +0 -48
- package/dist/shield-api-service-method-action-types.d.cts.map +0 -1
- package/dist/shield-api-service-method-action-types.d.mts +0 -48
- package/dist/shield-api-service-method-action-types.d.mts.map +0 -1
- package/dist/shield-api-service-method-action-types.mjs +0 -6
- package/dist/shield-api-service-method-action-types.mjs.map +0 -1
- package/dist/shield-api-service.cjs +0 -371
- package/dist/shield-api-service.cjs.map +0 -1
- package/dist/shield-api-service.d.cts +0 -164
- package/dist/shield-api-service.d.cts.map +0 -1
- package/dist/shield-api-service.d.mts +0 -164
- package/dist/shield-api-service.d.mts.map +0 -1
- package/dist/shield-api-service.mjs +0 -365
- package/dist/shield-api-service.mjs.map +0 -1
package/dist/backend.cjs
ADDED
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
3
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
4
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
5
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
6
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
7
|
+
};
|
|
8
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
9
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
10
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
11
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
|
+
};
|
|
13
|
+
var _ShieldRemoteBackend_instances, _ShieldRemoteBackend_getAccessToken, _ShieldRemoteBackend_baseUrl, _ShieldRemoteBackend_fetch, _ShieldRemoteBackend_pollingPolicy, _ShieldRemoteBackend_captureException, _ShieldRemoteBackend_initCoverageCheck, _ShieldRemoteBackend_getCoverageResult, _ShieldRemoteBackend_createHeaders;
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.parseSignatureRequestMethod = exports.makeInitCoverageCheckBody = exports.ShieldRemoteBackend = void 0;
|
|
16
|
+
const controller_utils_1 = require("@metamask/controller-utils");
|
|
17
|
+
const signature_controller_1 = require("@metamask/signature-controller");
|
|
18
|
+
const constants_js_1 = require("./constants.cjs");
|
|
19
|
+
const polling_with_policy_js_1 = require("./polling-with-policy.cjs");
|
|
20
|
+
class ShieldRemoteBackend {
|
|
21
|
+
constructor({ getAccessToken, getCoverageResultTimeout = 5000, // milliseconds
|
|
22
|
+
getCoverageResultPollInterval = 1000, // milliseconds
|
|
23
|
+
baseUrl, fetch: fetchFn, captureException: captureExceptionFn, }) {
|
|
24
|
+
_ShieldRemoteBackend_instances.add(this);
|
|
25
|
+
_ShieldRemoteBackend_getAccessToken.set(this, void 0);
|
|
26
|
+
_ShieldRemoteBackend_baseUrl.set(this, void 0);
|
|
27
|
+
_ShieldRemoteBackend_fetch.set(this, void 0);
|
|
28
|
+
_ShieldRemoteBackend_pollingPolicy.set(this, void 0);
|
|
29
|
+
_ShieldRemoteBackend_captureException.set(this, void 0);
|
|
30
|
+
__classPrivateFieldSet(this, _ShieldRemoteBackend_getAccessToken, getAccessToken, "f");
|
|
31
|
+
__classPrivateFieldSet(this, _ShieldRemoteBackend_baseUrl, baseUrl, "f");
|
|
32
|
+
__classPrivateFieldSet(this, _ShieldRemoteBackend_fetch, fetchFn, "f");
|
|
33
|
+
const { backoff, maxRetries } = computePollingIntervalAndRetryCount(getCoverageResultTimeout, getCoverageResultPollInterval);
|
|
34
|
+
__classPrivateFieldSet(this, _ShieldRemoteBackend_pollingPolicy, new polling_with_policy_js_1.PollingWithCockatielPolicy({
|
|
35
|
+
backoff,
|
|
36
|
+
maxRetries,
|
|
37
|
+
}), "f");
|
|
38
|
+
__classPrivateFieldSet(this, _ShieldRemoteBackend_captureException, (error) => {
|
|
39
|
+
try {
|
|
40
|
+
captureExceptionFn?.(error);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// ignore error thrown when calling captureException
|
|
44
|
+
}
|
|
45
|
+
}, "f");
|
|
46
|
+
}
|
|
47
|
+
async checkCoverage(req) {
|
|
48
|
+
let { coverageId } = req;
|
|
49
|
+
if (!coverageId) {
|
|
50
|
+
const reqBody = makeInitCoverageCheckBody(req.txMeta);
|
|
51
|
+
({ coverageId } = await __classPrivateFieldGet(this, _ShieldRemoteBackend_instances, "m", _ShieldRemoteBackend_initCoverageCheck).call(this, 'v1/transaction/coverage/init', reqBody));
|
|
52
|
+
}
|
|
53
|
+
const txCoverageResultUrl = `${__classPrivateFieldGet(this, _ShieldRemoteBackend_baseUrl, "f")}/v1/transaction/coverage/result`;
|
|
54
|
+
const coverageResult = await __classPrivateFieldGet(this, _ShieldRemoteBackend_instances, "m", _ShieldRemoteBackend_getCoverageResult).call(this, req.txMeta.id, coverageId, txCoverageResultUrl);
|
|
55
|
+
return {
|
|
56
|
+
coverageId,
|
|
57
|
+
message: coverageResult.message,
|
|
58
|
+
reasonCode: coverageResult.reasonCode,
|
|
59
|
+
status: coverageResult.status,
|
|
60
|
+
metrics: coverageResult.metrics,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
async checkSignatureCoverage(req) {
|
|
64
|
+
let { coverageId } = req;
|
|
65
|
+
if (!coverageId) {
|
|
66
|
+
const reqBody = makeInitSignatureCoverageCheckBody(req.signatureRequest);
|
|
67
|
+
({ coverageId } = await __classPrivateFieldGet(this, _ShieldRemoteBackend_instances, "m", _ShieldRemoteBackend_initCoverageCheck).call(this, 'v1/signature/coverage/init', reqBody));
|
|
68
|
+
}
|
|
69
|
+
const signatureCoverageResultUrl = `${__classPrivateFieldGet(this, _ShieldRemoteBackend_baseUrl, "f")}/v1/signature/coverage/result`;
|
|
70
|
+
const coverageResult = await __classPrivateFieldGet(this, _ShieldRemoteBackend_instances, "m", _ShieldRemoteBackend_getCoverageResult).call(this, req.signatureRequest.id, coverageId, signatureCoverageResultUrl);
|
|
71
|
+
return {
|
|
72
|
+
coverageId,
|
|
73
|
+
message: coverageResult.message,
|
|
74
|
+
reasonCode: coverageResult.reasonCode,
|
|
75
|
+
status: coverageResult.status,
|
|
76
|
+
metrics: coverageResult.metrics,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
async logSignature(req) {
|
|
80
|
+
try {
|
|
81
|
+
const initBody = makeInitSignatureCoverageCheckBody(req.signatureRequest);
|
|
82
|
+
const body = {
|
|
83
|
+
signature: req.signature,
|
|
84
|
+
status: req.status,
|
|
85
|
+
...initBody,
|
|
86
|
+
};
|
|
87
|
+
// cancel the pending get coverage result request
|
|
88
|
+
__classPrivateFieldGet(this, _ShieldRemoteBackend_pollingPolicy, "f").abortPendingRequest(req.signatureRequest.id);
|
|
89
|
+
const res = await __classPrivateFieldGet(this, _ShieldRemoteBackend_fetch, "f").call(this, `${__classPrivateFieldGet(this, _ShieldRemoteBackend_baseUrl, "f")}/v1/signature/coverage/log`, {
|
|
90
|
+
method: 'POST',
|
|
91
|
+
headers: await __classPrivateFieldGet(this, _ShieldRemoteBackend_instances, "m", _ShieldRemoteBackend_createHeaders).call(this),
|
|
92
|
+
body: JSON.stringify(body),
|
|
93
|
+
});
|
|
94
|
+
if (res.status !== 200) {
|
|
95
|
+
throw new Error(`Failed to log signature: ${res.status}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
const sentryError = createSentryError('Failed to log signature', error);
|
|
100
|
+
__classPrivateFieldGet(this, _ShieldRemoteBackend_captureException, "f")?.call(this, sentryError);
|
|
101
|
+
// rethrow the original error
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
async logTransaction(req) {
|
|
106
|
+
try {
|
|
107
|
+
const initBody = makeInitCoverageCheckBody(req.txMeta);
|
|
108
|
+
const body = {
|
|
109
|
+
transactionHash: req.transactionHash,
|
|
110
|
+
rawTransactionHex: req.rawTransactionHex,
|
|
111
|
+
status: req.status,
|
|
112
|
+
...initBody,
|
|
113
|
+
};
|
|
114
|
+
// cancel the pending get coverage result request
|
|
115
|
+
__classPrivateFieldGet(this, _ShieldRemoteBackend_pollingPolicy, "f").abortPendingRequest(req.txMeta.id);
|
|
116
|
+
const res = await __classPrivateFieldGet(this, _ShieldRemoteBackend_fetch, "f").call(this, `${__classPrivateFieldGet(this, _ShieldRemoteBackend_baseUrl, "f")}/v1/transaction/coverage/log`, {
|
|
117
|
+
method: 'POST',
|
|
118
|
+
headers: await __classPrivateFieldGet(this, _ShieldRemoteBackend_instances, "m", _ShieldRemoteBackend_createHeaders).call(this),
|
|
119
|
+
body: JSON.stringify(body),
|
|
120
|
+
});
|
|
121
|
+
if (res.status !== 200) {
|
|
122
|
+
throw new Error(`Failed to log transaction: ${res.status}`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
const sentryError = createSentryError('Failed to log transaction', error);
|
|
127
|
+
__classPrivateFieldGet(this, _ShieldRemoteBackend_captureException, "f")?.call(this, sentryError);
|
|
128
|
+
// rethrow the original error
|
|
129
|
+
throw error;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
exports.ShieldRemoteBackend = ShieldRemoteBackend;
|
|
134
|
+
_ShieldRemoteBackend_getAccessToken = new WeakMap(), _ShieldRemoteBackend_baseUrl = new WeakMap(), _ShieldRemoteBackend_fetch = new WeakMap(), _ShieldRemoteBackend_pollingPolicy = new WeakMap(), _ShieldRemoteBackend_captureException = new WeakMap(), _ShieldRemoteBackend_instances = new WeakSet(), _ShieldRemoteBackend_initCoverageCheck = async function _ShieldRemoteBackend_initCoverageCheck(path, reqBody) {
|
|
135
|
+
try {
|
|
136
|
+
const res = await __classPrivateFieldGet(this, _ShieldRemoteBackend_fetch, "f").call(this, `${__classPrivateFieldGet(this, _ShieldRemoteBackend_baseUrl, "f")}/${path}`, {
|
|
137
|
+
method: 'POST',
|
|
138
|
+
headers: await __classPrivateFieldGet(this, _ShieldRemoteBackend_instances, "m", _ShieldRemoteBackend_createHeaders).call(this),
|
|
139
|
+
body: JSON.stringify(reqBody),
|
|
140
|
+
});
|
|
141
|
+
if (res.status !== 200) {
|
|
142
|
+
throw new Error(`Failed to init coverage check: ${res.status}`);
|
|
143
|
+
}
|
|
144
|
+
return (await res.json());
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
const sentryError = createSentryError('Failed to init coverage check', error);
|
|
148
|
+
__classPrivateFieldGet(this, _ShieldRemoteBackend_captureException, "f")?.call(this, sentryError);
|
|
149
|
+
// rethrow the original error
|
|
150
|
+
throw error;
|
|
151
|
+
}
|
|
152
|
+
}, _ShieldRemoteBackend_getCoverageResult = async function _ShieldRemoteBackend_getCoverageResult(requestId, coverageId, coverageResultUrl) {
|
|
153
|
+
const reqBody = {
|
|
154
|
+
coverageId,
|
|
155
|
+
};
|
|
156
|
+
const headers = await __classPrivateFieldGet(this, _ShieldRemoteBackend_instances, "m", _ShieldRemoteBackend_createHeaders).call(this);
|
|
157
|
+
// Start measuring total end-to-end latency including retries and delays
|
|
158
|
+
const startTime = Date.now();
|
|
159
|
+
const getCoverageResultFn = async (signal) => {
|
|
160
|
+
const res = await __classPrivateFieldGet(this, _ShieldRemoteBackend_fetch, "f").call(this, coverageResultUrl, {
|
|
161
|
+
method: 'POST',
|
|
162
|
+
headers,
|
|
163
|
+
body: JSON.stringify(reqBody),
|
|
164
|
+
signal,
|
|
165
|
+
});
|
|
166
|
+
if (res.status === 200) {
|
|
167
|
+
// Return the result without latency here - we'll add total latency after polling completes
|
|
168
|
+
return (await res.json());
|
|
169
|
+
}
|
|
170
|
+
// parse the error message from the response body
|
|
171
|
+
let errorMessage = 'Timeout waiting for coverage result';
|
|
172
|
+
try {
|
|
173
|
+
const errorJson = await res.json();
|
|
174
|
+
errorMessage = `Failed to get coverage result: ${errorJson.message ?? errorJson.status}`;
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
errorMessage = `Failed to get coverage result: ${res.status}`;
|
|
178
|
+
}
|
|
179
|
+
throw new controller_utils_1.HttpError(res.status, errorMessage);
|
|
180
|
+
};
|
|
181
|
+
const result = await __classPrivateFieldGet(this, _ShieldRemoteBackend_pollingPolicy, "f").start(requestId, getCoverageResultFn);
|
|
182
|
+
// Calculate total end-to-end latency including all retries and delays
|
|
183
|
+
const now = Date.now();
|
|
184
|
+
const totalLatency = now - startTime;
|
|
185
|
+
return {
|
|
186
|
+
...result,
|
|
187
|
+
metrics: { latency: totalLatency },
|
|
188
|
+
};
|
|
189
|
+
}, _ShieldRemoteBackend_createHeaders = async function _ShieldRemoteBackend_createHeaders() {
|
|
190
|
+
const accessToken = await __classPrivateFieldGet(this, _ShieldRemoteBackend_getAccessToken, "f").call(this);
|
|
191
|
+
return {
|
|
192
|
+
'Content-Type': 'application/json',
|
|
193
|
+
Authorization: `Bearer ${accessToken}`,
|
|
194
|
+
};
|
|
195
|
+
};
|
|
196
|
+
/**
|
|
197
|
+
* Make the body for the init coverage check request.
|
|
198
|
+
*
|
|
199
|
+
* @param txMeta - The transaction metadata.
|
|
200
|
+
* @returns The body for the init coverage check request.
|
|
201
|
+
*/
|
|
202
|
+
function makeInitCoverageCheckBody(txMeta) {
|
|
203
|
+
return {
|
|
204
|
+
txParams: [
|
|
205
|
+
{
|
|
206
|
+
authorizationList: txMeta.txParams.authorizationList,
|
|
207
|
+
from: txMeta.txParams.from,
|
|
208
|
+
to: txMeta.txParams.to,
|
|
209
|
+
value: txMeta.txParams.value,
|
|
210
|
+
data: txMeta.txParams.data,
|
|
211
|
+
nonce: txMeta.txParams.nonce,
|
|
212
|
+
},
|
|
213
|
+
],
|
|
214
|
+
chainId: txMeta.chainId,
|
|
215
|
+
origin: txMeta.origin,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
exports.makeInitCoverageCheckBody = makeInitCoverageCheckBody;
|
|
219
|
+
/**
|
|
220
|
+
* Make the body for the init signature coverage check request.
|
|
221
|
+
*
|
|
222
|
+
* @param signatureRequest - The signature request.
|
|
223
|
+
* @returns The body for the init signature coverage check request.
|
|
224
|
+
*/
|
|
225
|
+
function makeInitSignatureCoverageCheckBody(signatureRequest) {
|
|
226
|
+
// TODO: confirm that do we still need to validate the signature data?
|
|
227
|
+
// signature controller already validates the signature data before adding it to the state.
|
|
228
|
+
// @link https://github.com/MetaMask/core/blob/main/packages/signature-controller/src/SignatureController.ts#L408
|
|
229
|
+
const method = parseSignatureRequestMethod(signatureRequest);
|
|
230
|
+
return {
|
|
231
|
+
chainId: signatureRequest.chainId,
|
|
232
|
+
data: signatureRequest.messageParams.data,
|
|
233
|
+
from: signatureRequest.messageParams.from,
|
|
234
|
+
method,
|
|
235
|
+
origin: signatureRequest.messageParams.origin,
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Parse the JSON-RPC method from the signature request.
|
|
240
|
+
*
|
|
241
|
+
* @param signatureRequest - The signature request.
|
|
242
|
+
* @returns The JSON-RPC method.
|
|
243
|
+
*/
|
|
244
|
+
function parseSignatureRequestMethod(signatureRequest) {
|
|
245
|
+
if (signatureRequest.type === signature_controller_1.SignatureRequestType.TypedSign) {
|
|
246
|
+
switch (signatureRequest.version) {
|
|
247
|
+
case constants_js_1.SignTypedDataVersion.V3:
|
|
248
|
+
return signature_controller_1.EthMethod.SignTypedDataV3;
|
|
249
|
+
case constants_js_1.SignTypedDataVersion.V4:
|
|
250
|
+
return signature_controller_1.EthMethod.SignTypedDataV4;
|
|
251
|
+
case constants_js_1.SignTypedDataVersion.V1:
|
|
252
|
+
default:
|
|
253
|
+
return signature_controller_1.SignatureRequestType.TypedSign;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return signatureRequest.type;
|
|
257
|
+
}
|
|
258
|
+
exports.parseSignatureRequestMethod = parseSignatureRequestMethod;
|
|
259
|
+
/**
|
|
260
|
+
* Compute the polling interval and retry count for the Cockatiel policy based on the timeout and poll interval given.
|
|
261
|
+
*
|
|
262
|
+
* @param timeout - The timeout in milliseconds.
|
|
263
|
+
* @param pollInterval - The poll interval in milliseconds.
|
|
264
|
+
* @returns The polling interval and retry count.
|
|
265
|
+
*/
|
|
266
|
+
function computePollingIntervalAndRetryCount(timeout, pollInterval) {
|
|
267
|
+
const backoff = new controller_utils_1.ConstantBackoff(pollInterval);
|
|
268
|
+
const computedMaxRetries = Math.floor(timeout / pollInterval) + 1;
|
|
269
|
+
const maxRetries = isNaN(computedMaxRetries) || !isFinite(computedMaxRetries)
|
|
270
|
+
? controller_utils_1.DEFAULT_MAX_RETRIES
|
|
271
|
+
: computedMaxRetries;
|
|
272
|
+
return {
|
|
273
|
+
backoff,
|
|
274
|
+
maxRetries,
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Create an error instance with a readable message, a cause and a context for Sentry.
|
|
279
|
+
*
|
|
280
|
+
* @param errorMessage - The error message.
|
|
281
|
+
* @param cause - The cause of the error.
|
|
282
|
+
* @returns A Sentry error.
|
|
283
|
+
*/
|
|
284
|
+
function createSentryError(errorMessage, cause) {
|
|
285
|
+
const error = new Error(errorMessage);
|
|
286
|
+
error.cause = cause;
|
|
287
|
+
return error;
|
|
288
|
+
}
|
|
289
|
+
//# sourceMappingURL=backend.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend.cjs","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ConstantBackoff,\n DEFAULT_MAX_RETRIES,\n HttpError,\n} from '@metamask/controller-utils';\nimport {\n EthMethod,\n SignatureRequestType,\n} from '@metamask/signature-controller';\nimport type { SignatureRequest } from '@metamask/signature-controller';\nimport type { TransactionMeta } from '@metamask/transaction-controller';\nimport type { AuthorizationList } from '@metamask/transaction-controller';\nimport type { Json } from '@metamask/utils';\n\nimport { SignTypedDataVersion } from './constants.js';\nimport { PollingWithCockatielPolicy } from './polling-with-policy.js';\nimport type {\n CheckCoverageRequest,\n CheckSignatureCoverageRequest,\n CoverageResult,\n CoverageStatus,\n LogSignatureRequest,\n LogTransactionRequest,\n ShieldBackend,\n} from './types.js';\n\nexport type InitCoverageCheckRequest = {\n txParams: [\n {\n authorizationList?: AuthorizationList;\n from: string;\n to?: string;\n value?: string;\n data?: string;\n nonce?: string;\n },\n ];\n chainId: string;\n origin?: string;\n};\n\nexport type InitSignatureCoverageCheckRequest = {\n chainId: string;\n data: Json;\n from: string;\n method: string;\n origin?: string;\n};\n\nexport type InitCoverageCheckResponse = {\n coverageId: string;\n};\n\nexport type GetCoverageResultRequest = {\n coverageId: string;\n};\n\nexport type GetCoverageResultResponse = {\n message?: string;\n reasonCode?: string;\n status: CoverageStatus;\n metrics: {\n latency?: number;\n };\n};\n\nexport class ShieldRemoteBackend implements ShieldBackend {\n readonly #getAccessToken: () => Promise<string>;\n\n readonly #baseUrl: string;\n\n readonly #fetch: typeof globalThis.fetch;\n\n readonly #pollingPolicy: PollingWithCockatielPolicy;\n\n readonly #captureException?: (error: Error) => void;\n\n constructor({\n getAccessToken,\n getCoverageResultTimeout = 5000, // milliseconds\n getCoverageResultPollInterval = 1000, // milliseconds\n baseUrl,\n fetch: fetchFn,\n captureException: captureExceptionFn,\n }: {\n getAccessToken: () => Promise<string>;\n getCoverageResultTimeout?: number;\n getCoverageResultPollInterval?: number;\n baseUrl: string;\n fetch: typeof globalThis.fetch;\n captureException?: (error: Error) => void;\n }) {\n this.#getAccessToken = getAccessToken;\n this.#baseUrl = baseUrl;\n this.#fetch = fetchFn;\n\n const { backoff, maxRetries } = computePollingIntervalAndRetryCount(\n getCoverageResultTimeout,\n getCoverageResultPollInterval,\n );\n\n this.#pollingPolicy = new PollingWithCockatielPolicy({\n backoff,\n maxRetries,\n });\n\n this.#captureException = (error: Error): void => {\n try {\n captureExceptionFn?.(error);\n } catch {\n // ignore error thrown when calling captureException\n }\n };\n }\n\n async checkCoverage(req: CheckCoverageRequest): Promise<CoverageResult> {\n let { coverageId } = req;\n if (!coverageId) {\n const reqBody = makeInitCoverageCheckBody(req.txMeta);\n ({ coverageId } = await this.#initCoverageCheck(\n 'v1/transaction/coverage/init',\n reqBody,\n ));\n }\n\n const txCoverageResultUrl = `${this.#baseUrl}/v1/transaction/coverage/result`;\n const coverageResult = await this.#getCoverageResult(\n req.txMeta.id,\n coverageId,\n txCoverageResultUrl,\n );\n return {\n coverageId,\n message: coverageResult.message,\n reasonCode: coverageResult.reasonCode,\n status: coverageResult.status,\n metrics: coverageResult.metrics,\n };\n }\n\n async checkSignatureCoverage(\n req: CheckSignatureCoverageRequest,\n ): Promise<CoverageResult> {\n let { coverageId } = req;\n if (!coverageId) {\n const reqBody = makeInitSignatureCoverageCheckBody(req.signatureRequest);\n ({ coverageId } = await this.#initCoverageCheck(\n 'v1/signature/coverage/init',\n reqBody,\n ));\n }\n\n const signatureCoverageResultUrl = `${this.#baseUrl}/v1/signature/coverage/result`;\n const coverageResult = await this.#getCoverageResult(\n req.signatureRequest.id,\n coverageId,\n signatureCoverageResultUrl,\n );\n return {\n coverageId,\n message: coverageResult.message,\n reasonCode: coverageResult.reasonCode,\n status: coverageResult.status,\n metrics: coverageResult.metrics,\n };\n }\n\n async logSignature(req: LogSignatureRequest): Promise<void> {\n try {\n const initBody = makeInitSignatureCoverageCheckBody(req.signatureRequest);\n const body = {\n signature: req.signature,\n status: req.status,\n ...initBody,\n };\n\n // cancel the pending get coverage result request\n this.#pollingPolicy.abortPendingRequest(req.signatureRequest.id);\n\n const res = await this.#fetch(\n `${this.#baseUrl}/v1/signature/coverage/log`,\n {\n method: 'POST',\n headers: await this.#createHeaders(),\n body: JSON.stringify(body),\n },\n );\n if (res.status !== 200) {\n throw new Error(`Failed to log signature: ${res.status}`);\n }\n } catch (error) {\n const sentryError = createSentryError(\n 'Failed to log signature',\n error as Error,\n );\n this.#captureException?.(sentryError);\n\n // rethrow the original error\n throw error;\n }\n }\n\n async logTransaction(req: LogTransactionRequest): Promise<void> {\n try {\n const initBody = makeInitCoverageCheckBody(req.txMeta);\n\n const body = {\n transactionHash: req.transactionHash,\n rawTransactionHex: req.rawTransactionHex,\n status: req.status,\n ...initBody,\n };\n\n // cancel the pending get coverage result request\n this.#pollingPolicy.abortPendingRequest(req.txMeta.id);\n\n const res = await this.#fetch(\n `${this.#baseUrl}/v1/transaction/coverage/log`,\n {\n method: 'POST',\n headers: await this.#createHeaders(),\n body: JSON.stringify(body),\n },\n );\n if (res.status !== 200) {\n throw new Error(`Failed to log transaction: ${res.status}`);\n }\n } catch (error) {\n const sentryError = createSentryError(\n 'Failed to log transaction',\n error as Error,\n );\n this.#captureException?.(sentryError);\n\n // rethrow the original error\n throw error;\n }\n }\n\n async #initCoverageCheck(\n path: string,\n reqBody: unknown,\n ): Promise<InitCoverageCheckResponse> {\n try {\n const res = await this.#fetch(`${this.#baseUrl}/${path}`, {\n method: 'POST',\n headers: await this.#createHeaders(),\n body: JSON.stringify(reqBody),\n });\n if (res.status !== 200) {\n throw new Error(`Failed to init coverage check: ${res.status}`);\n }\n return (await res.json()) as InitCoverageCheckResponse;\n } catch (error) {\n const sentryError = createSentryError(\n 'Failed to init coverage check',\n error as Error,\n );\n this.#captureException?.(sentryError);\n\n // rethrow the original error\n throw error;\n }\n }\n\n async #getCoverageResult(\n requestId: string,\n coverageId: string,\n coverageResultUrl: string,\n ): Promise<GetCoverageResultResponse> {\n const reqBody: GetCoverageResultRequest = {\n coverageId,\n };\n\n const headers = await this.#createHeaders();\n\n // Start measuring total end-to-end latency including retries and delays\n const startTime = Date.now();\n\n const getCoverageResultFn = async (\n signal: AbortSignal,\n ): Promise<Omit<GetCoverageResultResponse, 'metrics'>> => {\n const res = await this.#fetch(coverageResultUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify(reqBody),\n signal,\n });\n\n if (res.status === 200) {\n // Return the result without latency here - we'll add total latency after polling completes\n return (await res.json()) as Omit<GetCoverageResultResponse, 'metrics'>;\n }\n\n // parse the error message from the response body\n let errorMessage = 'Timeout waiting for coverage result';\n try {\n const errorJson = await res.json();\n errorMessage = `Failed to get coverage result: ${errorJson.message ?? errorJson.status}`;\n } catch {\n errorMessage = `Failed to get coverage result: ${res.status}`;\n }\n throw new HttpError(res.status, errorMessage);\n };\n\n const result = await this.#pollingPolicy.start(\n requestId,\n getCoverageResultFn,\n );\n\n // Calculate total end-to-end latency including all retries and delays\n const now = Date.now();\n const totalLatency = now - startTime;\n\n return {\n ...result,\n metrics: { latency: totalLatency },\n } as GetCoverageResultResponse;\n }\n\n async #createHeaders(): Promise<Record<string, string>> {\n const accessToken = await this.#getAccessToken();\n return {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${accessToken}`,\n };\n }\n}\n\n/**\n * Make the body for the init coverage check request.\n *\n * @param txMeta - The transaction metadata.\n * @returns The body for the init coverage check request.\n */\nexport function makeInitCoverageCheckBody(\n txMeta: TransactionMeta,\n): InitCoverageCheckRequest {\n return {\n txParams: [\n {\n authorizationList: txMeta.txParams.authorizationList,\n from: txMeta.txParams.from,\n to: txMeta.txParams.to,\n value: txMeta.txParams.value,\n data: txMeta.txParams.data,\n nonce: txMeta.txParams.nonce,\n },\n ],\n chainId: txMeta.chainId,\n origin: txMeta.origin,\n };\n}\n\n/**\n * Make the body for the init signature coverage check request.\n *\n * @param signatureRequest - The signature request.\n * @returns The body for the init signature coverage check request.\n */\nfunction makeInitSignatureCoverageCheckBody(\n signatureRequest: SignatureRequest,\n): InitSignatureCoverageCheckRequest {\n // TODO: confirm that do we still need to validate the signature data?\n // signature controller already validates the signature data before adding it to the state.\n // @link https://github.com/MetaMask/core/blob/main/packages/signature-controller/src/SignatureController.ts#L408\n const method = parseSignatureRequestMethod(signatureRequest);\n\n return {\n chainId: signatureRequest.chainId,\n data: signatureRequest.messageParams.data,\n from: signatureRequest.messageParams.from,\n method,\n origin: signatureRequest.messageParams.origin,\n };\n}\n\n/**\n * Parse the JSON-RPC method from the signature request.\n *\n * @param signatureRequest - The signature request.\n * @returns The JSON-RPC method.\n */\nexport function parseSignatureRequestMethod(\n signatureRequest: SignatureRequest,\n): string {\n if (signatureRequest.type === SignatureRequestType.TypedSign) {\n switch (signatureRequest.version) {\n case SignTypedDataVersion.V3:\n return EthMethod.SignTypedDataV3;\n case SignTypedDataVersion.V4:\n return EthMethod.SignTypedDataV4;\n case SignTypedDataVersion.V1:\n default:\n return SignatureRequestType.TypedSign;\n }\n }\n\n return signatureRequest.type;\n}\n\n/**\n * Compute the polling interval and retry count for the Cockatiel policy based on the timeout and poll interval given.\n *\n * @param timeout - The timeout in milliseconds.\n * @param pollInterval - The poll interval in milliseconds.\n * @returns The polling interval and retry count.\n */\nfunction computePollingIntervalAndRetryCount(\n timeout: number,\n pollInterval: number,\n): { backoff: ConstantBackoff; maxRetries: number } {\n const backoff = new ConstantBackoff(pollInterval);\n const computedMaxRetries = Math.floor(timeout / pollInterval) + 1;\n\n const maxRetries =\n isNaN(computedMaxRetries) || !isFinite(computedMaxRetries)\n ? DEFAULT_MAX_RETRIES\n : computedMaxRetries;\n\n return {\n backoff,\n maxRetries,\n };\n}\n\n/**\n * Create an error instance with a readable message, a cause and a context for Sentry.\n *\n * @param errorMessage - The error message.\n * @param cause - The cause of the error.\n * @returns A Sentry error.\n */\nfunction createSentryError(errorMessage: string, cause: Error): Error {\n const error = new Error(errorMessage) as Error & {\n cause: Error;\n };\n error.cause = cause;\n return error;\n}\n"]}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { SignatureRequest } from "@metamask/signature-controller";
|
|
2
|
+
import type { TransactionMeta } from "@metamask/transaction-controller";
|
|
3
|
+
import type { AuthorizationList } from "@metamask/transaction-controller";
|
|
4
|
+
import type { Json } from "@metamask/utils";
|
|
5
|
+
import type { CheckCoverageRequest, CheckSignatureCoverageRequest, CoverageResult, CoverageStatus, LogSignatureRequest, LogTransactionRequest, ShieldBackend } from "./types.cjs";
|
|
6
|
+
export type InitCoverageCheckRequest = {
|
|
7
|
+
txParams: [
|
|
8
|
+
{
|
|
9
|
+
authorizationList?: AuthorizationList;
|
|
10
|
+
from: string;
|
|
11
|
+
to?: string;
|
|
12
|
+
value?: string;
|
|
13
|
+
data?: string;
|
|
14
|
+
nonce?: string;
|
|
15
|
+
}
|
|
16
|
+
];
|
|
17
|
+
chainId: string;
|
|
18
|
+
origin?: string;
|
|
19
|
+
};
|
|
20
|
+
export type InitSignatureCoverageCheckRequest = {
|
|
21
|
+
chainId: string;
|
|
22
|
+
data: Json;
|
|
23
|
+
from: string;
|
|
24
|
+
method: string;
|
|
25
|
+
origin?: string;
|
|
26
|
+
};
|
|
27
|
+
export type InitCoverageCheckResponse = {
|
|
28
|
+
coverageId: string;
|
|
29
|
+
};
|
|
30
|
+
export type GetCoverageResultRequest = {
|
|
31
|
+
coverageId: string;
|
|
32
|
+
};
|
|
33
|
+
export type GetCoverageResultResponse = {
|
|
34
|
+
message?: string;
|
|
35
|
+
reasonCode?: string;
|
|
36
|
+
status: CoverageStatus;
|
|
37
|
+
metrics: {
|
|
38
|
+
latency?: number;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
export declare class ShieldRemoteBackend implements ShieldBackend {
|
|
42
|
+
#private;
|
|
43
|
+
constructor({ getAccessToken, getCoverageResultTimeout, // milliseconds
|
|
44
|
+
getCoverageResultPollInterval, // milliseconds
|
|
45
|
+
baseUrl, fetch: fetchFn, captureException: captureExceptionFn, }: {
|
|
46
|
+
getAccessToken: () => Promise<string>;
|
|
47
|
+
getCoverageResultTimeout?: number;
|
|
48
|
+
getCoverageResultPollInterval?: number;
|
|
49
|
+
baseUrl: string;
|
|
50
|
+
fetch: typeof globalThis.fetch;
|
|
51
|
+
captureException?: (error: Error) => void;
|
|
52
|
+
});
|
|
53
|
+
checkCoverage(req: CheckCoverageRequest): Promise<CoverageResult>;
|
|
54
|
+
checkSignatureCoverage(req: CheckSignatureCoverageRequest): Promise<CoverageResult>;
|
|
55
|
+
logSignature(req: LogSignatureRequest): Promise<void>;
|
|
56
|
+
logTransaction(req: LogTransactionRequest): Promise<void>;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Make the body for the init coverage check request.
|
|
60
|
+
*
|
|
61
|
+
* @param txMeta - The transaction metadata.
|
|
62
|
+
* @returns The body for the init coverage check request.
|
|
63
|
+
*/
|
|
64
|
+
export declare function makeInitCoverageCheckBody(txMeta: TransactionMeta): InitCoverageCheckRequest;
|
|
65
|
+
/**
|
|
66
|
+
* Parse the JSON-RPC method from the signature request.
|
|
67
|
+
*
|
|
68
|
+
* @param signatureRequest - The signature request.
|
|
69
|
+
* @returns The JSON-RPC method.
|
|
70
|
+
*/
|
|
71
|
+
export declare function parseSignatureRequestMethod(signatureRequest: SignatureRequest): string;
|
|
72
|
+
//# sourceMappingURL=backend.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend.d.cts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,gBAAgB,EAAE,uCAAuC;AACvE,OAAO,KAAK,EAAE,eAAe,EAAE,yCAAyC;AACxE,OAAO,KAAK,EAAE,iBAAiB,EAAE,yCAAyC;AAC1E,OAAO,KAAK,EAAE,IAAI,EAAE,wBAAwB;AAI5C,OAAO,KAAK,EACV,oBAAoB,EACpB,6BAA6B,EAC7B,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,qBAAqB,EACrB,aAAa,EACd,oBAAmB;AAEpB,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,EAAE;QACR;YACE,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;YACtC,IAAI,EAAE,MAAM,CAAC;YACb,EAAE,CAAC,EAAE,MAAM,CAAC;YACZ,KAAK,CAAC,EAAE,MAAM,CAAC;YACf,IAAI,CAAC,EAAE,MAAM,CAAC;YACd,KAAK,CAAC,EAAE,MAAM,CAAC;SAChB;KACF,CAAC;IACF,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,iCAAiC,GAAG;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,cAAc,CAAC;IACvB,OAAO,EAAE;QACP,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CACH,CAAC;AAEF,qBAAa,mBAAoB,YAAW,aAAa;;gBAW3C,EACV,cAAc,EACd,wBAA+B,EAAE,eAAe;IAChD,6BAAoC,EAAE,eAAe;IACrD,OAAO,EACP,KAAK,EAAE,OAAO,EACd,gBAAgB,EAAE,kBAAkB,GACrC,EAAE;QACD,cAAc,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;QACtC,wBAAwB,CAAC,EAAE,MAAM,CAAC;QAClC,6BAA6B,CAAC,EAAE,MAAM,CAAC;QACvC,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;QAC/B,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;KAC3C;IAwBK,aAAa,CAAC,GAAG,EAAE,oBAAoB,GAAG,OAAO,CAAC,cAAc,CAAC;IAyBjE,sBAAsB,CAC1B,GAAG,EAAE,6BAA6B,GACjC,OAAO,CAAC,cAAc,CAAC;IAyBpB,YAAY,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAmCrD,cAAc,CAAC,GAAG,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;CA6HhE;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,eAAe,GACtB,wBAAwB,CAe1B;AAyBD;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,gBAAgB,EAAE,gBAAgB,GACjC,MAAM,CAcR"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { SignatureRequest } from "@metamask/signature-controller";
|
|
2
|
+
import type { TransactionMeta } from "@metamask/transaction-controller";
|
|
3
|
+
import type { AuthorizationList } from "@metamask/transaction-controller";
|
|
4
|
+
import type { Json } from "@metamask/utils";
|
|
5
|
+
import type { CheckCoverageRequest, CheckSignatureCoverageRequest, CoverageResult, CoverageStatus, LogSignatureRequest, LogTransactionRequest, ShieldBackend } from "./types.mjs";
|
|
6
|
+
export type InitCoverageCheckRequest = {
|
|
7
|
+
txParams: [
|
|
8
|
+
{
|
|
9
|
+
authorizationList?: AuthorizationList;
|
|
10
|
+
from: string;
|
|
11
|
+
to?: string;
|
|
12
|
+
value?: string;
|
|
13
|
+
data?: string;
|
|
14
|
+
nonce?: string;
|
|
15
|
+
}
|
|
16
|
+
];
|
|
17
|
+
chainId: string;
|
|
18
|
+
origin?: string;
|
|
19
|
+
};
|
|
20
|
+
export type InitSignatureCoverageCheckRequest = {
|
|
21
|
+
chainId: string;
|
|
22
|
+
data: Json;
|
|
23
|
+
from: string;
|
|
24
|
+
method: string;
|
|
25
|
+
origin?: string;
|
|
26
|
+
};
|
|
27
|
+
export type InitCoverageCheckResponse = {
|
|
28
|
+
coverageId: string;
|
|
29
|
+
};
|
|
30
|
+
export type GetCoverageResultRequest = {
|
|
31
|
+
coverageId: string;
|
|
32
|
+
};
|
|
33
|
+
export type GetCoverageResultResponse = {
|
|
34
|
+
message?: string;
|
|
35
|
+
reasonCode?: string;
|
|
36
|
+
status: CoverageStatus;
|
|
37
|
+
metrics: {
|
|
38
|
+
latency?: number;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
export declare class ShieldRemoteBackend implements ShieldBackend {
|
|
42
|
+
#private;
|
|
43
|
+
constructor({ getAccessToken, getCoverageResultTimeout, // milliseconds
|
|
44
|
+
getCoverageResultPollInterval, // milliseconds
|
|
45
|
+
baseUrl, fetch: fetchFn, captureException: captureExceptionFn, }: {
|
|
46
|
+
getAccessToken: () => Promise<string>;
|
|
47
|
+
getCoverageResultTimeout?: number;
|
|
48
|
+
getCoverageResultPollInterval?: number;
|
|
49
|
+
baseUrl: string;
|
|
50
|
+
fetch: typeof globalThis.fetch;
|
|
51
|
+
captureException?: (error: Error) => void;
|
|
52
|
+
});
|
|
53
|
+
checkCoverage(req: CheckCoverageRequest): Promise<CoverageResult>;
|
|
54
|
+
checkSignatureCoverage(req: CheckSignatureCoverageRequest): Promise<CoverageResult>;
|
|
55
|
+
logSignature(req: LogSignatureRequest): Promise<void>;
|
|
56
|
+
logTransaction(req: LogTransactionRequest): Promise<void>;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Make the body for the init coverage check request.
|
|
60
|
+
*
|
|
61
|
+
* @param txMeta - The transaction metadata.
|
|
62
|
+
* @returns The body for the init coverage check request.
|
|
63
|
+
*/
|
|
64
|
+
export declare function makeInitCoverageCheckBody(txMeta: TransactionMeta): InitCoverageCheckRequest;
|
|
65
|
+
/**
|
|
66
|
+
* Parse the JSON-RPC method from the signature request.
|
|
67
|
+
*
|
|
68
|
+
* @param signatureRequest - The signature request.
|
|
69
|
+
* @returns The JSON-RPC method.
|
|
70
|
+
*/
|
|
71
|
+
export declare function parseSignatureRequestMethod(signatureRequest: SignatureRequest): string;
|
|
72
|
+
//# sourceMappingURL=backend.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend.d.mts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,gBAAgB,EAAE,uCAAuC;AACvE,OAAO,KAAK,EAAE,eAAe,EAAE,yCAAyC;AACxE,OAAO,KAAK,EAAE,iBAAiB,EAAE,yCAAyC;AAC1E,OAAO,KAAK,EAAE,IAAI,EAAE,wBAAwB;AAI5C,OAAO,KAAK,EACV,oBAAoB,EACpB,6BAA6B,EAC7B,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,qBAAqB,EACrB,aAAa,EACd,oBAAmB;AAEpB,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,EAAE;QACR;YACE,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;YACtC,IAAI,EAAE,MAAM,CAAC;YACb,EAAE,CAAC,EAAE,MAAM,CAAC;YACZ,KAAK,CAAC,EAAE,MAAM,CAAC;YACf,IAAI,CAAC,EAAE,MAAM,CAAC;YACd,KAAK,CAAC,EAAE,MAAM,CAAC;SAChB;KACF,CAAC;IACF,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,iCAAiC,GAAG;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,cAAc,CAAC;IACvB,OAAO,EAAE;QACP,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CACH,CAAC;AAEF,qBAAa,mBAAoB,YAAW,aAAa;;gBAW3C,EACV,cAAc,EACd,wBAA+B,EAAE,eAAe;IAChD,6BAAoC,EAAE,eAAe;IACrD,OAAO,EACP,KAAK,EAAE,OAAO,EACd,gBAAgB,EAAE,kBAAkB,GACrC,EAAE;QACD,cAAc,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;QACtC,wBAAwB,CAAC,EAAE,MAAM,CAAC;QAClC,6BAA6B,CAAC,EAAE,MAAM,CAAC;QACvC,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;QAC/B,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;KAC3C;IAwBK,aAAa,CAAC,GAAG,EAAE,oBAAoB,GAAG,OAAO,CAAC,cAAc,CAAC;IAyBjE,sBAAsB,CAC1B,GAAG,EAAE,6BAA6B,GACjC,OAAO,CAAC,cAAc,CAAC;IAyBpB,YAAY,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAmCrD,cAAc,CAAC,GAAG,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;CA6HhE;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,eAAe,GACtB,wBAAwB,CAe1B;AAyBD;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,gBAAgB,EAAE,gBAAgB,GACjC,MAAM,CAcR"}
|