Skip to content

feat: add chain data source and address to about page#2013

Merged
im-adithya merged 6 commits intogetAlby:masterfrom
Dunsin-cyber:feat/show-ldk-chainSource
Apr 6, 2026
Merged

feat: add chain data source and address to about page#2013
im-adithya merged 6 commits intogetAlby:masterfrom
Dunsin-cyber:feat/show-ldk-chainSource

Conversation

@Dunsin-cyber
Copy link
Copy Markdown
Contributor

@Dunsin-cyber Dunsin-cyber commented Jan 12, 2026

I noticed #1948 has been open for a while so I decided to take a crack at it.

  • Added GetChainDataSource helper to detect LDK verification medium
  • Exposed chainDataSourceType and chainDataSourceAddress in /api/info
  • Updated About settings page to display these details for LDK nodes
03 04

Summary by CodeRabbit

  • New Features
    • Settings/About now shows Chain Data Source details (provider type).
    • When available, the provider address is displayed beneath the type.
    • Backend responses include chain data source fields so the UI can surface them; displayed addresses are normalized for consistent presentation.

Copy link
Copy Markdown
Contributor

@frnandu frnandu left a comment

Choose a reason for hiding this comment

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

Hi, thanks for your PR, please resolve conflicts with master and address the feedback.

Comment thread api/api.go Outdated
Comment thread lnclient/ldk/ldk.go Outdated
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 16, 2026

📝 Walkthrough

Walkthrough

Enriches the API InfoResponse with chain data source fields, populates them for LDK backends via a new LDKService.GetChainDataSource(), and surfaces the values to frontend types and the About UI when present.

Changes

Cohort / File(s) Summary
API model
api/models.go
Added ChainDataSourceType and ChainDataSourceAddress to InfoResponse with JSON omitempty tags.
API handler
api/api.go
When backend is LDKBackendType, type-asserts the LN client for GetChainDataSource() and populates new chain data source fields in GetInfo.
LDK client
lnclient/ldk/ldk.go
Added (*LDKService).GetChainDataSource() (string, string) and sanitizeChainEndpoint(...); changed bitcoind identifier from bitcoind_rpcbitcoind.
LDK tests
lnclient/ldk/ldk_test.go
Added tests for sanitizeChainEndpoint covering bitcoind RPC and URL-style inputs (credential stripping, port defaulting, IPv6 handling).
Frontend types
frontend/src/types.ts
Added optional chainDataSourceType? and chainDataSourceAddress? to InfoResponse TypeScript interface.
Frontend UI
frontend/src/screens/settings/About.tsx
Added conditional rendering to display Chain Data Source type and optional address when present in info.

Sequence Diagram(s)

sequenceDiagram
  participant Frontend
  participant API
  participant LDKService
  participant Config

  Frontend->>API: GET /info
  API->>LDKService: svc.GetLNClient() -> type assert chainSourceProvider
  alt LN client supports chain source
    API->>LDKService: GetChainDataSource()
    LDKService->>Config: read env/config (bitcoind/electrum/esplora)
    Config-->>LDKService: source type + endpoint
    LDKService-->>API: sanitized type + address
  end
  API-->>Frontend: InfoResponse (includes chainDataSourceType/address)
  Frontend->>Frontend: render About UI with chain data source
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I sniffed the chain source by moonlit hair,
bitcoind, electrum, or esplora fair,
The service hums, the endpoint shines bright,
The UI hops forward to show it in light. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ 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 clearly describes the main change: exposing chain data source information on the about page for LDK nodes.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

Copy link
Copy Markdown
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.

♻️ Duplicate comments (2)
api/api.go (1)

1326-1328: ⚠️ Potential issue | 🟠 Major

Do not expose internal LND address in /api/info.

Publishing LNDAddress leaks internal node endpoint details and should be omitted from public info responses.

🔧 Proposed fix
 		switch backendType {
 		case config.LDKBackendType:
 			// Only LDK supports this right now. Using a local interface here
@@
 			if ldkService, ok := api.svc.GetLNClient().(chainSourceProvider); ok {
 				info.ChainDataSourceType, info.ChainDataSourceAddress = ldkService.GetChainDataSource()
 			}
-
-		case config.LNDBackendType:
-			info.ChainDataSourceType = "lnd"
-			info.ChainDataSourceAddress, _ = api.cfg.Get("LNDAddress", "")
 		}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/api.go` around lines 1326 - 1328, The code sets
info.ChainDataSourceAddress from the internal LNDAddress when handling
config.LNDBackendType; remove that exposure by not reading or assigning
api.cfg.Get("LNDAddress", "") to info.ChainDataSourceAddress in the LND branch
(leave it empty or masked instead), so the /api/info response no longer leaks
internal node endpoint details; update any tests or callers that assume this
field is populated for LND to expect empty/masked value.
lnclient/ldk/ldk.go (1)

2469-2480: ⚠️ Potential issue | 🟠 Major

Redact chain-source address secrets and return complete bitcoind endpoint.

This method can leak credentials if a URL contains userinfo, and the bitcoind branch currently drops the RPC port (incomplete address).

🔧 Proposed fix
+import "net/url"
+
+func sanitizeAddress(raw string) string {
+	u, err := url.Parse(raw)
+	if err != nil || u.Host == "" {
+		return raw
+	}
+	u.User = nil
+	return u.String()
+}
+
 func (ls *LDKService) GetChainDataSource() (string, string) {
 	if host := ls.cfg.GetEnv().LDKBitcoindRpcHost; host != "" {
-		return "bitcoind", host
+		port := ls.cfg.GetEnv().LDKBitcoindRpcPort
+		if port != "" {
+			return "bitcoind", host + ":" + port
+		}
+		return "bitcoind", host
 	}
 	if host := ls.cfg.GetEnv().LDKElectrumServer; host != "" {
-		return "electrum", host
+		return "electrum", sanitizeAddress(host)
 	}
 
 	// Fallback to Esplora
 	host := ls.cfg.GetEnv().LDKEsploraServer
-	return "esplora", host
+	return "esplora", sanitizeAddress(host)
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lnclient/ldk/ldk.go` around lines 2469 - 2480, GetChainDataSource currently
can leak credentials from userinfo in URLs and returns an incomplete bitcoind
address; fix by parsing the configured endpoints
(ls.cfg.GetEnv().LDKBitcoindRpcHost, LDKElectrumServer, LDKEsploraServer) as
URLs, strip any URL.User (redact username/password) before returning, and for
the bitcoind branch ensure the returned host includes an explicit host:port (use
the URL's port if present, otherwise append a sensible RPC port from config or a
default such as 8332) so the returned tuple is "bitcoind" plus a complete,
credential-free endpoint; update GetChainDataSource to perform parsing, userinfo
removal, and port normalization for all branches.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@api/api.go`:
- Around line 1326-1328: The code sets info.ChainDataSourceAddress from the
internal LNDAddress when handling config.LNDBackendType; remove that exposure by
not reading or assigning api.cfg.Get("LNDAddress", "") to
info.ChainDataSourceAddress in the LND branch (leave it empty or masked
instead), so the /api/info response no longer leaks internal node endpoint
details; update any tests or callers that assume this field is populated for LND
to expect empty/masked value.

In `@lnclient/ldk/ldk.go`:
- Around line 2469-2480: GetChainDataSource currently can leak credentials from
userinfo in URLs and returns an incomplete bitcoind address; fix by parsing the
configured endpoints (ls.cfg.GetEnv().LDKBitcoindRpcHost, LDKElectrumServer,
LDKEsploraServer) as URLs, strip any URL.User (redact username/password) before
returning, and for the bitcoind branch ensure the returned host includes an
explicit host:port (use the URL's port if present, otherwise append a sensible
RPC port from config or a default such as 8332) so the returned tuple is
"bitcoind" plus a complete, credential-free endpoint; update GetChainDataSource
to perform parsing, userinfo removal, and port normalization for all branches.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 437e44b6-3f94-4f2c-b50f-4315277255d0

📥 Commits

Reviewing files that changed from the base of the PR and between e963d6a and f2e3283.

📒 Files selected for processing (5)
  • api/api.go
  • api/models.go
  • frontend/src/screens/settings/About.tsx
  • frontend/src/types.ts
  • lnclient/ldk/ldk.go

Comment thread lnclient/ldk/ldk.go
}
}

func (ls *LDKService) GetChainDataSource() (string, string) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Instead of adding an LDK only method, can we return this in lnclient.NodeInfo optionally (*string) cc @rolznz, wdyt?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this is slightly different type of data, it's more internal configuration - do apps need to know about it? (a bit different than the network or alias for example)

@frnandu
Copy link
Copy Markdown
Contributor

frnandu commented Apr 2, 2026

ACK

@rolznz
Copy link
Copy Markdown
Member

rolznz commented Apr 3, 2026

@frnandu do you see any possibility of this being used by LND or CLN? otherwise I wonder if this should be a custom node command in LDK only.

@frnandu
Copy link
Copy Markdown
Contributor

frnandu commented Apr 3, 2026

I think this is mainly for LDK, so that later we can also give an option to change this to the user's self-hosted onchain esplora/electrum/bitcoind which is something that most wallets also provide and IMO quite an important and necessary feature for serious wallets.
In LND and CLN cases the user itself can configure this on his own there.

Copy link
Copy Markdown
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.

🧹 Nitpick comments (1)
lnclient/ldk/ldk.go (1)

2485-2517: Credentials properly stripped; consider edge case fallback.

The implementation correctly addresses the prior review feedback by setting u.User = nil to strip credentials. The URL parsing with "//" prefix fallback and net.JoinHostPort for IPv6 are well-handled.

One minor edge case: if both url.Parse(endpoint) and url.Parse("//" + endpoint) fail to produce a valid host (lines 2486-2492), the function returns the original endpoint unchanged. For truly malformed but credential-containing inputs, this could theoretically leak credentials. However, this is a defensive fallback for unlikely inputs.

Optional: Return empty string or error indicator for unparseable endpoints
 func sanitizeChainEndpoint(endpoint string, port string) string {
 	u, err := url.Parse(endpoint)
 	if err != nil || u.Host == "" {
 		u, err = url.Parse("//" + endpoint)
 	}
 	if err != nil {
-		return endpoint
+		return ""
 	}

 	u.User = nil
 	host := u.Hostname()
 	if host == "" {
-		return endpoint
+		return ""
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lnclient/ldk/ldk.go` around lines 2485 - 2517, sanitizeChainEndpoint
currently returns the original endpoint if URL parsing fails or no host is
found, which can leak credentials; update sanitizeChainEndpoint so that when
both url.Parse(endpoint) and url.Parse("//"+endpoint) fail or host is empty it
does not return the raw input but instead returns a safe fallback (e.g., empty
string or a clearly sanitized indicator) or strip credentials manually before
returning; locate and modify the error/host-fallback branch inside
sanitizeChainEndpoint (around the url.Parse handling and the host=="" check) to
ensure no userinfo from the original endpoint can be returned.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@lnclient/ldk/ldk.go`:
- Around line 2485-2517: sanitizeChainEndpoint currently returns the original
endpoint if URL parsing fails or no host is found, which can leak credentials;
update sanitizeChainEndpoint so that when both url.Parse(endpoint) and
url.Parse("//"+endpoint) fail or host is empty it does not return the raw input
but instead returns a safe fallback (e.g., empty string or a clearly sanitized
indicator) or strip credentials manually before returning; locate and modify the
error/host-fallback branch inside sanitizeChainEndpoint (around the url.Parse
handling and the host=="" check) to ensure no userinfo from the original
endpoint can be returned.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 02d9cfce-be2e-42a6-8765-b39b6276390a

📥 Commits

Reviewing files that changed from the base of the PR and between 47decd8 and ecd19d7.

📒 Files selected for processing (3)
  • frontend/src/screens/settings/About.tsx
  • lnclient/ldk/ldk.go
  • lnclient/ldk/ldk_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/screens/settings/About.tsx

@im-adithya im-adithya merged commit e157c28 into getAlby:master Apr 6, 2026
7 of 11 checks passed
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