caravan-bitcoin/caravan

Improve Type System for `Caravan-Clients` Package

开放

#192 创建于 2025年3月14日

 (2 条评论) (0 个反应) (0 位负责人)TypeScript (102 个派生)auto 404
@caravan/clientsdocumentationgood first issue

仓库指标

星标
 (85 个星标)
PR 合并指标
 (PR 指标待抓取)

描述

Summary

After digging through the codebase, I've noticed our type system in the caravan-clients package has several inconsistencies that make development harder than it needs to be. I'd like to propose a series of improvements to make our types more consistent, reduce any usage, and better align with Bitcoin RPC responses.

The Problems

Looking at the code, I've noticed a few issues:

  • Types are all over the place - We have similar types defined in multiple files, and it's not clear which ones we should use.
  • Too many any types - We're using any in a lot of places with eslint-disable comments and @ts-expect-error workarounds.
  • Inconsistent parameter handling - Sometimes we pass arrays like [imports, { rescan }], other times objects like { minconf: 0, maxconf: 9999999, addresses: addressParam }.
  • Type assertions without validation - We often just assume what the response structure will be rather than properly typing it.
  • Each backend returns different formats - bitcoind, blockstream, and mempool all return different structures, making it hard to work with.

Proposed Approach

I think we should tackle this in stages through several PRs:

Tasks

1. Centralize Type Definitions

  • Create a logical organization structure for types.
  • Move shared types from various files to types.ts.
  • Create consistent naming conventions for types.
  • Document types with JSDoc comments.
  • Remove duplicate/redundant type definitions.

2. Improve RPC Parameter Handling

  • Create a flexible RPCParams type that can handle both array and object formats:
    export type RPCParam = string | number | boolean | null | undefined | RPCParam[] | { [key: string]: RPCParam };
    export type RPCParams = RPCParam[] | Record<string, RPCParam>;
    
  • Update RPC call functions to use these types.
  • Document parameter patterns for different RPC methods.
  • Update BitcoindWalletParams interface to use better typing.

3. Create Response Type Mapping

  • Create a reference table of Bitcoin RPC methods to TypeScript interfaces:
    RPC Method Documentation URL Response Type Currently Used In
    getwalletinfo Link WalletInfoResponse wallet.ts
    listunspent Link ListUnspentResponse[] wallet.ts
  • Define accurate response types based on Bitcoin Core documentation.
  • Create a type mapping between RPC methods and their response types:
    export interface RPCMethodResponseMap {
      getwalletinfo: WalletInfoResponse;
      listunspent: ListUnspentResponse[];
      // ...other methods
    }
    
  • Add version information to types for future maintenance.

4. Make Core Functions Generic

  • Update callBitcoindWallet to be generic (similar to callBitcoind):
    export function callBitcoindWallet<T>({
      baseUrl,
      walletName,
      auth,
      method,
      params,
    }: BitcoindWalletParams): Promise<RPCResponse<T>>
    
  • Fix the @ts-expect-error annotations in various functions.
  • Update function calls to use appropriate type parameters.
  • Implement method-specific type overloads where helpful.

5. Create Type Hierarchies for Complex Types

  • Establish clear hierarchies for related types (especially transaction data).
  • Create base interfaces that can be extended for specific use cases.
  • Document relationships between types.
  • Update code to use these hierarchies effectively.

6. Implement Response Normalization Pattern

  • Create normalized internal formats for key data structures.
  • Implement adapter functions for different backend responses.
  • Update client methods to use normalized formats.
  • Document the normalization patterns.

7. Replace any with Proper Type Guards

  • Replace any with unknown in error handling.
  • Add proper type guards for API responses and errors.
  • Create utility functions for common type checking patterns.
  • Remove eslint-disable comments where possible.

8. Documentation and Maintenance Strategy

  • Add comprehensive JSDoc comments to all types.
  • Document the type update process for future Bitcoin Core changes.
  • Create a version tracking strategy for type definitions.
  • Add example usage in comments for complex types.

Implementation Plan

I suggest we tackle this incrementally to avoid disrupting current development:

  1. First PR: Address items 1-2 (centralize types, fix RPC parameter handling).
  2. Second PR: Address items 3-4 (method mapping, generic functions).
  3. Third PR: Address items 5 (type hierarchies, replace any).
  4. Fourth PR: Address items 6 (normalisation functionality).
  5. Fifth PR: Address items 7 ( replace any).
  6. Sixth PR: Address item 8 (documentation and maintenance).

Why This Matters

These changes will:

  • Make it easier to understand the codebase.
  • Catch more errors at compile-time instead of runtime.
  • Improve IDE autocompletion and hints.
  • Make the codebase more maintainable.
  • Make it easier to update when Bitcoin Core changes.
  • Reduce the cognitive load for devs working on the project.

I'm happy to tackle the first PR to get things started. What do you all think :)

贡献者指南