From d0c6ca6f812db7c6a8df6b226227adf7d6363b4c Mon Sep 17 00:00:00 2001 From: Anadudev Date: Mon, 31 Aug 2026 09:13:33 +0100 Subject: [PATCH 1/2] feat(sdk): surface typed contract error taxonomy end-to-end (#404) --- frontend/app/holder/page.tsx | 19 +++-- frontend/lib/__tests__/contracts.test.ts | 39 ++++++++- frontend/lib/contracts.ts | 85 +++++++++++++++--- frontend/packages/sdk/src/index.test.ts | 24 ++++++ frontend/packages/sdk/src/index.ts | 104 +++++++++++++++++++++-- 5 files changed, 240 insertions(+), 31 deletions(-) diff --git a/frontend/app/holder/page.tsx b/frontend/app/holder/page.tsx index f7ab8186..8f436bbf 100644 --- a/frontend/app/holder/page.tsx +++ b/frontend/app/holder/page.tsx @@ -34,7 +34,8 @@ import { submitProofs, MAX_BATCH_SIZE, parseContractError, - type ContractError, + ContractError, + isRetryableContractError, type ProofSubmissionParams, } from "@/lib/contracts"; import { @@ -1020,7 +1021,7 @@ function ProofFlow({ toast.error("Proof timed out — please try again."); return; } - const parsed = parseContractError((e as Error).message); + const parsed = e instanceof ContractError ? e : parseContractError((e as Error).message); setError(parsed); setErrorPhase("proving"); setStage("error"); @@ -1073,7 +1074,7 @@ function ProofFlow({ addEvent("verified", { txHash: hash }); toast.success(`Proof confirmed on-chain for ${cred.title}`, { txHash: hash }); } catch (e) { - const parsed = parseContractError((e as Error).message); + const parsed = e instanceof ContractError ? e : parseContractError((e as Error).message); setError(parsed); setErrorPhase("submitting"); setStage("error"); @@ -1287,8 +1288,8 @@ function ProofFlow({ )} )} - {/* Retry submission without re-proving when the proof exists */} - {errorPhase === "submitting" && proof && ( + {/* Retry submission without re-proving when the proof exists and error is retryable */} + {errorPhase === "submitting" && proof && error && isRetryableContractError(error) && (