Skip to content

Conversation

@Kukks
Copy link
Contributor

@Kukks Kukks commented Dec 10, 2025

Requires arkade-os/boltz-swap#41 first

Summary by CodeRabbit

  • New Features

    • Real-time swap updates and faster, more reliable swap actions in the app UI.
    • Mainnet environment support via a new startup script and configurable server URLs.
  • Chores

    • Added cross-env and updated start/build scripts to run sequentially and stop on errors.
    • Consistent API URL retrieval across Boltz and support screens.

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

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Dec 10, 2025

Deploying wallet-mutinynet with  Cloudflare Pages  Cloudflare Pages

Latest commit: 3c6f67c
Status:⚡️  Build in progress...

View logs

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 10, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

Replaces the legacy LightningSwapProvider with ArkadeLightning and SwapManager; refactors LightningContext to expose arkadeLightning, swapManager, and helper methods; updates init/fees/history flows and all call sites to use the new APIs; removes src/lib/lightning.ts.

Changes

Cohort / File(s) Summary
Build Configuration
package.json
Updated start and build scripts to use && chaining (stop-on-failure); added start:mainnet using cross-env with VITE_ARK_SERVER and VITE_BOLTZ_URL; added devDependency cross-env@^10.1.0.
Core Provider Removal
src/lib/lightning.ts
Removed entire LightningSwapProvider implementation (swap lifecycle, backups, refunds, helpers, and exports).
Core Provider Rewrite
src/providers/lightning.tsx
Replaced LightningSwapProvider with ArkadeLightning + BoltzSwapProvider + RestArkProvider + RestIndexerProvider; added SwapManager; context now exposes arkadeLightning, swapManager, and helper methods (createSubmarineSwap, createReverseSwap, claimVHTLC, refundVHTLC, payInvoice, getSwapHistory, getFees, getApiUrl); updated init, fees fetch, cleanup, and state management.
Limits Provider
src/providers/limits.tsx
Switched readiness and limit-fetching to rely on arkadeLightning instead of legacy swapProvider; updated effect deps and getLimits invocation.
Swap list & subscription
src/components/SwapsList.tsx
Replaced swap history source with arkadeLightning.getSwapHistory() and added real-time updates via swapManager.onSwapUpdate, updating swapHistory in-place or prepending new swaps.
Boltz screens
src/screens/Apps/Boltz/Index.tsx, src/screens/Apps/Boltz/Settings.tsx, src/screens/Apps/Boltz/Swap.tsx
Replaced swapProvider usage with getApiUrl() and context helper methods; renamed AppBoltzAppBoltzSettings; added swapManager subscription in Swap.tsx and switched claim/refund actions to claimVHTLC/refundVHTLC.
Support screen
src/screens/Settings/Support.tsx
Replaced swapProvider?.getApiUrl() with getApiUrl() from context; updated boltz URL construction.
Receive QR flow
src/screens/Wallet/Receive/QrCode.tsx
Replaced swapProvider?.createReverseSwap with createReverseSwap; guard on arkadeLightning; uses arkadeLightning.waitAndClaim(pendingSwap) for claim flow and updated navigation/error handling.
Send flow
src/screens/Wallet/Send/Details.tsx, src/screens/Wallet/Send/Form.tsx
Replaced swapProvider?.payInvoice / createSubmarineSwap calls with context payInvoice / createSubmarineSwap; replaced swapProvider?.getApiUrl() with getApiUrl().
Test Mocks
src/test/screens/mocks.ts
Removed swapProvider from mock; added arkadeLightning: null, swapManager: null, and mocked implementations for calcReverseSwapFee, createSubmarineSwap, createReverseSwap, claimVHTLC, refundVHTLC, payInvoice, getSwapHistory, getFees, getApiUrl, toggleConnection.

Sequence Diagram(s)

mermaid
sequenceDiagram
autonumber
participant UI as Client UI (components)
participant Ctx as LightningContext
participant AL as ArkadeLightning
participant SM as SwapManager
participant ArkAPI as REST Arkade/Boltz/API

Note over UI,Ctx: User triggers swap actions / views
UI->>Ctx: call createSubmarineSwap / createReverseSwap / payInvoice / getSwapHistory / getApiUrl
Ctx->>AL: delegate create/pay/getFees/getSwapHistory/getApiUrl
AL->>ArkAPI: HTTP calls to Arkade / Boltz / Indexer
ArkAPI-->>AL: responses (swap created, fees, history)
AL-->>Ctx: result (pending swap, fees, history)
Ctx->>SM: (on init) subscribe for swap updates
ArkAPI-->>SM: push/update events (via provider/websocket)
SM-->>Ctx: onSwapUpdate events
Ctx-->>UI: emit updated swap info (context state)
Note over UI,SM: UI subscribes via context to real-time updates

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Areas needing focused review:
    • src/providers/lightning.tsx: initialization, ArkadeLightning wiring, error handling, and cleanup.
    • Real-time subscription lifecycle: src/components/SwapsList.tsx and src/screens/Apps/Boltz/Swap.tsx (subscribe/unsubscribe correctness).
    • Payment/refund flows: payInvoice, waitForSwapSettlement, claim/refund handling and edge-case error paths.
    • Tests/mocks: ensure mockLightningContextValue covers new async behaviors.

Possibly related PRs

Suggested reviewers

  • bordalix
  • louisinger
  • tiero

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Use SwapManager' directly describes the primary change: replacing the LightningSwapProvider architecture with a new ArkadeLightning and SwapManager-based setup across multiple files.

📜 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 4d3743f and 3c6f67c.

📒 Files selected for processing (1)
  • src/screens/Apps/Boltz/Index.tsx (2 hunks)

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.

})
setLogger({
log: (...args: unknown[]) => consoleLog(...args ),
error: (...args: unknown[]) => consoleError(...args ),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Incompatible signature for consoleError()

setLogger({
log: (...args: unknown[]) => consoleLog(...args ),
error: (...args: unknown[]) => consoleError(...args ),
warn: (...args: unknown[]) => consoleWarn(...args),
Copy link
Collaborator

Choose a reason for hiding this comment

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

consoleWarn() doesn't exist

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Dec 15, 2025

Deploying wallet-bitcoin with  Cloudflare Pages  Cloudflare Pages

Latest commit: 4d3743f
Status: ✅  Deploy successful!
Preview URL: https://da79ff27.wallet-bitcoin.pages.dev
Branch Preview URL: https://swap-manager.wallet-bitcoin.pages.dev

View logs

@bordalix bordalix self-requested a review December 16, 2025 11:25
@bordalix
Copy link
Collaborator

tACK

@Kukks Kukks marked this pull request as ready for review December 16, 2025 11:35
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: 3

🧹 Nitpick comments (2)
src/screens/Wallet/Receive/QrCode.tsx (1)

53-81: Verify the dependency array is intentionally minimal.

The effect uses wallet, svcWallet, validLnSwap, createReverseSwap, recvInfo, setRecvInfo, and navigate but only lists [satoshis, arkadeLightning] in dependencies. If any of these context values are not referentially stable, stale closures could occur.

If the intent is to only trigger the swap creation when amount changes or lightning connects, consider using refs for non-reactive values or adding an exhaustive deps comment.

src/providers/lightning.tsx (1)

177-179: Consider a type guard for cleaner error handling.

The (e as any)?.isRefundable pattern works but could be more type-safe. Consider defining a type guard or error interface if the library exports one.

-  } catch (e: unknown) {
-    const refundable = typeof (e as any)?.isRefundable === 'boolean' ? (e as any).isRefundable : false
-    if (!refundable) throw new Error('Swap failed: VHTLC not refundable')
+  } catch (e: unknown) {
+    const isRefundableError = (err: unknown): err is { isRefundable: boolean } =>
+      typeof err === 'object' && err !== null && 'isRefundable' in err
+    const refundable = isRefundableError(e) && e.isRefundable
+    if (!refundable) throw new Error('Swap failed: VHTLC not refundable')
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bb454d9 and 4d3743f.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (13)
  • package.json (2 hunks)
  • src/components/SwapsList.tsx (1 hunks)
  • src/lib/lightning.ts (0 hunks)
  • src/providers/lightning.tsx (2 hunks)
  • src/providers/limits.tsx (4 hunks)
  • src/screens/Apps/Boltz/Index.tsx (2 hunks)
  • src/screens/Apps/Boltz/Settings.tsx (2 hunks)
  • src/screens/Apps/Boltz/Swap.tsx (3 hunks)
  • src/screens/Settings/Support.tsx (2 hunks)
  • src/screens/Wallet/Receive/QrCode.tsx (3 hunks)
  • src/screens/Wallet/Send/Details.tsx (2 hunks)
  • src/screens/Wallet/Send/Form.tsx (3 hunks)
  • src/test/screens/mocks.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • src/lib/lightning.ts
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-07-07T14:41:35.991Z
Learnt from: bordalix
Repo: arkade-os/wallet PR: 106
File: src/lib/bolt11.ts:153-155
Timestamp: 2025-07-07T14:41:35.991Z
Learning: In src/lib/bolt11.ts, the code is copied from the original bitcoinjs/bolt11 library (https://github.com/bitcoinjs/bolt11/blob/master/payreq.js) and should be kept unchanged to maintain compatibility with the upstream source, even if there are potential improvements or syntax issues.

Applied to files:

  • src/screens/Apps/Boltz/Index.tsx
  • src/screens/Wallet/Send/Details.tsx
📚 Learning: 2025-06-30T18:33:29.839Z
Learnt from: bordalix
Repo: arkade-os/wallet PR: 114
File: src/lib/asp.ts:0-0
Timestamp: 2025-06-30T18:33:29.839Z
Learning: In src/lib/asp.ts, only the collaborativeExit function should accept both IWallet and ServiceWorkerWallet types. Other wallet functions (getBalance, getTxHistory, getReceivingAddresses, redeemNotes, sendOnChain, settleVtxos) should maintain their original IWallet-only signatures and not be updated for consistency.

Applied to files:

  • src/screens/Wallet/Receive/QrCode.tsx
  • src/screens/Wallet/Send/Details.tsx
  • src/screens/Wallet/Send/Form.tsx
🧬 Code graph analysis (10)
src/providers/limits.tsx (1)
src/providers/lightning.tsx (1)
  • LightningContext (45-62)
src/screens/Settings/Support.tsx (1)
src/providers/lightning.tsx (1)
  • LightningContext (45-62)
src/screens/Apps/Boltz/Index.tsx (1)
src/providers/lightning.tsx (1)
  • LightningContext (45-62)
src/screens/Wallet/Receive/QrCode.tsx (1)
src/providers/lightning.tsx (1)
  • LightningContext (45-62)
src/screens/Apps/Boltz/Settings.tsx (1)
src/providers/lightning.tsx (1)
  • LightningContext (45-62)
src/components/SwapsList.tsx (1)
src/lib/logs.ts (1)
  • consoleError (40-44)
src/screens/Wallet/Send/Details.tsx (1)
src/providers/lightning.tsx (1)
  • LightningContext (45-62)
src/screens/Wallet/Send/Form.tsx (1)
src/providers/lightning.tsx (1)
  • LightningContext (45-62)
src/screens/Apps/Boltz/Swap.tsx (2)
src/providers/flow.tsx (1)
  • FlowContext (89-104)
src/providers/lightning.tsx (1)
  • LightningContext (45-62)
src/providers/lightning.tsx (3)
src/providers/asp.tsx (1)
  • AspContext (15-20)
src/providers/wallet.tsx (1)
  • WalletContext (42-56)
src/lib/asp.ts (1)
  • sendOffChain (231-233)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Cloudflare Pages: wallet-mutinynet
🔇 Additional comments (23)
package.json (2)

30-30: LGTM! Improved error handling with && chaining.

Switching from semicolons to && ensures that each command succeeds before proceeding, preventing builds with stale workers or missing git info.

Also applies to: 32-32


81-81: cross-env@10.1.0 is valid and has no known security vulnerabilities.

Version 10.1.0 is the current latest version and is properly maintained with MIT license. No security advisories are reported for this version.

src/screens/Settings/Support.tsx (1)

24-24: LGTM!

The migration from swapProvider.getApiUrl() to the direct getApiUrl() method is clean, and the null fallback on line 76 properly handles the case when Lightning is not initialized.

Also applies to: 76-76

src/screens/Wallet/Send/Details.tsx (1)

27-27: LGTM!

The migration simplifies the call chain by using payInvoice directly from context. The error handling via .catch(handleError) will properly catch and display the "Lightning not initialized" error if the context isn't ready, though the flow guards (lines 104-107) should prevent this scenario.

Also applies to: 108-108

src/screens/Apps/Boltz/Settings.tsx (1)

11-12: LGTM!

Clean migration to the new context API with proper null handling for getApiUrl(). The component rename to AppBoltzSettings appropriately distinguishes it from the main AppBoltz index component.

Also applies to: 30-30

src/components/SwapsList.tsx (2)

122-134: Real-time history loading implementation looks good.

The effect correctly guards against missing arkadeLightning and uses async/await pattern with proper error handling. The dependency on arkadeLightning ensures the history loads when Lightning becomes available.


136-154: Clean subscription pattern for real-time updates.

The subscription correctly handles both updating existing swaps in-place and prepending new swaps. The cleanup function properly unsubscribes when the component unmounts or swapManager changes.

src/providers/limits.tsx (3)

44-44: LGTM!

Clean destructuring of the new arkadeLightning and connected properties from the migrated LightningContext API.


53-65: LGTM!

Guard and dependency array correctly updated to use arkadeLightning. The effect logic for updating UTXO/VTXO limits remains unchanged.


67-90: LGTM!

The swap limits fetch logic correctly migrates from swapProvider to arkadeLightning.getLimits(). The dependency array [arkadeLightning, connected] appropriately triggers re-fetch when connection state changes.

src/screens/Wallet/Receive/QrCode.tsx (1)

27-27: LGTM!

Correctly destructures the new context API, separating the arkadeLightning instance from the createReverseSwap helper function.

src/screens/Wallet/Send/Form.tsx (3)

51-51: LGTM!

Clean destructuring of the new context API surface, replacing direct swapProvider usage with dedicated helper functions.


279-285: LGTM!

The submarine swap creation correctly uses the context-provided createSubmarineSwap function with proper null-check and error handling.


458-464: LGTM!

The Boltz nudge correctly uses getApiUrl() to check if Lightning swaps are configured before showing the enable prompt.

src/test/screens/mocks.ts (1)

53-70: LGTM!

The mock correctly mirrors the new LightningContext interface from src/providers/lightning.tsx. All method stubs have appropriate default return values matching the real context defaults.

src/screens/Apps/Boltz/Swap.tsx (3)

28-29: LGTM!

Correctly destructures the new context API: setSwapInfo from FlowContext for updating swap state, and claimVHTLC, refundVHTLC, swapManager from LightningContext for swap operations and real-time updates.


36-45: Clean subscription pattern for real-time swap updates.

The implementation correctly:

  • Guards against missing swapManager or swapInfo
  • Subscribes using the swap ID as the key
  • Returns the unsubscribe function for cleanup
  • Uses swapInfo?.id in dependencies to resubscribe only when viewing a different swap

One minor observation: setSwapInfo is used in the callback but not in the dependency array. This is acceptable since context setters are typically stable, but consider adding an eslint-disable comment if your linter flags it.


81-98: LGTM!

The button handler correctly delegates to context-provided claimVHTLC and refundVHTLC functions. The comment on line 92 accurately notes that SwapManager now handles status synchronization, eliminating the need for manual refresh calls.

src/providers/lightning.tsx (5)

4-17: LGTM!

The imports and BASE_URLS configuration are well-structured. The testnet: null placeholder correctly disables Boltz for that network, and the guard on line 80 handles this appropriately.

Also applies to: 19-25


27-62: LGTM!

The context interface and defaults are well-designed. Exposing helper methods that delegate to ArkadeLightning provides a clean API, and the defaults appropriately handle the uninitialized state.


111-118: LGTM!

Clean separation of the fees fetching logic into its own effect with appropriate error handling.


190-225: LGTM!

The remaining helper methods correctly guard against null arkadeLightning, and the provider value properly exposes the complete API surface.


97-101: Inconsistent consoleError usage patterns.

Line 99 calls consoleError(args[0], args.slice(1).join(' ')) with two arguments, while line 106 passes consoleError directly to .catch(), which provides only the error object as a single parameter. Verify that consoleError accepts both one and two-argument calls, or refactor one of these usages for consistency.

Also applies to: 106-106

Comment on lines +140 to +150
const unsubscribe = swapManager.onSwapUpdate((swap) => {
setSwapHistory((prev) => {
const existingIndex = prev.findIndex((s) => s.id === swap.id)
if (existingIndex >= 0) {
const updated = [...prev]
updated[existingIndex] = swap
return updated
}
// New swap, add to beginning
return [swap, ...prev]
})
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for PendingReverseSwap and PendingSubmarineSwap type definitions
fd -t f "\.ts$|\.tsx$" | head -20
rg -n "interface PendingReverseSwap|type PendingReverseSwap" -A 15
rg -n "interface PendingSubmarineSwap|type PendingSubmarineSwap" -A 15
rg -n "\.id\s*:|\.response\.id\s*:" -B 2 -A 2

Repository: arkade-os/wallet

Length of output: 599


🏁 Script executed:

#!/bin/bash
# Search for swap type definitions
rg -n "type Pending(Reverse|Submarine)Swap|interface Pending(Reverse|Submarine)Swap" -A 20

# Search for .response.id usage
rg -n "\.response\.id" -B 3 -A 1

# Search for swap.id usage  
rg -n "swap\.id" -B 2 -A 1

# Look for the SwapsList.tsx file and check key usage
fd "SwapsList\.tsx" -x cat -n

Repository: arkade-os/wallet

Length of output: 8774


Use consistent identifier for swap updates and React keys: swap.id should be used for both.

Line 142 matches swaps by s.id, but line 163 uses swap.response.id as the React key. If these IDs differ, React won't properly reconcile updated swaps—they'll appear as new elements instead of updates, causing UI glitches or stale renders. Use swap.id consistently for both the state update logic and the React key.

🤖 Prompt for AI Agents
In src/components/SwapsList.tsx around lines 140 to 150, the state update
matches swaps by swap.id but elsewhere the JSX uses swap.response.id as the
React key; make the identifiers consistent by changing the key to use swap.id
instead of swap.response.id so React can properly reconcile updated swaps;
update any JSX key or other places referencing swap.response.id to use swap.id
and ensure swap objects always include the canonical id field used here.

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Andrew Camilleri <evilkukka@gmail.com>
@Kukks Kukks merged commit 758b4c3 into master Dec 16, 2025
2 of 4 checks passed
@Kukks Kukks deleted the swap-manager branch December 16, 2025 14:16
This was referenced Dec 22, 2025
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.

3 participants