Skip to content

Improve Error Handling in smart-contract.ts: Raise Errors Instead of Returning Undefined #7

@AbdulRashidReshamwala

Description

@AbdulRashidReshamwala

Improve Error Handling in smart-contract.ts: Raise Errors Instead of Returning Undefined

Description

Currently, some functions in smart-contract.ts return undefined when encountering error conditions. This approach can lead to silent failures and make debugging more difficult. We should modify these functions to throw specific errors instead, which will make error handling more explicit and improve the overall reliability of the SDK.

Current Behavior

In smart-contract.ts, functions like getContract and makeBeacon return undefined when they encounter issues:

export function getContract(chainId: number): Reclaim | undefined {
  const config = CONTRACTS_CONFIG[chainId as keyof typeof CONTRACTS_CONFIG];
  if (!config) {
    return undefined;
  }
  // ...
}

export function makeBeacon(chainId: number = DEFAULT_CHAIN_ID): Beacon | undefined {
  const contract = getContract(chainId);
  if (!contract) {
    return undefined;
  }
  // ...
}

Proposed Changes

  1. Create specific error types for different failure scenarios.
  2. Modify functions to throw these errors instead of returning undefined.
  3. Update the function return types to remove | undefined.

Implementation Details

  1. Create new error types in src/utils/errors.ts:
export class ContractConfigurationError extends Error {
  constructor(chainId: number) {
    super(`No configuration found for chain ID: ${chainId}`);
    this.name = 'ContractConfigurationError';
  }
}

export class ContractInitializationError extends Error {
  constructor(chainId: number, cause?: unknown) {
    super(`Failed to initialize contract for chain ID: ${chainId}`);
    this.name = 'ContractInitializationError';
    this.cause = cause;
  }
}
  1. Update getContract function:
import { ContractConfigurationError, ContractInitializationError } from './utils/errors';

export function getContract(chainId: number): Reclaim {
  const config = CONTRACTS_CONFIG[chainId as keyof typeof CONTRACTS_CONFIG];
  if (!config) {
    throw new ContractConfigurationError(chainId);
  }

  try {
    const provider = new ethers.JsonRpcProvider(config.rpcUrl);
    return new Contract(config.address, ReclaimInterface, provider) as Reclaim;
  } catch (error) {
    throw new ContractInitializationError(chainId, error);
  }
}
  1. Update makeBeacon function:
export function makeBeacon(chainId: number = DEFAULT_CHAIN_ID): Beacon {
  const contract = getContract(chainId);
  return makeBeaconCacheable({
    async getState(epochId?: number): Promise<BeaconState> {
      const epoch = await contract.fetchEpoch(epochId ?? 0);
      if (epoch.id.isZero()) {
        throw new Error(`Invalid epoch ID: ${epochId}`);
      }

      // ... rest of the function ...
    },
  });
}

Tasks

  • Create new error types in src/utils/errors.ts
  • Update getContract function to throw errors instead of returning undefined
  • Update makeBeacon function to remove the null check on contract
  • Update return types of both functions to remove | undefined
  • Update any code that calls these functions to handle potential errors
  • Add unit tests to verify the new error handling behavior
  • Update documentation to reflect the new error handling approach

Benefits

  • Improved error handling and debugging
  • More predictable function behavior
  • Better type safety (no need to check for undefined returns)
  • Clearer API contract for SDK users

Potential Impacts

  • Any code currently checking for undefined returns from these functions will need to be updated to use try/catch blocks
  • SDK users will need to be informed about this change in error handling behavior

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions