NIP-44 ====== Geospatial Types ------------------------- `draft` `optional` `author:rossbates` `author:milesbates` ## Description An event of `kind 4326` is a geospatial note supporting various location-based clients such as transportation, travel, home automation, and social applications. The data for this event is stored in the `content` field and should contain only valid GeoJSON objects. This proposal recommends storing geographic features in standalone events that reference other `e` and `p` tags, similar to how `kind 7` responses work. By requiring geographic features to link to related keys and events, rather than embedding location data within events, collections of notes in nostr will remain composable. Using GeoJSON as the geospatial data type for nostr supports interoperability with existing web standards and designating it type `kind 4326` provides a standard method for future nostr kinds to integrate it in their applications. For example, developers might implement notes that represent objects such as calendar events, restaurant reviews, or concert tickets - in this situation each of these notes would have a convenient way to integrate existing location data using `e` and `p` tags linked to `kind 4326` notes. If no useable data exists, they can create new `kind 4326` notes. All of this would be fully backwards compatible with the nostr protocol. An object represented by `p` could potentially be a fixed location such as a building, a shape boundary such as a geofence or border, or a moving object such as a truck or a nostr user. Each of these potentially has geospatial data that can be represented using GeoJSON. There are no minimum or maximum number of `kind 4326` notes that can be associated with a given `p`, nor are there restrictions on who can create them. This provides the most freedom for relays and clients to build solutions for making nostr objects spatially aware while adhering to the existing protocol standards. ## Example Here is an example of how the use of `kind 4326` notes could be used in a real world example. In this scenario there are 3 nostr users (A,B,C) attending a nostr developer meetup in the evening who would like to privately share their location with their trusted contacts so they can coordinate dinner and transportation. They'll do this using the same nostr mobile app they use to communicate with a wider group of people. The meetup is taking place at the Bitcoin Commons in downtown Austin represented by the following note. ```json ["EVENT", { "id": "2953ae40dfc6c814cabef08a34e917e9886ffe3b11be54e0f14e0e76d1692197", "pubkey": "90f415eb9dd25616185f252f1565d9cfc0392906e4e2638d13fda1242aa00b09", "created_at": 1671975000, "kind": 4326, "tags": [], "content": "{'type': 'Point','coordinates': [-97.74274456131394,30.268100484614934]}", "sig": "0ecf4b5649366ab7f99123ff6ae9767bca988d8545300e545f09e1d9a956a0fa2e013ab12360c7abb4bbfa56338477f7ce5513754b06f472f5cc3eb40f6f2cab" }] ``` At 5:30 User A posts a kind 1 note using their nostr app reminding everyone about the event. In this note they tagged both the location as well as the 2 friends who will also be attending. This was done using the `e` tag for the location and the `p` of the contacts. ```json ["EVENT", { "id": "f040fc0ba2620264efb19d2764ceaa7978977256034594c9af5b4a5be356c797", "pubkey": "c403fbbc3808913bccdc4460986dd09f3985376ecf07d4b471d18644075d0c4c", "created_at": 1674603000, "kind": 1, "tags": [ ["e", "2953ae40dfc6c814cabef08a34e917e9886ffe3b11be54e0f14e0e76d1692197", "wss...", "root"], ["p", "3c8d410ef11ae8abbc541783cacecbb35075b93d23837fa59d59c3610c1c580c"], ["p", "24226e17fcecdab9277218ab126ee882192c6ae3f1fec5689924e77754f00c11"] ], "content": "Excited to see everyone this evening at the ATX nostr dev meetup.", "sig": "8a2228542bb69ab7b9a12824cd0df88eafd27e4993eec990c107b79a519754a436c1f5114188db254d8499cc6b7b5095ea34ade9173a8903739845da6d4a2815" }] ``` In the same post User A chooses the option to attach their current location (created as `kind 4326`) to the post. The app generates an event referencing the original `kind 1` note which goes to all public relays, while and both events gets posted to a private relay. At this point the client is still able to filter for all public and private responses to the `kinda 1` note. ```json ["EVENT", { "id": "9850551d116a4c2c69b7d084a6b27aa95e0ba6ddf8b04cac33145ab290465733", "pubkey": "c403fbbc3808913bccdc4460986dd09f3985376ecf07d4b471d18644075d0c4c", "created_at": 1674603000, "kind": 4326, "tags": [ ["e", "f040fc0ba2620264efb19d2764ceaa7978977256034594c9af5b4a5be356c797", "wss...", "reply"] ], "content": "{'type': 'Point','coordinates': [-97.73995249685214, 30.282439538024022]}", "sig": "026174991b8e956a4ef591c08bb69e506d5f42a07aa652d6af106a33a83017f646ed37f85e010aa0cd7b1e0beb0fc546c0acdb564a8daff84047d437e358f7e2" }] ``` Users A,B and C all have access to the same private relay which supports receiving and responding to `kind 4326` messages. When user A sends the location update that includes `p` tags it automatically generates a `kind 1` note for all parties. User B & C are able to respond using only a `kind 4326` note over the same private relay. These responses can include their current location coordinates, as well as other any other related `p` tags such as the Coffee Shop or Park they're currently at. User B Response: ```json ["EVENT", { "id": "49734138379434153a4af1275fe6afcc18937a326ff950875a0c7165ac2be123", "pubkey": "3c8d410ef11ae8abbc541783cacecbb35075b93d23837fa59d59c3610c1c580c", "created_at": 1674603213, "kind": 4326, "tags": [ ["e", "9850551d116a4c2c69b7d084a6b27aa95e0ba6ddf8b04cac33145ab290465733", "wss...", "reply"] ], "content": "{'type': 'Point','coordinates': [-97.7491855918345, 30.251096509429328]}", "sig": "b9889b3ae92ed5942a7270b6322b80d55230b256bd416d25e519ea07989a8eea8d105b0debb2d30366c70cd479b638453e16b2b9e8a016991b7f941fff553f05" }] ``` User C Response: ```json ["EVENT", { "id": "36fbb58a1dcd30aa3420eb456306435d4b06be4b804987fe000be8b58b2efed1", "pubkey": "24226e17fcecdab9277218ab126ee882192c6ae3f1fec5689924e77754f00c11", "created_at": 1674603321, "kind": 4326, "tags": [ ["e", "9850551d116a4c2c69b7d084a6b27aa95e0ba6ddf8b04cac33145ab290465733", "wss...", "reply"] ], "content": "{'type': 'Point','coordinates': [-97.75077606389179, 30.26308185185999]}", "sig": "230f53ea5aa2c9a979badbb400f31edafa227ae526f019c1ffadf69ec257b21c360ca6ef779ea592a4eb7ffa7e8cedd6b5877c99ff202d1ecbdca99f76137d4c" }] ``` This is a basic example to demonstrate the data structures showing how the initial handshake between peers would work. From here the private relay now has everything it needs act as a coordinator executing geofence and nearby queries on the notes, generating arrival estimates, routing suggestions, ride-share integration. There are many options that go beyond the scope of the NIP. ## Other Considerations **Privacy Controls**: notes with `kind 4326` can be routed separately to private and/or user specified relays for handling. This provides users with options to protect their private data if they choose, and it provides client developers a solution for combining public and private data into composite events. Beyond the protocol, we hope this design will prevent the abuses of the current generation of mobile apps which aggregate location data and monetize it on 3rd party ad-networks without the knowledge of their users. **Proof of Location**: This design makes it so anyone is free to build validation and attestation services that an event took place in a physical location. For example, users could check-in at a concert using any nostr client to receive a special badge. Attestation and issuance could originate from any number of trusted sources, such as the artist and/and venue, without requiring users to be running a specific application or platform. Attestation could come from sources such as nostr peers, payment systems, photos or QR codes - or a combination of these using nostr multi-sig. Location proofs could be provided for any valid event, by any signer, with no barriers to entry. **Decentralized Data Providers**: Support for nostr data types such as `kind 4326` will open up opportunities for nostr relay operators to serve as data service providers. A `kind 4326` event can be any valid geometry including buildings, geofences, and points of interest. This is similar to the concept of linked data URIs, but it's much simpler - `p` can represent any location on earth. Relay operators could charge for custom key/data management services. **Relay Performance**: By separating data types and content using this approach, relays can route events without the need for content inspection. Notes with `kind 4326` can be forwarded to backend indexing services which respond with new events when conditions are met. As the network grows, some relays may be dedicated solely to routing events based on their type. ## Open Issues ### NIP-16 What is the desired behavior when it's reasonable for an event to be either a Regular event (`1000 <= n < 10000`), Replaceable event (`10000 <= n < 20000`), or Ephemeral (`20000 <= n < 30000`) event as defined by NIP-16? Take for example a bus tracking application where the users are checking on the status of their bus identified by: ```json ["p", "b68cf380888a13fab39afb144fb9e9502a8560af85943fa0cdcf1e3e130a109d"] ``` A solution could be a new type created such as `kind 14326` or `kind 24326` for use as the "current status" location. If however the client app is also tracking the history of the bus then `kind 14326` is equal to the most recent `kind 4326`. Should this be something defined by the protocol, or left up to the developers? To be clear, this decision is not a technical challenge, but as types in nostr begin to increase some guidelines for how these types are assigned and used will need to be figured out. For now this NIP proposes using only `kind 4326` ## Other Notes - The value `4326` was selected because it is the default coordinate reference system (CRS) for the GeoJSON specification. If a client or relay wants to use another reference system the GeoJSON spec fully supports including it as a tag. - There have been suggestions about using a more compact binary encoding scheme to improve efficiency over the wire. This would require a format to be chosen which would inherently have implications for developers. Plain text ensures notes of this type can be exchanged by all relays and client no matter what languages or platforms they're using. - A proof-of-concept has been developed using a fork of Damus iOS as the client and a fork of Dave St. Germain's nostr_relay as the server. This will be made available at geonostr.org for people who want to participate testing. Reach out to `rossbates` on nostr if interested: `npub1u656f7znujcagfhtgngvtkcflhzptnj38enyzx85da0lh63sfj7qva332p`