Android Compatibility Contract
March 9, 2026 ยท View on GitHub
This document defines the cross-language contract for Android/Kotlin integrations that implement geohash-kit behavior without importing this TypeScript package directly.
Goal
- Keep TS and Kotlin implementations aligned for core geohash and Nostr helper outputs.
- Use checked test vectors as the source of truth for parity.
Contract Sources
- Vector schema:
vectors/schema.json - Versioned vectors:
vectors/core.encode.v1.jsonvectors/core.decode.v1.jsonvectors/core.neighbours.v1.jsonvectors/nostr.createGTagLadder.v1.jsonvectors/nostr.nearbyFilter.v1.json
Behavioral Rules To Match
core.encode(lat, lon, precision?)
- Latitude must be finite and in
[-90, 90]. - Longitude must be finite and in
[-180, 180]. - Precision must be finite, rounded to nearest integer, min
1, max12. - Invalid input throws
RangeError.
core.decode(hash)
- Empty hash throws
TypeError. - Non-base32 characters throw
TypeError. - Returns center point and half-cell error:
{ lat, lon, error: { lat, lon } }
core.neighbours(hash)
- Returns eight directions as keys:
n ne e se s sw w nw. - Longitude wraps across the antimeridian (
>180wraps to-180+,<-180wraps to180-). - Latitude does not wrap; it is clamped to
[-89.99999, 89.99999].
nostr.createGTagLadder(geohash, minPrecision?)
- Emits
["g", prefix]for each precision frommax(1, minPrecision)togeohash.length. - Empty geohash returns
[].
nostr.nearbyFilter(lat, lon, options?)
- Defaults:
precision=5,rings=1. - Produces
{ "#g": string[] }from center hash plus ring expansion. - Output is de-duplicated while preserving insertion order.
CI and Change Control
npm run vectors:checkvalidates stored vectors against current implementation.- CI runs this check and fails on output drift.
- If drift is intentional:
- update affected vector file(s),
- add a
CHANGELOG.mdnote describing the compatibility-impacting change.