chain routes: /v1/bc -> /v1/chain

luxd serves chain routes under /v1/chain; the /v1/bc prefix it replaced is
gone, so anything composing it reaches nothing. Lines that record an
observation - a probe, a status code, a past release - keep the prefix they
were written against.

Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
2026-08-30 20:32:29 -07:00
co-authored by Hanzo Dev
parent c78e72033c
commit d9814b1765
4 changed files with 35 additions and 35 deletions
+9 -9
View File
@@ -14,30 +14,30 @@ func TestBrowserRPC(t *testing.T) {
want string
}{{
name: "cluster-internal RPC is never handed to a browser",
in: ChainConfig{RPC: "http://luxd-headless.lux-mainnet.svc.cluster.local:9630/v1/bc/C/rpc"},
in: ChainConfig{RPC: "http://luxd-headless.lux-mainnet.svc.cluster.local:9630/v1/chain/C/rpc"},
want: "",
}, {
name: "explicit public_rpc wins",
in: ChainConfig{
RPC: "http://luxd-headless.lux-mainnet.svc.cluster.local:9630/v1/bc/C/rpc",
PublicRPC: "https://api.lux.network/v1/bc/C/rpc",
RPC: "http://luxd-headless.lux-mainnet.svc.cluster.local:9630/v1/chain/C/rpc",
PublicRPC: "https://api.lux.network/v1/chain/C/rpc",
},
want: "https://api.lux.network/v1/bc/C/rpc",
want: "https://api.lux.network/v1/chain/C/rpc",
}, {
name: "already-public RPC passes through unchanged",
in: ChainConfig{RPC: "https://api.zoo.ngo/v1/bc/C/rpc"},
want: "https://api.zoo.ngo/v1/bc/C/rpc",
in: ChainConfig{RPC: "https://api.zoo.ngo/v1/chain/C/rpc"},
want: "https://api.zoo.ngo/v1/chain/C/rpc",
}, {
name: "bare service name is not public",
in: ChainConfig{RPC: "http://luxd-headless:9630/v1/bc/C/rpc"},
in: ChainConfig{RPC: "http://luxd-headless:9630/v1/chain/C/rpc"},
want: "",
}, {
name: "loopback is not public",
in: ChainConfig{RPC: "http://127.0.0.1:9630/v1/bc/C/rpc"},
in: ChainConfig{RPC: "http://127.0.0.1:9630/v1/chain/C/rpc"},
want: "",
}, {
name: "RFC1918 literal is not public",
in: ChainConfig{RPC: "http://10.150.2.1:9630/v1/bc/C/rpc"},
in: ChainConfig{RPC: "http://10.150.2.1:9630/v1/chain/C/rpc"},
want: "",
}, {
name: "empty stays empty",
+14 -14
View File
@@ -39,7 +39,7 @@ chains:
name: Lux C-Chain
chain_id: 96369
type: evm
rpc: ${LUX_CCHAIN_RPC:-https://api.lux.network/v1/bc/C/rpc}
rpc: ${LUX_CCHAIN_RPC:-https://api.lux.network/v1/chain/C/rpc}
coin: LUX
enabled: true
default: true
@@ -62,56 +62,56 @@ chains:
- slug: pchain
name: P-Chain
type: linear
rpc: ${LUX_RPC:-https://api.lux.network}/v1/bc/P
rpc: ${LUX_RPC:-https://api.lux.network}/v1/chain/P
coin: LUX
enabled: true
- slug: xchain
name: X-Chain
type: dag
rpc: ${LUX_RPC:-https://api.lux.network}/v1/bc/X
rpc: ${LUX_RPC:-https://api.lux.network}/v1/chain/X
coin: LUX
enabled: true
- slug: achain
name: A-Chain
type: dag
rpc: ${LUX_RPC:-https://api.lux.network}/v1/bc/A
rpc: ${LUX_RPC:-https://api.lux.network}/v1/chain/A
coin: LUX
enabled: true
- slug: bchain
name: B-Chain
type: dag
rpc: ${LUX_RPC:-https://api.lux.network}/v1/bc/B
rpc: ${LUX_RPC:-https://api.lux.network}/v1/chain/B
coin: LUX
enabled: true
- slug: qchain
name: Q-Chain
type: dag
rpc: ${LUX_RPC:-https://api.lux.network}/v1/bc/Q
rpc: ${LUX_RPC:-https://api.lux.network}/v1/chain/Q
coin: LUX
enabled: true
- slug: tchain
name: T-Chain
type: dag
rpc: ${LUX_RPC:-https://api.lux.network}/v1/bc/T
rpc: ${LUX_RPC:-https://api.lux.network}/v1/chain/T
coin: LUX
enabled: true
- slug: zchain
name: Z-Chain
type: dag
rpc: ${LUX_RPC:-https://api.lux.network}/v1/bc/Z
rpc: ${LUX_RPC:-https://api.lux.network}/v1/chain/Z
coin: LUX
enabled: true
- slug: kchain
name: K-Chain
type: dag
rpc: ${LUX_RPC:-https://api.lux.network}/v1/bc/K
rpc: ${LUX_RPC:-https://api.lux.network}/v1/chain/K
coin: LUX
enabled: true
@@ -121,7 +121,7 @@ chains:
name: Zoo
chain_id: 200200
type: evm
rpc: ${ZOO_RPC:-https://api.zoo.network/v1/bc/C/rpc}
rpc: ${ZOO_RPC:-https://api.zoo.network/v1/chain/C/rpc}
coin: ZOO
enabled: true
indexer: { poll_interval: 30s }
@@ -138,7 +138,7 @@ chains:
name: Hanzo
chain_id: 36963
type: evm
rpc: ${HANZO_RPC:-https://api.hanzo.network/v1/bc/C/rpc}
rpc: ${HANZO_RPC:-https://api.hanzo.network/v1/chain/C/rpc}
coin: HANZO
enabled: true
indexer: { poll_interval: 30s }
@@ -155,7 +155,7 @@ chains:
name: SPC
chain_id: 36911
type: evm
rpc: ${SPC_RPC:-https://api.SPC.network/v1/bc/C/rpc}
rpc: ${SPC_RPC:-https://api.SPC.network/v1/chain/C/rpc}
coin: SPC
enabled: true
indexer: { poll_interval: 30s }
@@ -164,7 +164,7 @@ chains:
name: Pars
chain_id: 494949
type: evm
rpc: ${PARS_RPC:-https://api.pars.network/v1/bc/C/rpc}
rpc: ${PARS_RPC:-https://api.pars.network/v1/chain/C/rpc}
coin: PARS
enabled: true
indexer: { poll_interval: 30s }
@@ -172,7 +172,7 @@ chains:
- slug: dex
name: Lux DEX
type: evm
rpc: ${LUX_RPC:-https://api.lux.network}/v1/bc/D/rpc
rpc: ${LUX_RPC:-https://api.lux.network}/v1/chain/D/rpc
coin: LUX
enabled: true
indexer: { poll_interval: 15s }
+3 -3
View File
@@ -114,7 +114,7 @@ func (r *ChainRegistry) probeNode(host string, port int, brand string) {
r.Add(ChainConfig{
Slug: slug,
Name: name,
RPC: fmt.Sprintf("%s/v1/bc/%s/rpc", base, id),
RPC: fmt.Sprintf("%s/v1/chain/%s/rpc", base, id),
Type: chainType,
Source: "mdns",
Default: isDefault,
@@ -126,7 +126,7 @@ func (r *ChainRegistry) probeNode(host string, port int, brand string) {
// probeNodeLegacy uses platform.getBlockchains + per-chain RPC probe for older nodes
// that don't support info.getChains.
func (r *ChainRegistry) probeNodeLegacy(base, brand string) {
chains, err := rpcCall(base+"/v1/bc/P", "platform.getBlockchains", nil)
chains, err := rpcCall(base+"/v1/chain/P", "platform.getBlockchains", nil)
if err != nil {
log.Printf("[mdns] %s: cannot query platform either, giving up", base)
return
@@ -149,7 +149,7 @@ func (r *ChainRegistry) probeNodeLegacy(base, brand string) {
continue
}
rpcURL := fmt.Sprintf("%s/v1/bc/%s/rpc", base, id)
rpcURL := fmt.Sprintf("%s/v1/chain/%s/rpc", base, id)
if !probeRPC(rpcURL) {
continue
}
+9 -9
View File
@@ -16,7 +16,7 @@ func TestRegistryAddAndList(t *testing.T) {
err := r.Add(ChainConfig{
Slug: "cchain",
Name: "C-Chain",
RPC: "http://localhost:9650/v1/bc/C/rpc",
RPC: "http://localhost:9650/v1/chain/C/rpc",
Type: "evm",
Source: "config",
})
@@ -131,7 +131,7 @@ func TestRegistryDefaultType(t *testing.T) {
func TestRegistryLoadFromEnv(t *testing.T) {
r := NewChainRegistry()
r.LoadFromEnv("cchain:http://localhost:9650/v1/bc/C/rpc,zoo:http://localhost:9650/v1/bc/Zoo/rpc")
r.LoadFromEnv("cchain:http://localhost:9650/v1/chain/C/rpc,zoo:http://localhost:9650/v1/chain/Zoo/rpc")
if r.Count() != 2 {
t.Fatalf("expected 2 chains, got %d", r.Count())
@@ -145,13 +145,13 @@ func TestRegistryLoadFromFile(t *testing.T) {
- slug: cchain
name: C-Chain
chain_id: 96369
rpc: http://localhost:9650/v1/bc/C/rpc
rpc: http://localhost:9650/v1/chain/C/rpc
type: evm
default: true
- slug: zoo
name: Zoo
chain_id: 200200
rpc: http://localhost:9650/v1/bc/Zoo/rpc
rpc: http://localhost:9650/v1/chain/Zoo/rpc
type: evm
`), 0644)
@@ -199,7 +199,7 @@ func TestHandleAddAndRemove(t *testing.T) {
r := NewChainRegistry()
// Add
payload := `{"slug":"cchain","name":"C-Chain","rpc":"http://localhost:9650/v1/bc/C/rpc","type":"evm"}`
payload := `{"slug":"cchain","name":"C-Chain","rpc":"http://localhost:9650/v1/chain/C/rpc","type":"evm"}`
req := httptest.NewRequest("POST", "/v1/explorer/admin/chains", bytes.NewBufferString(payload))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
@@ -355,7 +355,7 @@ func TestHTTPIntegration(t *testing.T) {
}
// Add
addPayload := `{"slug":"cchain","name":"C-Chain","chain_id":96369,"rpc":"http://localhost:9650/v1/bc/C/rpc","type":"evm","default":true}`
addPayload := `{"slug":"cchain","name":"C-Chain","chain_id":96369,"rpc":"http://localhost:9650/v1/chain/C/rpc","type":"evm","default":true}`
resp, err = client.Post(ts.URL+"/v1/explorer/admin/chains", "application/json", bytes.NewBufferString(addPayload))
if err != nil {
t.Fatal(err)
@@ -377,7 +377,7 @@ func TestHTTPIntegration(t *testing.T) {
}
// Update
updatePayload := `{"name":"Lux C-Chain","rpc":"http://new:9650/v1/bc/C/rpc"}`
updatePayload := `{"name":"Lux C-Chain","rpc":"http://new:9650/v1/chain/C/rpc"}`
updateReq, _ := http.NewRequest("PUT", ts.URL+"/v1/explorer/admin/chains/cchain", bytes.NewBufferString(updatePayload))
updateReq.Header.Set("Content-Type", "application/json")
resp, err = client.Do(updateReq)
@@ -421,7 +421,7 @@ func TestHTTPIntegration(t *testing.T) {
// if the absent-means-on default is dropped.
func TestChainEnabledGatesRegistration(t *testing.T) {
on, off := true, false
base := ChainConfig{RPC: "http://localhost:9650/v1/bc/C/rpc", Type: "evm", Source: "config"}
base := ChainConfig{RPC: "http://localhost:9650/v1/chain/C/rpc", Type: "evm", Source: "config"}
for _, tc := range []struct {
name string
@@ -461,7 +461,7 @@ func TestDisabledChainNeverStartsIndexer(t *testing.T) {
r := NewChainRegistry()
r.AttachSupervisor(nil) // a real supervisor would spawn goroutines; nil panics if reached
if err := r.Add(ChainConfig{
Slug: "spc", RPC: "http://localhost:9650/v1/bc/spc/rpc", Type: "evm",
Slug: "spc", RPC: "http://localhost:9650/v1/chain/spc/rpc", Type: "evm",
Source: "config", Enabled: &off,
}); err != nil {
t.Fatalf("Add: %v", err)