The first step to request Proof of Location to the Trusted Location API is to prepare a POST call the API endpoint with the following body:
{"owner":"0x926CA7b35C2b5F528460A8f164054cE61BfCacFb", "message": "awesome.app wants you to sign in with your Ethereum account:\n0x926CA7b35C2b5F528460A8f164054cE61BfCacFb\n\nSign in Location Based NFT The application will know if you were located in one of the following regions in the time range below: from: Tue Dec 06 2022 16:58:58 GMT+0000 to: Tue Dec 06 2022 16:58:58 GMT+0000\n\nURI: http://localhost:3000\nVersion: 1\nChain ID: 4690\nNonce: CcWaTbGzTDPcqF1Ov\nIssued At: 2022-12-06T16:58:58.554Z\nExpiration Time: 2022-12-06T16:59:58.553Z'",
"signature": "0x740c730c6486c8edc56ff22322f16044d4b761dcdf717a067f8241e2bf54d7f477f79ba10cbe21d9efb14ee12fa0c8321972806ad7ea848a4248d575532332f81b",
"locations": [ {"scaled_latitude": 120520000, "scaled_longitude": 30400000, "distance": 1000, "from": 1669963142, "to": 1669964142},
{"scaled_latitude": 26092603, "scaled_longitude": 119255364, "distance": 1000, "from": 1669963142, "to": 1672555142},
{"scaled_latitude": 45481106, "scaled_longitude": 9146373, "distance": 500, "from": 1670216401, "to": 1670367600}
]}
owner: is the ioPay wallet address that the user associated with service
message: is a prepared SIWE (Sign In With Ethereum) message
signature: owner's is the signature of the SIWE message
locations: is an array of locations and time ranges, in the following format:
{ "scaled_latitude":120520000,// Integer(Location Latitude * 10^6)"scaled_longitude":30400000,// Integer(Longitude * 10^6)"distance":500,// Max distance from the location"from":1669963142,// Start of time range"to":1669964142// End of time range}
Create a SIWE message
the code below shows an example of how to generate a SIWE message and have the user sign it inside the Metamask or ioPay Mobile wallet:
import { SiweMessage } from"siwe";import moment from"moment";constOWNER_ADDRESS="0x926CA7b35C2b5F528460A8f164054cE61BfCacFb";constCHAIN_ID=4690;...createSiweMessage= () => {constmessage=newSiweMessage({ domain:globalThis.location.host, address:OWNER_ADDRESS, statement: `Sign in Location Based NFT The application will know if you were located in one of the following regions in the time range below: from: ${moment().utc().subtract(1, "days");} to: ${moment().utc().add(1, "days"}`,
uri:globalThis.location.origin, version:"1", chainId:CHAIN_ID, expirationTime:moment().add(1,"minutes").toISOString(), });returnmessage.prepareMessage();};
Example SIWE message
This is how a SIWE message would look like before it's prepared for the user:
{"domain":"awesome.app","address":"0x926CA7b35C2b5F528460A8f164054cE61BfCacFb","chainId":4690,"expirationTime":"2022-11-30T15:20:03.433Z","statement":"Sign in Location Based NFT","uri":"https://awesome.app","version":"1"}
This is how this message would look in Metamask after it's prepared and displayed to the user for signing in Metamask:
awesome.app wants you to sign in with your Ethereum account:
0x926CA7b35C2b5F528460A8f164054cE61BfCacFb
Sign in Location Based NFT The application will know if you were located in one of the following regions in the time range below: from: Mon Dec 05 2022 18:20:33 GMT+0000 to: Wed Dec 07 2022 18:20:33 GMT+0000
URI: https://awesome.app
Version: 1
Chain ID: 4690
Nonce: sVlTp2bcgCEYVz1Ou
Issued At: 2022-12-06T18:20:33.260Z
Expiration Time: 2022-12-06T18:21:33.259Z
Sign the SIWE message
The example below shows a possible way to sign the SIWE message in Metamask or ioPay mobile:
import { useSDK } from"@thirdweb-dev/react";constsdk=useSDK();...// Sign the SIWE message in the wallet appconstmessage=createSiweMessage();constsignature=awaitsdk?.wallet.sign(message);
Send the Query to GeoStream
Below is an example of how to send the query to GeoStream:
import axios from"axios";constNEXT_PUBLIC_APIURL="https://geo-test.w3bstream.com/api/pol";...constbody= { signature,// SIWE signature message,// Prepared SIWE message owner:this.owner,// User's ioPay address that was associated to GeoStream locations: [ // Locations to be queried, with resp. time ranges {"scaled_latitude": 120520000, "scaled_longitude": 30400000, "distance": 1000, "from": 1669963142, "to": 1669964142},
{"scaled_latitude": 26092603, "scaled_longitude": 119255364, "distance": 1000, "from": 1669963142, "to": 1672555142},
{"scaled_latitude": 45481106, "scaled_longitude": 9146373, "distance": 500, "from": 1670216401, "to": 1670367600}
] };// Query the proof of locationconstresponse=awaitaxios.post(`${NEXT_PUBLIC_APIURL}/api/get_sign_data_for_location`, body);// Get the respose data from the APIconstsignData:SIGN_DATA[] =response.data.result.data;
The API response data contain the actual Proofs of Location in the form of a subset of the queried locations, with some added information. Let's take a closer look:
For each GeoStream device that a user associated with the ioPay address, and for each queried location, the API will return a signed "(device, location)" entry if that device was actually in that location in the respective time range. Each entry will include the following fields:
{// The location data as provided in the query"scaled_latitude":45481106,"scaled_longitude":9146373,"distance":500,"from":129098787,"to":1779987,// The data of the user owned device that was in that location in that time range"devicehash":"0x...","imei":"123456789012345"// The GeoStream API signature of a message including the fields above"signature: "0x...", }
Each one of those entries can be easily verified by the GeoStream Verifier Contract.