Skip to main content
Development Preview — The SDK is under development.

Location Module

The LocationModule provides operations for creating, signing, and verifying location attestations using the Ethereum Attestation Service (EAS).
import { AstralSDK } from '@decentralized-geo/astral-sdk';

const astral = new AstralSDK({
  chainId: 84532,
  signer: wallet
});

// Access via astral.location
astral.location.offchain.*   // Offchain workflow
astral.location.onchain.*    // Onchain workflow
astral.location.build()      // Common operations
astral.location.encode()
astral.location.decode()

Common Operations

build()

Build an unsigned location attestation from input data.
astral.location.build(
  input: LocationAttestationInput
): Promise<UnsignedLocationAttestation>

Example

const unsigned = await astral.location.build({
  location: {
    type: 'Point',
    coordinates: [2.2945, 48.8584]
  },
  locationType: 'geojson-point',  // Optional - auto-detected
  memo: 'Eiffel Tower visit'
});

console.log(unsigned.eventTimestamp);
console.log(unsigned.location);  // Stringified GeoJSON
console.log(unsigned.locationType);  // 'geojson-point'

encode()

Encode an unsigned attestation for EAS.
astral.location.encode(
  attestation: UnsignedLocationAttestation,
  schemaType?: string  // Defaults to 'location'
): string

Example

const unsigned = await astral.location.build({ location: geojson });
const encoded = astral.location.encode(unsigned);

// Use encoded data with EAS directly if needed
console.log('Encoded:', encoded);

decode()

Decode EAS-encoded data back to attestation fields.
astral.location.decode(
  encodedData: string,
  schemaType?: string  // Defaults to 'location'
): Record<string, SchemaValue>

Example

// Decode from EAS attestation data
const decoded = astral.location.decode(attestation.data);

console.log(decoded.eventTimestamp);
console.log(decoded.locationType);
console.log(decoded.location);

Offchain Workflow

The offchain workflow creates EIP-712 signed attestations that can be verified without blockchain transactions.

offchain.create()

Build and sign an attestation in one step.
astral.location.offchain.create(
  input: LocationAttestationInput,
  options?: OffchainAttestationOptions
): Promise<OffchainLocationAttestation>

Example

const attestation = await astral.location.offchain.create({
  location: {
    type: 'Point',
    coordinates: [2.2945, 48.8584]
  },
  memo: 'Eiffel Tower',
  timestamp: new Date()
});

console.log('UID:', attestation.uid);
console.log('Signer:', attestation.signer);
console.log('Signature:', attestation.signature);

offchain.sign()

Sign a pre-built unsigned attestation.
astral.location.offchain.sign(
  unsigned: UnsignedLocationAttestation,
  options?: OffchainAttestationOptions
): Promise<OffchainLocationAttestation>

Example

// Build first
const unsigned = await astral.location.build({
  location: { type: 'Point', coordinates: [-122.4194, 37.7749] },
  memo: 'San Francisco'
});

// Sign separately
const signed = await astral.location.offchain.sign(unsigned);

console.log('UID:', signed.uid);

offchain.verify()

Verify an offchain attestation’s signature.
astral.location.offchain.verify(
  attestation: OffchainLocationAttestation,
  options?: OffchainAttestationOptions
): Promise<VerificationResult>

Example

const result = await astral.location.offchain.verify(attestation);

if (result.isValid) {
  console.log('Valid! Signed by:', result.signerAddress);
} else {
  console.log('Invalid:', result.reason);
}

offchain.publish()

Publish an offchain attestation to storage (IPFS, etc.).
astral.location.offchain.publish(
  attestation: OffchainLocationAttestation
): Promise<OffchainLocationAttestation>

Example

const published = await astral.location.offchain.publish(attestation);

console.log('Publications:', published.publications);
// [{ storageType: 'ipfs', reference: 'Qm...', publishedAt: 1234567890 }]

Onchain Workflow

The onchain workflow registers attestations directly on a blockchain via EAS.

onchain.create()

Build and register an attestation in one step.
astral.location.onchain.create(
  input: LocationAttestationInput,
  options?: OnchainAttestationOptions
): Promise<OnchainLocationAttestation>

Example

const attestation = await astral.location.onchain.create({
  location: {
    type: 'Polygon',
    coordinates: [[[
      [-122.42, 37.77],
      [-122.41, 37.77],
      [-122.41, 37.78],
      [-122.42, 37.78],
      [-122.42, 37.77]
    ]]]
  },
  memo: 'Property boundary'
});

console.log('UID:', attestation.uid);
console.log('Chain:', attestation.chain);
console.log('Tx Hash:', attestation.txHash);
console.log('Block:', attestation.blockNumber);

onchain.register()

Register a pre-built unsigned attestation.
astral.location.onchain.register(
  unsigned: UnsignedLocationAttestation,
  options?: OnchainAttestationOptions
): Promise<OnchainLocationAttestation>

Example

// Build first
const unsigned = await astral.location.build({
  location: geojson,
  memo: 'My location'
});

// Register separately
const onchain = await astral.location.onchain.register(unsigned);

console.log('Tx Hash:', onchain.txHash);

onchain.verify()

Verify an onchain attestation exists and is not revoked.
astral.location.onchain.verify(
  attestation: OnchainLocationAttestation,
  options?: OnchainAttestationOptions
): Promise<VerificationResult>

Example

const result = await astral.location.onchain.verify(attestation);

if (result.isValid) {
  console.log('Valid onchain attestation');
  console.log('Revoked:', result.revoked);
} else {
  console.log('Invalid:', result.reason);
}

onchain.revoke()

Revoke an onchain attestation.
astral.location.onchain.revoke(
  attestation: OnchainLocationAttestation,
  options?: OnchainAttestationOptions
): Promise<unknown>

Example

// Only works if attestation was created with revocable: true
if (attestation.revocable && !attestation.revoked) {
  await astral.location.onchain.revoke(attestation);
  console.log('Attestation revoked');
}

Input Types

LocationAttestationInput

interface LocationAttestationInput {
  // Location data - flexible format
  location: unknown;  // GeoJSON, WKT, coordinate pair, H3 index

  // Optional format hints
  locationType?: string;        // e.g., 'geojson-point', 'wkt-polygon', 'h3'
  targetLocationFormat?: string; // Convert to this format

  // Timing
  timestamp?: Date;  // Defaults to now

  // Media attachments
  media?: MediaInput[];

  // Additional fields
  memo?: string;
  recipient?: string;  // Ethereum address
}

Supported Location Formats

FormatlocationTypeExample
GeoJSON Pointgeojson-point{ type: 'Point', coordinates: [lon, lat] }
GeoJSON Polygongeojson-polygon{ type: 'Polygon', coordinates: [...] }
GeoJSON LineStringgeojson-linestring{ type: 'LineString', coordinates: [...] }
WKTwkt-*'POINT(-122.4194 37.7749)'
Coordinate Paircoordinates-decimal+lon-lat[-122.4194, 37.7749]
H3 Indexh3'8928308280fffff'
Location format is auto-detected when locationType is not specified.

Output Types

OffchainLocationAttestation

interface OffchainLocationAttestation {
  // From UnsignedLocationAttestation
  eventTimestamp: number;
  srs: string;
  locationType: string;
  location: string;
  recipeType: string[];
  recipePayload: string[];
  mediaType: string[];
  mediaData: string[];
  memo?: string;

  // Signature fields
  uid: string;
  signature: string;
  signer: string;
  version: string;

  // Storage
  publications?: PublicationRecord[];
}

OnchainLocationAttestation

interface OnchainLocationAttestation {
  // From UnsignedLocationAttestation
  eventTimestamp: number;
  srs: string;
  locationType: string;
  location: string;
  // ... other fields

  // Blockchain fields
  uid: string;
  attester: string;
  chain: string;
  chainId: number;
  txHash: string;
  blockNumber: number;
  revocable: boolean;
  revoked: boolean;
}

VerificationResult

interface VerificationResult {
  isValid: boolean;
  revoked?: boolean;
  signerAddress?: string;
  attestation?: LocationAttestation;
  reason?: string;
}

Coordinate Format

Coordinates use the GeoJSON standard: [longitude, latitude]
// San Francisco
const sf = {
  type: 'Point',
  coordinates: [-122.4194, 37.7749]  // [lon, lat]
};

// Polygon (counterclockwise, closed ring)
const area = {
  type: 'Polygon',
  coordinates: [[[
    [-122.42, 37.77],
    [-122.41, 37.77],
    [-122.41, 37.78],
    [-122.42, 37.78],
    [-122.42, 37.77]  // Close the ring
  ]]]
};

Next: Compute Module

Learn about geospatial computation methods