Skip to content

Commit cecec39

Browse files
authored
fix: server crash when async fetch call times out (#427)
* fix: server crash when async fetch call times out * comment * simplify client id
1 parent 8f3eb35 commit cecec39

File tree

3 files changed

+87
-96
lines changed

3 files changed

+87
-96
lines changed

src/server/routes/transaction/sendSignedUserOp.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Static, Type } from "@sinclair/typebox";
22
import { Value } from "@sinclair/typebox/value";
33
import { FastifyInstance } from "fastify";
44
import { StatusCodes } from "http-status-codes";
5-
import { deriveClientId } from "../../../utils/api-keys";
5+
import { thirdwebClientId } from "../../../utils/api-keys";
66
import { env } from "../../../utils/env";
77
import { standardResponseSchema } from "../../schemas/sharedApiSchemas";
88
import { getChainIdFromChain } from "../../utils/chain";
@@ -104,7 +104,7 @@ export async function sendSignedUserOp(fastify: FastifyInstance) {
104104
method: "POST",
105105
headers: {
106106
"Content-Type": "application/json",
107-
"x-client-id": deriveClientId(env.THIRDWEB_API_SECRET_KEY),
107+
"x-client-id": thirdwebClientId,
108108
"x-secret-key": env.THIRDWEB_API_SECRET_KEY,
109109
},
110110
body: JSON.stringify({

src/utils/api-keys.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { sha256HexSync } from "@thirdweb-dev/crypto";
2+
import { env } from "./env";
23

3-
export const deriveClientId = (secretKey: string): string => {
4-
const hashedSecretKey = sha256HexSync(secretKey);
5-
const derivedClientId = hashedSecretKey.slice(0, 32);
6-
return derivedClientId;
7-
};
4+
export const thirdwebClientId = sha256HexSync(
5+
env.THIRDWEB_API_SECRET_KEY,
6+
).slice(0, 32);

src/utils/usage.ts

Lines changed: 81 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { FastifyInstance } from "fastify";
55
import { contractParamSchema } from "../server/schemas/sharedApiSchemas";
66
import { walletParamSchema } from "../server/schemas/wallet";
77
import { getChainIdFromChain } from "../server/utils/chain";
8-
import { deriveClientId } from "./api-keys";
8+
import { thirdwebClientId } from "./api-keys";
99
import { env } from "./env";
1010
import { logger } from "./logger";
1111

@@ -73,107 +73,99 @@ const createHeaderForRequest = (input: CreateHeaderForRequestParams) => {
7373
};
7474

7575
export const withServerUsageReporting = (server: FastifyInstance) => {
76+
// Skip reporting if CLIENT_ANALYTICS_URL is not set.
77+
if (env.CLIENT_ANALYTICS_URL === "") {
78+
return;
79+
}
80+
7681
server.addHook("onResponse", async (request, reply) => {
82+
if (
83+
URLS_LIST_TO_NOT_REPORT_USAGE.has(reply.request.routerPath) ||
84+
reply.request.method === "OPTIONS"
85+
) {
86+
return;
87+
}
88+
89+
const headers = createHeaderForRequest({
90+
clientId: thirdwebClientId,
91+
});
92+
93+
const requestParams = request?.params as Static<typeof EngineRequestParams>;
94+
95+
const chainId = requestParams?.chain
96+
? await getChainIdFromChain(requestParams.chain)
97+
: "";
98+
99+
const requestBody: UsageEventSchema = {
100+
source: "engine",
101+
action: UsageEventTxActionEnum.APIRequest,
102+
clientId: thirdwebClientId,
103+
pathname: reply.request.routerPath,
104+
chainId: chainId || undefined,
105+
walletAddress: requestParams.walletAddress || undefined,
106+
contractAddress: requestParams.contractAddress || undefined,
107+
httpStatusCode: reply.statusCode,
108+
msTotalDuration: Math.ceil(reply.getResponseTime()),
109+
};
110+
111+
fetch(env.CLIENT_ANALYTICS_URL, {
112+
method: "POST",
113+
headers,
114+
body: JSON.stringify(requestBody),
115+
}).catch(() => {}); // Catch uncaught exceptions since this fetch call is non-blocking.
116+
});
117+
};
118+
119+
export const reportUsage = (usageParams: ReportUsageParams[]) => {
120+
// Skip reporting if CLIENT_ANALYTICS_URL is not set.
121+
if (env.CLIENT_ANALYTICS_URL === "") {
122+
return;
123+
}
124+
125+
usageParams.map(async (item) => {
77126
try {
78-
// If the CLIENT_ANALYTICS_URL is not set, then we don't want to report usage
79-
if (env.CLIENT_ANALYTICS_URL === "") {
80-
return;
81-
}
82-
83-
if (
84-
URLS_LIST_TO_NOT_REPORT_USAGE.has(reply.request.routerPath) ||
85-
reply.request.method === "OPTIONS"
86-
) {
87-
return;
88-
}
89-
90-
const derivedClientId = deriveClientId(env.THIRDWEB_API_SECRET_KEY);
91127
const headers = createHeaderForRequest({
92-
clientId: derivedClientId,
128+
clientId: thirdwebClientId,
93129
});
94130

95-
const requestParams = request?.params as Static<
96-
typeof EngineRequestParams
97-
>;
98-
99-
const chainId = requestParams?.chain
100-
? await getChainIdFromChain(requestParams.chain)
101-
: "";
102-
131+
const chainId = item.input.chainId
132+
? parseInt(item.input.chainId)
133+
: undefined;
103134
const requestBody: UsageEventSchema = {
104135
source: "engine",
105-
action: UsageEventTxActionEnum.APIRequest,
106-
clientId: derivedClientId,
107-
pathname: reply.request.routerPath,
108-
chainId: chainId || undefined,
109-
walletAddress: requestParams.walletAddress || undefined,
110-
contractAddress: requestParams.contractAddress || undefined,
111-
httpStatusCode: reply.statusCode,
112-
msTotalDuration: Math.ceil(reply.getResponseTime()),
136+
action: item.action,
137+
clientId: thirdwebClientId,
138+
chainId,
139+
walletAddress: item.input.fromAddress || undefined,
140+
contractAddress: item.input.toAddress || undefined,
141+
transactionValue: item.input.value || undefined,
142+
transactionHash: item.input.transactionHash || undefined,
143+
userOpHash: item.input.userOpHash || undefined,
144+
errorCode: item.input.onChainTxStatus
145+
? item.input.onChainTxStatus === 0
146+
? "EXECUTION_REVERTED"
147+
: undefined
148+
: item.error?.reason || undefined,
149+
functionName: item.input.functionName || undefined,
150+
extension: item.input.extension || undefined,
151+
retryCount: item.input.retryCount || undefined,
152+
provider: item.input.provider || undefined,
153+
msSinceSend: item.input.msSinceSend || undefined,
154+
msSinceQueue: item.input.msSinceQueue || undefined,
113155
};
114156

115157
fetch(env.CLIENT_ANALYTICS_URL, {
116158
method: "POST",
117159
headers,
118160
body: JSON.stringify(requestBody),
161+
}).catch(() => {}); // Catch uncaught exceptions since this fetch call is non-blocking.
162+
} catch (e) {
163+
logger({
164+
service: "worker",
165+
level: "error",
166+
message: `Error:`,
167+
error,
119168
});
120-
} catch (e) {}
169+
}
121170
});
122171
};
123-
124-
export const reportUsage = (usageParams: ReportUsageParams[]) => {
125-
try {
126-
usageParams.map(async (item) => {
127-
try {
128-
// If the CLIENT_ANALYTICS_URL is not set, then we don't want to report usage
129-
if (env.CLIENT_ANALYTICS_URL === "") {
130-
return;
131-
}
132-
133-
const derivedClientId = deriveClientId(env.THIRDWEB_API_SECRET_KEY);
134-
const headers = createHeaderForRequest({
135-
clientId: derivedClientId,
136-
});
137-
138-
const chainId = item.input.chainId
139-
? parseInt(item.input.chainId)
140-
: undefined;
141-
const requestBody: UsageEventSchema = {
142-
source: "engine",
143-
action: item.action,
144-
clientId: derivedClientId,
145-
chainId,
146-
walletAddress: item.input.fromAddress || undefined,
147-
contractAddress: item.input.toAddress || undefined,
148-
transactionValue: item.input.value || undefined,
149-
transactionHash: item.input.transactionHash || undefined,
150-
userOpHash: item.input.userOpHash || undefined,
151-
errorCode: item.input.onChainTxStatus
152-
? item.input.onChainTxStatus === 0
153-
? "EXECUTION_REVERTED"
154-
: undefined
155-
: item.error?.reason || undefined,
156-
functionName: item.input.functionName || undefined,
157-
extension: item.input.extension || undefined,
158-
retryCount: item.input.retryCount || undefined,
159-
provider: item.input.provider || undefined,
160-
msSinceSend: item.input.msSinceSend || undefined,
161-
msSinceQueue: item.input.msSinceQueue || undefined,
162-
};
163-
164-
fetch(env.CLIENT_ANALYTICS_URL, {
165-
method: "POST",
166-
headers,
167-
body: JSON.stringify(requestBody),
168-
});
169-
} catch (e) {}
170-
});
171-
} catch (error) {
172-
logger({
173-
service: "worker",
174-
level: "error",
175-
message: `Error:`,
176-
error,
177-
});
178-
}
179-
};

0 commit comments

Comments
 (0)