Skip to content

Remove third party dependency from bridge#4

Open
PastaPastaPasta wants to merge 1 commit intomainfrom
claude/remove-bridge-dependencies-X4Xu4
Open

Remove third party dependency from bridge#4
PastaPastaPasta wants to merge 1 commit intomainfrom
claude/remove-bridge-dependencies-X4Xu4

Conversation

@PastaPastaPasta
Copy link
Owner

@PastaPastaPasta PastaPastaPasta commented Jan 21, 2026

Migrates InstantSend lock retrieval from custom RPC endpoints (trpc.digitalcash.dev / rpc.digitalcash.dev) to use the standard DAPI gRPC subscription method subscribeToTransactionsWithProofs.

Changes:

  • Add @dashevo/dapi-client and @dashevo/dashcore-lib dependencies
  • Rewrite DAPIClient to use bloom filter subscription approach
  • Create bloom filter for txid and subscribe to transaction stream
  • Parse InstantSend lock messages and match by txid
  • Add TypeScript declarations for external CommonJS modules
  • Update vite.config.ts for CommonJS module handling

This removes dependency on third-party RPC endpoints and uses the official DAPI infrastructure for InstantSend lock retrieval.

Summary by CodeRabbit

  • Improvements

    • Enhanced transaction lock detection with real-time streaming subscriptions for faster, more efficient confirmation updates.
  • Chores

    • Added new dependencies and updated build configuration for improved compatibility.

✏️ Tip: You can customize this high-level summary in your review settings.

Migrates InstantSend lock retrieval from custom RPC endpoints
(trpc.digitalcash.dev / rpc.digitalcash.dev) to use the standard DAPI
gRPC subscription method subscribeToTransactionsWithProofs.

Changes:
- Add @dashevo/dapi-client and @dashevo/dashcore-lib dependencies
- Rewrite DAPIClient to use bloom filter subscription approach
- Create bloom filter for txid and subscribe to transaction stream
- Parse InstantSend lock messages and match by txid
- Add TypeScript declarations for external CommonJS modules
- Update vite.config.ts for CommonJS module handling

This removes dependency on third-party RPC endpoints and uses the
official DAPI infrastructure for InstantSend lock retrieval.
@coderabbitai
Copy link

coderabbitai bot commented Jan 21, 2026

📝 Walkthrough

Walkthrough

This pull request integrates a new subscription-based DAPI client library, replacing the previous RPC polling approach. It adds two dependencies, implements a bloom-filter-based transaction lock detection system via streaming subscriptions, includes comprehensive TypeScript type definitions, and updates Vite configuration to handle CommonJS/ESM module interoperability.

Changes

Cohort / File(s) Summary
Dependency Additions
package.json
Added @dashevo/dapi-client (^2.1.3) and @dashevo/dashcore-lib (^0.25.0) to support new subscription-based DAPI client architecture.
DAPI Client Refactoring
src/api/dapi.ts
Replaced RPC-based polling with subscription-based streaming architecture. Introduced BridgeDAPIClient class with bloom filter creation, instant lock parsing, and stream event handling (data, error, end). Added disconnect() lifecycle method and removed HTTP fetch-based logic.
Type Definitions
src/types/external.d.ts
Created ambient declarations for @dashevo/dapi-client (DAPIClientOptions, StreamResponse, CoreMethods) and @dashevo/dashcore-lib (BloomFilter, InstantLock interfaces and static methods).
Build Configuration
vite.config.ts
Added commonjsOptions.transformMixedEsModules: true, pinned external dependencies in optimizeDeps.include, and polyfilled process.env for browser compatibility.

Sequence Diagram

sequenceDiagram
    participant App as Application
    participant BDAPI as BridgeDAPIClient
    participant DAPIService as DAPI Service
    participant Blockchain as Blockchain Network
    
    App->>BDAPI: waitForInstantSendLock(txid, timeout)
    BDAPI->>BDAPI: createBloomFilterForTxid(txid)
    BDAPI->>BDAPI: getBestBlockHeight()
    BDAPI->>DAPIService: subscribeToTransactionsWithProofs(bloomFilter, {fromBlockHeight})
    DAPIService->>Blockchain: Open streaming subscription
    
    loop Monitor incoming transactions
        Blockchain-->>DAPIService: Transaction with proof
        DAPIService-->>BDAPI: Stream data event
        BDAPI->>BDAPI: parseInstantLockTxid(islockBytes)
        alt Matching txid found
            BDAPI->>App: Return Uint8Array (Promise resolves)
        else Continue monitoring
            BDAPI->>BDAPI: Wait for next data event
        end
    end
    
    alt Timeout exceeded
        BDAPI->>App: Reject Promise
    end
    
    App->>BDAPI: disconnect()
    BDAPI->>DAPIService: Close connection
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Poem

🐰 From polls to streams, the rabbit hops with glee,
Bloom filters bloom where subscriptions flow free,
No more waiting in loops—the data arrives with grace,
DAPI's new dance leaves polling's old pace! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title 'Remove third party dependency from bridge' is misleading because the changeset actually adds two new third-party dependencies (@dashevo/dapi-client and @dashevo/dashcore-lib) rather than removing dependencies. While it does migrate away from custom RPC endpoints, the title contradicts the actual changes made. Revise the title to accurately reflect the main change, such as 'Migrate InstantSend lock retrieval to DAPI subscription service' or 'Replace custom RPC endpoints with DAPI gRPC subscriptions'.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@src/api/dapi.ts`:
- Around line 143-146: The variable `stream` is typed as ReturnType<typeof
client.core.subscribeToTransactionsWithProofs> but that captures the Promise
type; update the annotation so `stream` reflects the resolved StreamResponse —
e.g., change its type to Awaited<ReturnType<typeof
client.core.subscribeToTransactionsWithProofs>> (or, if you prefer, use `any`
since `client` is `any`) and ensure the code uses the resolved `stream` after
awaiting client.core.subscribeToTransactionsWithProofs; the fix targets the
`stream` declaration in the Promise block where
`subscribeToTransactionsWithProofs` is awaited.

In `@vite.config.ts`:
- Around line 20-23: The define block currently replaces all process.env
references with an empty object which breaks usage of process.env.BASE_PATH;
update vite.config.ts to stop globally polyfilling 'process.env' and instead
either (a) define only the needed variable ('process.env.BASE_PATH') so the
build injects the real BASE_PATH value, or (b) change your code to read the
value via import.meta.env.BASE_PATH and remove the broad 'process.env' define;
locate the define object in vite.config.ts to implement the targeted change and
ensure BASE_PATH is preserved at build time.
🧹 Nitpick comments (3)
src/types/external.d.ts (1)

27-32: Consider returning this for method chaining.

The on() method typically returns this (or the stream itself) to allow method chaining, which is a common pattern in Node.js streams.

Suggested improvement
  interface StreamResponse {
-   on(event: 'data', callback: (data: unknown) => void): void;
-   on(event: 'error', callback: (error: Error) => void): void;
-   on(event: 'end', callback: () => void): void;
+   on(event: 'data', callback: (data: unknown) => void): this;
+   on(event: 'error', callback: (error: Error) => void): this;
+   on(event: 'end', callback: () => void): this;
    cancel(): void;
  }
src/api/dapi.ts (2)

13-29: Type duplication is acceptable but could diverge.

These local interface definitions duplicate types from src/types/external.d.ts. While this is a reasonable approach for type safety with dynamically loaded CommonJS modules, be aware that changes in external.d.ts won't automatically sync here.

Consider adding a comment linking to the ambient declarations or consolidating types.


218-224: Consider tracking stream errors for better diagnostics.

Currently, stream errors are logged but otherwise ignored, relying on the timeout to handle failures. This could make debugging difficult if transient errors occur repeatedly.

Optional improvement
+         let lastError: Error | null = null;
+
          stream.on('error', (error: Error) => {
            if (!resolved) {
              console.error('Stream error:', error);
+             lastError = error;
+             onProgress?.(`Stream error: ${error.message}`);
              // Don't reject immediately on stream errors, the timeout will handle it
              // Some stream errors are recoverable
            }
          });

Then include lastError in the timeout rejection message for context.

Comment on lines +143 to +146
return new Promise<Uint8Array>((resolve, reject) => {
let stream: ReturnType<typeof client.core.subscribeToTransactionsWithProofs> | null = null;
let timeoutId: ReturnType<typeof setTimeout> | null = null;
let resolved = false;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Incorrect type annotation for stream variable.

The subscribeToTransactionsWithProofs method returns Promise<StreamResponse>, but after awaiting it on line 175, stream holds the resolved StreamResponse, not the Promise. The current ReturnType<...> captures the Promise type incorrectly.

Proposed fix
    return new Promise<Uint8Array>((resolve, reject) => {
-     let stream: ReturnType<typeof client.core.subscribeToTransactionsWithProofs> | null = null;
+     let stream: { on: Function; cancel: () => void } | null = null;
      let timeoutId: ReturnType<typeof setTimeout> | null = null;
      let resolved = false;

Or simply use any since the client is already typed as any.

🤖 Prompt for AI Agents
In `@src/api/dapi.ts` around lines 143 - 146, The variable `stream` is typed as
ReturnType<typeof client.core.subscribeToTransactionsWithProofs> but that
captures the Promise type; update the annotation so `stream` reflects the
resolved StreamResponse — e.g., change its type to Awaited<ReturnType<typeof
client.core.subscribeToTransactionsWithProofs>> (or, if you prefer, use `any`
since `client` is `any`) and ensure the code uses the resolved `stream` after
awaiting client.core.subscribeToTransactionsWithProofs; the fix targets the
`stream` declaration in the Promise block where
`subscribeToTransactionsWithProofs` is awaited.

Comment on lines +20 to 23
define: {
// Polyfill for process.env in browser
'process.env': {},
},
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Potential issue: process.env polyfill may break BASE_PATH usage.

The define: { 'process.env': {} } on line 20-22 replaces all process.env references with an empty object at build time. However, line 4 uses process.env.BASE_PATH, which will now always resolve to undefined since the polyfill doesn't preserve environment variables.

Consider using a more targeted approach:

Proposed fix
  define: {
-   // Polyfill for process.env in browser
-   'process.env': {},
+   // Polyfill for process.env in browser while preserving BASE_PATH
+   'process.env': {
+     BASE_PATH: JSON.stringify(process.env.BASE_PATH || '/'),
+   },
  },

Alternatively, if BASE_PATH is set at build time via Vite's env handling, you could use import.meta.env.BASE_PATH instead.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
define: {
// Polyfill for process.env in browser
'process.env': {},
},
define: {
// Polyfill for process.env in browser while preserving BASE_PATH
'process.env': {
BASE_PATH: JSON.stringify(process.env.BASE_PATH || '/'),
},
},
🤖 Prompt for AI Agents
In `@vite.config.ts` around lines 20 - 23, The define block currently replaces all
process.env references with an empty object which breaks usage of
process.env.BASE_PATH; update vite.config.ts to stop globally polyfilling
'process.env' and instead either (a) define only the needed variable
('process.env.BASE_PATH') so the build injects the real BASE_PATH value, or (b)
change your code to read the value via import.meta.env.BASE_PATH and remove the
broad 'process.env' define; locate the define object in vite.config.ts to
implement the targeted change and ensure BASE_PATH is preserved at build time.

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