Skip to content

feat: implement typed error taxonomy and custom error classes (#18)#38

Open
TheDEV111 wants to merge 1 commit into
wraith-protocol:developfrom
TheDEV111:feat/typed-errors
Open

feat: implement typed error taxonomy and custom error classes (#18)#38
TheDEV111 wants to merge 1 commit into
wraith-protocol:developfrom
TheDEV111:feat/typed-errors

Conversation

@TheDEV111
Copy link
Copy Markdown

@TheDEV111 TheDEV111 commented May 31, 2026

closes #18

📝 Overview & Summary

Currently, the SDK throws plain, generic Error instances throughout its modules. This forces consumers to use brittle string-matching patterns in try/catch blocks to programmatically distinguish between specific error conditions (e.g. invalid meta-addresses, RPC failures, or view-tag mismatches).

This PR resolves Issue #18 by implementing a granular, typed hierarchy of custom error classes under src/errors.ts (re-exported from the SDK root entry point). These custom classes extend the native JavaScript Error class (guaranteeing runtime backwards-compatibility) while carrying enumerable, structured metadata payloads, stable error codes, and dynamic documentation links.


🛠️ Detailed Scope of Changes

1. The Error Hierarchy (src/errors.ts)

We have established a robust abstract taxonomy dividing errors into five primary functional domains:

WraithError (Abstract Base)
├── WraithInputError
│   ├── InvalidMetaAddressError
│   ├── InvalidNameError
│   ├── InvalidSignatureError
│   └── InvalidScalarError
├── WraithCryptoError
│   ├── KeyDerivationFailedError
│   ├── ViewTagMismatchError
│   └── ECDHFailedError
├── WraithNetworkError
│   ├── RPCRequestError
│   ├── RPCRetryExhaustedError
│   └── RetentionExceededError
├── WraithContractError
│   ├── NameNotFoundError
│   ├── NameAlreadyRegisteredError
│   ├── InsufficientAuthError
│   └── ContractRevertError
└── WraithBuilderError
    ├── InsufficientBalanceError
    └── UnsupportedAssetError

2. Properties & Serialization Support

Every subclass instances includes:

  • name: Automatically matches the class name.
  • code: A stable serializable constant string (e.g. "WRAITH/INPUT/INVALID_SIGNATURE") to retain class identity across network boundaries.
  • context: A structured object containing domain-specific parameters (e.g. statusCode, expectedLength, actualLength).
  • docsLink: A direct link referencing the specific error details in the documentation guide.
  • JSON Serialization: Native support via toJSON() on WraithError to ensure custom properties serialize cleanly with JSON.stringify(error).

3. Codebase-wide Refactoring

  • Generic Throw Replacements: Swept all modules across all supported chains (CKB, EVM, Solana, and Stellar) and the core Wraith Agent Client to replace plain throw new Error(...) calls with their typed equivalents.
  • JSDoc Enhancements: Updated @throws comments across public functions to document specific error behavior.

4. Testing & QA

  • Unit Tests (test/errors.test.ts): Added 17 unit tests verifying instanceof correctness (including ancestor matching like WraithInputError), name/code/docsLink generation, property preservation, and serialization.
  • Suite Adjustment: Updated existing signature-rejection test suites on all chains to expect the typed InvalidSignatureError exceptions.

5. Documentation

  • User Guide (docs/errors.md): Wrote a complete, premium-quality developer guide containing the class tree, property mappings, stable codes reference table, and rich try/catch integration examples.
  • Changelog (CHANGELOG.md): Noted the change in a new changelog file, warning developers about message string formatting adjustments.

⚠️ Impact & Migration Path

  • Runtime Non-Breaking: Applications that catch exceptions as generic Error instances remain unaffected because all custom classes inherit from Error.
  • Typing-Breaking for Brittle Matchers: Code relying on substring checks against error.message (e.g. .toThrow('Expected 65-byte signature')) will break. Integrators must update their catch statements to use modern instanceof checking:
import { InvalidSignatureError } from '@wraith-protocol/sdk';

try {
  const keys = deriveStealthKeys(badSig);
} catch (e) {
  if (e instanceof InvalidSignatureError) {
    console.error(`Expected signature length: ${e.context.expectedLength}`);
  }
}

✅ Verification & Testing Done

  • Vitest Results: Ran pnpm test, verifying that all 151 unit and E2E tests successfully pass.
  • Precommit Check: Format checking and TypeScript generation executed successfully under Husky hooks:
    ESM dist/index.js                 5.10 KB
    CJS dist/index.cjs                7.89 KB
    DTS dist/index.d.ts               8.62 KB
    ⚡️ Build success in 582ms

@drips-wave
Copy link
Copy Markdown

drips-wave Bot commented May 31, 2026

@TheDEV111 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@truthixify truthixify changed the base branch from main to develop June 1, 2026 15:33
@truthixify
Copy link
Copy Markdown
Contributor

The error hierarchy (src/errors.ts, 230 lines + 235 lines of tests) is the right shape. Same rebase situation.

git fetch origin
git rebase origin/develop
git push --force-with-lease

Keep src/errors.ts, test/errors.test.ts, the per-chain typed-throw migrations; resolve conflicts in files you didn't intend to rewrite by keeping develop's versions. Thanks @TheDEV111.

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.

Typed error taxonomy + custom error classes

2 participants