Research Preview — The SDK is under development.
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.
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 ();
All compute methods accept flexible input types:
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
// 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
);
Raw GeoJSON is not verified for authenticity. The inputRefs will contain a keccak256 hash of the geometry rather than a UID.
Compute Options
All methods require options:
interface ComputeOptions {
schema : string ; // Required: EAS schema UID for the result
recipient ?: string ; // Optional: recipient address (defaults to zero address)
}
Schema Requirements
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.
Operation Required Schema Type distance, area, lengthNumericPolicyAttestation contains, within, intersectsBooleanPolicyAttestation
// 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 for schema definitions and default UIDs.
Numeric Operations
distance()
Calculate the geodesic distance between two geometries.
astral . compute . distance (
from : Input ,
to : Input ,
options : ComputeOptions
): Promise < NumericComputeResult >
Example
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.
astral . compute . area (
geometry : Input ,
options : ComputeOptions
): Promise < NumericComputeResult >
Example
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.
astral . compute . length (
geometry : Input ,
options : ComputeOptions
): Promise < NumericComputeResult >
Example
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.
astral . compute . contains (
container : Input ,
containee : Input ,
options : ComputeOptions
): Promise < BooleanComputeResult >
Example
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.
astral . compute . within (
geometry : Input ,
target : Input ,
radius : number , // meters
options : ComputeOptions
): Promise < BooleanComputeResult >
Example
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).
astral . compute . intersects (
a : Input ,
b : Input ,
options : ComputeOptions
): Promise < BooleanComputeResult >
Example
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.
astral . compute . submit (
attestation : DelegatedAttestation
): Promise < AttestationResult >
Example
// 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.
astral . compute . estimate (
attestation : DelegatedAttestation
): Promise < bigint >
Example
const gas = await astral . compute . estimate ( result . delegatedAttestation );
console . log ( 'Estimated gas:' , gas . toString ());
// Proceed if acceptable
if ( gas < 200000 n ) {
await astral . compute . submit ( result . delegatedAttestation );
}
health()
Check the compute service health status.
astral . compute . health (): Promise < HealthStatus >
Example
const status = await astral . compute . health ();
console . log ( 'Service status:' , status . status );
console . log ( 'Database status:' , status . database );
Return Types
NumericComputeResult
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
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
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
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:
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 );
}
Next: EAS Integration Learn how the SDK integrates with EAS