• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

decentraland / realm-provider / 16318543255

16 Jul 2025 11:44AM UTC coverage: 39.12% (+22.7%) from 16.438%
16318543255

Pull #74

github

pentreathm
fix: tests feedback
Pull Request #74: feat: filter out outdated nodes and implement regional affinity

47 of 87 branches covered (54.02%)

Branch coverage included in aggregate %.

82 of 84 new or added lines in 5 files covered. (97.62%)

1 existing line in 1 file now uncovered.

113 of 322 relevant lines covered (35.09%)

16.83 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.16
/src/logic/geolocation.ts
1
import { COUNTRY_CENTROIDS } from './country-centroids'
3✔
2
import { CATALYST_NODES } from './catalyst-nodes-regions'
3✔
3
import { randomInt } from 'crypto'
3✔
4
import { RealmInfo } from '../types'
5

6
/**
7
 * Get the centroid [lat, lon] for a country code. Returns undefined if not found.
8
 */
9
export function getCountryCentroid(countryCode: string): [number, number] | undefined {
3✔
10
  return COUNTRY_CENTROIDS[countryCode.toUpperCase()]
63✔
11
}
12

13
/**
14
 * Calculate the Haversine distance (in km) between two lat/lon points.
15
 */
16
export function haversineDistance(lat1: number, lon1: number, lat2: number, lon2: number): number {
3✔
17
  function toRad(deg: number): number {
18
    return (deg * Math.PI) / 180
172✔
19
  }
20
  const R = 6371 // Earth radius in km
43✔
21
  const dLat = toRad(lat2 - lat1)
43✔
22
  const dLon = toRad(lon2 - lon1)
43✔
23
  const a =
24
    Math.sin(dLat / 2) * Math.sin(dLat / 2) +
43✔
25
    Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * Math.sin(dLon / 2) * Math.sin(dLon / 2)
26
  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
43✔
27
  return R * c
43✔
28
}
29

30
/**
31
 * Find the country code for a catalyst URL by matching against known nodes.
32
 */
33
export function getCountryForCatalystUrl(url: string): string | undefined {
3✔
34
  const normalizedUrl = url.replace(/^https?:\/\//, '').replace(/\/$/, '')
57✔
35
  const node = CATALYST_NODES.find((n) => n.url === normalizedUrl)
311✔
36
  return node?.country
57✔
37
}
38

39
/**
40
 * Given a request country code and a list of catalyst objects (each with a url),
41
 * return the index of the closest node.
42
 * If there are multiple nodes at the same minimum distance, pick one at random.
43
 * If no nodes have known countries, return the a random node as fallback.
44
 */
45
export function findClosestNode(requestCountry: string, catalysts: RealmInfo[]): number {
3✔
46
  if (catalysts.length === 0) return 0 // fallback: first node (though array is empty)
18✔
47

48
  const reqCentroid = getCountryCentroid(requestCountry)
17✔
49
  if (!reqCentroid) return randomInt(catalysts.length) // fallback: random node
17✔
50

51
  let minDist = Infinity
15✔
52
  let minIndices: number[] = []
15✔
53
  let hasKnownCountries = false
15✔
54

55
  catalysts.forEach((catalyst, idx) => {
15✔
56
    const country = getCountryForCatalystUrl(catalyst.url)
54✔
57
    if (!country) return // skip if country not found
54✔
58
    const nodeCentroid = getCountryCentroid(country)
40✔
59
    if (!nodeCentroid) return
40!
60

61
    hasKnownCountries = true
40✔
62
    const dist = haversineDistance(reqCentroid[0], reqCentroid[1], nodeCentroid[0], nodeCentroid[1])
40✔
63
    if (dist < minDist) {
40✔
64
      minDist = dist
23✔
65
      minIndices = [idx]
23✔
66
    } else if (dist === minDist) {
17!
NEW
67
      minIndices.push(idx)
×
68
    }
69
  })
70

71
  // If no catalysts have known countries, return random node
72
  if (!hasKnownCountries || minIndices.length === 0) {
15✔
73
    return randomInt(catalysts.length)
2✔
74
  }
75

76
  if (minIndices.length === 1) return minIndices[0]
13✔
77
  // Randomly select among ties using crypto.randomInt
NEW
78
  return minIndices[randomInt(minIndices.length)]
×
79
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc