Skip to content

improve(svm): add describeSolanaError helper#1446

Open
droplet-rl wants to merge 3 commits into
masterfrom
droplet/T90K0AL22-C03GHT4RV42-1779869895-829509-svm-error-helper
Open

improve(svm): add describeSolanaError helper#1446
droplet-rl wants to merge 3 commits into
masterfrom
droplet/T90K0AL22-C03GHT4RV42-1779869895-829509-svm-error-helper

Conversation

@droplet-rl

Copy link
Copy Markdown
Contributor

Summary

Add describeSolanaError(err) next to isSolanaError in src/arch/svm/provider.ts. Pure transform; returns a plain object holding the SolanaError diagnostic fields (name, optional message, code, context, recursively-described cause) that JSON loggers would otherwise drop, and {} for anything that isn't a SolanaError so callers can spread it unconditionally:

catch (err) {
  logger.error({ at: "...", message: "...", error: err, ...describeSolanaError(err) });
}

Why

A SolanaError keeps the rich diagnostics (program logs[], accounts, unitsConsumed, plus the wrapped TransactionError / InstructionError) on its context and cause fields. Most JSON loggers either replace an Error value with .stack (e.g. @risk-labs/logger's errorStackTracerFormatter) or JSON.stringify it — and Error.stack/Error.message/Error.name are non-enumerable on the prototype, so the structured payload that SolanaError adds gets silently dropped. The relayer dataworker is hitting this today on SVM refund-leaf execution failures: prod logs read only SolanaError: Transaction simulation failed at /across-relayer/node_modules/@solana/rpc-transformers/dist/index.node.cjs:332:22 …, with no way to tell whether it was a benign already-executed race, a stale blockhash, a custom program error, or RPC flake.

A private copy of this helper landed in across-protocol/relayer#3422 to unblock prod visibility. Moving it down to the SDK so the other consumers (indexer, relayer-madrid, quote-api, anything calling arch.svm.*) can share it. The relayer-side follow-up will swap its local copy for this SDK export.

Shape

For a preflight-failure SolanaError, describeSolanaError(err) now returns (in addition to whatever the logger does with error: err):

{
  "solanaError": {
    "name": "SolanaError",
    "message": "Transaction simulation failed",
    "code": -32002,
    "context": {
      "__code": -32002,
      "logs": ["Program log: refund leaf already executed"],
      "accounts": null,
      "unitsConsumed": 4321
    },
    "cause": {
      "name": "SolanaError",
      "code": 4615001,
      "context": { "__code": 4615001, "index": 3 }
    }
  }
}

Mirrors the structural-clone resilience that isSolanaError already has: the helper works whether the input is a live SolanaError instance or a JSON round-tripped object that lost its prototype chain.

Test plan

  • yarn lint-check (clean)
  • npx hardhat test test/describeSolanaError.test.ts (7 new unit tests pass — covers non-Solana inputs, plain SolanaError-like objects, Error subclasses, nested SolanaError causes, non-Solana Error causes, no-cause case, JSON serialization round-trips)
  • Wire into relayer (#3422 follow-up); confirm the new payload appears in bots-across-3839 Cloud Run logs after deploy

Thread: #bot-monitoring 1779869895.829509

🤖 Generated with Claude Code

…xtraction

`SolanaError` carries the rich diagnostics (program logs, accounts touched,
underlying `TransactionError` / `InstructionError`) on its `context` and `cause`
fields. JSON loggers either replace an `Error` value with `.stack` or
`JSON.stringify` it; both routes silently drop those fields. Consumers end up
with `SolanaError: Transaction simulation failed at ...` and no way to tell a
benign race apart from a real program-error.

Add `describeSolanaError(err)` next to `isSolanaError` in `arch/svm/provider`.
Returns `{ solanaError: { name, message?, code, context, cause? } }` for
SolanaErrors (recursing on SolanaError causes; falling back to `{ message }` for
non-Solana Error causes) and `{}` otherwise so callers can spread the result
unconditionally:

  catch (err) {
    logger.error({ ..., error: err, ...describeSolanaError(err) });
  }

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Comment thread src/arch/svm/provider.ts Outdated
}

/**
* Structured description of a SolanaError suitable for logging.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments in this file are too verbose - make them concise.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trimmed the JSDoc/block comments in src/arch/svm/provider.ts in 14f034f — kept terse one-liners over isSolanaError, SolanaErrorStruct, and SolanaErrorDescription, and condensed the describeSolanaError JSDoc to motivation + usage.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this file belong under test/provider/svm ? Colocated with other SVM provider tests?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — moved to test/providers/solana/describeSolanaError.test.ts alongside quorumFallbackRpcFactory.test.ts and utils.test.ts in 14f034f.

- Trim verbose JSDoc/block comments in src/arch/svm/provider.ts.
- Move describeSolanaError.test.ts under test/providers/solana/ alongside
  the other SVM provider tests.

Addresses pxrl review feedback on #1446.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@droplet-rl

Copy link
Copy Markdown
Contributor Author

Addressed pxrl's review on #1446 in commit 14f034f (pending checkpoint push):

  • src/arch/svm/provider.ts:59 — "Comments too verbose": Trimmed throughout. Replaced the multi-line JSDoc blocks over SolanaErrorStruct, SolanaErrorLike, isSolanaError, and SolanaErrorDescription with terse one-liners; condensed the describeSolanaError JSDoc to motivation + usage example. Net -51 / +15 lines in this file.
  • test/describeSolanaError.test.ts — "Colocate with SVM provider tests": git mvd to test/providers/solana/describeSolanaError.test.ts (next to quorumFallbackRpcFactory.test.ts and utils.test.ts); updated the import paths to the new depth.

Verified: npx hardhat test test/providers/solana/describeSolanaError.test.ts → 7/7 pass; yarn lint-check clean. Inline replies posted on both review threads.

Comment thread src/arch/svm/provider.ts
Comment on lines -4 to -7
/**
* SVM RPC provider error codes
* See https://www.quicknode.com/docs/solana/error-references
*/

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@droplet-rl Don't re-word existing comments unless their content is being changed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apologies — I misread the earlier review as flagging the whole file. Reverted the pre-existing JSDoc blocks (SVM error-code exports, SolanaErrorStruct, SolanaErrorLike, isSolanaError) to their original wording in 149ed9c. Only the new describeSolanaError JSDoc remains trimmed.

Revert the changes to JSDoc blocks for SVM error-code exports,
SolanaErrorStruct, SolanaErrorLike, and isSolanaError back to their
original wording; their content was not being changed by this PR.

The new describeSolanaError JSDoc remains as-is (terse, motivation +
usage).

Addresses pxrl review feedback on #1446.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@droplet-rl

Copy link
Copy Markdown
Contributor Author

Addressed pxrl's follow-up review on #1446 in commit 149ed9c (pending checkpoint push).

The feedback: I'd overreached on the first round — pxrl meant don't re-word existing comments in src/arch/svm/provider.ts, only my newly added ones. Reverted the JSDoc blocks over the SVM error-code re-exports, SolanaErrorStruct, SolanaErrorLike, and isSolanaError to their original byte-for-byte wording. Only the new describeSolanaError JSDoc remains in its trimmed form.

Net diff vs. the PR base is now strictly additive: the new SolanaErrorDescription type, the new describeSolanaError function, and the relocated test file — no edits to pre-existing code.

Verified: yarn lint-check clean, 7/7 tests pass. Inline reply posted on the new thread.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants