);
diff --git a/src/contracts/writer.ts b/src/contracts/writer.ts
index 6cac25aa..b18ea03f 100644
--- a/src/contracts/writer.ts
+++ b/src/contracts/writer.ts
@@ -1,3 +1,4 @@
+import * as Sentry from "@sentry/nextjs";
import { createWalletClient } from "viem";
import { nonceManager, privateKeyToAccount } from "viem/accounts";
import { celo } from "viem/chains";
@@ -81,6 +82,14 @@ export async function withWriterLock
(fn: () => Promise): Promise {
const lockId = await acquireWriterLock();
try {
return await fn();
+ } catch (error) {
+ Sentry.addBreadcrumb({
+ category: "writer",
+ message: "Writer lock transaction failed",
+ data: { lockId },
+ level: "error",
+ });
+ throw error;
} finally {
await releaseWriterLock(lockId);
}
diff --git a/src/instrumentation-client.ts b/src/instrumentation-client.ts
index 564d0c48..28e0759a 100644
--- a/src/instrumentation-client.ts
+++ b/src/instrumentation-client.ts
@@ -10,10 +10,22 @@ if (process.env.NODE_ENV === "production") {
dsn: "https://d4d2dfa789477bdaeea1a7e468f54d08@o4509168932880384.ingest.de.sentry.io/4509168934125648",
// Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control.
- tracesSampleRate: 1,
+ tracesSampleRate: 0.2,
// Setting this option to true will print useful information to the console while you're setting up Sentry.
debug: false,
+
+ ignoreErrors: [
+ /router state header.*could not be parsed/i,
+ /Failed to execute 'removeChild' on 'Node'/,
+ /Failed to execute 'insertBefore' on 'Node'/,
+ /Failed to execute 'appendChild' on 'Node'/,
+ /setPhotoOptions failed/,
+ /The associated Track is in an invalid state/,
+ /Proposal expired/,
+ /Connection interrupted/,
+ /Error invoking postEvent/,
+ ],
});
}
diff --git a/src/instrumentation.ts b/src/instrumentation.ts
index 8aff09f0..2186648b 100644
--- a/src/instrumentation.ts
+++ b/src/instrumentation.ts
@@ -10,4 +10,16 @@ export async function register() {
}
}
-export const onRequestError = Sentry.captureRequestError;
+export const onRequestError = (
+ ...args: Parameters
+) => {
+ const error = args[0];
+ if (
+ error instanceof Error &&
+ "code" in error &&
+ (error as Error & { code: string }).code === "FORBIDDEN"
+ ) {
+ return;
+ }
+ Sentry.captureRequestError(...args);
+};
diff --git a/src/server/api/models/token.ts b/src/server/api/models/token.ts
index eabcc644..848363b4 100644
--- a/src/server/api/models/token.ts
+++ b/src/server/api/models/token.ts
@@ -6,7 +6,7 @@ import {
type PublicClient,
type Transport,
} from "viem";
-import { type CeloChain, publicClient } from "~/config/viem.config.server";
+import { type CeloChain } from "~/config/viem.config.server";
export async function getTokenDetails(
client: PublicClient,
@@ -30,7 +30,7 @@ export async function getTokenDetails(
try {
const [name, symbol, decimals] = await Promise.all([
- publicClient.readContract({
+ client.readContract({
address,
abi: erc20Abi,
functionName: "name",
@@ -55,8 +55,11 @@ export async function getTokenDetails(
await redis.set(cacheKey, tokenDetails, { ex: 60 * 60 * 24 }); // 24 hours
return tokenDetails;
} catch (error) {
- console.error(error);
- throw new Error("Failed to fetch token details from contract");
+ console.error(`Failed to fetch token details for ${address}:`, error);
+ throw new Error(
+ `Failed to fetch token details for ${address}: ${error instanceof Error ? error.message : "Unknown error"}`,
+ { cause: error }
+ );
}
}