feat: map contract error codes 1-5 to human-readable messages in the SDK - #346
Open
theo372001 wants to merge 1 commit into
Open
feat: map contract error codes 1-5 to human-readable messages in the SDK#346theo372001 wants to merge 1 commit into
theo372001 wants to merge 1 commit into
Conversation
Adds describeContractError(code) to packages/client/src/errors.ts, covering the 5 stable error codes documented in contracts/sharibo/src/lib.rs (CircleNotFound, RoundNotFunded, WrongRoundTag, AlreadyClaimed, InvalidProof), each with a name, a user-facing sentence, and a hint. parseContractErrorCode() extracts the numeric code from a signAndSend() failure by matching the `Error(Contract, #N)` string @stellar/stellar-sdk's own AssembledTransaction embeds in a simulation-failure Error's message (traced through node_modules/@stellar/stellar-sdk's assembled_transaction.js and utils.js's `contractErrorPattern`, and cross-checked against the existing raw-string checks in scripts/e2e.ts's replay path and scripts/smoke.ts). describeError() ties the two together and falls back to the raw message for unrecognized codes or non-contract errors. Wires this into the app's claimAgain deliberate-replay demo (previously displaying the raw Error(Contract, crackedstudio#4)) via a new getErrorMessage() helper in App.tsx — filling in a function that was already referenced there and in fundMember's Freighter path but never defined. Also re-exports errors.js from packages/client/src/index.ts, which App.tsx and scripts/e2e.ts already import ContractError/RpcError from but which wasn't actually re-exported. Closes crackedstudio#53
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
Adds
describeContractError(code)topackages/client/src/errors.ts, covering the 5 stable error codes documented incontracts/sharibo/src/lib.rs(CircleNotFound,RoundNotFunded,WrongRoundTag,AlreadyClaimed,InvalidProof) — each returning a name, a user-facing sentence, and a hint. AddsparseContractErrorCode()to extract the numeric code out of asignAndSend()failure, anddescribeError()to tie both together with a raw-string fallback for anything unrecognized. Wires this into the app'sclaimAgaindeliberate-replay demo so it now shows"AlreadyClaimed: ..."prose instead of the rawError(Contract, #4).Why
Closes #53
When the contract rejects a claim, users currently see Soroban's raw
Error(Contract, #4)instead of something readable.Implementation notes
signAndSend()'s underlying@stellar/stellar-sdk(AssembledTransaction) throws a plainErrorwhose.messageembedsError(Contract, #<code>)— I traced this through the installed SDK'scontract/assembled_transaction.js(simulationDatagetter →SimulationFailedwith the RPC's raw diagnostic string) andcontract/utils.js, which defines its owncontractErrorPattern = /Error\(Contract, #(\d+)\)/for exactly this purpose. This matches the existing raw-string checks already in this repo atscripts/e2e.ts's replay path (message.includes("Error(Contract, #4)")) andscripts/smoke.ts(msg.includes("Error(Contract, #1)")). I was not able to runscripts/e2e.tslive — it requires a deployed testnet contract/admin secret I don't have, and the script currently has unrelated pre-existing syntax errors around its funding/proof-generation steps (duplicated blocks, mismatched braces) that predate this change and are out of scope here.parseContractErrorCode()'s regex is a superset of the SDK's own pattern and is covered by unit tests using both a realistic multi-line simulation-failure message and the exact minimal strings already used ine2e.ts/smoke.ts.getErrorMessageinapp/src/App.tsx: this function was already called inclaimAgain's catch block and in the FreighterfundMemberpath, but was never defined anywhere in the file (a pre-existing bug — the app didn't compile). I added it as a small wrapper around the newdescribeError(), mirroring the existingtoUiErrorhelper's Friendbot special-case.index.tsexport:packages/client/src/index.tsdidn't re-exporterrors.tseven thoughApp.tsxandscripts/e2e.tsalready importContractError/RpcErrorfrom@sharibo/client— also pre-existing and fixed here since it's required for this feature to be importable at all.packages/client) has substantial pre-existing, unrelated breakage onmain(missing exports intree.ts/prove.ts/config.ts, an undefinedwithRetryincontract.ts, a duplicateMerkleTreeidentifier intree.test.ts, etc. — confirmed viatsc --noEmitbefore and after this change, identical error list both times). I did not touch any of that; it's out of scope for Map on-chain error codes #1–#5 to human-readable messages in the SDK #53.Testing
packages/client/src/errors.test.ts(new, 12 cases covering all 5 known codes, 4 unknown/out-of-scope codes 0/6/7/8/999, the exactsignAndSend-shaped failure string, the minimale2e.ts/smoke.tsstrings, aContractErrorinstance, non-contract errors, and non-Error throws) — run vianpx tsx --test src/errors.test.ts(the package's ownvitest rundoesn't pick up any of this package'snode:test-style test files, including the pre-existing ones, due to a pre-existing test-runner mismatch unrelated to this change) — 12/12 passing.npx tsc --noEmitinpackages/clientandapp— my changes introduce zero new type errors versus the pre-existing baseline (verified by diffing output before/after viagit stash).cd app && npm run dev) — not run end-to-end; no live testnet contract available to exercise the actual replay demo in the browser. Unit-verified the exact string transformation instead (Error(Contract, #4)→"AlreadyClaimed: this proof's nullifier was already used; ...") via thedescribeErrortest cases above.Screenshots
Not applicable — no visual/layout change, only the text shown in the existing rejection banner.