> ## Documentation Index
> Fetch the complete documentation index at: https://astral-6ef288be-claude-ascii-globe-mouse-interaction-bupya.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Compute Module

> Verifiable geospatial computation methods

<Warning>
  **Research Preview** — The SDK is under development.
</Warning>

# Compute Module

The `ComputeModule` provides verifiable geospatial operations that run in a trusted execution environment. Each operation returns a signed delegated attestation that can be submitted to EAS.

```typescript theme={null}
import { AstralSDK } from '@decentralized-geo/astral-sdk';

const astral = new AstralSDK({
  chainId: 84532,
  signer: wallet,
  apiUrl: 'https://api.astral.global'
});

// Access via astral.compute
astral.compute.distance(from, to, options);
astral.compute.area(geometry, options);
astral.compute.length(geometry, options);
astral.compute.contains(container, containee, options);
astral.compute.within(geometry, target, radius, options);
astral.compute.intersects(a, b, options);
astral.compute.submit(delegatedAttestation);
astral.compute.estimate(delegatedAttestation);
astral.compute.health();
```

***

## Input Types

All compute methods accept flexible input types:

```typescript theme={null}
type Input =
  | string                    // Onchain attestation UID
  | GeoJSON.Geometry          // Raw GeoJSON geometry
  | GeoJSON.Feature           // GeoJSON Feature (geometry extracted)
  | { uid: string }           // Onchain reference
  | { uid: string, uri: string }  // Offchain reference
```

### Examples

```typescript theme={null}
// Using attestation UID
const result = await astral.compute.distance(
  '0x1234...abcd',  // UID
  '0x5678...efgh',  // UID
  options
);

// Using raw GeoJSON
const result = await astral.compute.distance(
  { type: 'Point', coordinates: [2.2945, 48.8584] },
  { type: 'Point', coordinates: [-0.1276, 51.5074] },
  options
);

// Mixing UIDs and GeoJSON
const result = await astral.compute.contains(
  boundaryUID,  // Polygon UID
  { type: 'Point', coordinates: [lon, lat] },  // Raw point
  options
);
```

<Note>
  Raw GeoJSON is not verified for authenticity. The `inputRefs` will contain a keccak256 hash of the geometry rather than a UID.
</Note>

***

## Compute Options

All methods require options:

```typescript theme={null}
interface ComputeOptions {
  schema: string;       // Required: EAS schema UID for the result
  recipient?: string;   // Optional: recipient address (defaults to zero address)
}
```

### Schema Requirements

<Warning>
  **Use the correct schema type** - Compute operations encode data differently than Location attestations. Using the wrong schema UID causes a data/schema mismatch where the attestation is stored but cannot be decoded correctly.
</Warning>

| Operation                          | Required Schema Type     |
| ---------------------------------- | ------------------------ |
| `distance`, `area`, `length`       | NumericPolicyAttestation |
| `contains`, `within`, `intersects` | BooleanPolicyAttestation |

```typescript theme={null}
// CORRECT: Boolean operation with Boolean schema
await compute.within(point, target, 500, {
  schema: BOOLEAN_POLICY_SCHEMA_UID  // bool result, bytes32[] inputRefs, ...
});

// WRONG: Boolean operation with Location schema
await compute.within(point, target, 500, {
  schema: LOCATION_SCHEMA_UID  // bytes geometry, string geometryType, ...
});
// The attestation is created but data is unreadable!
```

See [Schemas](/resources/schemas) for schema definitions and default UIDs.

***

## Numeric Operations

### distance()

Calculate the geodesic distance between two geometries.

```typescript theme={null}
astral.compute.distance(
  from: Input,
  to: Input,
  options: ComputeOptions
): Promise<NumericComputeResult>
```

#### Example

```typescript theme={null}
const result = await astral.compute.distance(
  userLocationUID,
  landmarkUID,
  { schema: SCHEMA_UID }
);

console.log(result.result);  // 523.45
console.log(result.units);   // 'meters'
console.log(result.operation);  // 'distance'

// Submit onchain
await astral.compute.submit(result.delegatedAttestation);
```

***

### area()

Calculate the area of a polygon.

```typescript theme={null}
astral.compute.area(
  geometry: Input,
  options: ComputeOptions
): Promise<NumericComputeResult>
```

#### Example

```typescript theme={null}
const result = await astral.compute.area(
  propertyBoundaryUID,
  { schema: SCHEMA_UID }
);

console.log(result.result);  // 5432.10
console.log(result.units);   // 'square_meters'
```

***

### length()

Calculate the length of a LineString.

```typescript theme={null}
astral.compute.length(
  geometry: Input,
  options: ComputeOptions
): Promise<NumericComputeResult>
```

#### Example

```typescript theme={null}
const result = await astral.compute.length(
  routeUID,
  { schema: SCHEMA_UID }
);

console.log(result.result);  // 2345.67
console.log(result.units);   // 'meters'
```

***

## Boolean Operations

### contains()

Check if a container geometry contains another geometry.

```typescript theme={null}
astral.compute.contains(
  container: Input,
  containee: Input,
  options: ComputeOptions
): Promise<BooleanComputeResult>
```

#### Example

```typescript theme={null}
const result = await astral.compute.contains(
  geofencePolygonUID,
  userLocationUID,
  { schema: SCHEMA_UID }
);

if (result.result) {
  console.log('User is inside the geofence!');
  await astral.compute.submit(result.delegatedAttestation);
}
```

***

### within()

Check if a geometry is within a specified radius of a target.

```typescript theme={null}
astral.compute.within(
  geometry: Input,
  target: Input,
  radius: number,  // meters
  options: ComputeOptions
): Promise<BooleanComputeResult>
```

#### Example

```typescript theme={null}
const result = await astral.compute.within(
  userLocationUID,
  landmarkUID,
  500,  // 500 meters
  { schema: SCHEMA_UID, recipient: userAddress }
);

if (result.result) {
  console.log('User is within 500m of the landmark!');
  // Submit to trigger resolver action
  await astral.compute.submit(result.delegatedAttestation);
}
```

***

### intersects()

Check if two geometries intersect (overlap).

```typescript theme={null}
astral.compute.intersects(
  a: Input,
  b: Input,
  options: ComputeOptions
): Promise<BooleanComputeResult>
```

#### Example

```typescript theme={null}
const result = await astral.compute.intersects(
  territory1UID,
  territory2UID,
  { schema: SCHEMA_UID }
);

console.log('Territories overlap:', result.result);
```

***

## Submission Methods

### submit()

Submit a delegated attestation to EAS. You pay gas; Astral remains the attester.

```typescript theme={null}
astral.compute.submit(
  attestation: DelegatedAttestation
): Promise<AttestationResult>
```

#### Example

```typescript theme={null}
// Compute first
const result = await astral.compute.within(
  userLocationUID,
  landmarkUID,
  500,
  { schema: SCHEMA_UID }
);

// Submit if the check passed
if (result.result) {
  const submission = await astral.compute.submit(result.delegatedAttestation);
  console.log('Attestation UID:', submission.uid);
}
```

***

### estimate()

Estimate gas for attestation submission.

```typescript theme={null}
astral.compute.estimate(
  attestation: DelegatedAttestation
): Promise<bigint>
```

#### Example

```typescript theme={null}
const gas = await astral.compute.estimate(result.delegatedAttestation);
console.log('Estimated gas:', gas.toString());

// Proceed if acceptable
if (gas < 200000n) {
  await astral.compute.submit(result.delegatedAttestation);
}
```

***

### health()

Check the compute service health status.

```typescript theme={null}
astral.compute.health(): Promise<HealthStatus>
```

#### Example

```typescript theme={null}
const status = await astral.compute.health();
console.log('Service status:', status.status);
console.log('Database status:', status.database);
```

***

## Return Types

### NumericComputeResult

```typescript theme={null}
interface NumericComputeResult {
  result: number;           // The computed value
  units: string;            // 'meters' or 'square_meters'
  operation: string;        // 'distance', 'area', or 'length'
  timestamp: number;        // Unix timestamp
  inputRefs: string[];      // UIDs or hashes of inputs
  attestation: {
    schema: string;
    attester: string;
    recipient: string;
    data: string;
    signature: string;
  };
  delegatedAttestation: {
    message: DelegatedAttestationMessage;
    signature: { v: number; r: string; s: string };
    attester: string;
  };
}
```

### BooleanComputeResult

```typescript theme={null}
interface BooleanComputeResult {
  result: boolean;          // The computed boolean
  operation: string;        // 'contains', 'within', or 'intersects'
  timestamp: number;        // Unix timestamp
  inputRefs: string[];      // UIDs or hashes of inputs
  attestation: {
    schema: string;
    attester: string;
    recipient: string;
    data: string;
    signature: string;
  };
  delegatedAttestation: {
    message: DelegatedAttestationMessage;
    signature: { v: number; r: string; s: string };
    attester: string;
  };
}
```

### DelegatedAttestation

```typescript theme={null}
interface DelegatedAttestation {
  message: {
    schema: string;
    recipient: string;
    expirationTime: bigint;
    revocable: boolean;
    refUID: string;
    data: string;
    value: bigint;
    nonce: bigint;
    deadline: bigint;
  };
  signature: {
    v: number;
    r: string;
    s: string;
  };
  attester: string;
}
```

***

## Complete Example

```typescript theme={null}
import { AstralSDK } from '@decentralized-geo/astral-sdk';
import { ethers } from 'ethers';

// Setup
const provider = new ethers.JsonRpcProvider('https://sepolia.base.org');
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);

const astral = new AstralSDK({
  chainId: 84532,
  signer: wallet,
  apiUrl: 'https://api.astral.global'
});

// Create a location attestation
const location = await astral.location.onchain.create({
  location: { type: 'Point', coordinates: [2.2951, 48.8580] },
  memo: 'Near Eiffel Tower'
});

// Check proximity to landmark
const EIFFEL_TOWER_UID = '0x...';  // Pre-registered landmark
const SCHEMA_UID = '0x...';       // Your resolver schema

const result = await astral.compute.within(
  location.uid,
  EIFFEL_TOWER_UID,
  500,  // 500 meters
  { schema: SCHEMA_UID, recipient: wallet.address }
);

console.log('Within 500m:', result.result);
console.log('Input refs:', result.inputRefs);

// Submit to trigger resolver
if (result.result) {
  const gas = await astral.compute.estimate(result.delegatedAttestation);
  console.log('Estimated gas:', gas.toString());

  const submission = await astral.compute.submit(result.delegatedAttestation);
  console.log('Attestation submitted:', submission.uid);
}
```

***

## How Delegated Attestations Work

| Step | Who            | Does What                                      |
| ---- | -------------- | ---------------------------------------------- |
| 1    | **Developer**  | Calls `compute.within()` or other method       |
| 2    | **Astral API** | Runs computation in TEE, signs attestation     |
| 3    | **Developer**  | Receives signed `delegatedAttestation`         |
| 4    | **Developer**  | Calls `compute.submit()` (pays gas)            |
| 5    | **EAS**        | Verifies signature, records Astral as attester |
| 6    | **Resolver**   | Checks `attestation.attester == astralSigner`  |

This pattern means:

* Astral does not need to pay gas for every computation
* Developers control when/whether to submit onchain
* Smart contracts can verify attestations came from Astral

***

## Signature Expiry

Delegated attestation signatures have a deadline:

```typescript theme={null}
const result = await astral.compute.within(uid1, uid2, 500, options);

// Check deadline (Unix timestamp)
const deadline = result.delegatedAttestation.message.deadline;
const now = BigInt(Math.floor(Date.now() / 1000));

if (now < deadline) {
  await astral.compute.submit(result.delegatedAttestation);
} else {
  // Signature expired - request new computation
  const newResult = await astral.compute.within(uid1, uid2, 500, options);
  await astral.compute.submit(newResult.delegatedAttestation);
}
```

<Card title="Next: EAS Integration" icon="arrow-right" href="/sdk/eas">
  Learn how the SDK integrates with EAS
</Card>
