Skip to content

Conversation

@bordalix
Copy link
Collaborator

@bordalix bordalix commented Oct 22, 2025

@louisinger please review

Summary by CodeRabbit

  • New Features

    • Eligible reverse swaps now auto-claim when status becomes claimable.
  • Improvements

    • Initialization expanded to fetch fees, refresh swap statuses, refund failed submarine swaps, retrieve swap history, and trigger auto-claims.
    • Better error handling and additional logging during initialization.
    • Server endpoints updated to new production URLs.
  • Chores

    • Updated swap library dependency.

@bordalix bordalix requested a review from Copilot October 22, 2025 09:50
@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Oct 22, 2025

Deploying wallet-signet with  Cloudflare Pages  Cloudflare Pages

Latest commit: 07bbca1
Status: ✅  Deploy successful!
Preview URL: https://08cb981a.wallet-23u.pages.dev
Branch Preview URL: https://fix-reverse-swaps.wallet-23u.pages.dev

View logs

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 22, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Replaces the lightning provider's sequential init with an async choresOnInit run in useEffect that fetches and sets fees, refreshes swap statuses, refunds failed submarine swaps, retrieves swap history, filters pending reverse swaps, and auto-claims reverse-claimable swaps; adds imports (isPendingReverseSwap, isReverseClaimableStatus, consoleLog) and updates Boltz and server base URLs.

Changes

Cohort / File(s) Summary
Lightning provider (imports, URL & init)
src/providers/lightning.tsx
Adds isPendingReverseSwap, isReverseClaimableStatus, and consoleLog imports; changes Boltz base URL to https://api.ark.boltz.exchange; replaces prior promise chain with async choresOnInit in useEffect that fetches/sets fees, refreshes swap statuses, refunds failed submarine swaps, retrieves swap history, filters pending reverse swaps, auto-claims reverse-claimable swaps, logs via consoleLog, and wraps errors in try/catch with consoleError.
Server constants
src/lib/constants.ts
Updates testServer and mainServer values from 'https://bitcoin-beta-v8.arkade.sh' to 'https://arkade.computer'.
Dependency bump
package.json
Upgrades @arkade-os/boltz-swap from 0.2.1 to 0.2.6.

Sequence Diagram(s)

sequenceDiagram
    participant UI as App (useEffect)
    participant Chore as choresOnInit
    participant Boltz as Boltz/API
    participant Store as State/Store

    UI->>Chore: invoke choresOnInit()

    rect rgb(230,245,255)
    Note over Chore: initialization steps
    Chore->>Boltz: fetchFees()
    Boltz-->>Chore: fees
    Chore->>Store: setFees()
    Chore->>Boltz: refreshSwapStatuses()
    Boltz-->>Chore: statuses
    Chore->>Boltz: refundFailedSubmarineSwaps()
    Boltz-->>Chore: refundsResult
    end

    rect rgb(235,255,235)
    Note over Chore: history + auto-claim
    Chore->>Boltz: getSwapHistory()
    Boltz-->>Chore: swaps[]
    Chore->>Chore: filter isPendingReverseSwap()
    alt reverse-claimable
        Chore->>Boltz: autoClaimReverseSwap()
        Chore->>Chore: consoleLog(claim)
    end
    end

    rect rgb(255,235,235)
    Note over Chore: errors
    Chore-->>UI: on error -> consoleError
    end

    Chore-->>UI: complete
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The pull request title "reclaim pending reverse swaps on service worker reload" accurately captures the primary functional change in the changeset. The main modification across the files is the refactoring of the initialization flow in src/providers/lightning.tsx to include auto-claiming of eligible reverse swaps with a reverse-claimable status when the service initializes, which aligns directly with the title's intent. The supporting changes—URL endpoint updates and dependency version bump—are auxiliary modifications that enable this core functionality. The title is concise, specific, and clearly communicates the key objective without unnecessary detail.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix_reverse_swaps

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f151652 and 07bbca1.

📒 Files selected for processing (1)
  • src/providers/lightning.tsx (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/providers/lightning.tsx (1)
src/lib/logs.ts (2)
  • consoleLog (35-38)
  • consoleError (40-44)
🔇 Additional comments (2)
src/providers/lightning.tsx (2)

5-5: LGTM!

The new imports (isPendingReverseSwap, isReverseClaimableStatus, consoleLog) are necessary for the auto-claim functionality and are used appropriately in the initialization logic.

Also applies to: 7-7


10-10: Boltz API endpoint verified successfully.

The new bitcoin endpoint (https://api.ark.boltz.exchange) is operational and responding correctly with HTTP 200 status. Configuration is ready for production use.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Oct 22, 2025

Deploying wallet-mutinynet with  Cloudflare Pages  Cloudflare Pages

Latest commit: 07bbca1
Status: ✅  Deploy successful!
Preview URL: https://f53dda4a.arkade-wallet.pages.dev
Branch Preview URL: https://fix-reverse-swaps.arkade-wallet.pages.dev

View logs

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds automatic reclaiming of pending reverse swaps when the service worker reloads, ensuring that swaps in claimable states are completed automatically.

Key changes:

  • Refactored initialization logic to check for pending reverse swaps in claimable status
  • Added automatic claiming of reverse swaps in 'transaction.mempool' state during provider initialization

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

const swaps = await swapProvider.getSwapHistory()
for (const swap of swaps.filter(isPendingReverseSwap)) {
// TODO: change with isReverseClaimableStatus from boltz-swap lib when available
if (['transaction.mempool'].includes(swap.status)) {
Copy link

Copilot AI Oct 22, 2025

Choose a reason for hiding this comment

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

Using an array with a single element in .includes() is unnecessary. Consider using a direct equality check swap.status === 'transaction.mempool' for better readability and performance.

Suggested change
if (['transaction.mempool'].includes(swap.status)) {
if (swap.status === 'transaction.mempool') {

Copilot uses AI. Check for mistakes.
Comment on lines 60 to 66
for (const swap of swaps.filter(isPendingReverseSwap)) {
// TODO: change with isReverseClaimableStatus from boltz-swap lib when available
if (['transaction.mempool'].includes(swap.status)) {
consoleLog('auto-claiming reverse swap:', swap.id)
swapProvider.claimVHTLC(swap).catch(consoleError)
}
}
Copy link

Copilot AI Oct 22, 2025

Choose a reason for hiding this comment

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

Multiple claims are fired concurrently without awaiting or limiting concurrency. Consider using Promise.all() to track completion or implementing sequential processing to avoid potential race conditions or resource exhaustion if many swaps are pending.

Suggested change
for (const swap of swaps.filter(isPendingReverseSwap)) {
// TODO: change with isReverseClaimableStatus from boltz-swap lib when available
if (['transaction.mempool'].includes(swap.status)) {
consoleLog('auto-claiming reverse swap:', swap.id)
swapProvider.claimVHTLC(swap).catch(consoleError)
}
}
const pendingReverseSwaps = swaps.filter(isPendingReverseSwap);
const claimPromises = [];
// TODO: change with isReverseClaimableStatus from boltz-swap lib when available
for (const swap of pendingReverseSwaps) {
if (['transaction.mempool'].includes(swap.status)) {
consoleLog('auto-claiming reverse swap:', swap.id);
claimPromises.push(swapProvider.claimVHTLC(swap).catch(consoleError));
}
}
await Promise.all(claimPromises);

Copilot uses AI. Check for mistakes.
@cloudflare-workers-and-pages
Copy link

Deploying wallet-bitcoin-v8 with  Cloudflare Pages  Cloudflare Pages

Latest commit: 0751048
Status: ✅  Deploy successful!
Preview URL: https://681fff35.wallet-v8.pages.dev
Branch Preview URL: https://fix-reverse-swaps.wallet-v8.pages.dev

View logs

Copy link
Contributor

@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: 0

🧹 Nitpick comments (2)
src/providers/lightning.tsx (2)

54-72: Guard against unmounted/stale provider before setState.

Add a cancellation flag and capture the current provider to avoid setting state after unmount or provider switch.

Apply this diff:

-    const choresOnInit = async () => {
-      try {
-        setFees(await swapProvider.getFees())
+    let cancelled = false
+    const sp = swapProvider
+    const choresOnInit = async () => {
+      try {
+        const f = await sp.getFees()
+        if (cancelled || sp !== swapProvider) return
+        setFees(f)
-        await swapProvider.refreshSwapsStatus()
-        await swapProvider.refundFailedSubmarineSwaps()
-        const swaps = await swapProvider.getSwapHistory()
+        await sp.refreshSwapsStatus()
+        await sp.refundFailedSubmarineSwaps()
+        const swaps = await sp.getSwapHistory()
         for (const swap of swaps.filter(isPendingReverseSwap)) {
           // TODO: change with isReverseClaimableStatus from boltz-swap lib when available
-          if (['transaction.mempool'].includes(swap.status)) {
-            consoleLog('auto-claiming reverse swap:', swap.id)
-            swapProvider.claimVHTLC(swap).catch(consoleError)
+          if (swap.status === 'transaction.mempool')) {
+            consoleLog('auto-claiming reverse swap', { id: swap.id })
+            void sp.claimVHTLC(swap).catch(e =>
+              consoleError(e, `auto-claim reverse swap ${swap.id}`)
+            )
           }
         }
       } catch (error) {
-        consoleError(error)
+        consoleError(error, 'choresOnInit')
       }
     }
     choresOnInit()
+    return () => { cancelled = true }

60-66: Auto-claim dedupe/backoff.

On reloads this loop may re-attempt claims repeatedly. Persist a short-lived “claim in-flight” marker (e.g., in memory or localStorage keyed by swap.id with a TTL) or gate by a last-attempt timestamp to avoid hammering.

Is swapProvider.claimVHTLC idempotent/retry-safe (e.g., no double-spend/broadcast spam)? If not, we should add a simple dedupe/TTL guard.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f696c3e and 0751048.

📒 Files selected for processing (1)
  • src/providers/lightning.tsx (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/providers/lightning.tsx (1)
src/lib/logs.ts (2)
  • consoleLog (35-38)
  • consoleError (40-44)
🔇 Additional comments (1)
src/providers/lightning.tsx (1)

5-7: LGTM on imports.

New symbols are used correctly and improve readability.

const swaps = await swapProvider.getSwapHistory()
for (const swap of swaps.filter(isPendingReverseSwap)) {
// TODO: change with isReverseClaimableStatus from boltz-swap lib when available
if (['transaction.mempool'].includes(swap.status)) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Also transaction.confirmed

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Oct 22, 2025

Deploying wallet-bitcoin with  Cloudflare Pages  Cloudflare Pages

Latest commit: 07bbca1
Status: ✅  Deploy successful!
Preview URL: https://4262129f.wallet-bitcoin.pages.dev
Branch Preview URL: https://fix-reverse-swaps.wallet-bitcoin.pages.dev

View logs

Copy link
Contributor

@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: 0

🧹 Nitpick comments (1)
src/providers/lightning.tsx (1)

60-66: Consider parallel processing for better performance with multiple pending swaps.

Claims are currently processed sequentially (await inside the loop), which is safe but may be slow when many swaps are pending. The individual error handling with .catch(consoleError) is good—it ensures one failure doesn't block others.

For better performance, consider processing claims in parallel:

-        for (const swap of swaps.filter(isPendingReverseSwap)) {
+        const pendingReverseSwaps = swaps.filter(isPendingReverseSwap);
+        const claimPromises = pendingReverseSwaps
+          .filter(swap => ['transaction.mempool', 'transaction.confirmed'].includes(swap.status))
+          .map(swap => {
+            consoleLog('auto-claiming reverse swap:', swap.id);
+            return swapProvider.claimVHTLC(swap).catch(consoleError);
+          });
+        await Promise.all(claimPromises);
-          // TODO: change with isReverseClaimableStatus from boltz-swap lib when available
-          if (['transaction.mempool', 'transaction.confirmed'].includes(swap.status)) {
-            consoleLog('auto-claiming reverse swap:', swap.id)
-            await swapProvider.claimVHTLC(swap).catch(consoleError)
-          }
-        }

However, if sequential processing is intentional (e.g., to avoid rate limiting or resource exhaustion), the current approach is fine.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1d7b1c1 and 6c87428.

📒 Files selected for processing (1)
  • src/providers/lightning.tsx (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/providers/lightning.tsx (1)
src/lib/logs.ts (2)
  • consoleLog (35-38)
  • consoleError (40-44)
🔇 Additional comments (2)
src/providers/lightning.tsx (2)

5-5: LGTM! Necessary imports for auto-claiming functionality.

The additions of isPendingReverseSwap and consoleLog are appropriate and used correctly in the new initialization logic.

Also applies to: 7-7


54-71: LGTM! Well-structured initialization logic that addresses the PR objective.

The refactoring to an async choresOnInit function with proper error handling is a good improvement. The implementation correctly:

  • Fetches necessary data (fees, swap status, history)
  • Refunds failed submarine swaps
  • Auto-claims pending reverse swaps with eligible statuses

The addition of 'transaction.confirmed' to the status check at line 62 addresses previous feedback from michael1011.

Copy link
Contributor

@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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/providers/lightning.tsx (2)

10-14: Critical: mainnet (‘bitcoin’) defaults to mutinynet URL.

This can mis-route mainnet users to a test network. Remove the unsafe fallback for bitcoin and fail closed unless an explicit mainnet URL is configured.

Apply:

-  bitcoin: import.meta.env.VITE_BOLTZ_URL ?? 'https://api.boltz.mutinynet.arkade.sh',
+  // Do not default mainnet to a testnet endpoint; require explicit config.
+  bitcoin: import.meta.env.VITE_BOLTZ_URL ?? '',

And surface a clear log before bailing:

-    if (!baseUrl) return // No boltz server for this network
+    if (!baseUrl) {
+      consoleError(`No Boltz URL configured for network "${aspInfo.network}". Skipping Lightning provider init.`);
+      return;
+    }

45-47: CI/CD does not set VITE_BOLTZ_URL for production; bitcoin mainnet will fall back to testnet URL.

The .github/workflows/ci.yml build step does not define VITE_BOLTZ_URL, and .env contains no such variable. Code at line 10 of src/providers/lightning.tsx falls back to 'https://api.boltz.mutinynet.arkade.sh' (testnet) when the env var is missing. This bypasses the "fail closed" check at line 46 since the fallback URL is truthy.

Required fixes:

  1. Explicitly set VITE_BOLTZ_URL in CI/CD for production builds (or deployment environment)
  2. Change the bitcoin fallback to undefined or null to ensure "fail closed" triggers for missing production config, preventing accidental testnet usage
♻️ Duplicate comments (1)
src/providers/lightning.tsx (1)

61-63: Good: includes both ‘transaction.mempool’ and ‘transaction.confirmed’.

This addresses the prior review asking to include confirmed.

🧹 Nitpick comments (2)
src/providers/lightning.tsx (2)

63-65: Style: prefer try/catch over await ... .catch() for readability.

You’re already inside try/catch; keep per-item errors local with a small inner try/catch (see previous diff).


63-64: Optional: redact verbose IDs in logs.

If logs are persisted, consider trimming swap.id (e.g., first 8 chars) to reduce exposure.

Example:

-            consoleLog('auto-claiming reverse swap:', swap.id)
+            consoleLog('auto-claiming reverse swap:', `${swap.id.slice(0, 8)}…`)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6c87428 and 5a7b437.

📒 Files selected for processing (1)
  • src/providers/lightning.tsx (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/providers/lightning.tsx (1)
src/lib/logs.ts (2)
  • consoleLog (35-38)
  • consoleError (40-44)
🔇 Additional comments (1)
src/providers/lightning.tsx (1)

5-7: LGTM on imports.

Use of FeesResponse, isPendingReverseSwap, Network, and log helpers is correct and tight.

Copy link
Contributor

@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: 1

♻️ Duplicate comments (1)
src/providers/lightning.tsx (1)

52-72: Add cleanup to prevent setState on unmounted component and stale provider access.

The async choresOnInit function can complete after the component unmounts or after swapProvider changes, leading to:

  • Line 56: setFees called on unmounted component (React warning)
  • Lines 57-66: Operations on a stale swapProvider instance

This issue was previously flagged in past reviews but remains unresolved.

Apply this diff to add cleanup:

  useEffect(() => {
    if (!swapProvider) return
+   let cancelled = false
+   const currentProvider = swapProvider
+
    const choresOnInit = async () => {
      try {
-       setFees(await swapProvider.getFees())
-       await swapProvider.refreshSwapsStatus()
-       await swapProvider.refundFailedSubmarineSwaps()
-       const swaps = await swapProvider.getSwapHistory()
+       const f = await currentProvider.getFees()
+       if (cancelled) return
+       setFees(f)
+       await currentProvider.refreshSwapsStatus()
+       await currentProvider.refundFailedSubmarineSwaps()
+       const swaps = await currentProvider.getSwapHistory()
        for (const swap of swaps.filter(isPendingReverseSwap)) {
-         // TODO: change with isReverseClaimableStatus from boltz-swap lib when available
          if (isReverseClaimableStatus(swap.status)) {
+           if (cancelled) return
            consoleLog('auto-claiming reverse swap:', swap.id)
-           await swapProvider.claimVHTLC(swap).catch(consoleError)
+           await currentProvider.claimVHTLC(swap).catch(consoleError)
          }
        }
      } catch (error) {
        consoleError(error)
      }
    }
    choresOnInit()
+   return () => {
+     cancelled = true
+   }
  }, [swapProvider])
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 811d621 and f151652.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (2)
  • package.json (1 hunks)
  • src/providers/lightning.tsx (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/providers/lightning.tsx (1)
src/lib/logs.ts (2)
  • consoleLog (35-38)
  • consoleError (40-44)
🔇 Additional comments (3)
src/providers/lightning.tsx (2)

5-5: LGTM!

The new imports align with the enhanced initialization logic and are used correctly in the choresOnInit function.

Also applies to: 7-7


10-10: LGTM!

The updated base URL aligns with the infrastructure changes for the Boltz swap API endpoint.

package.json (1)

7-7: Package version 0.2.6 is valid and has no known vulnerabilities.

Version 0.2.6 exists in the npm registry and no security vulnerabilities were found in the GitHub advisory database for this package. The dependency specification in package.json is correct.

Copy link
Contributor

@louisinger louisinger left a comment

Choose a reason for hiding this comment

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

tACK

@bordalix bordalix merged commit 66aee3d into master Oct 23, 2025
5 checks passed
@bordalix bordalix deleted the fix_reverse_swaps branch November 26, 2025 14:29
@coderabbitai coderabbitai bot mentioned this pull request Dec 16, 2025
This was referenced Jan 5, 2026
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.

4 participants