1- const ASSET_BUNDLE_REGISTRY = 'https://asset-bundle-registry.decentraland.org'
21const WORLDS_CONTENT_SERVER = 'https://worlds-content-server.decentraland.org'
32
43export interface WorldInfo {
@@ -15,6 +14,12 @@ export interface WorldInfo {
1514 banSceneId : string | null // Scene ID at ban time (for detecting redeploys)
1615}
1716
17+ interface WorldAboutResponse {
18+ configurations ?: {
19+ scenesUrn ?: string [ ]
20+ }
21+ }
22+
1823interface WorldEntity {
1924 id : string
2025 type : string
@@ -36,49 +41,60 @@ interface WorldEntity {
3641}
3742
3843/**
39- * Fetch world info from asset-bundle-registry
44+ * Fetch world info from worlds-content-server via /about endpoint
4045 */
4146export async function fetchWorldInfo ( worldName : string ) : Promise < WorldInfo > {
4247 let normalizedName = worldName . trim ( ) . toLowerCase ( )
4348
44- // Append .dcl.eth if not already present
4549 if ( ! normalizedName . endsWith ( '.dcl.eth' ) && ! normalizedName . endsWith ( '.eth' ) ) {
4650 normalizedName = `${ normalizedName } .dcl.eth`
4751 }
4852
49- const response = await fetch ( `${ ASSET_BUNDLE_REGISTRY } /entities/active` , {
50- method : 'POST' ,
51- headers : { 'Content-Type' : 'application/json' } ,
52- body : JSON . stringify ( { pointers : [ normalizedName ] } )
53- } )
53+ const aboutResponse = await fetch (
54+ `${ WORLDS_CONTENT_SERVER } /world/${ normalizedName } /about`
55+ )
5456
55- if ( ! response . ok ) {
56- throw new Error ( `Failed to fetch world info: ${ response . status } ` )
57+ if ( ! aboutResponse . ok ) {
58+ throw new Error ( `World " ${ normalizedName } " not found ` )
5759 }
5860
59- const entities : WorldEntity [ ] = await response . json ( )
60- const entity = entities [ 0 ]
61+ const aboutData : WorldAboutResponse = await aboutResponse . json ( )
62+ const scenesUrn = aboutData . configurations ?. scenesUrn
6163
62- if ( ! entity ) {
64+ if ( ! scenesUrn || scenesUrn . length === 0 ) {
6365 throw new Error ( `World "${ normalizedName } " not found` )
6466 }
6567
68+ const urn = scenesUrn [ 0 ]
69+ const hashMatch = urn . match ( / u r n : d e c e n t r a l a n d : e n t i t y : ( [ ^ ? ] + ) / )
70+ if ( ! hashMatch ) {
71+ throw new Error ( `Invalid scene URN format for "${ normalizedName } "` )
72+ }
73+ const entityHash = hashMatch [ 1 ]
74+
75+ const entityResponse = await fetch (
76+ `${ WORLDS_CONTENT_SERVER } /contents/${ entityHash } `
77+ )
78+
79+ if ( ! entityResponse . ok ) {
80+ throw new Error ( `Failed to fetch entity for "${ normalizedName } ": ${ entityResponse . status } ` )
81+ }
82+
83+ const entity : WorldEntity = await entityResponse . json ( )
84+
6685 const metadata = entity . metadata
6786 const title = metadata ?. display ?. title || metadata ?. worldConfiguration ?. name || normalizedName
6887 const description = metadata ?. display ?. description || null
6988 const owner = metadata ?. owner || null
7089 const tags = metadata ?. tags || [ ]
7190
72- // Build thumbnail URL if available
73- let thumbnail : string | null = null
74- if ( metadata ?. display ?. navmapThumbnail ) {
75- const thumbnailHash = entity . content ?. find (
76- c => c . file === metadata . display ?. navmapThumbnail
77- ) ?. hash
78- if ( thumbnailHash ) {
79- thumbnail = `${ WORLDS_CONTENT_SERVER } /contents/${ thumbnailHash } `
80- }
81- }
91+ const thumbnailFile = metadata ?. display ?. navmapThumbnail
92+ const thumbnailHash = thumbnailFile
93+ ? entity . content ?. find ( c => c . file === thumbnailFile ) ?. hash
94+ : undefined
95+ const thumbnail = thumbnailHash
96+ ? `${ WORLDS_CONTENT_SERVER } /contents/${ thumbnailHash } `
97+ : null
8298
8399 return {
84100 name : normalizedName ,
@@ -87,7 +103,7 @@ export async function fetchWorldInfo(worldName: string): Promise<WorldInfo> {
87103 thumbnail,
88104 owner,
89105 tags,
90- sceneId : entity . id ,
106+ sceneId : entityHash ,
91107 isBanned : false , // Will be updated by caller with local ban state
92108 banId : null ,
93109 banReason : null ,
0 commit comments